; '.-Gif LoaDer-.' E.O.S version	Loade tous les gifs de 4 … 256 couleurs
;
;			      þ CoDeD By NaNaRd þ
;
;	Salut … toi, “ codeur, ce chargeur de Gif est … ton entiŠre disposition
; utilise le dans tous tes programmes si tu le souhaite et am‚liore si tu le
; veux. (Ouf! ce fut une phrase difficile … sortir:-)

Locals
.386
CODE32 SEGMENT PUBLIC PARA 'CODE' USE32
ASSUME  CS:CODE32,DS:CODE32,ES:CODE32
INCLUDE ..\RESOURCE\EOS.INC

Gifname		db 'eclipse.gif',0	;les datas sp‚cifiques au loader sont
					;… la fin de ce fichier.
start32:
	mov edx,O Gifname
	call gif_load
	mov ax,13h	;mode MCGA 320x200x8bits
	dosint 10h
	call sendpal
	mov esi,[raw_buff]
	mov edi,[_0a0000h]
	mov ecx,64000/4
	rep movsd
	xor eax,eax
	dosint 16h	;wait a key
        mov ax,4c00h
        int 21h


;------------------------- Proc‚dure gif_load ---------------------------------
;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
;º									      º
;º	Entr‚e :							      º
;º			EDX : Offset du nom du fichier Gif		      º
;º			DS et ES : [Data32_Sel] 			      º
;º									      º
;º	Sortie :							      º
;º			[Raw_Buff] : 	 Offset de l'image d‚compress‚e	      º
;º					… utiliser avec Data32_Sel	      º
;º			[Raw_Buff0] : 	 Offset de l'image d‚compress‚e	      º
;º					… utiliser avec Zero_Sel	      º
;º			w[Xsize] et w[Ysize] : Largeur et hauteur de l'image  º
;º			palette[768] : palette en 6bits prˆte pour sendpal    º
;º			b[interlaced] : -1 si le gif est entrelac‚, 0 sinon.  º
;º									      º
;º	  Tous Les registres sont succeptibles d'avoir chang‚ de valeur,      º
;º	sauf les registres de segment et EBP.				      º
;º	  Attention ! Je ne gŠre pas les erreurs (mauvais fichier, etc...)    º
;º	C'est … vous de vous en occuper. Tout sera impecable dans une	      º
;º	prochaine version. Je vous conseille de mater mon code de toute fa‡on º
;º									      º
;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ¼
gif_load proc
	mov ah,load_external_file	;… changer pour internal, mais llink ne
				;veut pas des gif tels quels (non dietis‚s).
	int_eos			; Sortie de cette fction :
	mov esi,eax		;esi=adresse physique, eax=adresse dans Data32

	cmp d [esi],"8FIG"		;'GIF8'	J'verifie si C bien 1 Gif
	jnz abandon
;lecture du nombre de bits/pixels
	mov cl,[esi+10]	;indicateur de r‚solution
	add esi,13
        and ecx,0111b	;seulement les 3  derniers bits
        inc ecx
        mov b imgbits,cl
        mov eax,1
        shl eax,cl
        mov w ncolors,ax
        mov ecx,eax      ;=palette
	add ecx,eax
	add ecx,eax
        call shiftpal
extloop:
	cmp b [esi],21h		;"!":signature des blocks d'extension
        jne noext
	add esi,2
	xor ecx,ecx
	mov cl,b [esi]
;aplic:
	add esi,ecx
	inc esi
	mov cl,b[esi]
aplic2:
	or cl,cl
	je aplicfin
	add esi,ecx
	inc esi
	mov cl,b [esi]
	jmp aplic2
aplicfin:
	inc esi
	jmp extloop
noext:
	inc esi
	mov eax,d [esi+4]
	mov ecx,d [esi+6]
        mov w xsize,ax
        mov w ysize,cx
;lecture du nbre de bits/pix
	mov cl,b [esi+8]
        xor eax,eax
        test cl,64      ;image entrelac‚e?
        jz nointerlaced
        not eax
nointerlaced:
	add esi,9
        mov b interlaced,al
        test cl,128      ;palette locale?
        je noloc
        and ecx,0111b
        inc ecx
        mov b imgbits,cl
        mov eax,1
        shl eax,cl
        mov w ncolors,ax
        mov ecx,eax
	add ecx,eax
	add ecx,eax
        call shiftpal

