;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; 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
;/*****************************************************************************
;*
;* SOURCE FILE NAME = DRAWBITS.ASM
;*
;* DESCRIPTIVE NAME = DrawBits at level of device driver.
;*
;*
;* VERSION      V2.0
;*
;* DATE         05/11/90
;*
;* DESCRIPTION  Draws a portion of standard-formatted Bitmap directly onto the
;*              screen
;*
;*               . The standard-formatted Bitmap can have 1/4/8/24 bits/pel
;*                 but only one plane.
;*               . length in byte of 1 scan does not exceed 64k
;*               . The target device 3/4 plane EGA/VGA display
;*               . No RasterOperations are supported and direct copy is done.
;*               . Bound checking of the source rectangle is done against the
;*                 screen extents before in DrawBits, BitBlt,
;*                 enumerate_clip_rects, and do_drawbits.
;*               . Returns 1 in AX to indicate success (0 => failure)
;*
;*
;* FUNCTIONS    OEMDrawBits
;*
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   12/06/88                     Amit Chatterjee  [amitc] Created for Windows
;*                                for DIScreenBlt
;*   05/11/90                     Viroon Touranachun [viroont] Adapted for PM
;*   01/28/93              61319  Boundary condition problem in OEMDrawBits.
;*   03/09/93              61978  Correct DrawBits with DC Palette Use
;*   03/09/93              62532    "        "       "   "    "     "
;*
;*****************************************************************************/

        .386

        .xlist

INCL_GPIBITMAPS         equ     1       ; for bitmap info structure
INCL_GPIPRIMITIVES      equ     1
DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1
DINCL_BB_ROPS           equ     1

        include pmgre.inc
        include driver.inc
        include display.inc
        include egafam.inc
        include assert.mac
        include extern.inc
        include protos.inc
        include palette.inc             ;JMW
        .list

        .MODEL FLAT

        ASSUME  CS:FLAT,SS:FLAT,DS:FLAT,ES:FLAT

        .DATA

;/*
;**   Tables for BitCount-dependent routines
;*/

FullXFer        equ     this DWORD      ; has the xfer routine addresses

                DWORD   copy_1_bp_full
                DWORD   copy_4_bp_full
                DWORD   copy_8_bp_full
                DWORD   copy_24_bp_full

InitProc        equ     this DWORD      ; has the init routine addresses

                DWORD   odb_init_1_bit_per_pel
                DWORD   odb_init_4_bits_per_pel
                DWORD   odb_init_8_bits_per_pel
                DWORD   odb_init_24_bits_per_pel

ODB_SRC_HUGE    equ     01h             ;indicate the huge source bitmap

d_FullXFer      equ     this DWORD      ; has the xfer routine addresses

                DWORD   copy_1_bp_full
                DWORD   d_copy_4_bp_full
                DWORD   d_copy_8_bp_full
                DWORD   copy_24_bp_full

s_FullXFer      equ     this DWORD      ; has the xfer routine addresses

                DWORD   copy_1_bp_full
                DWORD   s_copy_4_bp_full
                DWORD   s_copy_8_bp_full
                DWORD   copy_24_bp_full

bkmix           BYTE    0               ; Background mix
bkclr           BYTE    0               ; Background color

        .CODE


