;*DDK*************************************************************************/
;
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/
        page    ,132
;-----------------------------Module-Header-----------------------------;
; Module Name:  FDDECOMP.ASM
;
;   This module contains         DBCS WIFE font support functions
;   fot DBCS OS/2 PM font drivers.
;
; Created: 15-Oct-1991
; Author:  Takashi Itoh [jl03313 @ ymtvm3, IBM Japan]
; Author:  Soh Ohta     [jl09057 @ ymtvm3, IBM Japan]
;
;                       Refer to Copyright Inscruction Form No.G120-2083
;
; Exported Functions:   none
;
; Public Functions:     Bitblt
;
; Public Data:          none
;
; General Description:
;
; Modified:
; 12-Jan-1994 N.Iuchi @IU1  (JS06276, PJ11735) HATSU displayed incorrectly.
;-----------------------------------------------------------------------;

        .286p
        .xlist
        include cmacros.inc
        include resmap.inc
        .list

        createSeg   _TEXT, Decomp, WORD, PUBLIC, CODE


sBegin  Decomp
        assumes cs,Decomp

;---------------------------Public-Routine------------------------------;
; DecompWinImage
;
; Decompress compressed image.
;
; Entry:
;
;   VOID PASCAL DecompWinImage (npEncInfo, npFlat, npComp, cbComp);
;
;   NPENCODE npEncInfo;     // encoding information
;   NPBYTE   npFlat;        // address to store decompressed image
;   NPBYTE   npComp;        // address of compressed image
;   NPBYTE   cbComp;        // size of compressed image in bytes
;
; Returns:
;       none.
; Registers Destroyed:
; Registers Preserved:
;       SI,DI,DS
; History:
;   23-Sep-1991 -by-    Soh Ohta [jl09057 @ ymtvm3]
; Massive change.
;-----------------------------------------------------------------------;

        assumes ds,nothing
        assumes es,nothing

cProc   DecompWinImage,<NEAR,PUBLIC,PASCAL,NODATA>,<si,di>

        parmW   npEncInfo               ; encoding information
        parmW   npFlat                  ; address to store decompressed image
        parmW   npComp                  ; address of compressed image
        parmW   cbComp                  ; size of compressed image in bytes

        localW  iBit                    ; bit stream bit position
        localW  x                       ; 
        localW  cxExt                   ; 
        localW  cyExt                   ; 
        localW  nibbles                 ; number of nibbles in a scanline
        localW  cbScan                  ; number of bytes   in a scanline
        localW  cbFill                  ; leading blank bytes

        localV  seqFlags,%(MAXHEIGHT)

cBegin

        cld

; Prepare basic parameters.

        mov     bx,npEncInfo            ; DS:BX --> npEncInfo
        xor     ah,ah
        mov     al,[bx].ec_cy
        mov     cyExt,ax                ; cyExt = npEncInfo->cy
        mov     al,[bx].ec_cx
        mov     cxExt,ax                ; cxExt = npEncInfo->cx
        mov     bx,ax
        shr     bx,2
        mov     nibbles,bx              ; nibbles = cxExt/4
        dec     ax
        shr     ax,3
        inc     ax
        mov     cbScan,ax               ; cbScan = (cxExt-1)/8+1

; Fill decompressed image production buffer with zeros.

        mul     cyExt
        mov     cx,ax
        shr     cx,1                    ; CX = (cbScan*cyExt)/2
        mov     ax,ds
        mov     es,ax
        mov     di,npFlat               ; ES:DI --> npFlat
        xor     ax,ax
        rep     stosw

; If the source data is uncompressed, then do special case.

        mov     ax,cxExt
        mul     cyExt
        shr     ax,3
        cmp     cbComp,ax               ; cbComp==cxExt*cyExt/8?
        jnz     prepare_decomp          ; no, prepare for decompressiion

