;*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 NOSCOPED
OPTION EPILOGUE:NONE
;/*****************************************************************************
;*
;* SOURCE FILE NAME = BMC_ETI.ASM
;*
;* DESCRIPTIVE NAME = Handles bitmap conversions
;*
;*
;* VERSION      V2.0
;*
;* DATE         05/16/87
;*
;* DESCRIPTION  Handles bitmap conversions, from external
;*              formats to internal formats                           
;*              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_ext_to_int  
;*
;* 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/12/87                     Walt Moore [waltm] Created.
;*   11/09/87                     Bob Grudem [bobgru] Internal color bitmaps
;*                                always use interleaved (i.e. huge)
;*      scanline format.
;*   12/08/92              53733  Mono bitmap color non inversion
;*
;*****************************************************************************/

        .386

        .xlist

INCL_DOSMVDM            equ     1
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 display.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

EXTERNDEF       copy_i1e1       :DWORD  ; Defined in BMC_ITE.ASM
EXTERN   DOS32FLATTOSEL:NEAR

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

anpfnPreProc    label   DWORD

        DWORD   eti_1
        DWORD   eti_4
        DWORD   eti_8
        DWORD   eti_24

;/*
;** Excerpt from VVD.H
;*/

DDFORMAT_4PLANE         equ 1                            ;display driver formats supported

VVDSYSREQ_COPYBITMAP    equ 8

MAX_SCANLINES           equ 65535
    
VVRECT              struct

 vvr_ulDDFormat     DWORD                        ?  ;display driver format
 vvr_cx             DWORD                        ?  ;width of DD bitmap buffer
 vvr_cy             DWORD                        ?  ;height of DD bitmap buffer
 vvr_rcl            RECTL       <>               ;rectangle requested
 vvr_pbColorXlate   DWORD                        ?  ;display driver color translation table

VVRECT              ends

;/*
;** End of excerpt from VVD.H
;*/


load_with_seg_check macro

                    lodsb

                    endm
        .CODE

page

;/***************************************************************************
;*
;* FUNCTION NAME = bmc_ext_to_int 
;*
;* DESCRIPTION   = Bitmap conversion, external format to internal 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,
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DX:AX = # of scanlines translated 
;* RETURN-ERROR  = DX:AX = -1  
;*
;**************************************************************************/

        ALIGN   4

bmc_ext_to_int  PROC SYSCALL USES esi edi,      npbm:DWORD, pbmi:DWORD,
                                                pBuf:DWORD, cyScans:DWORD,
                                                iStart:DWORD, pdc:DWORD

                LOCAL   scans_copied:DWORD,          
                        scanline_count:DWORD,     
                        bitmap_width:DWORD,       
                        bitmap_height:DWORD,      
                        lp_bits:DWORD,            
                        width_scan:DWORD          
                LOCAL   next_scan:DWORD,          
                        scans_per_seg:DWORD,      
                        prev_offset:DWORD,        
                        scan_byte_count:DWORD,   
                        full_byte_proc:DWORD      
                LOCAL   partial_byte_flags:DWORD, 
                        partial_byte_proc:DWORD, 
                        huge_scans_left:DWORD,   
                        some_temp:DWORD,
                        buffer_adjust:DWORD,      
                        temp_byte_count:DWORD,   
                        convert_C0:DWORD,         
                        convert_C1:DWORD,         
                        convert_C2:DWORD          
                LOCAL   convert_C3:DWORD,         
                        alignment:DWORD,          
                        scan_length:DWORD,        
                        temp_bit_count:DWORD,     
                        rgb_size:DWORD,              
                        fbsd:BYTE,                 
                        color_xlate[256]:BYTE,   
                        vvddrcl:VVRECT

ifdef   FIREWALLS

        DebugMsg <bmc_ext_to_int CLIFFL bmc_eti.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.
;*/

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

eti_log_error:

        xchg    eax,ebx

        save_error_code

        mov     eax,-1

eti_get_out:

        jmp     eti_exit

        ALIGN   4

eti_xfered_all_relay:

        jmp     eti_xfered_all

        ALIGN   4

eti_numbers_ok:

        or      eax,cyScans
        jz      eti_xfered_all_relay
        mov     ebx,pbmi                          ;Validate bitmap info structure
        mov     ecx,1                             ; signal maximum check
        call    check_bitmap_info
        mov     ebx,PMERR_INV_INFO_TABLE
        jecxz   eti_log_error

ifdef FIREWALLS

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

eti_cbi_failed:

        rip     text,<check_bitmap_info returned an illegal value>
@@:
        test    al,1
        jnz     eti_cbi_failed

endif
        xchg    eax,ebx
        mov     esi,anpfnPreProc[ebx]            ;Save preprocessor's address

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

        mov     edi,npbm

        ASSUME  edi:PTR BITMAP

        mov     eax,[edi].bm_sd.sd_cx
        mov     bitmap_width,eax
        mov     eax,[edi].bm_sd.sd_cy
        mov     bitmap_height,eax
        mov     al,[edi].bm_sd.sd_fb             ;Color format, huge, CAN_CROSS_SEG
        mov     fbsd,al                           ;  (if we set it)
        mov     cl,al
        and     ax,SD_NONNULL                     ;If a null surface, return
        jz      eti_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
        test    cl,SD_HUGE
        jz      eti_isnt_huge_bitmap