;/***************************************************************************
;*
;* FUNCTION NAME = OEMDrawBits
;*
;* DESCRIPTION   = This function is a working routine to draw a
;*                 standard-formatted bitmap directly (ROP_SRCCOPY) to the
;*                 screen.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


OEMDrawBits     PROC SYSCALL USES esi edi,      pddcDst:DWORD, xDst:DWORD,
                                                yDst:DWORD, psdSrc:DWORD,
                                                xSrc:DWORD, ySrc:DWORD,
                                                cxExt:DWORD, cyExt:DWORD,
                                                usMix:DWORD, ipcBkgnd:DWORD,
                                                fsBlt:DWORD
                LOCAL   lpBits:DWORD,
                        cbSrcScan:DWORD,
                        lpScreen:DWORD,
                        cbDstScan:DWORD,
                        cBitCount:DWORD,
                        lpClrTab:DWORD
                LOCAL   fbFlags:DWORD,
                        pfnFullXfer:DWORD,
                        bUnusedPel:DWORD,
                        cPelsAtATime:DWORD,
                        scan_per_bank:WORD,
                        dst_scan_line_left:WORD,
                        bank_select:WORD
;/*
;** Get the bitmap information
;*/

        DebugMsg <OEMDrawBits DRAWBITS CLIFFL>

        cld
        mov     esi,psdSrc              ; source surface definition

        ASSUME  esi:PTR BITMAP

        mov     eax,[esi].bm_sd.sd_cbScan
        mov     cbSrcScan,eax           ; source scan width in bytes
        mov     eax,[esi].bm_sd.sd_pBits
        mov     lpBits,eax              ; pointer to the caller-supplied bits
        mov     eax,[esi].bm_sd.sd_pClrTab
        mov     lpClrTab,eax            ; pointer to the color mapping table
        mov     esi,[esi].bm_sd.sd_pbmi ; pointer to the bitmap info

        ASSUME  esi:PTR BITMAPINFOHEADER

        movzx   ecx,[esi].bmp_cBitCount ; the number of bits per pel (assume old)

        ASSUME  esi:PTR BITMAPINFOHEADER2

        cmp     [esi].bmp2_cbFix,size BITMAPINFOHEADER
        je      odb_have_info           ; it's old header, we know it's uncomp.

;/*
;** OEMDrawBits only draws the uncompressed bitmap. If it is a compressed bitmap
;** this is a good chance to pass it to RLEDrawBits.
;*/

odb_new_header:

        movzx   ecx,[esi].bmp2_cBitCount ;the number of bits per pel
        cmp     [esi].bmp2_cbFix,OFFSET BITMAPINFOHEADER2.bmp2_ulCompression
        jbe     odb_have_info           ;must be uncompressed

odb_check_compress:

        cmp     [esi].bmp2_ulCompression,BCA_UNCOMP
        je      odb_have_info

        INVOKE  RLEDrawBits, pddcDst, xDst, yDst, esi, xSrc, ySrc, cxExt, cyExt,
                                lpBits, lpClrTab

        jmp     odb_end                 ;already draw to screen

odb_have_info:

        mov     cBitCount,ecx

        mov     ebx,pddcDst
        test    [ebx].DDC.ddc_fbClrTbl,DDC_PALETTE
        jz      palette_end

;    for (i = 0; i < pdc->Palette->usCountStored; i++)
;    {
;        /**************************************************************/
;        /* Use the current mapping for this entry.                    */
;        /**************************************************************/
;        SPad.ausConvertTable[i] = pdc->Palette->entries[i].bCurrent;
;    }

        mov     ebx,[ebx].DDC.ddc_npdevpal
        mov     ecx,[ebx].DEVPAL.usCountStored
        mov     edi,lpClrTab

        mov     edx,esi
        add     edx,[esi].bmp2_cbFix                  ; edx = rgb[]

;            61978
;            62532
; If we are here we must have a palette for this dc.  The next steps are
; 1- get the rgb value from the bitmap
; 2- see if we have an index or an RGB value (BBO_PAL_COLORS)
; 3- if index then use the index in the current palette
;    else if rgb value then get the nearest palette index
; 4- store the value into the local color table ptr.

convert_loop:

        mov     eax,[edx]

        test    fsBlt,BBO_PAL_COLORS
        jnz     @f

        push    eax
        mov     eax,pddcDst
        push    eax
        call    NearestPaletteIndex
        add     esp,8
@@:
        mov     al,[ebx].DEVPAL.entries[eax*sizeof PALENTRY].bCurrent
        stosb
        add     edx,4
        loop    convert_loop

palette_end:

;/*
;** Cursor Exclusion for a device destination
;*/

odb_cursor_exclude:

        mov     esi,cxExt
        mov     edi,cyExt
        dec     esi                     ;Make extents inclusive of last point
        dec     edi
        mov     ecx,xDst                ;Set left
        mov     edx,yDst                ;Set top
        add     esi,ecx                 ;Set right
        add     edi,edx                 ;Set bottom

        INVOKE  far_exclude                     ;Exclude the area from the screen

;/*
;** calculate the offset to the start byte in the map and the screen and the
;** position of the first pel in the screen byte and on the map.
;*/

