;*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
OPTION EPILOGUE:NONE
;/*****************************************************************************
;*
;* SOURCE FILE NAME = BMC_ITE.ASM
;*
;* DESCRIPTIVE NAME = Bitmap Conversion - Internal to External
;*
;*
;* VERSION      V2.0
;*
;* DATE         05/16/87
;*
;* DESCRIPTION
;*              There are four standard bitmap formats.  All device drivers
;*              are required to be able to translate between any of these
;*              formats and their own internal formats. The standard formats
;*              are as follows:
;*
;*                                    Bitcount                 Planes
;*                                    --------                 ------
;*                                       1                     1
;*                                       4                     1
;*                                       8                     1
;*                                      24                     1
;*
;*              These formats are chosen because they are identical or similar
;*              to all formats commonly used by raster devices.  Only single
;*              plane formats are standard, but it is very easy to convert these
;*              to any multiple plane format used internally by a device.
;*
;*              The pixel data is stored in the bitmap in the order of the co-
;*              ordinates as they would appear on a display screen.  That is,
;*              the pixel in the lower left corner is the first in the bitmap.
;*              Pixels are scanned to the right and up from there.  The first
;*              pixel's bits are stored beginning in the lowest order bits of
;*              the first byte.  The data for pixels in each scan line is packed
;*              together tightly.  Each scanline, however, will be padded at the
;*              end so that each scan line begins on a DWORD boundary.
;*
;* FUNCTIONS    bmc_int_to_ext
;*
;*
;* NOTES        NONE
;*
;* STRUCTURES   NONE
;*
;* EXTERNAL REFERENCES
;*
;*              NONE
;*
;* EXTERNAL FUNCTIONS
;*
;*              NONE
;*
;* CHANGE ACTIVITY =
;*   DATE      FLAG        APAR   CHANGE DESCRIPTION
;*   --------  ----------  -----  --------------------------------------
;*   mm/dd/yy  @Vr.mpppxx  xxxxx  xxxxxxx
;*   05/16/87                     Written by Walt Moore
;*   11/09/87                     Bob Grudem [bobgru] Internal color bitmaps
;*                                always use interleaved (i.e. huge)
;*                                scanline format.
;*   05/01/90                     Viroon Touranachun [viroont] Add the inquiry
;*                                option, i.e., pBuf = NULL, for requesting just
;*                                the extracted size.
;*   02/05/93              50297  Return # of scans requested for the Dest
;*                                bitmap rather than the # of scans in the
;*                                src bitmap.
;*
;*****************************************************************************/

        .386

        .xlist

INCL_GRE_BITMAPS        equ     1
INCL_GPIBITMAPS         equ     1
INCL_GPIERRORS          equ     1

        include pmgre.inc

DINCL_ENABLE            equ     1
DINCL_BITMAP            equ     1

        include driver.inc
        include assert.mac
        include extern.inc
        include protos.inc

        .list

        .MODEL FLAT

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

        .DATA

        .xlist

        include bmi2.inc

        .list

;/*
;** The CAN_CROSS_SEG flag is overlayed on top of the sd_fb flag taken
;** from the surface definition of the bitmap.  SD_DEVICE must be null
;** else we don't have a bitmap.
;*/

CAN_CROSS_SEG   equ     SD_DEVICE                ;User's buffer will cross seg boundary

;/*
;** anpfnPreProc is the dispatch table for the function to perform
;** any preprocessing required for the given format
;*/

anpfnPreProc    label   DWORD

        DWORD   ite_1
        DWORD   ite_4
        DWORD   ite_8
        DWORD   ite_24


;/*
;** temp_color_table will be for translating 4 to 24 until
;** the dynamic color tables are in place.
;** must match that in phycolor until phycolor can be modifed
;** to have it's table in CS
;*/


temp_color_table label BYTE

        DWORD   00000000h                         ;Black
        DWORD   00000080h                         ;Blue
        DWORD   00008000h                         ;Green
        DWORD   00008080h                         ;Cyan
        DWORD   00800000h                         ;Red
        DWORD   00800080h                         ;Magenta
        DWORD   00808000h                         ;Yellow
        DWORD   00808080h                         ;White

ifdef VGA

        DWORD   00CCCCCCh                         ;Light Gray
else
        DWORD   00202020h                         ;Black
endif
        DWORD   000000FFh                         ;Blue
        DWORD   0000FF00h                         ;Green
        DWORD   0000FFFFh                         ;Cyan
        DWORD   00FF0000h                         ;Red
        DWORD   00FF00FFh                         ;Magenta
        DWORD   00FFFF00h                         ;Yellow
        DWORD   00FFFFFFh                         ;White

;/*
;** fixed_color_table is the default color table which the
;** device is programmed with.
;*/

fixed_color_table label byte

        BYTE    000h,000h,000h                    ;Black
        BYTE    080h,000h,000h                    ;Blue
        BYTE    000h,080h,000h                    ;Green
        BYTE    080h,080h,000h                    ;Cyan
        BYTE    000h,000h,080h                    ;Red
        BYTE    080h,000h,080h                    ;Magenta
        BYTE    000h,080h,080h                    ;Yellow
        BYTE    080h,080h,080h                    ;White

ifdef VGA

        BYTE    0CCh,0CCh,0CCh                    ;Light Gray
else
        BYTE    020h,020h,020h                    ;Black
endif
        BYTE    0FFh,000h,000h                    ;Blue
        BYTE    000h,0FFh,000h                    ;Green
        BYTE    0FFh,0FFh,000h                    ;Cyan
        BYTE    000h,000h,0FFh                    ;Red
        BYTE    0FFh,000h,0FFh                    ;Magenta
        BYTE    000h,0FFh,0FFh                    ;Yellow
        BYTE    0FFh,0FFh,0FFh                    ;White

SIZE_FIXED_COLOR_TABLE  = $-fixed_color_table

fixed_color_table2 label byte

        BYTE    000h,000h,000h,000h               ;Black
        BYTE    080h,000h,000h,000h               ;Blue
        BYTE    000h,080h,000h,000h               ;Green
        BYTE    080h,080h,000h,000h               ;Cyan
        BYTE    000h,000h,080h,000h               ;Red
        BYTE    080h,000h,080h,000h               ;Magenta
        BYTE    000h,080h,080h,000h               ;Yellow
        BYTE    080h,080h,080h,000h               ;White