;/*
;** The bitmap is a huge bitmap.
;*/

eti_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
        sub     ebx,ecx                           ;If starting scan is outside bitmap
        jbe     eti_xfered_all_relay              ; surface, then nothing to copy
                                                  ;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

        mov     eax,[edi].bmi2_cbFix             ;ES:DI --> where color table is
        mov     rgb_size,(SIZE RGB)
        cmp     eax,SIZE BITMAPINFOHEADER
        je      eti_got_rgb_size

ifdef FIREWALLS

        mov     ebx,[edi].bmi2_cbFix

        assert  ebx,LE,64

        .errnz  (SIZE BITMAPINFOHEADER2)-64

        shr     bl,1

        assert  NC

        add     ebx,OFFSET ok_cbFix
        mov     bl,BYTE PTR [ebx]

        assert  bl,NE,0

endif

        mov     rgb_size,(SIZE RGB2)

eti_got_rgb_size:

        add     edi,eax
        call    esi

;/*
;** 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

;/*
;** Before we start computing buffer offsets now, let's see if this
;** request is for a VDD (in which case we let the VDD supply the bits
;** for us).
;*/

        sub     edx,edx

        cmp     WORD PTR pBuf[2],0   

;/*
;** The old 16 bit code checked here for a 0 selector.
;** That means that it's a request to let the vdd supply the
;** bits, and to use the low word as a screen group ID.
;**           
;*/

        jne     eti_not_vdd                       ;Normal SetBitmapBits call

        DebugMsg2 <pBuf == 0 DosRequestVDD in bmc_ext_to_int!!! >
        mov     vvddrcl.vvr_ulDDFormat,DDFORMAT_4PLANE
        mov     ecx,bitmap_height
        mov     vvddrcl.vvr_cy,ecx
        mov     ecx,bitmap_width
        mov     vvddrcl.vvr_cx,ecx

        mov     vvddrcl.vvr_rcl.rcl_xLeft,edx
        mov     edx,ecx                           ;DX == width
        dec     edx
        mov     vvddrcl.vvr_rcl.rcl_xRight,edx
        mov     edx,eax
        mov     vvddrcl.vvr_rcl.rcl_yBottom,edx
        sub     edx,cyScans
        inc     edx
        mov     vvddrcl.vvr_rcl.rcl_yTop,edx

        lea     eax,color_xlate
        mov     vvddrcl.vvr_pbColorXlate,eax

        mov     edx,vvddrcl.vvr_cy
        mov     eax,vvddrcl.vvr_cx
        mul     edx

;/*
;** 4 bits/pel / 8 bits/byte = 1/2 bytes/pel
;*/

if BITS_PEL EQ 4
        .ERRNZ  BITS_PEL-4
        shr     eax,1   ; divide by 2
        mov     edx,eax
elseif BITS_PEL EQ 8
        .ERRNZ  BITS_PEL-8

;/*
;** No divide necessary
;*/

else
        .ERR
endif


        INVOKE  DosRequestVDD, 
                hVideoVDD,              ; HVDD
                pBuf,                   ; was pBuf= SGID
                VVDSYSREQ_COPYBITMAP,   ; ULONG
                SIZE VVRECT,            ; ULONG
                ADDR vvddrcl,           ; PVOID
                edx,                    ; ULONG (size)
                lp_bits                 ; PVOID

        or      eax,eax                           ;any error?
        jnz     eti_vdd_error                     ;yes
        jmp     eti_xfered_all

        ALIGN   4

eti_vdd_error:

        DebugMsg2 <DosRequestVDD Returned Error>
        sub     eax,eax
        jmp     eti_exit                          ;propagate error back to Shield

        ALIGN   4


eti_not_vdd:

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

        mov     esi,pBuf                          ;Source is user's buffer (this pointer

eti_next_scan:

eti_in_segment:

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

eti_see_about_partial:

        mov     ecx,partial_byte_flags           ;Process any partial byte
        jecxz   eti_no_partial_byte
        mov     ebx,alignment
        call    partial_byte_proc

eti_no_partial_byte:

        pop     edi
        dec     scanline_count
        jz      eti_xfered_all                    ;Transfered all scans

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

        jmp     eti_next_scan

        ALIGN   4

eti_xfered_all:

        mov     eax,scans_copied                 ;Return number of scans copied

eti_exit:
OPTION EPILOGUE:EPILOGUEDEF
        
        fw_zero <ecx>

        RET
page

OPTION EPILOGUE:NONE

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

        ALIGN   4