odb_calc_src_offset:

        mov     eax,ySrc                ; get the Y origin of the map
        mul     cbSrcScan               ; the result is in DX:AX

        assert  edx,E,0

        mov     ebx,eax
        mov     eax,xSrc                ; get the starting X pel no
        mul     cBitCount               ; no of bits per pel


        shr     eax,3                   ; get the no of bytes
        add     eax,ebx                 ; add in the contribution on CX:BX

;/*
;** add in the contribution of the original start offset of the bits.
;*/

        add     lpBits,eax              ; update the offset

;/*
;** now calculate the address of the start byte in the screen blt area.
;*/

odb_calc_dst_offset:

        xor     edx,edx
        mov     eax,BANK_SIZE
        mov     ebx,SCREEN_DSCAN
        div     ebx
        mov     scan_per_bank,ax
        mov     dst_scan_line_left,ax

        mov     cbDstScan,SCREEN_DSCAN  ; destination scan width in bytes
        mov     eax,yDst                ; get the Y origin (top scan)
        add     eax,cyExt               ; move it to the bottom of scan
        push    eax
        dec     eax

        mul     cbDstScan               ; no of bytes in a scan

        assert  edx,E,0

        mov     ebx,xDst                ; get the x origin
        mov     ecx,ebx
        add     eax,ebx                 ; this is the start offset

        mov     edx,eax
        movzx   eax,ax
        shr     edx,16                  ; dl is now have the bank number
        mov     bank_select,dx
        call    set_bank_select

        mov     lpScreen,eax

        pop     eax
        div     scan_per_bank

        or      dx,dx                   ;At the top of the bank?               
        jz      @f                      ;yes, lines left already set           
        mov     dst_scan_line_left,dx
@@:                                     ;                                      
        mov     esi,pddcDst             ; ES:SI => the dest. ddc

;/*
;** Check for background mixes of BM_SRCTRANSPARENT or BM_DESTTRANSPARENT.
;** BM_SRCTRANSPARENT will result in pels from the source bitmap matching
;** the presentation space background color NOT to be copied to the
;** destination bitmap. (OVERLAY)
;** BM_DESTTRANSPARENT will result in pels from the source bitmap ONLY
;** being copied to the destination pels that match the presentation space
;** background color. (UNDERLAY)
;** If either is requested, save the background color and background mix.
;*/

        ASSUME  esi:PDDC
        ;-----------------------------------------------------------------
        ; Destination transparent ?
        ;-----------------------------------------------------------------
        cmp     [esi].ddc_pa.pa_ba.ba_bkmix,BM_DESTTRANSPARENT

        ;-----------------------------------------------------------------
        ; If not, check for SRCTRANSPARENT
        ;-----------------------------------------------------------------
        jne     @f

        ;-----------------------------------------------------------------
        ; Background mix is BM_DESTTRANSPARENT
        ;-----------------------------------------------------------------
        mov     bkmix,BM_DESTTRANSPARENT

        ;-----------------------------------------------------------------
        ; Is our IPC is valid?
        ;-----------------------------------------------------------------
        test    [esi].ddc_pa.pa_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV
        jz      dtColorsValid

        ;-----------------------------------------------------------------
        ; Convert logical color to valid physical color.
        ;-----------------------------------------------------------------
        push    ebx
        lea     ebx,[esi].ddc_pa.pa_ba
        INVOKE  MakeColorsValid
        pop     ebx
        jns     short dtSetBkClr
dtColorsValid:
        mov     ax,[esi].ddc_pa.pa_ba.ba_ipcBack         ;Save background color
dtSetBkClr:

        mov     bkclr,al

        jmp     bkmix_known
@@:
        ;-----------------------------------------------------------------
        ; Source transparent ?
        ;-----------------------------------------------------------------
        cmp     [esi].ddc_pa.pa_ba.ba_bkmix,BM_SRCTRANSPARENT
        jne     @f

        mov     bkmix,BM_SRCTRANSPARENT

        ;-----------------------------------------------------------------
        ; Is our IPC is valid?
        ;-----------------------------------------------------------------
        test    [esi].ddc_pa.pa_ba.ba_fb,BA_CLR_INVALID or BA_CLR_BACK_INV
        jz      stColorsValid

        ;-----------------------------------------------------------------
        ; Convert logical color to valid physical color.
        ;-----------------------------------------------------------------
        push    ebx
        lea     ebx,[esi].ddc_pa.pa_ba
        INVOKE  MakeColorsValid
        pop     ebx
        jns     short stSetBkClr