;------------------------------Pseudo-Code------------------------------;
;   <non compressed image>
;
;   for (x=0; x<nibbles; x++) {
;       npBits=npFlat+x/2;
;       for (y=0; y<cyExt; y+=2) {                      ;@IU1
;           byte=npComp[(y+x*cyExt)/2];
;           if (x%2==0) {
;               nibble1 = byte&0xf0;
;               nibble2 = byte<<4;
;           } else {
;               nibble1 = byte>>4;
;               nibble2 = byte&0x0f;
;           }
;           *npBits|=nibble1;
;           npBits+=cbScan;
;           *npBits|=nibble2;
;           npBits+=cbScan;                             ;@IU1
;       }
;   }
;-----------------------------------------------------------------------;

        mov     si,npComp               ; SI = npComp
        mov     bx,cyExt                ; BX = cyExt
        mov     cx,cbScan               ; CX = cbScan
        xor     dl,dl                   ; DL = x

next_nibble:
        mov     di,dx
        and     di,0ffh
        shr     di,1
        add     di,npFlat               ; DI = npBits = npFlat+x/2
        xor     dh,dh                   ; DH = y
next_scan:
        mov     al,bl
        mul     dl
        add     al,dh
        adc     ah,0
        shr     ax,1
        xchg    ax,bx
        mov     bl,[si][bx]             ; AL = npComp[(y+x*cyExt)/2]
        xchg    ax,bx
        mov     ah,0f0h
        and     ah,al                   ; AH = nibble1 (hi4bits)
        shl     al,4                    ; AL = nibble2 (hi4bits)
        test    dl,1
        jz      @f
        shr     ax,4                    ; AH = nibble1 (lo4bits)
                                        ; AL = nibble2 (lo4bits)
    @@: or      [di],ah                 ; *npBits|=nibble1;
        add     di,cx                   ; npBits+=cbScan;
        or      [di],al                 ; *npBits|=nibble2;
        add     di,cx                   ; npBits+=cbScan;       ;@IU1
        inc     dh                      ; y++
        inc     dh                      ; y++                   ;@IU1
        cmp     dh,bl                   ; y<cyExt?
        jb      next_scan               ; yes...

        inc     dl                      ; x++
        cmp     dl,byte ptr nibbles     ; x<nibbles?
        jb      next_nibble             ; yes...
        jmp     decomp_done

;------------------------------Pseudo-Code------------------------------;
; <setup procedure>
;
;   memset (seqFlags,0,MAXHEIGHT);
;
;   iBit=1; // initial bit position in bit stream (1..).
;   if (bit(npComp,iBit)) {
;       while (bit(npComp,++iBit)) {    // skip leading white scanlines.
;           cbFill+=cbScan;             // number of bytes to be skipped.
;           cyExt--;                    // scanline count to be decompressed.
;       }
;       while (bit(npComp,++iBit))      // drop trailing white scanlines.
;           cyExt--;                    // scanline count to be decompressed.
;   }
;   if (bit(npComp,++iBit))
;       for (y=cyExt; y>0; y--)
;           seqFlags[y-1] = bit(npComp,++iBit);
;-----------------------------------------------------------------------;

prepare_decomp:
        mov     ax,ss                   ; memset (seqFlags,0,MAXHEIGHT);
        mov     es,ax
        lea     di,seqFlags             ; ES:DI --> seqFlags
        mov     cx,MAXHEIGHT/2
        xor     ax,ax
        rep     stosw

        mov     si,npComp               ; SI = npComp
        mov     di,cyExt                ; DI = cyExt
        mov     dh,byte ptr cbScan      ; DH = cbScan
        mov     dl,0                    ; DL = cbFill (leading blank bytes)
        mov     cx,1                    ; CX = iBit   (bit stream bit  position)
        mov     bx,0                    ; BX = iByte  (bit stream byte position)
        mov     al,80h                  ; AL = bitmask (iBit,iByte)
        test    [si][bx],al             ; bit(npComp,iBit)!=1?
        jz      no_white_scans          ;   then no white (blank) scans