eti_1::

        xor     eax,eax
        mov     buffer_adjust,eax                ;Everything will be dword aligned
        mov     partial_byte_flags,eax           ;Will never have a partial byte

        mov     ax,WORD PTR [edi][0]             ;Convert color for all 0 pixels
        mov     dl,BYTE PTR [edi][2]
        call    rgb_to_ipc
        mov     cl,al
        add     edi,rgb_size
        mov     ax,WORD PTR [edi][0]             ;Convert color for all 1 pixels
        mov     dl,BYTE PTR [edi][2]
 call rgb_to_ipc

        xor     cl,al                             ;0 where colors are the same
        test    fbsd,SD_COLOR                     ;Monochrome destination?
        jnz     eti_1_not_mono                    ;  No, must be 4 plane

;/*
;**       Mono to mono.  Set up to copy as is, store all 0's, or invert,
;**       depending on the two passed colors.
;*/

 mov cl,1Fh      ; force different colors to
        ; invert mono ;**           

        shr     cl,4                              ;Align bits for eti_1_get_proc
        shr     al,4

        errnz   MONO_BIT-00010000b

        call    eti_1_get_proc
        lea     ebx,copy_e1i1_partial
        jmp     eti_1_have_proc

        ALIGN   4

eti_1_not_mono:

        call    eti_1_get_proc
        mov     convert_C0,edx
        call    eti_1_get_proc
        mov     convert_C1,edx
        call    eti_1_get_proc
        mov     convert_C2,edx
        call    eti_1_get_proc
        mov     convert_C3,edx
        lea     edx,copy_e1i4
        lea     ebx,copy_e1i4_partial

eti_1_have_proc:

        mov     full_byte_proc,edx
        mov     partial_byte_proc,ebx            ;Might need this for seg boundaries

;/*
;** 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

        ret


mono_convert    label   DWORD

        DWORD   copy_0s                           ;Same color, color is 0
        DWORD   copy_1s                           ;Same color, color is 1
        DWORD   copy_inverted                     ;Different colors, inverted
        DWORD   copy_i1e1                         ;Different colors, as is

eti_1_get_proc:

        shr     cl,1                              ;Short little function to return
        rcl     ebx,1                             ;  the function address of the
        shr     al,1                              ;  routine to copy the mono
        rcl     ebx,3                             ;  source bits
 and ebx,00001100b
        mov     edx,mono_convert[ebx]

        ret

page

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

        ALIGN   4

eti_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
        call    create_color_table               ;Create the color table to use
        lea     eax,copy_e4i1
        lea     ebx,copy_e4i1_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      eti_4_have_proc                  ;It is mono
        lea     eax,copy_e4i4
        lea     ebx,copy_e4i4_partial

eti_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 eti_8
;*
;* DESCRIPTION   = Bitmap conversion, external 8 bit to internal format                     
;*                                                                                          
;*                 This routine is responsible for all preprocessing for converting         
;*                 from external 8 bit format to our internal formats                       
;*
;*                 Registers Preserved:         
;*                       BP,DS,ES               
;*                 Registers Destroyed:         
;*                       AX,BX,CX,DX,SI,DI,FLAGS
;*
;* INPUT         = ES:DI --> where color table is 
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

eti_8::

        xor     eax,eax                           ;Will not require any buffer adjustment
        mov     buffer_adjust,eax
        mov     ecx,256                           ;There will be 256 color table entries
        call    create_color_table               ;Create the color table to use
        lea     eax,copy_e8i1
        lea     ebx,copy_e8i1_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      eti_8_have_proc                  ;It is mono
        lea     eax,copy_e8i4
        lea     ebx,copy_e8i4_partial

eti_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 dword becomes
        mov     ebx,eax                           ;  a nibble in our bitmap
        shr     eax,3
        mov     scan_byte_count,eax
        and     bl,11111100b                      ;4 source bytes = 1 dest nibble
        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
        mov     alignment,ebx                     ;Save alignment of last byte

        ret

page

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


        ALIGN   4

eti_24::

        lea     eax,copy_e24i1
        lea     ebx,copy_e24i1_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      eti_24_have_proc                 ;  Yes

eti_24_not_mono:

        lea     eax,copy_e24i4
        lea     ebx,copy_e24i4_partial

eti_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
        mov     ecx,eax                          ;Save original width in bytes
        add     eax,3                            ;Need to round up to a double word
        and     al,11111100b                     ;and (~(size DWORD - 1))
        mov     scan_length,eax                  ;Set # bytes of user buffer required

;/*
;** determine how many bytes we need to pad out the scanline to a dword
;** boundary
;*/

        mov     eax,ecx                           ;get original width in bytes
        neg     eax
        and     eax,00000011b                     ;how far into the last dword?
        mov     buffer_adjust,eax

        and     ebx,00000111b                     ;Can have up to 7 bits in the last
        mov     partial_byte_flags,ebx           ;  byte to convert
        neg     ebx                               ; shift the last byte
        add     ebx,8
        and     ebx,00000111b                     ;Max is 7 bits of alignment
        mov     alignment,ebx                     ;Save alignment of last byte

        ret

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE create_color_table
;*
;* DESCRIPTION   = The color table for translating from user colors to our colors           
;*                 is generated                                                             
;*
;*                 Registers Preserved:         
;*                       BP,DS,ES               
;*                 Registers Destroyed:         
;*                       AX,BX,CX,DX,DI,FLAGS  
;*
;* INPUT         = ES:DI --> where color table is
;*                 CX    =   total number of color table entries
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