stColorsValid:
        mov     ax,[esi].ddc_pa.pa_ba.ba_ipcBack         ;Save background color
stSetBkClr:

        mov     bkclr,al

        jmp     bkmix_known
@@:
        mov     bkmix,0

bkmix_known:


        mov     esi,[esi].ddc_npsd     ; ES:SI => the dest. surface

        ASSUME  esi:nothing

        mov     ebx,[ESI].SURFACE.sd_pBits
        add     lpScreen,ebx            ; destination address

;/*
;** now get the address of the full and partial byte proces that we will be
;** using depending on the bits per pel.
;*/

odb_get_xfer_addr:

        mov     ebx,cBitCount           ; get the bits per pel
        shl     ebx,4                   ; if BX = 1 => BX = 0
        shl     bh,6                    ; if BX = 4 => BX = 1
        add     bh,bl                   ; if BX = 8 => BX = 2
        shr     ebx,14                  ; if BX = 24 => BX = 3
        shl     ebx,2                   ; quad for dword offset

        cmp     bkmix,BM_SRCTRANSPARENT
        jnz     @f
        mov     eax,s_FullXFer[ebx]     ; get the src transparent transfer routine
        jmp     bkmix_done
@@:
        cmp     bkmix,BM_DESTTRANSPARENT
        jnz     @f
        mov     eax,d_FullXFer[ebx]     ; get the dest transparent transfer routine
        jmp     bkmix_done
@@:
        mov     eax,FullXFer[ebx]       ; get the transfer routine

bkmix_done:

        mov     pfnFullXfer,eax
        mov     ebx,InitProc[ebx]       ; get the appropriate init procs addr
        jmp     ebx                     ; do the format specific inits

;/*
;**  the format specific initialization routines follow here.
;**  ES:DI points to the color table.
;**
;**  For monochrome, we need to know how many bits in the first source byte
;**     (from the left) are unused and init color table
;**  For 4 bpp, we need to know wheter we start with the high nibble or the
;**     low nibble and init the color table.
;**  For 8 bpp, we always have each pel starts at the byte boundary, so just
;**     init the color table.
;**  For 24 bpp, do nothing.
;**
;*/

odb_init_1_bit_per_pel::

        mov     eax,xSrc                ; the start pel number in a scan
        and     eax,7                   ; the number of pel unused in 1st byte
        mov     BYTE PTR bUnusedPel,al
        jmp     odb_init_8_bits_per_pel

odb_init_4_bits_per_pel::

        mov     eax,xSrc                ; start BMP pel number in a byte
        shr     eax,1                   ; if odd we start with low nibble
        rcl     bUnusedPel,1            ; LSB bit for low nibble usage

odb_init_8_bits_per_pel::

        mov     ebx,lpClrTab            ; the color mapping table

odb_init_24_bits_per_pel::

odb_init_board:

odb_start_draw:

        mov     esi,lpBits              ; the strting point of the bits
        mov     edi,lpScreen            ; the start on the screen
        mov     ecx,cyExt               ; the number of scans to copy

;/*
;** We will draw one scan at a time so that we can determine which
;** byte-transfer routines we will use.
;*/

odb_blt_next_scan:
ifdef   cross_seg
        mov     dl,bank_select
        call    far_set_bank_select
endif   ;cross_seg

;/*
;** test to see if the current scan will span a segment
;*/


;/*
;** the scan will cross a segment somewhere, so use the pfnGetByte proc which tests
;** for segment crossings
;*/

odb_blt_next_scan_continue:

        push    ecx                     ; save scan loop count
        push    esi
        push    edi                     ; save the source and target pointers
        mov     ecx,cxExt               ; the no of pels to blt

        Call    pfnFullXfer             ; do the blt of a scan

        pop     edi
        pop     esi                     ; get back the pointers
        pop     ecx                     ; get back the no of scans left to blt
        sub     edi,cbDstScan           ; we map top to bottom

        dec     dst_scan_line_left
        jnz     @f
        push    scan_per_bank
        pop     dst_scan_line_left
        dec     bank_select
        mov     dx,bank_select
        call    set_bank_select
        add     edi,BANK_SIZE
@@:
        add     esi,cbSrcScan           ; update to the next scan
        loop    odb_blt_next_scan       ; blt all the scans

