home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Interdit
/
pc-interdit.iso
/
graph
/
gif.asm
< prev
next >
Wrap
Assembly Source File
|
1994-10-07
|
13KB
|
319 lines
.286
clr=256 ;code d'effacement de l'alphabet
eof=257 ;code de fin de fichier
w equ word ptr
b equ byte ptr
data segment public
extrn gifname:dataptr ;Nom du fichier Gif, avec ".gif" + db 0
extrn vscreen:dword ;pointe sur la mémoire de destination
extrn palette:dataptr ;palette de destination
extrn vram_pos:word ;position à l'intérieur de la mémoire d'écran
extrn rest:word ;nbre de codes restant à copier
extrn numerr:word; ;indicateur d'erreur
handle dw 0 ;handle DOS pour fichier Gif
buff db 768 dup (0) ;buffer des données lues
buffInd dw 0 ;pointeur à l'intérieur de ce buffer
abStack db 1281 dup (0) ;pile de décodage
ab_prfx dw 4096 dup (0) ;alphabet, préfixe
ab_suffx dw 4096 dup (0) ;alphabet, suffixe
free dw 0 ;position libre dans l'alphabet
nbbit dw 0 ;nombre de bits dans un code
max dw 0 ;nombre maximum d'entrées dans un alphabet à nbbit
stackp dw 0 ;pointeur dans la pile de l'alphabet
restbits dw 0 ;nombre de bits à lire
restbyte dw 0 ;nombre d'octets disponibles dans le buffer
casspecial dw 0 ;mémoire pour le cas spécial
act_code dw 0 ;code traité
old_code dw 0 ;code précédent
readbyt dw 0 ;code en cours de lecture
lbyte dw 0 ;dernier code lu
data ends
extrn p13_2_modex:far ;utilisé en cas de dépassement du segment
code segment public
assume cs:code,ds:data
public readgif
GifRead proc pascal n:word
;lit n octets dans le fichier
mov ax,03f00h ;fonction 3fh de l'interruption 21h
mov bx,handle ;charge le handle
mov cx,n ; et le nombre d'octets à lire
lea dx,buff ;pointe sur le buffer de destination
int 21h ;exécute l'interruption
ret
gifread endp
GifOpen proc pascal
;ouvre le fichier Gif pour y accéder en lecture
mov ax,03d00h ;fonction 3dh: ouvrir
lea dx,gifname + 1 ;pointe sur le nom (saute l'octet qui mémorise la taille)
int 21h ;exécute l'interruption
mov handle,ax ;sauvegarde le handle
ret
gifopen endp
GifClose proc pascal
;ferme le fichier Gif
mov ax,03e00h ;fonction 3eh: fermer
mov bx,handle ;charge le handle
int 21h ;exécute l'interruption
ret
gifclose endp
GifSeek proc pascal ofs:dword
;positionne le pointeur du fichier
mov ax,04200h ;fonction 42h,
mov bx,w handle ;sous-fonction 0: Seek relatif au début du fichier
mov cx,word ptr ofs + 2 ;charge l'offset
mov dx,word ptr ofs
int 21h ;exécute l'interruption
ret
Endp
ShiftPal proc pascal
;adapte la palette 24 bits au format VGA (18 bits)
mov ax,ds ;segment de données pour tables source et destination
mov es,ax
mov si,offset buff ;lecture dans le buffer de données
lea di,palette ;écriture dans la palette de destination
mov cx,768d ;traite 786 octets
@l1:
lodsb ;lit un octet
shr al,2 ;le convertit
stosb ;et l'enregistre
loop @l1
ret
Endp
FillBuff proc pascal
;lit tout un bloc du fichier en Buf
call gifread pascal,1 ;lit un octet
mov al,b buff[0] ;transfère la taille en al
xor ah,ah
mov w restbyte,ax ;et la mémorise en restbyte
call gifread pascal, ax ;lit les octets
ret
Endp
GetPhysByte proc pascal
;lit un octet dans le buffer
push bx ;bx préservé pour l'appelant
cmp w restbyte,0 ;plus de données dans le buffer ?
ja @yadurab
pusha ;remplit à nouveau le buffer
call fillbuff
popa
mov w buffInd,0 ;réinitialise le pointeur
@yadurab: ;il y a des données dans le buffer
mov bx,w buffInd ;charge le pointeur
mov al,b buff[bx] ;lit un octet
inc w buffInd ;déplace le pointeur
pop bx ;c'est tout
ret
Endp
GetLogByte proc pascal
;lit un code dans le buffer en exploitant GetPhysByte
push si ;registre "si" préservé pour l'appelant
mov ax,w nbbit ;lit la taille en bits du code
mov si,ax ;et la sauvegarde
mov dx,w restbits ;décale lbyte de 8-restbits vers la droite
mov cx,8
sub cx,dx ;calcule la différence
mov ax,w lByte
shr ax,cl ;et lance le décalage
mov w act_code,ax ;sauve le code
sub si,dx ;restbits déjà lus -> soustraire
@nextbyte:
call getphysbyte ;lit un nouvel octet
xor ah,ah
mov w lByte,ax ;le met en lByte pour le prochain code
dec w restbyte ;octet traité
mov bx,1 ;masque les bits restants dans l'octet
mov cx,si ;fixe le nombre de bits
shl bx,cl ;décale 1 du nombre de bits
dec bx ;et décrémente
and ax,bx ;masque le code
mov cx,dx ;effectue le décalage recherché
shl ax,cl ;de restbits vers la gauche
add w act_code,ax ;ajoute le résultat
sbb dx,w nbbit ;diminue le nombre restbits
add dx,8 ;de ce qui dépasse 8 bits
jns @positif
add dx,8
@positif:
sub si,8 ;jusqu'à 8 bits cherchés -> soustraire
jle @fini ;<= 0 -> tout est fini
add dx,w nbbit ;sinon augmente restbits du nombre de bits manquants
sub dx,8
jmp @nextbyte ;et on continue
@fini:
mov w restbits,dx ;sauve le nombre de bits restants pour le prochain appel
mov ax,w act_code ;et charge ax
pop si
ret
Endp
ReadGif proc pascal
;lit en vscreen un fichier Gif appelé gifname,
;en cas de dépassement, stockage en mémoire d'écran
push ds ;sauvegarde ds
call GifOpen ;ouvre le fichier
jnc ok ;erreur ?
mov numerr,1 ;la signaler et conclure
pop ds
ret
ok:
call gifseek pascal, 0,13d ;saute les 13 premiers octets
push 768d ;lit les 768 octets de la palette
call gifread
call shiftpal ;et l'enregistre avec conversion
call gifread pascal,1 ;passe un octet
@extloop: ;laisse tomber les blocs d'extension
cmp w buff[0],21h ;encore un bloc d'extension ? ?
jne @noext ;non, on continue
call gifread pascal,2 ;les deux premiers octets...
mov al,b buff[1] ;...donnent la longueur du bloc...
inc al ;...si on ajoute 1
xor ah,ah
call gifread pascal, ax ;on passe par dessus
jmp @extloop
@noext:
call gifread pascal, 10d ;lit le reste de l'IDB
test b buff[8],128 ;une palette locale ?
je @noloc ;non on poursuit
push 768 ;lit la palette
call gifread
call shiftpal ;et la convertit
@noloc:
les di,dword ptr vscreen ;charge l'adresse de destination
mov w lbyte,0 ;dernier code lu 0
mov w free,258 ;première entrée libre 258
mov w nbbit,9 ;nb de bits d'un code = 9
mov w max,511 ;donc maximum d'entrées = 511
mov w stackp,0 ;pointeur sur début
mov w restbits,0 ;pas de bits restants
mov w restbyte,0 ;rien à chercher
@mainloop: ;boucle pour chaque code
call getlogByte ;lit un code
cmp ax,eof ;signature fin de fichier ?
jne @no_abandon
jmp @abandon ;oui, abandonne
@no_abandon:
cmp ax,clr ;code clr ?
jne @no_clear
jmp @clear ;oui efface l'alphabet
@no_clear:
mov w readbyt,ax ;sauve le code actuel
cmp ax,w free ;est-il déjà dans l'alphabet ? (<free)
jb @code_in_ab ;oui, passe au traitement
mov ax,w old_code ;non, donc cas spécial, transmettre
mov w act_code,ax ;au traitement la dernière chaîne
mov bx,w stackp
mov cx,w casspecial ;et accrocher le premier caractère (toujours concret)
mov w abstack[bx],cx ;gère la pile
inc w stackp ;en conséquence
@code_in_ab: ;code disponible dans l'alphabet :
cmp ax,clr ;< code clr ?
jb @concret ;oui, caractère concret
@fillstack_loop: ;sinon passe au décodage
mov bx,w act_code ;le code est un pointeur dans l'alphabet
shl bx,1 ;Word Array (!)
push bx
mov ax,w ab_suffx[bx] ;cherche le suffixe, qui est concret
mov bx,w stackp ;le place sur la pile
shl bx,1 ;considérée comme Word Array
mov w abstack[bx],ax
inc w stackp
pop bx
mov ax,w ab_prfx[bx] ;cherche le préfixe
mov w act_code,ax ;le prend comme code courant
cmp ax,clr;> code clr
ja @fillstack_loop ;poursuit le décodage
@concret: ;plus que des caractères concrets sur la pile
mov bx,w stackp ;empile le dernier code
shl bx,1 ;comme Word Array
mov w abstack[bx],ax
mov w casspecial,ax ;en prend note aussi pour le cas spécial
inc w stackp ;fait progresser le pointeur
mov bx,w stackp ;prépare la lecture de la pile
dec bx ;décrémente le pointeur
shl bx,1 ;sur Word Array
@readstack_loop: ;traite la pile
mov ax,w abstack[bx] ;prend un caractère
stosb ;et l'écrit dans la mémoire de destination
cmp di,0 ;dépasse-t-on le segment ?
jne @noovl1
call p13_2_modex pascal,vram_pos,16384d
add vram_pos,16384d ;exploite la mémoire d'écran
les di,dword ptr vscreen ;nouvelle position en mémoire VGA
@noovl1:
dec bx ;pointeur de pile sur l'élément suivant
dec bx
jns @readstack_loop ;fini ? non on poursuit
mov w stackp,0 ;réinitialise le pointeur de pile
mov bx,w free ;met à jour l'alphabet
shl bx,1 ;à la position "free"
mov ax,w old_code ;écrit le dernier code dans préfixe
mov w ab_prfx[bx],ax
mov ax,w act_code ;et le code courant dans suffixe
mov w ab_suffx[bx],ax
mov ax,w readbyt ;le code lu est le plus récent
mov w old_code,ax
inc w free ;met à jour la dernière position libre dans l'alphabet
mov ax,w free
cmp ax,w max ;déjà saturé ??
ja @no_mainloop
jmp @mainloop ;non, on continue
@no_mainloop:
cmp b nbbit,12 ;nombre de bits déjà égal à 12 ?
jb @no_mainloop2
jmp @mainloop ;oui, alors on recommence simplement
@no_mainloop2:
inc w nbbit ;sinon on l'augmente
mov cl,b nbbit ;nouveau maximum d'entrées
mov ax,1 ;1 décalé de nbbit vers la gauche
shl ax,cl
dec ax ;puis décrémenté
mov w max,ax ;enregistre le maximum
jmp @mainloop ;revient à la boucle principale
@clear: ;réinitialise l'alphabet:
mov w nbbit,9 ;nbbit reprend la valeur de départ
mov w max,511 ;le maximum d'entrées est 511
mov w free,258 ;première place libre = 258
call getlogbyte ;lit le code suivant
mov w casspecial,ax ;le note pour le cas spécial
mov w old_code,ax ;et comme ancien code
stosb ;passe directement en mémoire car concret
cmp di,0 ;dépassement de segment ?
jne @noovl2
call p13_2_modex pascal,vram_pos,16384d
add vram_pos,16384d ;stockage dans la mémoire d'écran
les di,dword ptr vscreen ;avance le pointeur en mémoire VGA
@noovl2:
jmp @mainloop ;retour à la boucle principale
@abandon: ;abandon par code Eof
call gifclose ;ferme le fichier
mov rest,di ;mémorise le nombre de codes restant à copier
pop ds ;et clôture
ret
Endp
code ends
end