ifdef VGA

        BYTE    0CCh,0CCh,0CCh,000h               ;Light Gray
else
        BYTE    020h,020h,020h,000h               ;Black
endif
        BYTE    0FFh,000h,000h,000h               ;Blue
        BYTE    000h,0FFh,000h,000h               ;Green
        BYTE    0FFh,0FFh,000h,000h               ;Cyan
        BYTE    000h,000h,0FFh,000h               ;Red
        BYTE    0FFh,000h,0FFh,000h               ;Magenta
        BYTE    000h,0FFh,0FFh,000h               ;Yellow
        BYTE    0FFh,0FFh,0FFh,000h               ;White

SIZE_FIXED_COLOR_TABLE2 = $-fixed_color_table2

bmi2_fill_point    label   byte

        BYTE      0                            ; Should never be invalid
        BYTE      ite_cBitCount - ite_ulIdentifier
        BYTE      ite_ulCompression - ite_ulIdentifier
        BYTE      ite_cbImage - ite_ulIdentifier
        BYTE      ite_cxResolution - ite_ulIdentifier
        BYTE      ite_cyResolution - ite_ulIdentifier
        BYTE      ite_cclrUsed - ite_ulIdentifier
        BYTE      ite_cclrImportant - ite_ulIdentifier
        BYTE      ite_usUnits - ite_ulIdentifier
        BYTE      ite_usReserved - ite_ulIdentifier
        BYTE      ite_usRecording - ite_ulIdentifier
        BYTE      ite_usRendering - ite_ulIdentifier
        BYTE      ite_cSize1 - ite_ulIdentifier
        BYTE      ite_cSize2 - ite_ulIdentifier
        BYTE      ite_ulColorEncoding - ite_ulIdentifier
        BYTE      ite_ulIdentifier - ite_ulIdentifier

DEFAULT_VALUE      equ    000000000h

MAX_SCANLINES      equ    65535

store_with_seg_check    macro

                        stosb

                        endm

        .CODE
page
;/***************************************************************************
;*
;* FUNCTION NAME =  bmc_int_to_ext
;*
;* DESCRIPTION   = Bitmap conversion, internal format to external format
;*
;*                 This is the driving routine for bitmap conversions from our
;*                 internal formats to the external formats which we support.
;*
;*                 Registers Preserved:
;*                       SI,DI,BP,DS
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,FLAGS
;*
;* INPUT         = npbm:DWORD
;*                 pBuf:DWORD
;*                 iStart:DWORD
;*                 pbmi:DWORD
;*                 cyScans:DWORD
;*                 DummyParamater1:DWORD
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = # of scanlines translated
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

bmc_int_to_ext  PROC SYSCALL USES edi esi,      npbm:DWORD, pbmi:DWORD,
                                                pBuf:DWORD, cyScans:DWORD,
                                                iStart:DWORD, DummyParamater1:DWORD
                LOCAL   scans_copied:DWORD,
                        scanline_count:DWORD,
                        bitmap_width:DWORD,
                        bitmap_height:DWORD,
                        lp_bits:DWORD,
                        width_scan:DWORD,
                        next_scan:DWORD
                LOCAL   scans_per_seg:DWORD,
                        prev_offset:DWORD,
                        scan_byte_count:DWORD,
                        full_byte_proc:DWORD,
                        partial_byte_flags:DWORD,
                        partial_byte_proc:DWORD,
                        huge_scans_left:DWORD
                LOCAL   some_temp:DWORD,
                        buffer_adjust:DWORD,
                        temp_byte_count:DWORD,
                        rgb_size:DWORD,
                        scan_length:DWORD,
                        fbsd:BYTE

ifdef   FIREWALLS
        DebugMsg <bmc_int_to_ext CLIFFL bmc_ite.asm>

        mov     ebx,npbm

        ASSUME  ebx:PTR BITMAP

        cmp     [ebx].bm_sd.sd_usId,SURFACE_IDENT
        jne     bmc_not_a_bitmap
        test    [ebx].bm_sd.sd_fb,SD_DEVICE
        jz      bmc_its_a_Bitmap

bmc_not_a_bitmap:

        rip     text,<Bitmap Conversions - Surface is not a bitmap>

bmc_its_a_Bitmap:

endif

        cld
        xor     eax,eax
        mov     scans_copied,eax

;/*
;** Validate the parameters passed in.  We will only support the standard
;** formats.  We will not return bits in a device dependant format.  They
;** cannot give us bogus numbers for the start scan and count.
;*/

        ASSUME  ebx:NOTHING

        mov     ebx,PMERR_INV_SCAN_START ;The starting scan must be 0-65535
        cmp     iStart,MAX_SCANLINES
        jg      ite_log_error
        mov     ebx,PMERR_INV_LENGTH_OR_COUNT
        cmp     cyScans,MAX_SCANLINES
        jle     ite_numbers_ok

ite_log_error:

        xchg    eax,ebx

        save_error_code

        mov     eax,-1

ite_get_out:

        jmp     ite_exit

ite_inv_format:

        mov     ebx,PMERR_INV_INFO_TABLE
        jmp     ite_log_error

ite_numbers_ok:

        mov     ebx,pbmi                ;Validate bitmap info structure
        xor     ecx,ecx                 ; only check required fields
        call    check_bitmap_info
        jecxz   ite_inv_format

ifdef FIREWALLS

        cmp     eax,12                   ;We should always get back 0,4,8,12
        jbe     @F

ite_cbi_failed:

        rip     text,<check_bitmap_info returned an illegal value>
@@:
        test    al,1
        jnz     ite_cbi_failed
endif
        xchg    eax,ebx
        mov     esi,anpfnPreProc[ebx]            ;Save preprocessor's address
        xchg    eax,ebx