know_leading_whites:
        inc     cx                      ; iBit++;
        ror     al,1                    ;   "
        adc     bx,0                    ;   "
        test    [si][bx],al             ; bit(npComp,iBit)==0?
        jz      know_trailing_whites    ;   then leading whites are now known
        add     dl,dh                   ; cbFill+=cbScan;
        dec     di                      ; cyExt--;
        jmp     short know_leading_whites
know_trailing_whites:
        inc     cx                      ; iBit++;
        ror     al,1                    ;   "
        adc     bx,0                    ;   "
        test    [si][bx],al             ; bit(npComp,iBit)==0?
        jz      no_white_scans          ;   then trailing whites are now known
        dec     di                      ; cyExt--;
        jmp     short know_trailing_whites
no_white_scans:
        mov     cyExt,di                ; save computed height
        inc     cx
        ror     al,1
        adc     bx,0
        test    [si][bx],al             ; bit(npComp,iBit)==0?
        jz      setup_done              ; ... setup completed
setup_seqflags:                         ; y=cyExt;
        dec     di                      ; y--;
        jz      setup_done
        inc     cx                      ; iBit++;
        ror     al,1                    ;   "
        adc     bx,0                    ;   "
        mov     ah,[si][bx]
        and     ah,al
        mov     seqFlags[di-1],ah       ; seqFlags[y-1]=bit(npComp,iBit);
        jmp     short setup_seqflags
setup_done:
        xor     dh,dh                   ; save computed values
        mov     cbFill,dx               ; cbFill = leading blank bytes
        mov     iBit,cx                 ; iBit  = current bit stream bit position

;------------------------------Pseudo-Code------------------------------;
; <decompression logic>
;
;   for (x=0; x<nibbles; x++) {         // x = current stripe (4pel wide)
;       npBits=npFlat+cbFill+x/2;       // npBits = vertical stripe base addr
;       bCache=0;                       // bCache = decompressed data cache
;       for (y=cyExt; y>0;) {           // y = current scanline
;
;           mask=getword(npComp,iBit);  // get word from bit stream
;           // search key index
;           for (key=1; lpEncInfo->Huff[key].mask<mask;)        key++;
;           if ((lpEncInfo->Huff[key].mask!=mask)||(mask==-1))  key--;
;           iBit+=lpEncInfo->Huff[key].len; // proceed bit position
;           data=lpEncInfo->Huff[key].data;
;
;           if (data<MAXROW) {
;               bCache<<=4;
;               nibble=lpEncInfo->Dcmp[(bCache+data)/2];
;               nibble=(data%2)?(nibble&0xf):(nibble>>4);
;               bCache|=nibble;             // keep this nibble into cache
;               if (x%2==0) nibble<<=4;
;               do {                        // store decompressed image
;                   *npBits|=nibble;
;                   npBits+=cbScan;
;               } while ((--y) && (seqFlags[y-1]));
;
;           } else {
;               nibble=bCache&0xf;
;               bCache=(bCache<<4)|nibble;
;               if (x%2==0) nibble<<=4;
;               for (; data>=MAXROW;) {     // store decompressed image
;                   *npBits|=nibble;
;                   npBits+=cbScan;
;                   if (--y==0)
;                       break;
;                   if (seqFlags[y-1]==0)
;                       data--;
;               }
;           }
;       }
;   }
;-----------------------------------------------------------------------;

        mov     x,0
        jmp     horz_update             ; initialize loop then do vert_loop

; DI = decompressed image storing offset (npBits)
; DL = bit stream cache (bCache)
; SI = remaining number of vertical scans (y)
; x  = remaining number of 4bit wide horizontal stripes

; Get mask data from bit stream current position