noloc:		;initialisation des differentes variables.
	inc esi		;on saute le nbits
        xor     ebx,ebx
        mov     w lbyte,bx       ;pas de dernier code lu
	mov	ax,w ncolors
	mov	w clr,ax	;code clear= ncolors
	inc	eax
	mov	w eof,ax	;code eof= ncolors + 1
	inc	eax
	mov	w free,ax	;ncolors + 2 = 1Šre entr‚e libre
	mov	w freesav,ax
        add     cl,b imgbits
	inc 	ecx
        mov     b nbbit,cl	;au d‚part, nbbits= imgbits + 1
        mov	b nbbitsav,cl
	mov     eax,1
        shl     eax,cl
        dec     eax
        mov     w max,ax	;max = 2^nbbits - 1
        mov	w maxsav,ax
        mov     d stackp,ebx
        mov     d restbits,ebx
        mov     d restbyte,ebx

goon:
	movzx eax,xsize
	movzx ecx,ysize
	mul ecx
	xchg edx,eax	;taille
	mov ah,Allocate_Memory
	int_eos
	jc not_enough_ram
	mov [raw_buff0],eax
	mov [raw_buff],edx
	mov edi,edx

mainloop: ;þþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþþ
        call getlogbyte
        cmp ax,w eof	;fin du fichier
        je abandon
        cmp ax,w clr	;nouvel alphabet
        je clear
        mov w readbyt,ax
        cmp ax,w free
        jb code_in_ab   ;jmp si code dans ab
        mov ax,w old_code
        mov w act_code,ax
        mov ebx,d stackp
        mov cx,w casspecial
        mov w abstack[ebx],cx
        inc d stackp
code_in_ab:
        cmp ax,w clr
        jb  concret
fillstack_loop:
  movzx ebx,w act_code             ;le code est un pointeur dans l'alphabet
  add ebx,ebx                    ;Word Array (!)
  push ebx
  mov eax,d ab_suffx[ebx]         ;cherche le suffixe, qui est concret
  mov ebx,d stackp               ;le place sur la pile
  add ebx,ebx                    ;consid‚r‚e comme Word Array
  mov w abstack[ebx],ax
  inc d stackp
  pop ebx
  mov eax,d ab_prfx[ebx]          ;cherche le pr‚fixe
  mov w act_code,ax             ;le prend comme code courant
  cmp ax,w clr
        ja fillstack_loop
concret:
  mov ebx,d stackp               ;empile le dernier code
  add ebx,ebx                   ;comme Word Array
  mov w abstack[ebx],ax
  mov w casspecial,ax           ;en prend note aussi pour le cas sp‚cial 
  inc d stackp                  ;fait progresser le pointeur
  mov ebx,d stackp               ;pr‚pare la lecture de la pile
mov ecx,ebx
  dec ebx                        ;d‚cr‚mente le pointeur
  add ebx,ebx                  ;sur Word Array 
readstack_loop:
  mov al,b abstack[ebx]          ;prend un caractŠre
   sub ebx,2                     ;pointeur de pile sur l'‚l‚ment suivant
  stosb
loop readstack_loop	;loop=rame sur 486 mais speede sur 6x86
  mov d stackp,ecx              ;r‚initialise le pointeur de pile (ecx=0)
  movzx ebx,w free              ;met … jour l'alphabet
  add ebx,ebx                   ;… la position "free" 
  mov ax,w old_code             ;‚crit le dernier code dans pr‚fixe
  mov w ab_prfx[ebx],ax
  mov ax,w act_code             ;et le code courant dans suffixe
  mov w ab_suffx[ebx],ax
  mov ax,w readbyt              ;le code  lu est le plus r‚cent
  mov w old_code,ax
  inc w free
  inc eax
  mov ax,w free
  cmp ax,w max
  jna mainloop
  cmp b nbbit,12                ;nombre de bits d‚j… ‚gal … 12 ?
  jnb mainloop
  inc b nbbit                   ;sinon on l'augmente
  mov eax,1                     ;1 d‚cal‚ de nbbit vers la gauche
  mov cl,b nbbit                ;nouveau maximum d'entr‚es
  shl eax,cl
  dec eax                       ;puis d‚cr‚ment‚
  mov w max,ax                  ;enregistre le maximum 
  jmp mainloop