create_color_table:

        xor     esi,esi                           ;Index into saved colors

ctt_next_color:

        mov     ax,WORD PTR [edi][0]
        mov     dl,BYTE PTR [edi][2]
        add     edi,rgb_size
        call    rgb_to_ipc
        mov     BYTE PTR color_xlate[esi],al
        inc     esi
        loop    ctt_next_color

        ret

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

        ALIGN   4

copy_0s:

        xor     eax,eax
        call    copy_0_or_1

        ret

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

        ALIGN   4

copy_1s:

        mov     eax,-1

        call    copy_0_or_1

        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_0_or_1
;*
;* DESCRIPTION   = The destination is filled with either 0's or 1's as indicated 
;*                                                                                   
;*                 It is the caller's responsibility to handle all segment crossings.
;*                                                                                   
;*                 This routine is used for:                                         
;*                     external mono to internal mono                                
;*                     external mono to internal four plane                          
;*
;*                 Registers Preserved:     
;*                       ES,DS,BP           
;*                 Registers Destroyed:     
;*                       AX,DX,SI,FLAGS     
;*
;* INPUT         = DS:SI --> source                 
;*                 ES:DI --> destination            
;*                 CX     =  number of bytes to copy
;*                 AX     =  fill value (00h,FFh)
;*                 Direction flag cleared           
;*
;* OUTPUT        = DS:SI --> next destination byte 
;*                 Direction flag cleared         
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/


        ALIGN   4

copy_0_or_1:

        add     esi,ecx                           ;Update source pointer
        mov     edx,ecx
        xor     ecx,ecx
        ror     edi,1                             ;Set 'C' if dest on odd boundary
        rcl     ecx,1                             ;CX = 1 if on odd boundary
        sub     edx,ecx                           ;Update count for odd byte
        rol     edi,1                             ;Restore initial dest address
        rep     stosb                             ;Move possible odd aligned byte
        mov     ecx,edx                           ;Move complete words
        shr     ecx,1
        rep     stosw
        rcl     ecx,1                             ;Process trailing odd byte
        rep     stosb

        ret

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_inverted 
;*
;* DESCRIPTION   = The destination is filled with the inverse of the source. 
;*                                                                                   
;*                 It is the caller's responsibility to handle all segment crossings.
;*                                                                                   
;*                 This routine is used for:                                         
;*                     external mono to internal mono                                
;*                     external mono to internal four plane                          
;*
;*                 Registers Preserved:     
;*                       ES,DS,BP           
;*                 Registers Destroyed:     
;*                       AX,BX,DX,FLAGS     
;*
;* INPUT         = DS:SI --> source                 
;*                 ES:DI --> destination            
;*                 CX     =  number of bytes to copy
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_inverted:

        test    esi,1
        jz      ci_first_not_odd
        lodsb
        not     al
        stosb
        dec     ecx

ci_first_not_odd:

        shr     ecx,1
        jecxz   ci_last_byte

ci_words:

        lodsw
        not     ax                                ;NOT doesn't alter any flags
        stosw
        loop    ci_words

ci_last_byte:

        rcl     ecx,1
        jecxz   ci_all_done
        lodsb
        not     al
        stosb

ci_all_done:

        ret

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e1i1_partial
;*
;* DESCRIPTION   = copy external 1 to internal 1                                       
;*                                                                                     
;*                 A source is copied into an internal mono bitmap.                    
;*                                                                                     
;*                 This code handles crossing the segment boundary                     
;*
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 BX     =  mask and alignment control                 
;*                 CX     =  number of destination pixels to accumulate 
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e1i1_partial:

        mov     ecx,1                             ;Load one complete source byte
        call    full_byte_proc
        dec     esi                               ;Let load_with_seg_check deal with

        load_with_seg_check                      ;  updating the selecotr if needed

        ret

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e1i4 
;*
;* DESCRIPTION   = copy external 1 to internal 4
;*                                                                                     
;*                 The source is copied to all four planes of the destination, with    
;*                 color conversion via the passed color table taking place.           
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e1i4:

        push    edi

        add     edi,width_scan                    ;Start with second plane.
        push    esi
        push    edi
        push    ecx
        call    convert_C1
        pop     ecx
        pop     edi
        pop     esi

        add     edi,width_scan
        push    esi
        push    edi
        push    ecx
        call    convert_C2
        pop     ecx
        pop     edi
        pop     esi

        add     edi,width_scan
        push    esi
        push    ecx
        call    convert_C3
        pop     ecx
        pop     esi

        pop     edi                               ;Finish with first plane.
        call    convert_C0                        ;Leave SI,DI as returned.

        ret

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e1i4_partial
;*
;* DESCRIPTION   = copy external 1 to internal 4
;*                                                                                     
;*                 The source is copied to all four planes of the destination, with    
;*                 color conversion via the passed color table taking place.           
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e1i4_partial:

        push    edi

        add     edi,width_scan
        mov     ecx,1                             ;Only want to grab a single byte
        call    convert_C1
        dec     esi
        dec     edi

        add     edi,width_scan
        mov     ecx,1
        call    convert_C2
        dec     esi
        dec     edi

        add     edi,width_scan
        mov     ecx,1
        call    convert_C3
        dec     esi

        pop     edi
        mov     ecx,1
        call    convert_C0
        dec     esi                               ;Let load_with_seg_check deal with

        load_with_seg_check                      ;  updating the selecotr if needed

        ret

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e4i4 
;*
;* DESCRIPTION   = copy external 4 bit packed pixel to internal 4 plane               
;*                                                                                     
;*                 The source is copied to all four planes of the destination, with    
;*                 color conversion via the passed color table taking place            
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e4i4:

        mov     temp_byte_count,ecx

