home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 8 Other / 08-Other.zip / GIFASM.ZIP / DECOMP.ASM
Assembly Source File  |  1990-03-27  |  6KB  |  247 lines

  1. ; asm routines for decompressing Compuserve GIF lzw data.
  2. ; note:  you must supply the putbyte routine and the header reading routines
  3. ;
  4. ; NOTE!  THIS CODE HAS NOT BEEN TESTED WITH OS/2. It was written for DOS and
  5. ;        recently modified to be used with OS/2. I haven't had the time to
  6. ;        work with or test the OS/2 version.
  7. ;
  8. ;
  9. ; GIF and 'Graphics Interchange Format' are trademarks of Compuserve, 
  10. ; Inc., an H&R Block Company
  11. ;
  12. ;
  13. ;
  14. ;
  15. ; MS C 5.1 prototype
  16. ;
  17. ; SHORT pascal gifdecompress(USHORT codesize,     // initial code size
  18. ;                            SHORT  (*getbyte)(), // routine to get byte from file
  19. ;                            VOID   (*putbyte)(SHORT), // routine to write byte to file
  20. ;                            SEL    lzwseg);      // selector for decompression table 
  21. ; return values
  22. ;
  23. ;     0    Normal completion
  24. ;    -1    Invalid code size
  25. ; caution - no other error codes are returned.
  26. ;
  27. ;
  28.  
  29. ; lzw decompression table entry
  30.  
  31. lzwrec             STRUC
  32. prev    DW     ?            ; prefix code
  33. char    DB     ?            ; suffix char
  34. lzwrec             ENDS
  35.  
  36. ; Declare segments
  37.     .MODEL     LARGE,PASCAL
  38.  
  39.     .DATA
  40. codesize DW     ?
  41. getbyte  DD     ?
  42. lzwseg   DW     ?    
  43.     
  44.     
  45.     .CODE
  46.  
  47. gifdecompress    PROC    USES si di, cdsz:WORD,get_byte:PTR,putbyte:PTR,lzw_seg:WORD
  48.  
  49.     mov    ax,lzw_seg              ; Set selector for decompression table
  50.     mov     lzwseg,ax
  51.     les    ax,get_byte             ; Set pointer for getbyte routine
  52.     mov     WORD PTR getbyte,ax
  53.     mov    WORD PTR getbyte+2,es
  54.     mov    ax,cdsz            ; Validate code size
  55.     mov     codesize,ax
  56.     
  57.     cmp    ax,2            ; Code size < 2?
  58.     jl    cserr            ; Yes, error
  59.     cmp    ax,8            ; Code size <= 8?
  60.     jle    init            ; Yes, it's good
  61. cserr:    mov    ax,-1            ; Code size error
  62.     jmp    l1a
  63.  
  64. init:    xor    ax,ax            ; Initialize variables
  65.     mov    remaining,ax
  66.     mov    bits,ax
  67.     mov    bits+2,ax
  68.     mov    stack_count,ax
  69.     call    init_tab        ; Initialize table
  70. l1:    call    read_code        ; Get a code
  71.     cmp    ax,eof            ; End of file?
  72.     jne    l2            ; No
  73.     xor    ax,ax            ; Zero return
  74. l1a:    
  75.     ret                ; Done
  76.  
  77. l2:    cmp    ax,clear        ; Clear code?
  78.     jne    l7            ; No
  79.     call    init_tab        ; Initialize table
  80.     call    read_code        ; Read next code
  81.     mov    cur_code,ax        ; Initialize variables
  82.     mov    old_code,ax
  83.     mov    k,al
  84.     mov    fin_char,al
  85.     mov    al,k
  86.     push    es            ; Preserve seg reg
  87.     push    ax            ; Character to be passed
  88.     call    putbyte                    ; Write character
  89.     add    sp,2            ; Adjust stack
  90.     pop    es
  91.     jmp    short l1        ; Get next code
  92. l7:    mov    cur_code,ax        ; Save new code
  93.     mov    in_code,ax
  94.     mov    es,lzwseg        ; Point to hash table
  95.     cmp    ax,free_code        ; Code in table? (k<w>k<w>k)
  96.     jl    l11            ; Yes
  97.     mov    ax,old_code        ; Get previous code
  98.     mov    cur_code,ax        ; Make current
  99.     mov    al,fin_char        ; Get old last char
  100.     push    ax            ; Push it
  101.     inc    stack_count
  102. l11:    mov    ax,clear        ; Code or character?
  103.     cmp    ax,cur_code
  104.     jg    l15            ; Char
  105.     mov    bx,cur_code        ; Convert code to address
  106.     call    index
  107.     mov    al,es:2[si]        ; Get suffix char
  108.     push    ax            ; Push it
  109.     inc    stack_count
  110.     mov    ax,es:[si]        ; Get prefix code
  111.     mov    cur_code,ax        ; Save it
  112.     jmp    short l11        ; Translate again
  113. l15:    push    ds            ; Restore seg reg
  114.     pop    es
  115.     mov    ax,cur_code        ; Get code
  116.     mov    fin_char,al        ; Save as final, k
  117.     mov    k,al
  118.     push    ax            ; Push it
  119.     inc    stack_count
  120.     mov    cx,stack_count        ; Pop stack
  121.     jcxz    l18            ; If anything there
  122. l17:    pop    ax
  123.     push    cx            ; Save registers
  124.     push    es
  125.     push    ax            ; Character to be passed
  126.     call    putbyte                    ; Write character
  127.     add    sp,2            ; Adjust stack
  128.     pop    es            ; Restore registers
  129.     pop    cx
  130.     loop    l17
  131. l18:    mov    stack_count,cx        ; Clear count on stack
  132.     call    add_code        ; Add new code to table
  133.     mov    ax,in_code        ; Save input code
  134.     mov    old_code,ax
  135.     mov    bx,free_code        ; Hit table limit?
  136.     cmp    bx,max_code
  137.     jl    l23            ; Less means no
  138.     cmp    nbits,12        ; Still within twelve bits?
  139.     je    l23            ; No (next code should be clear)
  140.     inc    nbits            ; Increase code size
  141.     shl    max_code,1        ; Double max code
  142. l23:    jmp    l1            ; Get next code
  143. gifdecompress    ENDP
  144.  
  145.     .DATA
  146.  
  147. clear        DW    ?
  148. eof        DW    ?
  149. cur_code    DW    ?
  150. old_code    DW    ?
  151. in_code     DW    ?
  152. free_code    DW    ?
  153. stack_count    DW    ?
  154. nbits        DW    ?
  155. max_code    DW    ?
  156. fin_char    DB    ?
  157. k        DB    ?
  158.  
  159.     .CODE
  160.  
  161. read_code    PROC    NEAR
  162. rd1:    mov    cx,remaining        ; Get bits held
  163.     cmp    cx,nbits        ; Have bits required for code?
  164.     jge    rd3            ; Yes
  165.     push    es            ; Preserve seg reg
  166.     call    getbyte                    ; No, get a byte
  167.     pop    es
  168.     mov    cx,remaining        ; Get bits held
  169.     xor    dx,dx
  170.     jcxz    rd2a            ; If zero, don't need to shift
  171. rd2:    shl    ax,1            ; Shift to into place
  172.     rcl    dx,1
  173.     loop    rd2
  174. rd2a:    mov    bits,dx         ; Move new bits in
  175.     mov    cx,bits+2
  176.     or    ax,cx
  177.     mov    bits+2,ax
  178.     add    remaining,8        ; Increment remainding count
  179.     jmp    short rd1        ; See if have required bits now
  180. rd3:    mov    dx,bits         ; Get bits remaining
  181.     mov    ax,bits+2
  182.     mov    bx,nbits
  183.     dec    bx
  184.     shl    bx,1
  185.     and    ax,masks[bx]        ; Mask off unwanted bits
  186.     push    ax            ; Save code
  187.     mov    ax,bits+2        ; Get low order bits
  188.     mov    cx,nbits
  189. rd4:    shr    dx,1            ; Shift rest of bits
  190.     rcr    ax,1
  191.     loop    rd4
  192.     mov    bits,dx         ; Save new bits remaining
  193.     mov    bits+2,ax
  194.     mov    ax,nbits        ; Compute new remaining count
  195.     sub    remaining,ax
  196.     pop    ax            ; Restore code
  197.     ret
  198. read_code    ENDP
  199.  
  200.     .DATA
  201. masks        DW    0001h,0003h,0007h,000fh
  202.         DW    001fh,003fh,007fh,00ffh
  203.         DW    01ffh,03ffh,07ffh,0fffh
  204. remaining    DW    ?
  205. bits        DW    2 DUP (?)
  206.  
  207.     .CODE
  208. init_tab    PROC    NEAR
  209.     mov    cx,codesize        ; Get code size
  210.     mov    ax,1
  211.     shl    ax,cl            ; Compute clear code
  212.     mov    clear,ax
  213.     inc    ax            ; Compute end of info code
  214.     mov    eof,ax
  215.     inc    ax            ; Compute first free entry in
  216.     mov    free_code,ax        ; Code table
  217.     inc    cx            ; Compute bits per code
  218.     mov    nbits,cx
  219.     mov    ax,1            ; Compute maximum code value
  220.     shl    ax,cl
  221.     mov    max_code,ax
  222.     ret
  223. init_tab    ENDP
  224.  
  225. index        PROC    NEAR
  226.     mov    si,bx
  227.     shl    si,1            ; si = bx * 3 (3 byte hash entries)
  228.     add    si,bx            ; si = bx * 2 + bx
  229.     ret
  230. index        ENDP
  231.  
  232. add_code    PROC    NEAR
  233.     mov    bx,free_code        ; Get new code
  234.     call    index            ; Convert to address
  235.     push    es            ; Preserve seg reg
  236.     mov    es,lzwseg        ; Point to hash table
  237.     mov    al,k            ; Get suffix char
  238.     mov    es:[si].char,al     ; Save it
  239.     mov    ax,old_code        ; Get prefix code
  240.     mov    es:[si].prev,ax     ; Save it
  241.     pop    es
  242.     inc    free_code        ; Set next code
  243.     ret
  244. add_code    ENDP
  245.  
  246.     END
  247.