odb_exit:

        INVOKE  far_unexclude           ; re-draw the cursor

odb_end:

        RET

;/***************************************************************************
;*
;* FUNCTION NAME = copy_1_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 1 bits per
;*                 pixel case
;*
;*                 Registers Destroyed:
;*                       AL,CX,flags
;*
;* INPUT         = DS:SI     --  current byte in the map
;*                 ES:DI     --  current byte in the screen
;*                    AH     --  current bit position in the first byte
;*                 GS:BX     --  address of color mapping table
;*                    CX     --  number of pels to convert
;*                    DX     --  BIT MASK register address
;*
;* OUTPUT        = DS:SI,ES:DI -- next bytes in respective areas
;*                 AH          -- updated bit mask
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

copy_1_bp_full::

;/*
;** the first source byte may yield partial number of pels
;** shift left the contents till the start pel is on left edge
;*/

        lodsb                           ; get the first byte
        push    ecx                     ; save
        mov     cl,BYTE PTR bUnusedPel  ; no of pels not used in 1st byte
        shl     al,cl                   ; the first pel is on the edge
        neg     cl
        add     cl,8                    ; the number of pels left in byte
        movzx   ecx,cl
        mov     cPelsAtATime,ecx
        pop     ecx

copy_1_bp_loop:

        xchg    al,ah                   ; get the current mask
        push    ecx                     ; save # to convert

;/*
;** cPelsAtATime has the number of pels in the byte, usually 8 except for first
;** and last
;*/

        cmp     ecx,cPelsAtATime        ; 8 or more bits left
        jbe     copy_1_bp_same_byte     ; no partial byte
        mov     ecx,cPelsAtATime        ; convert the 8 bits in the byte

copy_1_bp_same_byte:

        push    ecx                     ; save mask and byte
        shl     ah,1                    ; get the next oel into carry
        rcl     cl,1                    ; get the pel value
        and     cl,1                    ; only 1 bit significant
        xchg    al,cl                   ; save mask in cl, get pel in al
        xlat                            ; get the converted value
        xchg    BYTE PTR [edi],al       ; write the pel
        mov     al,cl                   ; get the mask in al
        ror     al,1                    ; next bit position
        adc     edi,0                   ; update screen pointer if needed
        pop     ecx                     ; get back byte and mask
        loop    copy_1_bp_same_byte     ; convert the byte
        pop     ecx                     ; get back remaining bits
        mov     ah,al                   ; get back mask in ah
        sub     ecx,cPelsAtATime        ; 8 or less were just converted
        jbe     copy_1_bp_done          ; CX <= 0 means we have done all
        lodsb                           ; get the next byte
        mov     cPelsAtATime,8          ; do 8 bits in it
        jmp     copy_1_bp_loop          ; continue in loop

copy_1_bp_done:

        ret