ce4i4_next_dest_byte:

        mov     temp_bit_count,4                 ;Four source bytes per dest byte
        lea     ebx,color_xlate

ce4i4_next_byte:

        lodsb                                     ;Get 2 bits worth of source data
        mov     ah,al
        shr     al,4
        xlat                                      ;Get the actual colors to use
        shr     al,1
        rcl     cl,1
        shr     al,1
        rcl     ch,1
        shr     al,1
        rcl     dl,1
        shr     al,1
        rcl     dh,1
        mov     al,ah
        and     al,00001111b
        xlat                                      ;Get the actual colors to use
        shr     al,1
        rcl     cl,1                              ;Save C0 bit
        shr     al,1
        rcl     ch,1                              ;Save C1 bit
        shr     al,1
        rcl     dl,1                              ;Save C2 bit
        shr     al,1
        rcl     dh,1                              ;Save C3 bit
        dec     temp_bit_count
        jnz     ce4i4_next_byte
        mov     ebx,width_scan
        mov     BYTE PTR [edi][ebx],ch           ;Save C1
        add     edi,ebx
        mov     BYTE PTR [edi][ebx],dl           ;Save C2
        shl     ebx,1
        mov     BYTE PTR [edi][ebx],dh           ;Save C3
        shr     ebx,1
        sub     edi,ebx
        mov     al,cl
        stosb                                     ;Save C0
        dec     temp_byte_count
        jnz     ce4i4_next_dest_byte

        ret


page

;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e8i4    
;*
;* DESCRIPTION   = copy external 8 bit packed pixel to internal 4 plane                
;*                                                                                     
;*                 The source is copied to all four planes of the destination, with    
;*                 color conversion via the passed color table taking place            
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e8i4:

        mov     temp_byte_count,ecx

ce8i4_next_dest_byte:

        mov     ah,8                              ;Eight source bytes per dest byte
        lea     ebx,color_xlate

ce8i4_next_byte:

        lodsb                                     ;Get 2 bits of source data
        xlat                                      ;Get the actual colors to use
        shr     al,1
        rcl     cl,1
        shr     al,1
        rcl     ch,1
        shr     al,1
        rcl     dl,1
        shr     al,1
        rcl     dh,1
        dec     ah
        jnz     ce8i4_next_byte
        mov     ebx,width_scan
        mov     BYTE PTR [edi][ebx],ch           ;Save C1
        add     edi,ebx
        mov     BYTE PTR [edi][ebx],dl           ;Save C2
        shl     ebx,1
        mov     BYTE PTR [edi][ebx],dh           ;Save C3
        shr     ebx,1
        sub     edi,ebx
        mov     al,cl
        stosb                                     ;Save C0
        dec     temp_byte_count
        jnz     ce8i4_next_dest_byte

        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e24i4   
;*
;* DESCRIPTION   = copy external 24 bit RGB to internal 4 plane                        
;*                                                                                     
;*                 The source is copied to all four planes of the destination, with    
;*                 color conversion via the actual RGB triplet.                        
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e24i4:

        mov     temp_byte_count,ecx

ce24i4_next_dest_byte:

        mov     temp_bit_count,8                 ;Conversions per destination byte

ce24i4_next_byte:

        lodsw
        xchg    eax,edx
        lodsb
        xchg    eax,edx
        call    rgb_to_ipc
        shr     al,1
        rcl     bl,1
        shr     al,1
        rcl     bh,1
        shr     al,1
        rcl     cl,1
        shr     al,1
        rcl     ch,1
        dec     temp_bit_count
        jnz     ce24i4_next_byte
        xchg    eax,ebx
        mov     ebx,width_scan
        mov     BYTE PTR [edi][ebx],ah           ;Save C1
        add     edi,ebx
        mov     BYTE PTR [edi][ebx],cl           ;Save C2
        shl     ebx,1
        mov     BYTE PTR [edi][ebx],ch           ;Save C3
        shr     ebx,1
        sub     edi,ebx
        stosb                                     ;Save C0
        dec     temp_byte_count
        jnz     ce24i4_next_dest_byte

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e4i1    
;*
;* DESCRIPTION   = copy external 4 bit packed pixel to internal 1 plane                
;*                                                                                     
;*                 The source is copied to the destination, with color conversion      
;*                 via the passed color table taking place                             
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e4i1:

        lea     ebx,color_xlate

