home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC Underground
/
UNDERGROUND.ISO
/
magn
/
gif.asm
< prev
next >
Wrap
Assembly Source File
|
1995-07-28
|
12KB
|
317 lines
clr=256 ;code for "clear alphabet"
eof=257 ;code for "end of file"
w equ word ptr
b equ byte ptr
data segment public
extrn buffer:dataptr ;pointer to destination buffer
extrn gifname:dataptr ;name of Gif, incl. ".gif" + db 0
extrn errorno:word; ;flag for error
palette db 768 dup (?) ;destination palette
handle dw 0 ;DOS handle for Gif file
Buf db 768 dup (0) ;buffer of read/input data
BufInd dw 0 ;pointer within this buffer
abStack db 1281 dup (0) ;stack for decoding a byte
ab_prfx dw 4096 dup (0) ;alphabet, prefix portion
ab_tail dw 4096 dup (0) ;alphabet, tail portion
free dw 0 ;next free position in alphabet
width1 dw 0 ;number of bits in a byte
max dw 0 ;maximum alphabet length for current width
stackp dw 0 ;pointer within alphabet stack
restbits dw 0 ;number of bits remaining to be read
restbyte dw 0 ;number of bytes still in buffer
specialcase dw 0 ;buffer for special case
cur_code dw 0 ;code just processed
old_code dw 0 ;previous code
readbyt dw 0 ;byte just read
lbyte dw 0 ;last physical byte read
data ends
code segment public
assume cs:code,ds:data
.286
public readgif
GifRead proc pascal n:word
;reads n physical bytes from file
mov ax,03f00h ;function 3fh of Interrupt 21h: read
mov bx,handle ;load handle
mov cx,n ;load number of bytes to read
lea dx,buf ;pointer to destination buffer
int 21h ;execute interrupt
ret
gifread endp
GifOpen proc pascal
;opens the Gif file for read access
mov ax,03d00h ;function 3dh: open
lea dx,gifname + 1 ;pointer to name (skip length byte)
int 21h ;execute
mov handle,ax ;save handle
ret
gifopen endp
GifClose proc pascal
;closes Gif file
mov ax,03e00h ;function 3eh: close
mov bx,handle ;load handle
int 21h ;execute
ret
gifclose endp
GifSeek proc pascal Ofs:dword
;positioning within the file
mov ax,04200h ;function 42h,
mov bx,w handle ;subfunction 0: seek relative to start of file
mov cx,word ptr Ofs + 2 ;load offset
mov dx,word ptr Ofs
int 21h ;execute
ret
Endp
ShiftPal proc pascal
;aligns 24-bit palette format to 18-bit VGA format
mov ax,ds ;source and destination arrays in the data segment
mov es,ax
mov si,offset Buf ;read from data buffer
lea di,palette ;write to palette
mov cx,768d ;copy 786 bytes
@l1:
lodsb ;get bytes
shr al,2 ;convert
stosb ;and write
loop @l1
ret
Endp
FillBuf proc pascal
;reads a block from the file in buf
call gifread pascal,1 ;read one byte
mov al,b buf[0] ;load length after al
xor ah,ah
mov w restbyte,ax ;and store in restbyte
call gifread pascal, ax ;read bytes
ret
Endp
GetPhysByte proc pascal
;gets a physical byte from the buffer
push bx ;caller needs bx
cmp w restbyte,0 ;no more data in buffer ?
ja @restthere
pusha ;then refill buffer
call fillbuf
popa
mov w bufind,0 ;and reset pointer
@restthere: ;data in buffer
mov bx,w BufInd ;load buffer pointer
mov al,b Buf[bx] ;get byte
inc w bufind ;move pointer
pop bx ;finished
ret
Endp
GetLogByte proc pascal
;gets a logical byte from the buffer, uses GetPhysByte
push si ;caller needs si
mov ax,w width1 ;get byte width
mov si,ax ;and store
mov dx,w restbits ;shift lbyte 8 remaining bits to the right
mov cx,8
sub cx,dx ;obtain difference
mov ax,w lByte
shr ax,cl ;and shift
mov w cur_code,ax ;store code
sub si,dx ;remaining bits already obtained -> subtract
@nextbyte:
call getphysbyte ;get new byte
xor ah,ah
mov w lByte,ax ;store in lbyte for next logical byte
dec w restbyte ;mark byte as obtained
mov bx,1 ;mask remaining bits in obtained byte
mov cx,si ;add number of bits
shl bx,cl ;shift 1 by number
dec bx ;and decrement
and ax,bx ;mask byte
mov cx,dx ;shift to correct position
shl ax,cl ;(by remaining bytes to the left)
add w cur_code,ax ;and add to result
sbb dx,w width1 ;decrement remaining bits
add dx,8 ;by amount exceeding 8 bits
jns @positive
add dx,8
@positive:
sub si,8 ;up to 8 bits obtained -> subtract
jle @finished ;<= 0 -> finished, end
add dx,w width1 ;otherwise increment remaining bits by missing bits
sub dx,8
jmp @nextbyte ;and continue
@finished:
mov w restbits,dx ;store remaining bits for next call
mov ax,w cur_code ;and load ax
pop si
ret
Endp
ReadGif proc pascal
;loads a Gif image called gifname in buffer
push ds ;store ds
call GifOpen ;open file
jnc ok ;error ?
mov errorno,1 ;then issue message and end
pop ds
ret
ok:
call gifseek pascal, 0,13d ;skip first 13 bytes
push 768d ;load 768 bytes of palette
call gifread
call shiftpal ;and convert to "palette"
call gifread pascal,1 ;skip one byte
@extloop: ;skip extension blocks
cmp w buf[0],21h ;another extension block existing ?
jne @noext ;no, then continue
call gifread pascal,2 ;read first two bytes
mov al,b buf[1] ;data block length
inc al ;increment by one
xor ah,ah
call gifread pascal, ax ;and skip
jmp @extloop
@noext:
call gifread pascal, 10d ;read remainder of IDB
test b buf[8],128 ;local palette ?
je @noloc ;no, then continue
push 768 ;otherwise read
call gifread
call shiftpal ;and set
@noloc:
les di,dword ptr buffer ;load destination address
mov w lbyte,0 ;last read byte 0
mov w free,258 ;first free entry 258
mov w width1,9 ;byte width 9 bits
mov w max,511 ;so maximum entry is 511
mov w stackp,0 ;stack pointer to beginning
mov w restbits,0 ;no remaining bits
mov w restbyte,0 ;or remaining bytes to obtain
@mainloop: ;run for each logical byte
call getlogByte ;get logical byte
cmp ax,eof ;end of file - ID
jne @no_abort
jmp @abort ;yes, then end
@no_abort:
cmp ax,clr ;clr-code ?
jne @no_clear
jmp @clear ;yes, then clear alphabet
@no_clear:
mov w readbyt,ax ;store current byte
cmp ax,w free ;code already in alphabet (<free)
jb @code_in_ab ;yes, then output
mov ax,w old_code ;no, then special case, i.e., give last string
mov w cur_code,ax ;for processing
mov bx,w stackp
mov cx,w specialcase ;and add first character (always concrete)
mov w abstack[bx],cx ;enter onto stack
inc w stackp ;move stack pointer forward
@code_in_ab: ;code exists in alphabet:
cmp ax,clr ;< clr code ?
jb @concrete ;then concrete character
@fillstack_loop: ;otherwise decode
mov bx,w cur_code ;current code as pointer in alphabet
shl bx,1 ;word-array (!)
push bx
mov ax,w ab_tail[bx] ;get tail, (concrete)
mov bx,w stackp ;push onto stack
shl bx,1 ;likewise word-array
mov w abstack[bx],ax ;enter
inc w stackp
pop bx
mov ax,w ab_prfx[bx] ;get prefix
mov w cur_code,ax ;give as current code for decoding
cmp ax,clr ;> clr-code
ja @fillstack_loop ;then continue decoding
@concrete: ;now just the concrete values onto the stack
mov bx,w stackp ;push last code onto stack
shl bx,1 ;word-array
mov w abstack[bx],ax
mov w specialcase,ax ;also keep for special case
inc w stackp ;move pointer forward
mov bx,w stackp ;prepare to read stack
dec bx ;move pointer backward and
shl bx,1 ;align with word-array
@readstack_loop: ;process stack
mov ax,w abstack[bx] ;get character from stack
stosb ;and write to destination memory
@noovl1:
dec bx ;stack pointer to next element
dec bx
jns @readstack_loop ;finished processing ? no, then continue
mov w stackp,0 ;set stack pointer variable to 0
mov bx,w free ;now enter in alphabet
shl bx,1 ;go to position "free"
mov ax,w old_code ;write last code in prefix
mov w ab_prfx[bx],ax
mov ax,w cur_code ;current code in tail
mov w ab_tail[bx],ax
mov ax,w readbyt ;store byte read as last code
mov w old_code,ax
inc w free ;to next position in alphabet
mov ax,w free
cmp ax,w max ;maximum reached ?
ja @no_mainloop
jmp @mainloop ;no, then continue
@no_mainloop:
cmp b width1,12 ;has width1 reached 12 bits ?
jb @no_mainloop2
jmp @mainloop ;yes, then continue
@no_mainloop2:
inc w width1 ;otherwise increment
mov cl,b width1 ;calculate new maximum value
mov ax,1 ;shift 1 by new width1 to the left
shl ax,cl
dec ax ;and decrement
mov w max,ax ;enter
jmp @mainloop ;and go back to main loop
@clear: ;reset alphabet:
mov w width1,9 ;width1 back to original value
mov w max,511 ;reset maximum to 511
mov w free,258 ;first free position at 258
call getlogbyte ;get next byte
mov w specialcase,ax ;record as special case
mov w old_code,ax ;and also as last byte read
stosb ;this value directly to memory, because concrete
@noovl2:
jmp @mainloop ;go back to main loop
@abort: ;terminate through eof-code
call gifclose ;close file
pop ds ;end
ret
Endp
public setpal
SetPal proc pascal ;sends the palette to the VGA
push si
mov si,offset palette ;get address
mov cx,256*3 ;get number of colors
xor al,al
mov dx,03c8h ;external palette RAM, pixel write address
out dx,al ;set from color 0
inc dx ;pixel color value
rep outsb ;send all colors to VGA
pop si
ret
Endp
code ends
end