clear:
	mov ax,w freesav
	mov w free,ax
	mov al,b nbbitsav
	mov b nbbit,al
	mov ax,w maxsav
	mov w max,ax
        call getlogbyte
        mov w casspecial,ax
        mov w old_code,ax
	stosb
        jmp mainloop

abandon:
	ret
not_enough_ram:
	mov ah,exit_error
	mov edx,O ram_err
	int_eos
endp
;------------------------------ proc‚dures -----------------------------------

shiftpal proc near
        mov edi,offset palette
        shr ecx,2
@l1:
        lodsd
        shr eax,2
        stosd
        dec ecx
        jnz @l1
        ret
endp

sendpal proc near	;envoie automatiquement la palette dans la VGA.
	movzx ecx,w ncolors	;Ne Fait pas vraiment partie du loader
	mov eax,ecx
	add ecx,ecx
	mov dx,3c8h
	add ecx,eax
	xor eax,eax
	out dx,al
	inc edx
	mov esi,offset palette
	rep outsb	;… changer car certaines cartes n'apprecient pas
	ret		;(on le dit mais j'en ai jamais vu!)
endp

getphysbyte proc near   ;destroy ebx
	xor eax,eax
        cmp d restbyte,0
        ja @yadurab
	lodsb		;longueur du data block
	mov d restbyte,eax
@yadurab:
	dec d restbyte
	lodsb
	ret
endp

getlogbyte proc near
	mov dh,b nbbit
	mov dl,b restbits
	mov cl,8
        sub cl,dl
        movzx eax,w lbyte	;pour garder les restbits interressants
        shr eax,cl	;d‚cale lbyte de 8-restbits vers la droite
        mov w act_code,ax
        cmp dh,dl
        ja  @glbsuite
	mov cl,dh
	mov ebx,1
	shl ebx,cl
        dec ebx
        and eax,ebx
        sub dl,dh
        mov b restbits,dl
	mov w act_code,ax
        ret
@glbsuite:		;si il faut lire au moins un byte physique
        sub dh,dl	;soustraire les restbits d‚ja lus
@nextbyte:
        call getphysbyte
        mov w lbyte,ax
        mov ebx,1
        mov cl,dh
        shl ebx,cl
        dec ebx
	and eax,ebx
        mov cl,dl
        shl eax,cl
        add w act_code,ax	;important de rester en word!
        sbb dl,b nbbit
        add dl,8
        jns @positif
        add dl,8
@positif:
        sub dh,8
        jle @fini
        add dl,b nbbit
        sub dl,8
        jmp @nextbyte
@fini:
        mov b restbits,dl
        mov ax,w act_code
        ret
endp

;---------------------------- datas -------------------------------------------
ram_err		db '     þ Not enough room to uncompress gif.$'
align 2	;needed? I'm not a king of Pentium optimization...
raw_buff	dd ?	;addresse du buffer de destination dans Data32_sel
raw_buff0	dd ?	;addresse du buffer de destination dans Zero_Sel
palette		db 768	dup (?)	;palette d‚ja shift‚e a la fin....
buffind         dd ?
abstack         db 1282 dup (?)
ab_prfx         dw 4096 dup (?)
ab_suffx        dw 4096 dup (?)
free            dw ?
freesav         dw ?
nbbit           db ?
nbbitsav        db ?
max             dw ?
maxsav          dw ?
stackp          dd ?
restbits        dd ?
restbyte        dd ?
casspecial      dw ?
act_code        dw ?
old_code        dw ?
readbyt         dw ?
lbyte           dw ?
clr             dw ?	;code clear
eof             dw ?	;code 'end of file'
ncolors         dw ?
xsize           dw ?	;devinez
ysize           dw ?	; ! ! !
interlaced      db ?
imgbits         db ?	;nombre de bits de l'image (de 2 … 8)
			; Toutefois, dans le buffer de destination,
code32 ends		; Chaque pixel = un octet
end