ce4i1_next_dest_byte:

        mov     dl,4                              ;Four source bytes per dest byte

ce4i1_next_byte:

        lodsb                                     ;Get 1 bit of source data
        mov     ah,al
        shr     al,4
        xlat                                      ;Get the actual colors to use
        shl     al,4

        errnz   MONO_BIT-00010000b

        rcl     dh,1
        mov     al,ah
        and     al,00001111b
        xlat    
        shl     al,4

        errnz   MONO_BIT-00010000b

        rcl     dh,1                              ;Set C0 bit
        dec     dl
        jnz     ce4i1_next_byte
        mov     al,dh
        stosb
        loop    ce4i1_next_dest_byte

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e8i1    
;*
;* DESCRIPTION   = copy external 8 bit packed pixel to internal 1 plane                
;*                                                                                     
;*                 The source is copied to the destination, with color conversion      
;*                 onversion via the passed color table taking place                   
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e8i1:

ce8i1_next_dest_byte:

        mov     ah,8                              ;Eight source bytes per dest byte
        lea     ebx,color_xlate

ce8i1_next_byte:

        lodsb                                     ;Get 1 bit of source data
        xlat                                      ;Get the actual colors to use
        shl     al,4
        errnz   MONO_BIT-00010000b
        rcl     dl,1
        dec     ah
        jnz     ce8i1_next_byte
        mov     al,dl
        stosb
        loop    ce8i1_next_dest_byte

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e24i1   
;*
;* DESCRIPTION   = copy external 24 bit RGB to internal 1 plane                        
;*                                                                                     
;*                 The source is copied to the destination, with the RGB triplet       
;*                 being converted into black/white.                                   
;*                                                                                     
;*                 It is the caller's responsibility to handle all segment crossings.  
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CX     =  number of destination bytes to xlate       
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e24i1:

ce24i1_next_dest_byte:

        mov     bh,8                              ;8 conversion per destination byte

ce24i1_next_byte:

        lodsw
        xchg    ax,dx
        lodsb
        xchg    ax,dx
        call    rgb_to_ipc
        shl     al,4                              ;Get control bits

        errnz   MONO_BIT-00010000b               ;Mono bit must be this bit

        rcl     bl,1                              ;Accumulate mono bits here
        dec     bh
        jnz     ce24i1_next_byte
        mov     al,bl
        stosb
        loop    ce24i1_next_dest_byte

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e4i4_partial 
;*
;* DESCRIPTION   = copy external 4 bit packed pixel to internal 4 plane, partial byte
;*                                                                                     
;*                 The source is copied to all four planes of the destination, with    
;*                 color conversion via the passed color table taking place            
;*                                                                                     
;*                 This code handles crossing the segment boundary                     
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CL     =  number of destination bits to accumulate   
;*                 BX     =  mask and alignment control                
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e4i4_partial:

        push    ebx                               ;Save masking and alignment control
        shr     cl,1                              ;Source is nibbles
        mov     temp_bit_count,ecx               ;Save number of dest bits to collect
        lea     ebx,color_xlate

ce4i4p_next_byte:

        load_with_seg_check                      ;Get 2 bits of source data

        mov     ah,al
        shr     al,4
        xlat                                      ;Get the actual colors to use
        shr     al,1
        rcl     cl,1                              ;Set C0 bit
        shr     al,1
        rcl     ch,1                              ;Set C1 bit
        shr     al,1
        rcl     dl,1                              ;Set C2 bit
        shr     al,1
        rcl     dh,1                              ;Set C3 bit
        mov     al,ah
        and     al,00001111b
        xlat    
        shr     al,1
        rcl     cl,1
        shr     al,1
        rcl     ch,1
        shr     al,1
        rcl     dl,1
        shr     al,1
        rcl     dh,1
        dec     temp_bit_count
        jnz     ce4i4p_next_byte

ce4i4p_save_byte:

        pop     ebx                               ;Restore masking and alignment
        call    align_and_store_all

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e8i4_partial 
;*
;* DESCRIPTION   = copy external 8 bit packed pixel to internal 4 plane, partial byte  
;*                                                                                     
;*                 The source is copied to all four planes of the destination, with    
;*                 color conversion via the passed color table taking place            
;*                                                                                     
;*                 This code handles crossing the segment boundary                     
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CL     =  number of destination bits to accumulate   
;*                 BX     =  mask and alignment control                
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e8i4_partial:

        push    ebx                               ;Save masking and alignment control
        mov     ah,cl                             ;Set AH = number of dest bits needed
        lea     ebx,color_xlate