;/***************************************************************************
;*
;* FUNCTION NAME = copy_4_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 4 bits per
;*                 pixel case
;*
;*                 Registers Destroyed:
;*                       AL,CX,flags
;*
;* INPUT         = DS:SI  --  current byte in the map
;*                 ES:DI  --  current byte in the screen
;*                 AH     --  current bit position in the first byte
;*                 GS:BX  --  address of color mapping table
;*                 CX     --  number of pels to convert
;*                 DX     --  BIT MASK register address
;*
;* OUTPUT        = DS:SI,ES:DI --  next bytes in respective areas
;*                 AH          --  updated bit mask
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


copy_4_bp_full::

        lodsb                           ; process first byte separately
        test    bUnusedPel,1            ; is just the low nibble to be used
        jnz     copy_4_bp_low_nibble    ; yes
        jmp     @F                      ; already fetch the 1st byte

copy_4_bp_loop:

        lodsb                           ; get the next source byte
@@:
        push    eax                     ; save the byte
        shr     al,4                    ; get the high nibble into low pos
        xlat                            ; get the mapping index
        xchg    BYTE PTR [edi],al       ; write the pel
        pop     eax                     ; get back pel
        inc     edi                     ; position to next target byte

copy_4_bp_next_nibble:

        dec     ecx                     ; one more pel done
        jecxz   copy_4_bp_done

copy_4_bp_low_nibble:

        and     al,0fh                  ; get the lower 4 bits
        xlat                            ; get the mapping index
        xchg    BYTE PTR [edi],al       ; write the pel
        inc     edi                     ; next target  byte

copy_4_bp_next_byte:

        loop    copy_4_bp_loop          ; process all the remaining pels

copy_4_bp_done:

        ret

;/***************************************************************************
;*
;* FUNCTION NAME = d_copy_4_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 4 bits per
;*                 pixel case with a background mix of BM_DESTTRANSPARENT
;*
;*                 Registers Destroyed:
;*                       AL,CX,flags
;*
;* INPUT         = DS:SI  --  current byte in the map
;*                 ES:DI  --  current byte in the screen
;*                 GS:BX  --  address of color mapping table
;*                 CX     --  number of pels to convert
;*
;* OUTPUT        = DS:SI,ES:DI --  next bytes in respective areas
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

d_copy_4_bp_full::
        push    edx
        mov     dl,bkclr
        lodsb                           ; process first byte separately
        test    bUnusedPel,1            ; is just the low nibble to be used
        jnz     d_copy_4_bp_low_nibble  ; yes
        jmp     @F                      ; already fetch the 1st byte

d_copy_4_bp_loop:

        lodsb                           ; get the next source byte
@@:
        mov     ah,al                   ; save the byte
        cmp     dl,byte ptr[edi]        ; Color == background color ?
        jne     d_color_not_found1      ; If not, skip drawing pel
        shr     al,4                    ; get the high nibble into low pos
        xlat                            ; get the mapping index
        xchg    BYTE PTR [edi],al       ; write the pel

d_color_not_found1:

        inc     edi                     ; position to next target byte

d_copy_4_bp_next_nibble:

        mov     al,ah                   ; get back pel
        dec     ecx                     ; one more pel done
        jecxz   d_copy_4_bp_done

d_copy_4_bp_low_nibble:

        cmp     dl,byte ptr[edi]        ; Color == background color ?
        jne     d_color_not_found2      ; If not, skip drawing pel
        and     al,0fh                  ; get the lower 4 bits
        xlat                            ; get the mapping index
        xchg    BYTE PTR [edi],al       ; write the pel

d_color_not_found2:

        inc     edi                     ; next target  byte

d_copy_4_bp_next_byte:

        loop    d_copy_4_bp_loop        ; process all the remaining pels

d_copy_4_bp_done:
        pop     edx
        ret


;/***************************************************************************
;*
;* FUNCTION NAME = s_copy_4_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 4 bits per
;*                 pixel case with a background mix of BM_SRCTRANSPARENT
;*
;*                 Registers Destroyed:
;*                       AL,CX,flags
;*
;* INPUT         = DS:SI  --  current byte in the map
;*                 ES:DI  --  current byte in the screen
;*                 GS:BX  --  address of color mapping table
;*                 CX     --  number of pels to convert
;*
;* OUTPUT        = DS:SI,ES:DI --  next bytes in respective areas
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

s_copy_4_bp_full::
        lodsb                           ; process first byte separately
        test    bUnusedPel,1            ; is just the low nibble to be used
        jnz     s_copy_4_bp_low_nibble  ; yes
        jmp     @F                      ; already fetch the 1st byte

s_copy_4_bp_loop:

        lodsb                           ; get the next source byte
@@:
        mov     ah,al                   ; save the byte
        shr     al,4                    ; get the high nibble into low pos
        xlat                            ; get the mapping index
        cmp     al,bkclr                ; Color == background color ?
        je      s_color_found1          ; If so, skip drawing pel
        xchg    BYTE PTR [edi],al       ; write the pel

s_color_found1:

        inc     edi                     ; position to next target byte

s_copy_4_bp_next_nibble:

        mov     al,ah                   ; get back pel
        dec     ecx                     ; one more pel done
        jecxz   s_copy_4_bp_done

s_copy_4_bp_low_nibble:

        and     al,0fh                  ; get the lower 4 bits
        xlat                            ; get the mapping index
        cmp     al,bkclr                ; Color == background color ?
        je      s_color_found2          ; If so, skip drawing pel
        xchg    BYTE PTR [edi],al       ; write the pel

s_color_found2:

        inc     edi                     ; next target  byte

s_copy_4_bp_next_byte:

        loop    s_copy_4_bp_loop        ; process all the remaining pels

s_copy_4_bp_done:
        ret

;/***************************************************************************
;*
;* FUNCTION NAME = copy_8_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 8 bits per
;*                 pixel case
;*
;*                 Registers Destroyed:
;*                      AL,CX,flags
;*
;* INPUT         = DS:SI     --  current byte in the map
;*                 ES:DI     --  current byte in the screen
;*                    AH     --  current bit position in the first byte
;*                 GS:BX     --  address of color mapping table
;*                    CX     --  number of pels to convert
;*                    DX     --  BIT MASK register address
;*
;* OUTPUT        = DS:SI,ES:DI -- next bytes in respective areas
;*                          AH -- updated bit mask
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


copy_8_bp_full::

        lodsb                           ; get the next source byte
        xlat                            ; get the mapping index value
        stosb                           ; write the pel
        loop    copy_8_bp_full          ; repeat till all bytes processed
        ret


;/***************************************************************************
;*
;* FUNCTION NAME = d_copy_8_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 8 bits per
;*                 pixel case with a background mix of BM_DESTTRANSPARENT
;*
;*                 Registers Destroyed:
;*                      AL,CX,flags
;*
;* INPUT         = DS:SI     --  current byte in the map
;*                 ES:DI     --  current byte in the screen
;*                 GS:BX     --  address of color mapping table
;*                    CX     --  number of pels to convert
;*
;* OUTPUT        = DS:SI,ES:DI -- next bytes in respective areas
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

d_copy_8_bp_full::

        mov     ah,bkclr

d_copy_8_bp_full_loop:

        lodsb                           ; get the next source byte
        xlat                            ; get the mapping index value
        cmp     ah,byte ptr[edi]        ; Color == background color ?
        jne     d_color_not_found       ; If not, skip drawing pel
        stosb                           ; If so, set the pel
        loop    d_copy_8_bp_full_loop   ; Get the next byte
        jmp     @f

d_color_not_found:

        inc     edi                     ; Trans color not found, point to next byte
        loop    d_copy_8_bp_full_loop   ; repeat till all bytes processed
@@:
        ret


;/***************************************************************************
;*
;* FUNCTION NAME = s_copy_8_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 8 bits per
;*                 pixel case with a background mix of BM_SRCTRANSPARENT
;*
;*                 Registers Destroyed:
;*                      AL,CX,flags
;*
;* INPUT         = DS:SI     --  current byte in the map
;*                 ES:DI     --  current byte in the screen
;*                 GS:BX     --  address of color mapping table
;*                    CX     --  number of pels to convert
;*
;* OUTPUT        = DS:SI,ES:DI -- next bytes in respective areas
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

s_copy_8_bp_full::

        lodsb                           ; get the next source byte
        xlat                            ; get the mapping index value
        cmp     al,bkclr                ; Color == background color ?
        je      s_color_found           ; If so, skip drawing pel
        stosb                           ; If not, set the pel
        loop    s_copy_8_bp_full        ; Get the next byte
        jmp     @f

s_color_found:

        inc     edi                     ; Trans color not found, point to next byte
        loop    s_copy_8_bp_full        ; repeat till all bytes processed
@@:
        ret

;/***************************************************************************
;*
;* FUNCTION NAME = copy_24_bp_full
;*
;* DESCRIPTION   = handles the blt of a scan or a part of it for 24 bits per
;*                 pixel case
;*
;*                 Registers Destroyed:
;*                      AL,BX,CX,flags
;*
;* INPUT         = DS:SI     --  current byte in the map
;*                 ES:DI     --  current byte in the screen
;*                    AH     --  current bit position in the first byte
;*                    CX     --  number of pels to convert
;*                    DX     --  BIT MASK register address
;*
;* OUTPUT        = DS:SI,ES:DI -- next bytes in respective areas
;*                          AH -- updated bit mask
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

copy_24_bp_full::

        lodsb                           ; get the blue pel
        mov     dl,al                   ; have blue in dl
        lodsb                           ; get green
        mov     ah,al                   ; have it in ah
        lodsb                           ; get red in al
        xchg    dl,al                   ; DL = red, AH = green, AL = blue

        INVOKE  rgb_to_ipc              ; do the mapping => AL = physical color

        xchg    BYTE PTR [edi],al       ; xfer the pel
        inc     edi                     ; go the next screen byte
        loop   copy_24_bp_full          ; process all the other bytes
        ret


OEMDrawBits     ENDP

        end
