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

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