home *** CD-ROM | disk | FTP | other *** search
/ PC Underground / UNDERGROUND.ISO / magn / gif.asm < prev    next >
Assembly Source File  |  1995-07-28  |  12KB  |  317 lines

  1. clr=256                         ;code for "clear alphabet"
  2. eof=257                         ;code for "end of file"
  3. w equ word ptr
  4. b equ byte ptr
  5.  
  6. data segment public
  7.   extrn buffer:dataptr        ;pointer to destination buffer
  8.   extrn gifname:dataptr         ;name of Gif, incl. ".gif" + db 0
  9.   extrn errorno:word;           ;flag for error
  10.  
  11.   palette db 768 dup (?)        ;destination palette
  12.  
  13.   handle     dw 0               ;DOS handle for Gif file
  14.   Buf        db 768 dup (0)     ;buffer of read/input data
  15.   BufInd     dw 0               ;pointer within this buffer
  16.   abStack    db 1281 dup (0)    ;stack for decoding a byte
  17.   ab_prfx    dw 4096 dup (0)    ;alphabet, prefix portion
  18.   ab_tail    dw 4096 dup (0)    ;alphabet, tail portion
  19.   free       dw 0               ;next free position in alphabet
  20.   width1     dw 0               ;number of bits in a byte
  21.   max        dw 0               ;maximum alphabet length for current width
  22.   stackp     dw 0               ;pointer within alphabet stack
  23.   restbits   dw 0               ;number of bits remaining to be read
  24.   restbyte   dw 0               ;number of bytes still in buffer
  25.   specialcase dw 0              ;buffer for special case
  26.   cur_code   dw 0               ;code just processed
  27.   old_code   dw 0               ;previous code
  28.   readbyt    dw 0               ;byte just read
  29.   lbyte      dw 0               ;last physical byte read
  30. data ends
  31.  
  32.  
  33. code segment public
  34. assume cs:code,ds:data
  35. .286
  36.  
  37. public readgif
  38. GifRead proc pascal n:word
  39. ;reads n physical bytes from file
  40.   mov ax,03f00h                 ;function 3fh of Interrupt 21h: read
  41.   mov bx,handle                 ;load handle
  42.   mov cx,n                      ;load number of bytes to read
  43.   lea dx,buf                    ;pointer to destination buffer
  44.   int 21h                       ;execute interrupt
  45.   ret
  46. gifread endp
  47.  
  48. GifOpen proc pascal
  49. ;opens the Gif file for read access
  50.   mov ax,03d00h                 ;function 3dh: open
  51.   lea dx,gifname + 1            ;pointer to name (skip length byte)
  52.   int 21h                       ;execute
  53.   mov handle,ax                 ;save handle
  54.   ret
  55. gifopen endp
  56.  
  57. GifClose proc pascal
  58. ;closes Gif file
  59.   mov ax,03e00h                 ;function 3eh: close
  60.   mov bx,handle                 ;load handle
  61.   int 21h                       ;execute
  62.   ret
  63. gifclose endp
  64.  
  65. GifSeek proc pascal Ofs:dword
  66. ;positioning within the file
  67.   mov ax,04200h                 ;function 42h,
  68.   mov bx,w handle               ;subfunction 0: seek relative to start of file
  69.   mov cx,word ptr Ofs + 2       ;load offset
  70.   mov dx,word ptr Ofs
  71.   int 21h                       ;execute
  72.   ret
  73. Endp
  74. ShiftPal proc pascal
  75. ;aligns 24-bit palette format to 18-bit VGA format
  76.   mov ax,ds                     ;source and destination arrays in the data segment
  77.   mov es,ax
  78.   mov si,offset Buf             ;read from data buffer
  79.   lea di,palette                ;write to palette
  80.   mov cx,768d                   ;copy 786 bytes
  81. @l1:
  82.   lodsb                         ;get bytes
  83.   shr al,2                      ;convert
  84.   stosb                         ;and write
  85.   loop @l1
  86.   ret
  87. Endp
  88. FillBuf proc pascal
  89. ;reads a block from the file in buf
  90.   call gifread pascal,1         ;read one byte
  91.   mov al,b buf[0]               ;load length after al
  92.   xor ah,ah
  93.   mov w restbyte,ax             ;and store in restbyte
  94.   call gifread pascal, ax       ;read bytes
  95.   ret
  96. Endp
  97.  
  98. GetPhysByte proc pascal
  99. ;gets a physical byte from the buffer
  100.   push bx                       ;caller needs bx
  101.   cmp w restbyte,0              ;no more data in buffer ?
  102.   ja @restthere
  103.   pusha                         ;then refill buffer
  104.   call fillbuf
  105.   popa
  106.   mov w bufind,0                ;and reset pointer
  107. @restthere:                     ;data in buffer
  108.   mov bx,w BufInd               ;load buffer pointer
  109.   mov al,b Buf[bx]              ;get byte
  110.   inc w bufind                  ;move pointer
  111.   pop bx                        ;finished
  112.   ret
  113. Endp
  114.  
  115. GetLogByte proc pascal
  116. ;gets a logical byte from the buffer, uses GetPhysByte
  117.   push si                       ;caller needs si 
  118.   mov ax,w width1               ;get byte width
  119.   mov si,ax                     ;and store
  120.   mov dx,w restbits             ;shift lbyte 8 remaining bits to the right
  121.   mov cx,8
  122.   sub cx,dx                     ;obtain difference
  123.   mov ax,w lByte
  124.   shr ax,cl                     ;and shift
  125.   mov w cur_code,ax             ;store code
  126.   sub si,dx                     ;remaining bits already obtained -> subtract
  127. @nextbyte:
  128.   call getphysbyte              ;get new byte
  129.   xor ah,ah
  130.   mov w lByte,ax                ;store in lbyte for next logical byte
  131.   dec w restbyte                ;mark byte as obtained 
  132.  
  133.   mov bx,1                      ;mask remaining bits in obtained byte
  134.   mov cx,si                     ;add number of bits 
  135.   shl bx,cl                     ;shift 1 by number 
  136.   dec bx                        ;and decrement
  137.   and ax,bx                     ;mask byte
  138.  
  139.   mov cx,dx                     ;shift to correct position
  140.   shl ax,cl                     ;(by remaining bytes to the left) 
  141.   add w cur_code,ax             ;and add to result 
  142.  
  143.   sbb dx,w width1               ;decrement remaining bits 
  144.   add dx,8                      ;by amount exceeding 8 bits
  145.   jns @positive
  146.   add dx,8
  147. @positive:
  148.   sub si,8                      ;up to 8 bits obtained -> subtract
  149.   jle @finished                 ;<= 0 -> finished, end
  150.   add dx,w width1               ;otherwise increment remaining bits by missing bits 
  151.   sub dx,8
  152.   jmp @nextbyte                 ;and continue
  153. @finished:
  154.   mov w restbits,dx             ;store remaining bits for next call 
  155.   mov ax,w cur_code             ;and load ax
  156.   pop si
  157.   ret
  158. Endp
  159.  
  160. ReadGif proc pascal
  161. ;loads a Gif image called gifname in buffer
  162.   push ds                       ;store ds
  163.   call GifOpen                  ;open file
  164.   jnc ok                        ;error ?
  165.   mov errorno,1                 ;then issue message and end
  166.   pop ds
  167.   ret
  168.  
  169. ok:
  170.   call gifseek pascal, 0,13d    ;skip first 13 bytes
  171.   push 768d                     ;load 768 bytes of palette
  172.   call gifread
  173.   call shiftpal                 ;and convert to "palette"
  174.   call gifread pascal,1         ;skip one byte 
  175.  
  176. @extloop:                       ;skip extension blocks
  177.   cmp w buf[0],21h              ;another extension block existing ?
  178.   jne @noext                    ;no, then continue
  179.     call gifread pascal,2       ;read first two bytes 
  180.     mov al,b buf[1]             ;data block length 
  181.     inc al                      ;increment by one 
  182.     xor ah,ah
  183.     call gifread pascal, ax     ;and skip
  184.   jmp @extloop
  185.  
  186. @noext:
  187.   call gifread pascal, 10d      ;read remainder of IDB
  188.   test b buf[8],128             ;local palette ?
  189.   je @noloc                     ;no, then continue
  190.     push 768                    ;otherwise read 
  191.     call gifread
  192.     call shiftpal               ;and set
  193.  
  194. @noloc:
  195.   les di,dword ptr buffer       ;load destination address
  196.  
  197.   mov w lbyte,0                 ;last read byte 0
  198.   mov w free,258                ;first free entry 258
  199.   mov w width1,9                ;byte width 9 bits
  200.   mov w max,511                 ;so maximum entry is 511
  201.   mov w stackp,0                ;stack pointer to beginning
  202.   mov w restbits,0              ;no remaining bits 
  203.   mov w restbyte,0              ;or remaining bytes to obtain 
  204. @mainloop:                      ;run for each logical byte 
  205.   call getlogByte               ;get logical byte
  206.   cmp ax,eof                    ;end of file - ID
  207.   jne @no_abort
  208.   jmp @abort                  ;yes, then end
  209. @no_abort:
  210.   cmp ax,clr                    ;clr-code ?
  211.   jne @no_clear
  212.   jmp @clear                    ;yes, then clear alphabet
  213. @no_clear:
  214.   mov w readbyt,ax              ;store current byte
  215.   cmp ax,w free                 ;code already in alphabet (<free)
  216.   jb @code_in_ab                ;yes, then output
  217.   mov ax,w old_code             ;no, then special case, i.e., give last string
  218.   mov w cur_code,ax             ;for processing
  219.   mov bx,w stackp
  220.   mov cx,w specialcase          ;and add first character (always concrete)
  221.   mov w abstack[bx],cx          ;enter onto stack
  222.   inc w stackp                  ;move stack pointer forward
  223. @code_in_ab:                    ;code exists in alphabet:
  224.   cmp ax,clr                    ;< clr code ?
  225.   jb @concrete                  ;then concrete character
  226. @fillstack_loop:                ;otherwise decode
  227.   mov bx,w cur_code             ;current code as pointer in alphabet
  228.   shl bx,1                      ;word-array (!)
  229.   push bx
  230.   mov ax,w ab_tail[bx]          ;get tail, (concrete)
  231.   mov bx,w stackp               ;push onto stack
  232.   shl bx,1                      ;likewise word-array
  233.   mov w abstack[bx],ax          ;enter
  234.   inc w stackp
  235.   pop bx
  236.   mov ax,w ab_prfx[bx]          ;get prefix
  237.   mov w cur_code,ax             ;give as current code for decoding
  238.   cmp ax,clr                    ;> clr-code
  239.   ja @fillstack_loop            ;then continue decoding
  240. @concrete:                      ;now just the concrete values onto the stack
  241.   mov bx,w stackp               ;push last code onto stack
  242.   shl bx,1                      ;word-array
  243.   mov w abstack[bx],ax
  244.   mov w specialcase,ax           ;also keep for special case
  245.   inc w stackp                  ;move pointer forward
  246.   mov bx,w stackp               ;prepare to read stack
  247.   dec bx                        ;move pointer backward and
  248.   shl bx,1                      ;align with word-array
  249. @readstack_loop:                ;process stack
  250.   mov ax,w abstack[bx]          ;get character from stack
  251.   stosb                         ;and write to destination memory
  252.  
  253. @noovl1:
  254.   dec bx                        ;stack pointer to next element
  255.   dec bx
  256.   jns @readstack_loop           ;finished processing ? no, then continue
  257.   mov w stackp,0                ;set stack pointer variable to 0
  258.   mov bx,w free                 ;now enter in alphabet
  259.   shl bx,1                      ;go to position "free" 
  260.   mov ax,w old_code             ;write last code in prefix
  261.   mov w ab_prfx[bx],ax
  262.   mov ax,w cur_code             ;current code in tail
  263.   mov w ab_tail[bx],ax
  264.   mov ax,w readbyt              ;store byte read as last code
  265.   mov w old_code,ax
  266.   inc w free                    ;to next position in alphabet
  267.   mov ax,w free
  268.   cmp ax,w max                  ;maximum reached ?
  269.   ja @no_mainloop
  270.   jmp @mainloop                 ;no, then continue
  271. @no_mainloop:
  272.   cmp b width1,12               ;has width1 reached 12 bits ?
  273.   jb @no_mainloop2
  274.   jmp @mainloop                 ;yes, then continue
  275. @no_mainloop2:
  276.   inc w width1                  ;otherwise increment
  277.   mov cl,b width1               ;calculate new maximum value
  278.   mov ax,1                      ;shift 1 by new width1 to the left
  279.   shl ax,cl
  280.   dec ax                        ;and decrement
  281.   mov w max,ax                  ;enter
  282.   jmp @mainloop                 ;and go back to main loop
  283. @clear:                         ;reset alphabet:
  284.   mov w width1,9                ;width1 back to original value
  285.   mov w max,511                 ;reset maximum to 511
  286.   mov w free,258                ;first free position at 258
  287.   call getlogbyte               ;get next byte 
  288.   mov w specialcase,ax           ;record as special case
  289.   mov w old_code,ax             ;and also as last byte read
  290.   stosb                         ;this value directly to memory, because concrete
  291.  
  292. @noovl2:
  293.   jmp @mainloop                 ;go back to main loop
  294. @abort:                         ;terminate through eof-code
  295.   call gifclose                 ;close file
  296.   pop ds                        ;end
  297.   ret
  298. Endp
  299.  
  300. public setpal
  301. SetPal proc pascal              ;sends the palette to the VGA
  302.   push si
  303.   mov si,offset palette         ;get address
  304.   mov cx,256*3                  ;get number of colors
  305.   xor al,al
  306.   mov dx,03c8h                  ;external palette RAM, pixel write address
  307.   out dx,al                     ;set from color 0
  308.   inc dx                        ;pixel color value
  309.  
  310.   rep outsb                     ;send all colors to VGA
  311.   pop si
  312.   ret
  313. Endp
  314. code ends
  315. end
  316.  
  317.