ce8i4p_next_byte:

        load_with_seg_check                      ;Get 2 bits of source data

        xlat                                      ;Get the actual colors to use
        shr     al,1
        rcl     cl,1                              ;Set C0 bit
        shr     al,1
        rcl     ch,1                              ;Set C1 bit
        shr     al,1
        rcl     dl,1                              ;Set C2 bit
        shr     al,1
        rcl     dh,1                              ;Set C3 bit
        dec     ah
        jnz     ce8i4p_next_byte

ce8i4p_save_byte:

        pop     ebx                               ;restore masking and alignment
        call    align_and_store_all

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e24i4_partial  
;*
;* DESCRIPTION   = copy external 24 bit RGB to internal 4 plane, partial byte            
;*                                                                                       
;*                 The source is copied to all four planes of the destination, with      
;*                 color conversion via the actual RGB triplet.                          
;*                                                                                       
;*                 This code handles crossing the segment boundary                       
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CL     =  number of destination bits to accumulate   
;*                 BX     =  mask and alignment control                
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e24i4_partial:

        push    ebx                               ;Save masking and alignment control
        movzx   ecx,cl
        mov     temp_byte_count,ecx

ce24i4p_next_byte:

        lodsw
        xchg    ax,dx
        lodsb
        xchg    ax,dx

ce24i4p_have_source:

        call    rgb_to_ipc
        shr     al,1
        rcl     cl,1                              ;Set C0 bit
        shr     al,1
        rcl     ch,1                              ;Set C1 bit
        shr     al,1
        rcl     bl,1                              ;Set C2 bit
        shr     al,1
        rcl     bh,1                              ;Set C3 bit
        dec     temp_byte_count
        jnz     ce24i4p_next_byte

ce24i4p_save_byte:

        xchg    bx,dx
        pop     ebx                               ;restore masking and alignment
        call    align_and_store_all

        ret

page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e4i1_partial   
;*
;* DESCRIPTION   = copy external 4 bit packed pixel to internal 1 plane, partial byte    
;*                                                                                       
;*                 The source is copied to the destination, with color conversion        
;*                 via the passed color table taking place                               
;*                                                                                       
;*                 This code handles crossing the segment boundary                       
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CL     =  number of destination bits to accumulate   
;*                 BX     =  mask and alignment control                
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e4i1_partial:

        mov     edx,ebx                           ;Save masking and alignment control
        lea     ebx,color_xlate
        shr     cl,1                              ;Source is nibbles

ce4i1p_next_byte:

        load_with_seg_check                      ;Get 2 bits of source data

        mov     ah,al
        shr     al,4
        xlat                                      ;Get the actual colors to use
        shl     al,4

        errnz   MONO_BIT-00010000b

        rcl     ch,1                              ;Set C0 bit
        mov     al,ah
        and     al,00001111b
        xlat    
        shl     al,4
        rcl     ch,1

        errnz   MONO_BIT-00010000b

        dec     cl
        jnz     ce4i1p_next_byte

ce4i1p_save_byte:

        mov     al,ch
        mov     ebx,edx                           ;Restore masking and alignment control
        call    align_and_store

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e8i1_partial   
;*
;* DESCRIPTION   = copy external 8 bit packed pixel to internal 1 plane, partial byte    
;*                                                                                       
;*                 The source is copied to destination, with color conversion            
;*                 via the passed color table taking place                               
;*                                                                                       
;*                 This code handles crossing the segment boundary                       
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CL     =  number of destination bits to accumulate   
;*                 BX     =  mask and alignment control                
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/
        ALIGN   4

copy_e8i1_partial:

        mov     edx,ebx                           ;Save masking and alignment control
        lea     ebx,color_xlate

ce8i1p_next_byte:

        load_with_seg_check

        xlat    
        shl     al,4
        rcl     ch,1

        errnz   MONO_BIT-00010000b

        dec     cl
        jnz     ce8i1p_next_byte

ce8i1p_save_byte:

        mov     al,ch
        mov     ebx,edx                           ;Restore masking and alignment control
        call    align_and_store

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e24i1_partial  
;*
;* DESCRIPTION   = copy external 24 bit RGB to internal 1 plane, partial byte       e    
;*                                                                                       
;*                 The source is copied to the destination, with color conversion        
;*                 via the actual RGB triplet.                                           
;*                                                                                       
;*                 This code handles crossing the segment boundary                       
;*                                                                                     
;*                 Registers Preserved:        
;*                       ES,DS,BP              
;*                 Registers Destroyed:        
;*                       AX,BX,DX,SI,DI,FLAGS  
;*
;* INPUT         = DS:SI --> source                                     
;*                 ES:DI --> destination                                
;*                 CL     =  number of destination bits to accumulate   
;*                 BX     =  mask and alignment control                
;*
;* OUTPUT        = DS:SI --> next source byte
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

copy_e24i1_partial:

ce24i1p_next_byte:

        lodsw
        xchg    ax,dx
        lodsb
        xchg    ax,dx

ce24i1p_have_source:

        call    rgb_to_ipc
        shr     al,1
        rcl     ch,1
        dec     cl
        jnz     ce24i1p_next_byte

ce24i1p_save_byte:

        mov     al,cl
        call    align_and_store

        ret