;/*
;** Copy the bitmap data as necessary to local frame storage
;*/

        mov     edi,npbm

        ASSUME  edi:PTR BITMAP

        mov     eax,[edi].bm_sd.sd_cx   ;Must set height and width before
        mov     bitmap_width,eax        ;  checking for a null bitmap
        mov     edx,[edi].bm_sd.sd_cy   ;Preserve AX and DX until height
        mov     bitmap_height,edx       ;and width are set below

        ASSUME  ebx:PTR BITMAPINFO

        cmp     [ebx].bmi_cbFix,SIZE BITMAPINFOHEADER
        jne     ite_new_header

        mov     [ebx].bmi_cx,ax

        mov     edx,cyScans                 ;             50297

        mov     [ebx].bmi_cy,dx
        mov     rgb_size,(SIZE RGB)
        jmp     ite_done_with_bmi

ite_new_header:                             ; fill in remaining fields

        push    esi                         ; save si

        ASSUME  ebx:PTR BITMAPINFO2

        assert  [ebx].bmi2_cbFix,LE,65535   ; cbFix must be valid by this point

        mov     esi,[ebx].bmi2_cbFix

        assert  esi,LE,64

        .errnz  (SIZE BITMAPINFOHEADER2)-64

        shr     esi,1

        assert  NC

        add     esi,OFFSET ok_cbFix
        movzx   esi,BYTE PTR [esi]

        assert  esi,NE,0                ; cbFix not invalid

        add     esi,OFFSET bmi2_fill_point
        movzx   esi,BYTE PTR [esi]
        add     esi,OFFSET ite_ulIdentifier
        jmp     esi

ite_ulIdentifier::

ite_ulColorEncoding::

ite_cSize2::

        mov     [ebx].bmi2_cSize2,DEFAULT_VALUE

ite_cSize1::

        mov     [ebx].bmi2_cSize1,DEFAULT_VALUE

ite_usRendering::

ite_usRecording::

ite_usReserved::

ite_usUnits::

        mov     [ebx].bmi2_usUnits,BRU_METRIC

ite_cclrImportant::

        movzx   ecx,[ebx].bmi2_cBitCount
        mov     esi,1
        shl     esi,cl                            ;24-bpp ==> SI = 0
        mov     [ebx].bmi2_cclrImportant,esi
        jmp     ite_already_computed_colors

ite_cclrUsed::

        movzx   ecx,[ebx].bmi2_cBitCount
        mov     esi,1
        shl     esi,cl                            ;24-bpp ==> SI = 0

ite_already_computed_colors:

        mov     [ebx].bmi2_cclrUsed,esi

ite_cyResolution::

        mov     [ebx].bmi2_cyResolution,DEFAULT_VALUE

ite_cxResolution::

        mov     [ebx].bmi2_cxResolution,DEFAULT_VALUE

ite_cbImage::

        mov     [ebx].bmi2_cbImage,DEFAULT_VALUE

ite_ulCompression::

ite_cBitCount::

        mov     [ebx].bmi2_cx,eax
        mov     [ebx].bmi2_cy,edx

        mov     rgb_size,(SIZE RGB2)
        pop     esi                           ; restore si

ite_done_with_bmi:

        mov     al,[edi].bm_sd.sd_fb          ;Color format, huge, CAN_CROSS_SEG
        mov     fbsd,al                       ;  (if we set it)
        mov     cl,al
        and     eax,SD_NONNULL                ;If a null surface, return
        jz      ite_get_out                   ;  0 scans copied.
        mov     eax,[edi].bm_sd.sd_pBits
        mov     lp_bits,eax
        mov     eax,[edi].bm_sd.sd_cbScan
        mov     width_scan,eax
        mov     ebx,[edi].bm_sd.sd_dScan
        mov     next_scan,ebx

ite_isnt_huge_bitmap:

;/*
;** We have gathered up most of the bitmap data necessary for doing
;** the conversion.  Compute the real starting scan Y and the number
;** of scanlines to copy.
;*/

        mov     ecx,iStart
        mov     ebx,bitmap_height
        cmp     ecx,ebx                 ;If starting scan is outside bitmap
        jb      @F                      ;  want count to become 0 so we'll
        mov     ecx,ebx                 ;  exit after color table is set
@@:     sub     ebx,ecx                 ;Compute number of scans to move
        mov     eax,cyScans

        usmin_ax   ebx

        mov     scanline_count,eax
        mov     scans_copied,eax                 ;We will return this value

;/*
;** Now perform the format specific initialization.
;*/

        mov     edi,pbmi

        ASSUME  edi:PTR BITMAPINFO2

        add     edi,[edi].bmi2_cbFix             ;ES:DI --> where color table is
        call    esi

;/*
;** If pBuf is NULL, it is an inquiry and we have retreived all the information.
;*/

        cmp     pBuf,0                  ;is it an inquiry?
        je      ite_xfered_all

        cmp     scanline_count,0
        je      ite_xfered_all

;/*
;**  Format specific initialization has been performed.  Compute
;**  the real starting scan Y and the number of scanlines to copy.
;**  If a huge bitmap and the scans to be copied are contained
;**  within the same segment, then we can treat it as a normal bitmap.
;*/

        mov     eax,bitmap_height                ;Invert the Y coordinate
        sub     eax,iStart
        dec     eax
        xor     edx,edx

ite_finish_y_calc:

        mul     next_scan                         ;Compute offset within the segment
        add     eax,lp_bits                       ;Compute segment of the bits
        xchg    eax,esi

        mov     edi,pBuf                          ;Dest is user's buffer (this pointer

;/*
;**  See if we will cross a segment boundary in the user's buffer.
;**  If so, special code will have to be used for copying any source
;**  scan which would cross the boundary.
;*/
        mov     ecx,scanline_count
        mov     eax,scan_length
        mul     ecx
        add     eax,edi


ite_in_segment:

        push    esi                               ;Save bitmap scan start address
        mov     ecx,scan_byte_count              ;Set translation procedure loop count
        jecxz   ite_see_about_partial            ;No full bytes!
        call    full_byte_proc                    ;Process all complete bytes

ite_see_about_partial:

        mov     ecx,partial_byte_flags           ;Process any partial byte
        jecxz   ite_no_partial_byte
        call    partial_byte_proc