vert_loop:
        push    si                      ; SI = remaining number of scans
        mov     si,npComp               ; DS:SI --> npComp (bit stream)
        mov     bx,iBit
        mov     cx,bx
        shr     bx,3                    ; BX = bit stream byte position
        and     cx,7                    ; CX = bit stream bit  position
        mov     ax,[si][bx]
        xchg    ah,al
        mov     bl,[si][bx+2]
        xor     bh,bh                   ; AH:AL:BL:BH = 1st:2nd:3rd:nul byte
        shl     ax,cl
        shl     bx,cl
        or      al,bh                   ; AX = mask data

; Search key index to access encoding information table, and
; get huffman data from the table.

        mov     si,npEncInfo            ; DS:SI --> npEncInfo
        xor     bx,bx
next_key_index:
        add     bx,(SIZE MASKTBL)
        cmp     [si].ec_Huff[bx].mt_mask,ax
        jb      next_key_index
        jne     prev_key_index
        cmp     ax,-1
        jne     have_key_index
prev_key_index:
        sub     bx,(SIZE MASKTBL)
have_key_index:                         ; BX = key index
        xor     ax,ax
        xor     cx,cx
        mov     al,[si].ec_Huff[bx].mt_len
        mov     cl,[si].ec_Huff[bx].mt_data
        add     iBit,ax                 ; proceed bit position
        cmp     cx,MAXROW
        jae     use_seq_flags

; The case huffman data < MAXROW. Do decompress.

use_huffman_data:
        xor     dh,dh
        shl     dx,4                    ; DL = bCache<<=4;
        mov     bx,dx
        or      bl,cl
        shr     bx,1                    ; 'C' = huffman data LSB
        mov     al,[si].ec_Dcmp[bx]
        jc      @f
        shr     al,4
    @@: and     al,0fh                  ; AL = nibble (lower 4 bits)
        or      dl,al                   ; DL = bCache|=nibble;
        test    x,1
        jnz     hd_have_nibble
        shl     al,4                    ; adjust nibble data within a byte

hd_have_nibble:
        pop     si                      ; SI = remaining number of scans
hd_store_loop:                          ; do {
        or      [di],al                 ;     *npBits|=nibble;
        add     di,cbScan               ;     npBits+=cbScan;
        dec     si                      ; } while ((--y) && (seqFlags[y-1]));
        jz      horz_check              ; 
        cmp     byte ptr seqFlags[si-1],0; 
        je      vert_loop               ; 
        jmp     short hd_store_loop     ; 

; The case huffman data >= MAXROW. Do decompress.

use_seq_flags:
        and     dl,0fh
        mov     al,dl                   ; AL = nibble=bCache&0xf;
        shl     dl,4
        or      dl,al                   ; DL = bCache=(bCache<<4)|nibble;
        test    x,1
        jnz     sf_have_nibble
        shl     al,4                    ; adjust nibble data within a byte

sf_have_nibble:
        pop     si                      ; SI = remaining number of scans
        sub     cx,(MAXROW-1)
sf_store_loop:                          ; for (; data>=MAXROW;) {
        or      [di],al                 ;     *npBits|=nibble;
        add     di,cbScan               ;     npBits+=cbScan;
        dec     si                      ;     if (--y==0)
        jz      horz_check              ;         break;
        cmp     byte ptr seqFlags[si-1],0;    if (seqFlags[y-1]==0)
        jne     sf_store_loop           ;         data--;
        loop    sf_store_loop           ; }
        jmp     vert_loop               ; 

; Outer loop looping logic.

horz_check:
        inc     x
        mov     ax,x
        cmp     ax,nibbles              ; (--x)<nibbles?
        jae     decomp_done             ; --> decompression done
horz_update:
        mov     di,x
        shr     di,1
        add     di,cbFill
        add     di,npFlat               ; DI = npBits = npFlat+cbFill+x/2
        mov     si,cyExt                ; SI = remaining number of scans (y)
        xor     dl,dl                   ; DL = bCache = 0
        jmp     vert_loop

decomp_done:
cEnd

sEnd    Decomp

End