ce24i1p_next_seg:

        load_with_seg_check

        xchg    al,ah

        load_with_seg_check

        xchg    al,ah
        xchg    dx,ax

        load_with_seg_check

        xchg    dx,ax
        jmp     ce24i1p_have_source


page

;/***************************************************************************
;*
;* PRIVATE ROUTINE align_and_store_all 
;*
;* DESCRIPTION   = All four planes of the bitmap, at the current location, are set       
;*                 to the given values                                                   
;*                                                                                       
;*                 Registers Preserved:        
;*                       BP,DS,ES,BP           
;*                 Registers Destroyed:        
;*                       AX,BX,CX,DX  
;*
;* INPUT         = ES:DI --> destination                                
;*                 CL     =  C0 byte                                    
;*                 CH     =  C1 byte                 
;*                 DL     =  C2 byte                 
;*                 DH     =  C3 byte                  
;*                 BL     =  shift count for alignment
;*
;* OUTPUT        = ES:DI --> next destination byte   
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

align_and_store_all:

        push    edi
        mov     al,cl                             ;Save C0 bit
        call    align_and_store
        dec     edi
        add     edi,width_scan                    ;--> next plane's bytes
        mov     al,ch                             ;Save C1 bit
        call    align_and_store
        dec     edi
        add     edi,width_scan                    ;--> next plane's bytes
        mov     al,dl                             ;Save C2 bit
        call    align_and_store
        dec     edi
        add     edi,width_scan                    ;--> next plane's bytes
        mov     al,dh                             ;Save C3 bit
        call    align_and_store
        pop     edi
        inc     edi

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE align_and_store
;*
;* DESCRIPTION   = The given byte is stored into the bitmap, being aligned to the        
;*                 left hand side of byte
;*                                                                                       
;*                 Registers Preserved:          
;*                       AH,BX,CX,DX,SI,BP,DS,ES 
;*                 Registers Destroyed:          
;*                       AL                      
;*
;* INPUT         = ES:DI --> destination                                
;*                 AL     =  byte to save                               
;*                 BL     =  shift count for alignment 
;*
;* OUTPUT        = ES:DI --> next destination byte   
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        ALIGN   4

align_and_store:

        xchg    bx,cx
        shl     al,cl                             ;Perform any needed alignment
        stosb
        xchg    bx,cx

        DebugMsg <LEAVING bmc_ext_to_int CLIFFL bmc_eti.asm>
        ret

bmc_ext_to_int  ENDP


        public  eti_1   
        public  eti_4   
        public  eti_8   
        public  eti_24  
        public  create_color_table 
        public  copy_0s 
        public  copy_1s 
        public  copy_0_or_1                      
        public  copy_inverted                    
        public  copy_e1i1_partial 
        public  copy_e1i4                        
        public  copy_e1i4_partial 
        public  copy_e4i4                        
        public  copy_e8i4                        
        public  copy_e24i4                       
        public  copy_e4i1                        
        public  copy_e8i1                        
        public  copy_e24i1                       
        public  copy_e4i4_partial 
        public  copy_e8i4_partial 
        public  copy_e24i4_partial 
        public  copy_e4i1_partial 
        public  copy_e8i1_partial 
        public  copy_e24i1_partial 
        public  align_and_store_all 
        public  align_and_store 

        public  eti_log_error
        public  eti_get_out
        public  eti_xfered_all_relay
        public  eti_numbers_ok
        public  eti_isnt_huge_bitmap
        public  eti_next_scan
        public  eti_in_segment
        public  eti_see_about_partial
        public  eti_no_partial_byte
        public  eti_xfered_all
        public  eti_exit
        public  eti_1_not_mono
        public  eti_1_have_proc
        public  eti_1_get_proc
        public  eti_4_have_proc
        public  eti_8_have_proc
        public  eti_24_not_mono
        public  eti_24_have_proc
        public  ctt_next_color
        public  ci_first_not_odd
        public  ci_words
        public  ci_last_byte
        public  ci_all_done
        public  ce4i4_next_dest_byte
        public  ce4i4_next_byte
        public  ce8i4_next_dest_byte
        public  ce8i4_next_byte
        public  ce24i4_next_dest_byte
        public  ce24i4_next_byte
        public  ce4i1_next_dest_byte
        public  ce4i1_next_byte
        public  ce8i1_next_dest_byte
        public  ce8i1_next_byte
        public  ce24i1_next_dest_byte
        public  ce24i1_next_byte
        public  ce4i4p_next_byte
        public  ce4i4p_save_byte
        public  ce8i4p_next_byte
        public  ce8i4p_save_byte
        public  ce24i4p_next_byte
        public  ce24i4p_have_source
        public  ce24i4p_save_byte
        public  ce4i1p_next_byte
        public  ce4i1p_save_byte
        public  ce8i1p_next_byte
        public  ce8i1p_save_byte
        public  ce24i1p_next_byte
        public  ce24i1p_have_source
        public  ce24i1p_save_byte
        public  ce24i1p_next_seg
end