ite_no_partial_byte:

        pop     esi
        dec     scanline_count
        jz      ite_xfered_all                    ;Transfered all scans

        sub     esi,next_scan                     ;--> next bitmap scanline
        add     edi,buffer_adjust                ;Align to dword boundary

        jmp     ite_in_segment          ; !!!! -CL-  !!!!!

;/*
;** compute and save the size of the bitmap extracted
;*/

ite_xfered_all:

        mov     ebx,pbmi                          ;calculate the number of bytes returned
        cmp     [ebx].bmi2_cbFix,OFFSET BITMAPINFO2.bmi2_cbImage
        jbe     ite_return_val
        movzx   eax,[ebx].bmi2_cBitCount
        mul     [ebx].bmi2_cx
        add     eax,31                   ;Don't forget 32 bit aligned
        shr     eax,3
        and     eax,not 3
        mul     scans_copied            ;multiply with the number of scans
        mov     [ebx].bmi2_cbImage,eax

ite_return_val:

        mov     eax,scans_copied                 ;Return number of scans copied
        xor     edx,edx

ite_exit:
OPTION EPILOGUE:EPILOGUEDEF

        fw_zero <ecx>

        RET

OPTION EPILOGUE:NONE
page
;/***************************************************************************
;*
;* PRIVATE ROUTINE ite_1
;*
;* DESCRIPTION   = Bitmap conversion, internal format to external 1 bit
;*
;*                 This routine is responsible for all preprocessing for converting
;*                 from our internal formats to external 1 bit format
;*
;*                 Registers Preserved:
;*                       BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,FLAGS
;*
;* INPUT         = ES:DI --> where color table would go
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ite_1::

        xor     eax,eax
        mov     buffer_adjust,eax                ;Everything will be dword aligned
        mov     partial_byte_flags,eax           ;Will never have a partial byte
        lea     eax,FLAT:copy_i1e1            ;Assume monochrome bitmap
        lea     ebx,FLAT:copy_i1e1_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      ite_1_have_proc                  ;  Yes

;/*
;**  yet another set of !'s !!!
;**  need to somehow build the color table translation data here
;**  when we decide how to throw out information when going 4 to 1
;*/

        lea     eax,copy_i4e1           ;Color bitmap
        lea     ebx,copy_i4e1_partial

ite_1_have_proc:

        mov     full_byte_proc,eax
        mov     partial_byte_proc,ebx

;/*
;** Whenever we allocated a scanline (or each scan of a color
;** bitmap), we allocated to a dword boundary.  If we just
;** translate for the width of the scan in bytes, the required
;** dword alignment will be maintained.
;*/

        mov     eax,width_scan                    ;Moving all bytes of the scan
        mov     scan_byte_count,eax
        mov     scan_length,eax                          ;Set # bytes of user buffer required
                                                  ;  for one bitmap scan
        mov     ecx,2                             ;Two color table entries
        call    create_mono_color_table
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE ite_4
;*
;* DESCRIPTION   = Bitmap conversion, internal format to external 4 bit
;*
;*                 This routine is responsible for all preprocessing for converting
;*                 from our internal formats to external 4 bit format
;*
;*                 Registers Preserved:
;*                       BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,FLAGS
;*
;* INPUT         = ES:DI --> where color table would go
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ite_4::

        xor     eax,eax
        mov     buffer_adjust,eax                ;Everything will be dword aligned
        mov     partial_byte_flags,eax           ;Will never have a partial byte
        mov     ecx,16                            ;There will be 16 color table entries
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jnz     ite_4_not_mono                    ;Not mono, must be color
        call    create_mono_color_table
        lea     eax,copy_i1e4
        lea     ebx,copy_i1e4_partial
        jmp     ite_4_have_proc

ite_4_not_mono:

        call    create_color_color_table
        lea     eax,copy_i4e4
        lea     ebx,copy_i4e4_partial

ite_4_have_proc:

        mov     full_byte_proc,eax
        mov     partial_byte_proc,ebx            ;Might need this for seg boundaries
        mov     eax,bitmap_width                 ;Compute the number of source bytes
        add     eax,7                             ;We can force dword alignment by
        shr     eax,3                             ;  always xlating a multiple of 8 bits
        mov     scan_byte_count,eax
        shl     eax,2                             ;1 source byte = 4 dest bytes
        mov     scan_length,eax                          ;Set # bytes of user buffer required
        ret                                       ;  for one bitmap scan
page

;/***************************************************************************
;*
;* PRIVATE ROUTINE ite_8
;*
;* DESCRIPTION   = Bitmap conversion, internal format to external 8 bit
;*
;*                 This routine is responsible for all preprocessing for converting
;*                 from our internal formats to external 8 bit format
;*
;*                 Registers Preserved:
;*                       BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,FLAGS
;*
;* INPUT         = ES:DI --> where color table would go
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ite_8::

        xor     eax,eax                           ;Will not require any buffer adjustment
        mov     buffer_adjust,eax
        mov     ecx,256                           ;There will be 256 color table entries
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jnz     ite_8_not_mono                    ;Not mono, must be color
        call    create_mono_color_table
        lea     eax,copy_i1e8
        lea     ebx,copy_i1e8_partial
        jmp     ite_8_have_proc

ite_8_not_mono:

        call    create_color_color_table
        lea     eax,copy_i4e8
        lea     ebx,copy_i4e8_partial

ite_8_have_proc:

        mov     full_byte_proc,eax
        mov     partial_byte_proc,ebx
        mov     eax,bitmap_width                 ;Compute the number of source bytes
        add     eax,3                             ;  to convert. Each nibble becomes
        mov     ebx,eax                           ;  a double word in the destination
        shr     eax,3
        mov     scan_byte_count,eax
        and     bl,11111100b                      ;1 source nibble = 4 dest bytes
        mov     scan_length,ebx                          ;Set # bytes of user buffer required
        and     ebx,4                             ;Will either have a partial nibble or
        mov     partial_byte_flags,ebx           ;  no extra nibble to xlate
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE ite_24
;*
;* DESCRIPTION   = Bitmap conversion, internal format to external 24 bit RGB
;*
;*                 This routine is responsible for all preprocessing for converting
;*                 from our internal formats to external 24 bit RGB format
;*
;*                 Registers Preserved:
;*                       BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,SI,DI,FLAGS
;*
;* INPUT         = ES:DI --> where color table would go
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ite_24::

        lea     eax,copy_i1e24
        lea     ebx,copy_i1e24_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      ite_24_have_proc                 ;  Yes

ite_24_not_mono:

        lea     eax,copy_i4e24
        lea     ebx,copy_i4e24_partial

ite_24_have_proc:

        mov     full_byte_proc,eax
        mov     partial_byte_proc,ebx
        mov     ecx,3
        mov     eax,bitmap_width                 ;Compute the number of source bytes
        mov     ebx,eax                           ;  to convert. Each bit becomes
        shr     eax,cl                            ;  three bytes in the destination
        mov     scan_byte_count,eax
        mov     eax,ebx                           ;1 source bit = 3 dest bytes
        mul     ecx
        add     eax,ecx                           ;Need to round up to a double word
        and     al,11111100b
        mov     scan_length,eax                          ;Set # bytes of user buffer required
        and     ebx,00000111b                     ;Can have up to 7 bits in the last
        mov     partial_byte_flags,ebx           ;  byte to convert
        and     bl,00000011b                      ;Compute number of bytes to pad with
        mov     buffer_adjust,ebx
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE create_mono_color_table
;*
;* DESCRIPTION   = The color table for monochrome source bitmaps is created.  The
;*                 table will consists of all black except for the last entry which
;*                 will be white.
;*
;*
;*                 Registers Preserved:
;*                       SI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,DI,FLAGS
;*
;* INPUT         = ES:DI --> where color table would go
;*                 CX    =   total number of color table entries to generate
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

create_mono_color_table:

        dec     ecx
        mov     eax,rgb_size
        mul     ecx
        mov     ecx,eax
        xor     eax,eax
        shr     ecx,1
        rep     stosw
        rcl     ecx,1
        rep     stosb
        dec     eax
        stosw
        stosb
        cmp     rgb_size,(size RGB)
        je      cmct_end

        .errnz  (size RGB)-3

        .errnz  (size RGB2)-4

        inc     eax
        stosb

cmct_end:

        ret
page
;/***************************************************************************
;*
;* PRIVATE ROUTINE create_color_color_table
;*
;* DESCRIPTION   = The color table for color source bitmaps is created.  The table
;*                 will consists of the 16 fixed colors for the driver.  The remaining
;*                 entries will be set to black, even though we will never generate
;*                 those indicies.
;*
;*                 Registers Preserved:
;*                       SI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,BX,CX,DX,DI,FLAGS
;*
;* INPUT         = ES:DI --> where color table would go
;*                 CX    =   total number of color table entries to generate
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

create_color_color_table:

        mov     ebx,ecx                           ;Save total table count
        xchg    eax,esi                           ;Don't destroy si

        cmp     rgb_size,(SIZE RGB)
        jne     ccct_new_rgb
        lea     esi,fixed_color_table
        mov     ecx,(SIZE_FIXED_COLOR_TABLE) shr 2

        .errnz  (SIZE_FIXED_COLOR_TABLE) AND 3

        rep     movsd

        jmp     ccct_done_with_fixed_table

ccct_new_rgb:

        assert  rgb_size,E,4

        .errnz  (SIZE RGB2)-4

        lea     esi,fixed_color_table2
        mov     ecx,(SIZE_FIXED_COLOR_TABLE2) shr 2

        .errnz  (SIZE_FIXED_COLOR_TABLE2) AND 3

        rep     movsd

ccct_done_with_fixed_table:

        xchg    eax,esi                           ;Restore caller's SI
        sub     ebx,16                  ;number of fixed colors
        jle     ccct_exit                         ;All done
        mov     ecx,ebx
        mov     eax,rgb_size
        mul     ecx
        mov     ecx,eax
        xor     eax,eax                           ;Fill rest of table with black
        shr     ecx,1
        rep     stosw
        rcl     ecx,1
        rep     stosb

ccct_exit:

        ret
page

xlate_1_to_4    label   word

        dw      0000000000000000b                ;0000b
        dw      0000000000001111b                ;0001b
        dw      0000000011110000b                ;0010b
        dw      0000000011111111b                ;0011b
        dw      0000111100000000b                ;0100b
        dw      0000111100001111b                ;0101b
        dw      0000111111110000b                ;0110b
        dw      0000111111111111b                ;0111b
        dw      1111000000000000b                ;1000b
        dw      1111000000001111b                ;1001b
        dw      1111000011110000b                ;1010b
        dw      1111000011111111b                ;1011b
        dw      1111111100000000b                ;1100b
        dw      1111111100001111b                ;1101b
        dw      1111111111110000b                ;1110b
        dw      1111111111111111b                ;1111b

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e1
;*
;* DESCRIPTION   = The given number of bytes are copied from source to destination.
;*                                                                                   g
;*                 It is the caller's responsibility to handle all segment crossings.
;*
;*                 This routine is used for:
;*                     internal mono to external mono
;*                     external mono to internal mono
;*
;*                 Registers Preserved:
;*                       DX,BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to copy
;*                 Direction flag cleared
;* OUTPUT        = ES:DI --> next destination byte
;*                 Direction flag cleared
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

_TUNE segment USE32 PUBLIC 'CODE'
PUBLIC copy_i1e1

copy_i1e1::

        xchg    eax,ecx                           ;Save count of bytes to mov in AX
        xor     ecx,ecx
        ror     esi,1                             ;Set 'C' if source on odd boundary
        rcl     ecx,1                             ;CX = 1 if on odd boundary
        sub     eax,ecx
        rol     esi,1                             ;Restore initial source address
        rep     movsb                             ;Move possible odd aligned byte
        xchg    eax,ecx                           ;Move complete words
        shr     ecx,1
        rep     movsw
        rcl     ecx,1                             ;Process trailing odd byte
        rep     movsb
        ret
_TUNE ENDS
page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e4
;*
;* DESCRIPTION   = copy internal 1 bit to external 4 bit packed pixel
;*
;*                 The destination is filled with the source data, with each source
;*                 bit expanded to a nibble in the destination.
;*
;*                 It is the caller's responsibility to handle all segment crossings,
;*                 and to ensure that there are enough bytes of destination available
;*                 to hold the data.
;*
;*                 This routine is used for:
;*                     internal mono to external four-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i1e4:

        mov     edx,00011110b                     ;Mask for bits to convert

ci1e4_next_byte:

        lodsb
        mov     ebx,eax
        shr     bl,3
        and     ebx,edx
        mov     bx,WORD PTR xlate_1_to_4[ebx]
        xchg    eax,ebx
        xchg    ah,al
        stosw
        shl     ebx,1
        and     ebx,edx
        mov     ax,WORD PTR xlate_1_to_4[ebx]
        xchg    ah,al
        stosw
        loop    ci1e4_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e4_partial
;*
;* DESCRIPTION   =
;*
;*            copy internal 1 bit to external 4 bit packed pixel, partial byte
;*
;*            The destination is filled with the source data, with each source
;*            bit expanded to a nibble in the destination.  This routine handles
;*            partial bytes where some portion of the first or last byte needs
;*            to be saved.
;*
;*            This routine will handle the destination (user's buffer) crossing
;*            a segment boundary during the translation of the source byte.
;*            The source will never cross a segment boundary since it is an
;*            internal bitmap and all scans are allocated to fit within a
;*            segment.
;*
;*            Since this routine always writes nibbles, it is guaranteed that
;*            the shift count passed in is even.
;*
;*            This routine shouldn't be called very often, so a short loop will
;*            be sufficient for our needs.
;*
;*            This routine is used for:
;*                internal mono to external four-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i1e4_partial:

        lea     ebx,xlate_1_to_4 + 1
        lodsb
        mov     ah,al
        shr     ecx,1                             ;/2 for number of iterations
        movzx   ecx,cl

ci1e4p_next_byte:

        rol     ax,2
        and     al,00000011b
        shl     ax,1                              ;Fetching bytes from a word table
        xlat

        store_with_seg_check

        loop    ci1e4p_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e8
;*
;* DESCRIPTION   = copy internal 1 bit to external 8 bit packed pixel
;*
;*                 The destination is filled with the source data, with each source
;*                 bit expanded to a byte in the destination.
;*
;*                 It is the caller's responsibility to handle all segment crossings,
;*                 and to ensure that there are eight bytes of destination available
;*                 to hold each byte of source data.
;*
;*                 This routine is used for:
;*                     internal mono to external eight-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i1e8:

ci1e8_next_byte:

        lodsb
        xchg    eax,ebx
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        loop    ci1e8_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e8_partial
;*
;* DESCRIPTION   =
;*
;*            copy internal 1 bit to external 8 bit packed pixel, partial byte
;*
;*            The destination is filled with the source data, with each source
;*            bit expanded to a byte in the destination.   This routine handles
;*            partial bytes where some portion of the first or last byte needs
;*            to be saved.
;*
;*            This routine will handle the destination (user's buffer) crossing
;*            a segment boundary during the translation of the source byte.
;*            The source will never cross a segment boundary since it is an
;*            internal bitmap and all scans are allocated to fit within a
;*            segment.
;*
;*            This routine shouldn't be called very often, so a short loop will
;*            be sufficient for our needs.
;*
;*            This routine is used for:
;*                internal mono to external eight-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i1e8_partial:

        lodsb
        xchg    eax,ebx
        movzx   ecx,cl

ci1e8p_next_byte:

        shl     bl,1
        sbb     al,al

        store_with_seg_check

        loop    ci1e8p_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e24
;*
;* DESCRIPTION   = copy internal 1 bit to external 24 bit RGB
;*
;*                 The destination is filled with the source data, with each source
;*                 bit expanded to a full RGB triplet in the destination.  The colors
;*                 being translated are black and white, so no color lookup is required
;*
;*                 It is the caller's responsibility to handle all segment crossings,
;*                 and to ensure that there are 24 bytes of destination available to
;*                 hold each source byte of data.
;*
;*                 This routine is used for:
;*                     internal mono to external RGB (24-bit packed pixels)
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i1e24:

ci1e24_next_byte:

        lodsb
        xchg    ax,bx
        shl     bl,1
        sbb     ax,ax
        stosw
        shl     bl,1
        sbb     ah,ah
        stosw
        mov     al,ah
        stosw
        shl     bl,1
        sbb     ax,ax
        stosw
        shl     bl,1
        sbb     ah,ah
        stosw
        mov     al,ah
        stosw
        shl     bl,1
        sbb     ax,ax
        stosw
        shl     bl,1
        sbb     ah,ah
        stosw
        mov     al,ah
        stosw
        shl     bl,1
        sbb     ax,ax
        stosw
        shl     bl,1
        sbb     ah,ah
        stosw
        mov     al,ah
        stosw
        loop    ci1e24_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e24_partial
;*
;* DESCRIPTION   =
;*
;*            copy internal 1 bit to external 24 bit RGB, partial byte
;*
;*            The destination is filled with the source data, with each source
;*            bit expanded to a full RGB triplet in the destination.  The colors
;*            being translated are black and white, so no color lookup is required.
;*
;*            This routine handles partial bytes where some portion of the first
;*            or last byte needs to be saved.
;*
;*            This routine will handle the destination (user's buffer) crossing
;*            a segment boundary during the translation of the source byte.
;*            The source will never cross a segment boundary since it is an
;*            internal bitmap and all scans are allocated to fit within a
;*            segment.
;*
;*            This routine shouldn't be called very often, so a short loop will
;*            be sufficient for our needs.
;*
;*            This routine is used for:
;*                internal mono to external RGB (24-bit packed pixels)
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i1e24_partial:

        lodsb
        xchg    ax,dx
        movzx   ecx,cl

ci1e24p_next_byte:

        shl     dl,1
        sbb     ax,ax
        stosw
        stosb

ci1e24p_loop_next:

        loop    ci1e24p_next_byte

ci1e24p_no_more_sels:

        ret

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i1e1_partial
;*
;* DESCRIPTION   = A Byte is copied from the source to destination.
;*
;*                 This routine will handle the destination (user's buffer) crossing
;*                 a segment boundary during the translation of the source byte.
;*                 The source will never cross a segment boundary since it is an
;*                 internal bitmap and all scans are allocated to fit within a
;*                 segment.
;*
;*                 Registers Preserved:
;*                       DX,BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CL     =  number of pixels to translate (Will always be 8)
;*                 Direction flag cleared
;* OUTPUT        = ES:DI --> next destination byte
;*                 Direction flag cleared
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i1e1_partial:

        lodsb

        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e1
;*
;* DESCRIPTION   =
;*
;*         copy internal 4 plane to external 1 bit
;*
;*         The destination is filled with the source data.  All four planes
;*         of the source byte are combined to form the single destination byte.
;*
;*         It is the caller's responsibility to handle all segment crossings,
;*         and to ensure that there are enough bytes of destination available
;*         to hold the data.
;*
;*         Since there will be information loss in going from four color to
;*         one color, all colors which match the  background color
;*         will be mapped to 1, and all other colors will be mapped to the
;*         forground color.  This is the same strategy used in color
;*         to mono bitblts.
;*
;*         This routine is used for:
;*             internal four-plane to external mono
;*
;*                 Registers Preserved:
;*                       DX,BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CL     =  number of pixels to translate (Will always be 8)
;*                 Direction flag cleared
;* OUTPUT        = ES:DI --> next destination byte
;*                 Direction flag cleared
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e1:


        mov     ebx,width_scan

ci4e1_next_byte:

        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ah,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        lodsb                                     ;Get C0 color, update source pointer
        and     eax,edx                           ;just favor black
        and     al,ah
        stosb
        loop    ci4e1_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e1_partial
;*
;* DESCRIPTION   =
;*
;*         copy internal 4 plane to external 1 bit, partial byte
;*
;*         The destination is filled with the source data.  All four planes
;*         of the source byte are combined to form the single destination byte.
;*
;*         This routine will handle the destination (user's buffer) crossing
;*         a segment boundary during the translation of the source byte.
;*         The source will never cross a segment boundary since it is an
;*         internal bitmap and all scans are allocated to fit within a
;*         segment.
;*
;*         Since there will be information loss in going from four color to
;*         one color, all colors which match the !!!??? background color
;*         will be mapped to 1, and all other colors will be mapped to the
;*         !!!??? forground color.  This is the same strategy used in color
;*         to mono bitblts.
;*
;*         This routine is used for:
;*             internal four-plane to external mono
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of pixels to translate (Will always be 8)
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e1_partial:


        mov     ebx,width_scan
        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ah,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        lodsb                                     ;Get C0 color, update source pointer
        and     eax,edx                           ;!!!For now, just favor black
        and     al,ah

        store_with_seg_check

        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e4
;*
;* DESCRIPTION   =
;*
;*         copy internal 4 plane to external 4 bit packed pixel
;*
;*         The destination is filled with the source data.  All four planes
;*         of the source byte are used to form the nibble for the destination
;*         byte.
;*
;*         It is the caller's responsibility to handle all segment crossings,
;*         and to ensure that there are enough bytes of destination available
;*         to hold the data.
;*
;*         Since there will be information loss in going from four color to
;*         one color, all colors which match the !!!??? background color
;*         will be mapped to 1, and all other colors will be mapped to the
;*         !!!??? forground color.  This is the same strategy used in color
;*         to mono bitblts.
;*
;*         This routine is used for:
;*             internal four-plane to external 4-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of bytes to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e4:



        mov     ebx,width_scan
        push    ebp
        mov     ebp,ecx                           ;Use BP for loop counter

ci4e4_next_byte:

        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ch,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        mov     cl,BYTE PTR [esi]                 ;Get C0 color, update source pointer
        inc     esi

        mov     ah,4                              ;Set # bytes to write

ci4e4_next_dest_byte:

        shl     dh,1                              ;Collect 1st nibble
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1
        shl     dh,1                              ;Collect 2nd nibble
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1
        stosb
        dec     ah
        jnz     ci4e4_next_dest_byte
        dec     ebp
        jnz     ci4e4_next_byte
        pop     ebp

        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e4_partial
;*
;* DESCRIPTION   =
;*
;*          copy internal 4 plane to external 4 bit packed pixel, partial byte
;*
;*          The destination is filled with the source data.  All four planes
;*          of the source byte are used to form the nibble for the destination
;*          byte.
;*
;*          This routine handles partial bytes where some portion of the first
;*          or last byte needs to be saved.
;*
;*          This routine will handle the destination (user's buffer) crossing
;*          a segment boundary during the translation of the source byte.
;*          The source will never cross a segment boundary since it is an
;*          internal bitmap and all scans are allocated to fit within a
;*          segment.
;*
;*          Since this routine always writes nibbles, it is guaranteed that
;*          the shift count passed in is even.
;*
;*          This routine is used for:
;*              internal four-plane to external 4-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 BX     =  index to next plane
;*                 CL     =  number of pixels to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e4_partial:



        mov     ebx,width_scan
        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ah,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        lodsb                                     ;Get C0 color, update source pointer
        xchg    eax,ecx
        mov     ah,al
        shr     ah,1                              ;/2 for correct number of iterations

ci4e4p_next_byte:

        shl     dh,1                              ;Collect 1st nibble
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1
        shl     dh,1                              ;Collect 2nd nibble
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1

        store_with_seg_check

        dec     ah
        jnz     ci4e4p_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e8
;*
;* DESCRIPTION   =
;*
;*          copy internal 4 plane to external 8 bit packed pixel
;*
;*          The destination is filled with the source data.  All four planes
;*          of the source byte are used to form the byte for the destination.
;*
;*          It is the caller's responsibility to handle all segment crossings,
;*          and to ensure that there are enough bytes of destination available
;*          to hold the data.
;*
;*          Since there will be information loss in going from four color to
;*          one color, all colors which match the !!!??? background color
;*          will be mapped to 1, and all other colors will be mapped to the
;*          !!!??? forground color.  This is the same strategy used in color
;*          to mono bitblts.
;*
;*          This routine is used for:
;*              internal four-plane to external 8-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS,BP
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of pixels to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e8:



        mov     ebx,width_scan
        push    ebp
        mov     ebp,ecx                           ;Use BP for loop counter

ci4e8_next_byte:

        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ch,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        mov     cl,BYTE PTR [esi]                 ;Get C0 color, update source pointer
        inc     esi
        mov     ah,08h                            ;There will be 8 bytes of destination

ci4e8_next_dest_byte:

        xor     al,al                             ;Collect and store a nibble
        shl     dh,1
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1
        stosb
        dec     ah
        jnz     ci4e8_next_dest_byte
        dec     ebp
        jnz     ci4e8_next_byte
        pop     ebp
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e8_partial
;*
;* DESCRIPTION   =
;*
;*          copy internal 4 plane to external 8 bit packed pixel, partial byte
;*
;*          The destination is filled with the source data.  All four planes
;*          of the source byte are used to form the byte for the destination.
;*
;*          This routine handles partial bytes where some portion of the first
;*          or last byte needs to be saved.
;*
;*          This routine will handle the destination (user's buffer) crossing
;*          a segment boundary during the translation of the source byte.
;*          The source will never cross a segment boundary since it is an
;*          internal bitmap and all scans are allocated to fit within a
;*          segment.
;*
;*          This routine is used for:
;*              internal four-plane to external 8-bit packed pixels
;*
;*                 Registers Preserved:
;*                       BP,ES,DS
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CL     =  number of pixels to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e8_partial:



        mov     ebx,width_scan
        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ah,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        lodsb                                     ;Get C0 color, update source pointer
        xchg    eax,ecx
        mov     ah,al

ci4e8p_next_byte:

        xor     al,al                             ;Collect and store a nibble
        shl     dh,1
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1

        store_with_seg_check

        dec     ah
        jnz     ci4e8p_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e24
;*
;* DESCRIPTION   =
;*
;*          copy internal 4 plane to external 24 bit RGB
;*
;*          The destination is filled with the source data.  All four planes
;*          of the source byte are used to form the RGB triplet for the
;*          destination.
;*
;*          It is the caller's responsibility to handle all segment crossings,
;*          and to ensure that there are enough bytes of destination available
;*          to hold the data.
;*
;*          Since there will be information loss in going from four color to
;*          one color, all colors which match the !!!??? background color
;*          will be mapped to 1, and all other colors will be mapped to the
;*          !!!??? forground color.  This is the same strategy used in color
;*          to mono bitblts.
;*
;*          This routine is used for:
;*              internal four-plane to external RGB (24-bit packed)
;*
;*                 Registers Preserved:
;*                       BP,ES,DS
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CX     =  number of pixels to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*                 DS:SI --> next source byte
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e24:



        mov     temp_byte_count,ecx              ;Save # bytes to xlate

ci4e24_next_byte:

        mov     ebx,width_scan
        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ch,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        mov     cl,BYTE PTR [esi]                 ;Get C0 color, update source pointer
        inc     esi
        xchg    esi,ebx
        mov     ah,08h                            ;There will be 8 triplets stored

ci4e24_next_dest_byte:

        xor     esi,esi                           ;Collect and store a triplet
        shl     dh,1
        rcl     si,1
        shl     dl,1
        rcl     si,1
        shl     ch,1
        rcl     si,1
        shl     cl,1
        rcl     si,1
        shl     si,2                              ;Indexing into dwords

        mov     al,temp_color_table[esi][2]
        mov     si,WORD PTR temp_color_table[esi][0]

        xchg    eax,esi
        stosw
        xchg    eax,esi
        stosb
        dec     ah
        jnz     ci4e24_next_dest_byte
        xchg    esi,ebx
        dec     temp_byte_count
        jnz     ci4e24_next_byte
        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_i4e24_partial
;*
;* DESCRIPTION   =
;*
;*          copy internal 4 plane to external 24 bit RGB, partial byte
;*
;*          The destination is filled with the source data.  All four planes
;*          of the source byte are used to form the RGB triplet for the
;*          destination.
;*
;*          This routine handles partial bytes where some portion of the first
;*          or last byte needs to be saved.
;*
;*          This routine will handle the destination (user's buffer) crossing
;*          a segment boundary during the translation of the source byte.
;*          The source will never cross a segment boundary since it is an
;*          internal bitmap and all scans are allocated to fit within a
;*          segment.
;*
;*          This routine is used for:
;*              internal four-plane to external RGB (24-bit packed)
;*
;*                 Registers Preserved:
;*                       BP,ES,DS
;*                 Registers Destroyed:
;*                       AX,BX,DX,SI,FLAGS
;*
;* INPUT         = DS:SI --> source
;*                 ES:DI --> destination
;*                 CL     =  number of pixels to xlate
;* OUTPUT        = ES:DI --> next destination byte
;*                 DS:SI --> next source byte
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;**************************************************************************/

copy_i4e24_partial:




        mov     ebx,width_scan
        add     esi,ebx
        shl     ebx,1
        mov     dh,BYTE PTR [esi][ebx]            ;Get C3 color
        shr     ebx,1
        mov     dl,BYTE PTR [esi][ebx]            ;Get C2 color
        mov     ah,BYTE PTR [esi]                 ;Get C1 color
        sub     esi,ebx
        lodsb                                     ;Get C0 color, update source pointer
        xchg    eax,ecx
        mov     ah,al                             ;Set number of pixels to xlate
        xchg    esi,ebx

ci4e24p_next_byte:

        xor     esi,esi                           ;Collect and store a triplet
        shl     dh,1
        rcl     si,1
        shl     dl,1
        rcl     si,1
        shl     ch,1
        rcl     si,1
        shl     cl,1
        rcl     si,1
        shl     si,2                              ;Indexing into dwords

        mov     al,temp_color_table[esi][2]
        mov     si,WORD PTR temp_color_table[esi][0]

        xchg    eax,esi
        stosw
        xchg    eax,esi
        stosb

ci4e24p_loop_next:

        dec     ah
        jnz     ci4e24p_next_byte

ci4e24p_no_more_sels:

        xchg    esi,ebx
        ret

ci4e24p_next_sel:

        xchg    ax,si
        xchg    al,ah
        xchg    al,ah
        xchg    ax,si
        jmp     ci4e24p_loop_next

        DebugMsg <LEAVING bmc_int_to_ext CLIFFL bmc_ite.asm>
bmc_int_to_ext  ENDP

end
