;*DDK*************************************************************************/
;
; COPYRIGHT (C) Microsoft Corporation, 1989
; COPYRIGHT    Copyright (C) 1995 IBM Corporation
;
;    The following IBM OS/2 WARP source code is provided to you solely for
;    the purpose of assisting you in your development of OS/2 WARP device
;    drivers. You may use this code in accordance with the IBM License
;    Agreement provided in the IBM Device Driver Source Kit for OS/2. This
;    Copyright statement may not be removed.;
;*****************************************************************************/

        page    ,132

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.
;*   06/23/94              85526  Added MONO_BIT to Create_color_table when
;*                                BCE_PALETTE flag was used.
;*
;*****************************************************************************/

        .386

        .xlist

ifdef PALMGR2
INCL_GRE_PALETTE        equ     1
endif
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             ;!!!needed for mono-bit, must
        include assert.mac              ;!!! fix this dependancy
        include extern.inc
        include protos.inc
ifdef PALMGR2
        include palette.inc
endif

        .list

        .MODEL FLAT

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

        .DATA
pbmiGlobal      DWORD   0
        .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

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


ifdef PALMGR2
bmc_ext_to_int  PROC SYSCALL USES esi edi,      npbm:DWORD, pbmi:DWORD,
                                                pBuf:DWORD, cyScans:DWORD,
                                                iStart:DWORD,pddc:DWORD
else
bmc_ext_to_int  PROC SYSCALL USES esi edi,      npbm:DWORD, pbmi:DWORD,
                                                pBuf:DWORD, cyScans:DWORD,
                                                iStart:DWORD
endif
                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,
                        fbsd:BYTE,
                        temp_bit_count:DWORD,
                        rgb_size:DWORD,
                        color_xlate[256]:WORD,
                        vvddrcl:VVRECT

ifdef PALMGR2
                LOCAL   fbPal:DWORD,rgb:RGB2
endif


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

eti_xfered_all_relay:

        jmp     eti_xfered_all

eti_numbers_ok:

        or      eax,cyScans
        jz      eti_xfered_all_relay
        mov     ebx,pbmi                ;Validate bitmap info structure
        mov     pbmiGlobal,ebx
        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
                                ;corresponds as follows:
                                ; 0 =>  1 bit  per pel
                                ; 4 =>  4 bits per pel
                                ; 8 =>  8 bits per pel
                                ;12 => 24 bits per pel
        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
                                        ;gets eti_ 1,4,8,or 24


ifdef PALMGR2

;/*
;**        /**************************************************************/
;**        /* Check to see if we have been passed the special BCE_PALETTE*/
;**        /* format.                                                    */
;**        /* This only applies if there is a palette in the current DC  */
;**        /* (Higher level code will have raised an error if they asked */
;**        /* for the special format without having a palette)           */
;**        /**************************************************************/
;**        if ((pdc->DCIColFormat == LCOLF_PALETTE) &&
;**            (pSourceHeader->cbFix >= SIZE_ALL_BM2_FIELDS(pSourceHeader)) &&
;**            (SPad.pExternalHeader->ulColorEncoding == BCE_PALETTE))
;**        {
;**            SPad.fbFlags = CONV_BCE_PALETTE;
;**        }
;**        else
;**        {
;**            SPad.fbFlags = 0;
;**        }
;*/

        mov     fbPal,0

        mov     eax,pddc
        test    [eax].DDC.ddc_fbClrTbl,DDC_PALETTE
        jz      @F
        mov     eax,pbmi                ;Validate bitmap info structure
        cmp     [eax].BITMAPINFO2.bmi2_cbFix,SIZEOF BITMAPINFOHEADER
        je      @F      ;must be new header, not old
        cmp     [eax].BITMAPINFO2.bmi2_ulColorEncoding,BCE_PALETTE
        jnz     @F
        mov     fbPal,BCE_PALETTE
@@:

endif

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

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.
;** in flat model a 0 in the Hi word of the flat pointer
;** could be valid!!!, but there is no other way to check this
;** so for now we must check or crash!!!
;*/

        jne     eti_not_vdd             ;Normal SetBitmapBits call

        DebugMsg <pBuf == 0!!! in bmc_ext_to_int>

        mov     vvddrcl.vvr_ulDDFormat,DDFORMAT_4PLANE
        mov     ecx,bitmap_height       ;zero high word of ECX at same time
        mov     vvddrcl.vvr_cy,ecx
        mov     ecx,bitmap_width        ;high word is already zeroed this time
        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


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

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

eti_vdd_error:

        sub     eax,eax
        jmp     eti_exit                ;propagate error back to Shield


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

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


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     alignment,eax
        mov     scan_byte_count,eax

        test    fbsd,SD_COLOR           ;Monochrome destination?
        jnz     eti_1_not_mono          ;  No, must be 4 plane

        lea     edx, copy_e1i1
        lea     ebx, copy_e1i1_partial
        jmp     eti_1_have_proc


eti_1_not_mono:
        lea     edx, copy_e1i8
        lea     ebx, copy_e1i8_partial

eti_1_have_proc:

        mov     full_byte_proc,edx
        mov     partial_byte_proc,ebx   ;Might need this for seg boundaries
        mov     ecx, 2                  ; There will be 2 color table entries
        call    create_color_table      ; Create the color table to use

;/*
;** 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,bitmap_width
        mov     edx,eax
        mov     ecx, 31
        add     eax, ecx                        ; try to allign to dword
        not     ecx
        and     eax, ecx                        ; ax is alligned to dwords
        mov     ebx,eax                 ; save the dword max bitmap width

;/*
;** calculate the internal move count
;*/

        mov     eax,edx
        shr     eax,3
        mov     scan_byte_count,eax
        mov     scan_length,eax         ;Set # bytes of user buffer required

;/*
;** calculate the internal remaining pixel count
;*/

        shl     eax,3
        sub     edx,eax
        mov     partial_byte_flags,edx
        jz      eti1_skip

;/*
;** calculate the monochrome shift alignment count
;*/

        sub     edx,8
        neg     edx
        mov     alignment,edx

eti1_skip:

;/*
;** calculate the external dword adjustment
;*/

        sub     ebx,bitmap_width
        shr     ebx,3
        mov     buffer_adjust,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
;*
;**************************************************************************/


eti_4::

        xor     eax,eax
        mov     buffer_adjust,eax       ;Everything will be dword aligned
        mov     partial_byte_flags,eax
        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_e4i8
        lea     ebx,copy_e4i8_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
        mov     edx,eax
        add     eax, 7                  ; force dword alignment of the source
        and     al, 0f8h
        mov     ebx,eax

;/*
;** process mono & 8 bit separately
;*/
        test    fbsd, SD_COLOR
        jne     eti_4t8_color

;/*
;** calculate the monochrome internal move count
;*/
        mov     eax,edx
        shr     eax,3
        mov     scan_byte_count,eax

;/*
;** calculate the monochrome internal remaining pixel count
;*/

        mov     eax,edx
        and     eax,0111b
        mov     partial_byte_flags,eax
        jz      eti_4t1_color

;/*
;** calculate the monochrome shift alignment count
;*/
        sub     eax,8
        neg     eax
        mov     alignment,eax

;/*
;** calculate the external dword adjustment
;*/

eti_4t1_color:
        sub     ebx,edx
        shr     ebx,1
        mov     buffer_adjust,ebx
        ret

eti_4t8_color:

;/*
;** calculate the color internal move count, with no int_remaining_pixel_count
;*/

        inc     edx                     ; we will process any excess pel
        shr     edx,1                    ; # of source BYTES
        mov     scan_byte_count,edx

;/*
;** calculate the external dword adjustment
;*/
        shr     ebx,1                   ; make a byte count
        sub     ebx,edx                 ; get the remaining bytes
        mov     buffer_adjust,ebx       ; save the difference

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

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_e8i8
        lea     ebx,copy_e8i8_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
        mov     edx,eax
        add     eax,3                   ;  to convert.  Each dword becomes
        and     al,11111100b            ;4 source bytes = 1 dest nibble
        mov     ebx,eax                 ;  a nibble in our bitmap

        test    fbsd, SD_COLOR
        jne     eti_8_color3


;/*
;** calc the mono internal move count
;*/

        mov     eax,edx
        shr     eax,3
        mov     scan_byte_count,eax
;/*
;** calculate the mono internal remaining count
;*/
        mov     eax,edx
        and     eax,0111b
        mov     partial_byte_flags,eax
        jz      eti_8t1_mono
;/*
;** calculate the mono shift alignment count
;*/
        sub     eax,8
        neg     eax
        mov     alignment,eax

eti_8t1_mono:
        sub     ebx,edx
        mov     buffer_adjust,ebx
        ret

eti_8_color3:

;/*
;** calc the color external map's dword alignment value
;*/
        sub     ebx,edx
        mov     buffer_adjust,ebx       ; dword alignment of source

;/*
;** calc the color internal move count - bytes, not pels
;*/
        mov     eax,edx
        shr     eax,3                   ; make it a byte count
        mov     scan_byte_count,eax

;/*
;** no remaining pixel count on color destination maps
;*/

        shl     eax,3
        sub     edx,eax
        mov     partial_byte_flags,edx
        jz      eti_8t8_color

;/*
;** calc the remaining pixel count
;*/

        sub     edx,8
        neg     edx
        mov     alignment,edx

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


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_e24i8
        lea     ebx,copy_e24i8_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

        push    eax
        and     eax,0011b               ; if already aligned, skip the calc
        jz      eti_24_isaligned
        sub     eax,4
        neg     eax

eti_24_isaligned:
        mov     buffer_adjust,eax
        pop     eax

        add     eax,ecx                 ;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

        and     ebx, 00000111b           ; Can have up to 7 bits in the last
        mov     partial_byte_flags,ebx  ;  byte to convert
        jz      eti_24tx

        test    fbsd, SD_COLOR          ; Monochrome destination?
        jnz     eti_24tx                ; no, skip next calculation

        sub     ebx, 8
        neg     ebx                       ; shift the last byte
        mov     alignment,ebx ; align for internal 1 bit/pixel mode

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

create_color_table:

;/*
;** VOID DRIVERCALL TableExtToInt(VOID)
;** {
;**    if (pdc->DCIColFormat == LCOLF_PALETTE)
;*/


        PUSH    EBX
        ASSUME  EBX:NOTHING
        mov     ebx,pddc
        ddc?    ebx

        test    [ebx].DDC.ddc_fbClrTbl,DDC_PALETTE
        jz      cct_not_pal

;/*
;**        GetConvertTableForPalette();
;*/

        call    GetConvertTableForPalette
        jmp     cct_done

;/*
;**    }
;**    else if (SPad.cExternalBitCount == 1)
;*/

cct_not_pal:
        cmp     ecx,2   ; 1bpp
        jne     cct_not_extmono

;/*
;**    {
;**        if (SPad.cInternalBitCount == 1)
;*/

        test    fbsd,SD_COLOR           ;Monochrome destination?
        jnz     cct_not_intmono         ;  No, must be color
;/*
;**        {
;**            GetMonoConvertTable();
;*/

        call    GetMonoConvertTable
        jmp     cct_done

;/*
;**        }
;**        else
;*/

cct_not_intmono:
;/*
;**        {
;**            GetMonoToColourConvertTable();
;*/

        call    GetMonoToColourConvertTable
        jmp     cct_done
;/*
;**        }
;**    }
;**    else if (SPad.cInternalBitCount == 1)
;*/

cct_not_extmono:
        test    fbsd,SD_COLOR           ;Monochrome destination?
        jnz     cct_not_intmono2                ;  No, must be color

;/*
;**    {
;**        GetColourToMonoConvertTable();
;*/

        call    GetColourToMonoConvertTable
        jmp     cct_done
;/*
;**    }
;**    else
;*/

cct_not_intmono2:

;/*
;**    {
;**        GetColourToColourConvertTable();
;*/

        call    GetColourToColourConvertTable
;/*
;**    }
;** } /* TableExtToInt */
;*/

cct_done:
        POP     EBX
        ret

;/***************************************************************************
;*
;* FUNCTION NAME = GetConvertTableForPalette
;*
;* DESCRIPTION   = Gets the colour conversion table when the colour format
;*                 is LCOLF_PALETTE.  Maps the exteral indices or colours to
;*                 indices into the current palette.
;*
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

;/*
;** VOID DRIVERCALL GetConvertTableForPalette(VOID)
;*/

GetConvertTableForPalette:
;/*
;** {
;**    ULONG   i;
;**    PRGB2   pExtRGB;
;**
;**    /******************************************************************/
;**    /* Work out where the external colour table starts.               */
;**    /******************************************************************/
;**    pExtRGB = (PRGB2)
;**            ((PBYTE)SPad.pExternalHeader + SPad.pExternalHeader->cbFix);
;**
;** pExtRGB in edi already
;**
;**    if ( SPad.fbFlags & CONV_BCE_PALETTE )
;*/

        test    fbPal,BCE_PALETTE
        jz      gctfp_not_bce

;/*
;**    {
;**        for (i = 0; i < SPad.usExtTabSize; i++)
;*/

        lea     esi,color_xlate                 ;Index into saved colors
        mov     eax,0
gctfp_loop1_top:

;/*
;**        {
;**            /**********************************************************/
;**            /* We pick up just the blue byte from the external table  */
;**            /* which we know is the one holding the index.            */
;**            /**********************************************************/
;**            SPad.ausConvertTable[i] = pExtRGB->bBlue;
;*/

        ASSUME  EDI:NOTHING
        mov     al,[edi].RGB2.rgb2_bBlue
        test    fbsd,SD_COLOR                                   ;          
        jne     @f                                              ;          
;/*                                                                     ;          
;**     /**********************************************************/    ;          
;**     /* Because the ITE code does not distinguish between      */    ;          
;**     /* foreground and background colors when converting       */    ;          
;**     /* BCE_PALETTE bitmaps, and we should never be called     */    ;          
;**     /* with a BCE_PALETTE bitmap that we did not first        */    ;          
;**     /* output through the ITE code, we should ignore the same */    ;          
;**     /* here and the colors should be back to the correct      */    ;          
;**     /* state.                                                 */    ;          
;**     /**********************************************************/    ;          
;*/                                                                     ;          
        mov     ah,al                                           ;          
        .errnz  MONO_BIT - 00000001b                            ;          
@@:                                                             ;          
        mov     WORD PTR [esi],ax
        xor     ah,ah                                           ;          

;/*
;**            /**********************************************************/
;**            /* To be using BCE_PALETTE then we must have the new      */
;**            /* format header, and so be using RGB2s in the external   */
;**            /* color table                                            */
;**            /**********************************************************/
;**            pExtRGB++;
;*/

        add     edi,rgb_size

;/*
;**        }
;*/

        add     esi,SIZEOF WORD
        dec     ecx
        jnz     gctfp_loop1_top
        jmp     gctfp_done
;/*
;**    }
;**    else /* external table is not already the mapping we need */
;*/

gctfp_not_bce:

;/*
;**
;**    {
;**        for (i = 0; i < SPad.usExtTabSize; i++)
;*/

        lea     esi,color_xlate                 ;Index into saved colors
gctfp_loop2_top:

;/*
;**        {
;**            SPad.ausConvertTable[i] =
;**                                  (USHORT)NearestPaletteIndex(*pExtRGB);
;*/

        ddc?    ebx

        push    ecx
        INVOKE  NearestPaletteIndex,
                ebx,
                RGB2 PTR [edi]
        pop     ecx

        test    fbsd,SD_COLOR                                   ;          
        jne     gctfp_not_mono_int                              ;          
        cmp     al,byte ptr [ebx].DDC.ddc_ia.ia_ba.ba_clrBack   ;          
        .errnz  MONO_BIT - 00000001b                            ;          
        setne   ah                                              ;          
gctfp_not_mono_int:                                             ;          
        mov     WORD PTR [esi],ax

;/*
;**
;**            pExtRGB = (PRGB2)((PBYTE)pExtRGB + SPad.usIncrement);
;**        }
;*/

        add     edi,rgb_size
        add     esi,2
        dec     ecx
        jnz     gctfp_loop2_top
;/*
;**    }
;*/

gctfp_done:
        ret

;/*
;** } /* GetConvertTableForPalette */

;/***************************************************************************
;*
;* FUNCTION NAME = GetMonoConvertTable
;*
;* DESCRIPTION   = Creates a conversion table for a mono bitmap
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

;/*
;** VOID DRIVERCALL GetMonoConvertTable(VOID)
;*/

GetMonoConvertTable:

;/*
;**{
;**#pragma message( __FILE__"(1271) : Warning: algorithm differs from VGA/8514")
;**    SPad.ausConvertTable[0] = 1;
;**    SPad.ausConvertTable[1] = 0;
;**        mov     BYTE PTR color_xlate[1],1       ;Add 1 to index for mono
;**        mov     BYTE PTR color_xlate[3],0       ;Add 1 to index for mono
;*/

        lea     esi,color_xlate+1               ;Index into saved colors
gmct_loop1_top:

;/*
;**    {
;**        SPad.ausConvertTable[i] = MapRGBToMono(pExtRGB);
;*/


;JMW    MapRGBToMono    <RGB2 PTR [EDI]>,TRASHEDX
        mov     eax, DWORD PTR [edi]             ;JMW
        and     eax,0ffffffh                     ;JMW
        seta    al                               ;JMW

        mov     BYTE PTR [esi],al
        add     edi,rgb_size
        add     esi,2
        dec     ecx
        jnz     gmct_loop1_top
        ret

;/*
;**} /* GetMonoConvertTable */


;/***************************************************************************
;*
;* FUNCTION NAME = GetMonoToColourConvertTable
;*
;* DESCRIPTION   = Creates a conversion table from a mono bitmap to a colour bitmap
;*
;*                 For various historical reasons (ie VGA did it) the colour table
;*                 associated with an external bitmap is ignored.
;*                 Colour 0 is converted to the current background colour
;*                 Colour 1 is converted to the current foreground colour
;*
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

;/*
;** VOID DRIVERCALL GetMonoToColourConvertTable(VOID)
;*/

GetMonoToColourConvertTable:

;/*
;**{
;**    SPad.ausConvertTable[0] = LogToPhyIndex(pdc->DCICurImgAts.ibnd.lBackColor);
;**    SPad.ausConvertTable[1] = LogToPhyIndex(pdc->DCICurImgAts.ibnd.lColor);
;*/

        ddc?    ebx

        INVOKE  LogToPhyIndex,
                ebx,
                [ebx].DDC.ddc_ia.ia_ba.ba_clrBack

        mov     WORD PTR color_xlate[0],ax

        INVOKE  LogToPhyIndex,
                ebx,
                [ebx].DDC.ddc_ia.ia_ba.ba_clr

        mov     WORD PTR color_xlate[2],ax
        ret
;/*
;**} /* GetMonoToColourConvertTable */
;*/

;/***************************************************************************
;*
;* FUNCTION NAME = GetColourToMonoConvertTable
;*
;* DESCRIPTION   = Creates a conversion table for translating from colour to mono.
;*                 Each entry in the table is 0 or 1 depending on whether the source
;*                 colour is closer to black or white.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

;/*
;** VOID DRIVERCALL GetColourToMonoConvertTable(VOID)
;*/

GetColourToMonoConvertTable:

;/*
;** {
;**    PRGB2   pExtRGB;
;**    ULONG   i;
;**
;**    /******************************************************************/
;**    /* Work out where the external colour table starts.               */
;**    /******************************************************************/
;**    pExtRGB = (PRGB2)
;**            ((PBYTE)SPad.pExternalHeader + SPad.pExternalHeader->cbFix);
;**
;**    for (i = 0;
;**         i < SPad.usExtTabSize;
;**         i++, pExtRGB = (PRGB2)((PBYTE)pExtRGB + SPad.usIncrement) )
;*/

        lea     esi,color_xlate+1               ;Index into saved colors
gctmct_loop1_top:

;/*
;**    {
;**        SPad.ausConvertTable[i] = MapRGBToMono(pExtRGB);
;*/

        MapRGBToMono    <RGB2 PTR [EDI]>,TRASHEDX

        mov     BYTE PTR [esi],al

        add     edi,rgb_size
        add     esi,2
        dec     ecx
        jnz     gctmct_loop1_top
        ret

;/*
;**    }
;** } /* GetColourToMonoConvertTable */
;*/


;/***************************************************************************
;*
;* FUNCTION NAME = GetColourToColourTable
;*
;* DESCRIPTION   = Creates a conversion table for translating from colour to colour.
;*                 Each entry in the table is mapped to the nearest colour in either
;*                 the physical palette or the (realizable) logical colour table.
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

;/*
;** VOID DRIVERCALL GetColourToColourConvertTable(VOID)
;*/

GetColourToColourConvertTable:

;/*
;**{
;**    PRGB2   pExtRGB;
;**    ULONG   i;
;**
;**    /******************************************************************/
;**    /* Work out where the external colour table starts.               */
;**    /******************************************************************/
;**    pExtRGB = (PRGB2)
;**            ((PBYTE)SPad.pExternalHeader + SPad.pExternalHeader->cbFix);
;**
;**    for (i = 0;
;**         i < SPad.usExtTabSize;
;**         i++, pExtRGB = (PRGB2)((PBYTE)pExtRGB + SPad.usIncrement) )
;*/

        ddc?    ebx

        lea     esi,color_xlate                 ;Index into saved colors
gctcct_loop1_top:

;/*
;**    {
;**        if (fRealizeSupported &&
;**            (pdc->DCIColStatus & LCOL_REALIZABLE))
;*/

        push    ecx

        test    [ebx].DDC.ddc_fbClrTbl,DDC_REALIZABLE
        jz      gctcct_not_realizable

;/*
;**        {
;**            SPad.ausConvertTable[i] =
;**                              (USHORT)NearestRealizableIndex(*pExtRGB);
;*/


        INVOKE  NearestRealizableIndex,
                ebx,
                RGB2 PTR [edi]

        jmp     gctcct_done_if

;/*
;**        }
;**
;**        else /* colour table is not realizable */
;*/

gctcct_not_realizable:

;/*
;**        {
;**            SPad.ausConvertTable[i] =
;**                          (USHORT)NearestDefaultPhysicalIndex(*pExtRGB);
;*/

        INVOKE  NearestDefaultPhysicalIndex,
                ebx,
                RGB2 PTR [edi]

;/*
;**        }
;*/

gctcct_done_if:
        pop     ecx
        mov     WORD PTR [esi],ax

        add     edi,rgb_size
        add     esi,2
        dec     ecx
        jnz     gctcct_loop1_top

;/*
;**    }
;**
;**    /******************************************************************/
;**    /* If internal and external bitcounts are both 4 then we will have*/
;**    /* set up a pel for pel conversion table with 16 enties in it.    */
;**    /* We will be able to process data far quicker if we now convert  */
;**    /* this into a byte to byte table with 256 entries in it.         */
;**    /******************************************************************/
;**#pragma message( __FILE__"(1345) : Optimization: could convert pel/pel table to byte/byte")
;**
;*/

        ret

;/*
;** } /* GetColourToColourConvertTable */
;*/

page

;/***************************************************************************
;*
;* FUNCTION NAME = copy_e1i1
;*
;* DESCRIPTION   = copy external 1 to internal 1
;*
;* INPUT         = NONE
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

public   copy_e1i1
copy_e1i1:
        lea     ebx,color_xlate+1       ;add 1 for monochrome
        mov     al,BYTE ptr [ebx]
        mov     bl,BYTE ptr [ebx+2]
        or      al,al
        jz      chk_zeroed
        or      bl,bl
        jnz     copy_e1i1_oned
        jmp     copy_e1i1_inverted
chk_zeroed:
        or      bl,bl
        jz      copy_e1i1_zeroed

copy_e1i1_normal:
        push    ecx
        shr     ecx,2
        rep     movsd
        pop     ecx
        and     ecx,3
        rep     movsb
        ret

copy_e1i1_inverted:
        push    ecx
        shr     ecx,2
        jecxz   no_double
@@:
        lodsd
        not     eax
        stosd
        loop    @b
no_double:
        pop     ecx
        and     ecx,3
        jecxz   no_byte
@@:
        lodsb
        not     al
        stosb
        loop    @b
no_byte:
        ret

copy_e1i1_zeroed:
        add     esi     ,ecx
        sub     eax     ,eax
        push    ecx
        shr     ecx,2
        rep     stosd
        pop     ecx
        and     ecx,3
        rep     stosb
        ret

copy_e1i1_oned:
        add     esi     ,ecx
        mov     eax     ,-1
        push    ecx
        shr     ecx,2
        rep     stosd
        pop     ecx
        and     ecx,3
        rep     stosb
        ret


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


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

;/***************************************************************************
;*
;* FUNCTION NAME = copy_e1i8
;*
;* 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.
;*
;*                  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
;*
;**************************************************************************/

copy_e1i8:
        lea     ebx, color_xlate
        xor     al, al
        xlat    byte ptr [ebx]
        mov     ah, al
        mov     al, 2
        xlat    byte ptr [ebx]
        mov     bx, ax                  ;bh = color for bit '0'
        xor     bl, bh                  ;bl = color for bit '1' xor bh

ce1i8_next_byte_32:
        mov     dl, 2
        lodsb
        mov     dh,al

ce1i8_next_pixel_32:
        shl     dh, 1
        sbb     al, al
        and     al, bl                  ;if 1 select bh|bl
        xor     al, bh                  ;if 0 select bh

        shl     dh, 1
        sbb     ah, ah
        and     ah, bl                  ;if 1 select bh|bl
        xor     ah, bh                  ;if 0 select bh

        shl     eax,16

        shl     dh, 1
        sbb     al, al
        and     al, bl                  ;if 1 select bh|bl
        xor     al, bh                  ;if 0 select bh

        shl     dh, 1
        sbb     ah, ah
        and     ah, bl                  ;if 1 select bh|bl
        xor     ah, bh                  ;if 0 select bh

        ror     eax,16

        stosd
        dec     dl
        jne     ce1i8_next_pixel_32

        loop    ce1i8_next_byte_32

        ret

page

;/***************************************************************************
;*
;* FUNCTION NAME = copy_e1i8_partial
;*
;* DESCRIPTION   =  copy external 1 to internal 8
;*
;*                  The source is copied to all four planes of the destination,
;*                  with color conversion via the passed color table taking place.
;*
;*                  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
;*
;**************************************************************************/


copy_e1i8_partial:
        lea     ebx, color_xlate
        xor     al, al
        xlat    byte ptr [ebx]
        mov     ah, al
        mov     al, 2
        xlat    byte ptr [ebx]
        mov     bx, ax                  ;bh = color for bit '0'
        xor     bl, bh                  ;bl = color for bit '1' xor bh

        lodsb
        mov     ah, al

ce1i8p_next_pixel:
        shl     ah, 1
        sbb     al, al
        and     al, bl                  ;if 1 select bh|bl
        xor     al, bh                  ;if 0 select bh
        stosb
        loop    ce1i8p_next_pixel
        dec     esi
        load_with_seg_check

        ret

page

;/***************************************************************************
;*
;* FUNCTION NAME = copy_e4i8
;*
;* 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.
;*
;*                  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
;*
;**************************************************************************/

copy_e4i8:

        lea     ebx, color_xlate
        cmp     cx,4
        jb      ce4i8_next_pixel
        push    ecx
        shr     ecx,2

ce4i8_next_pixel_32:

        lodsd
        mov     edx,eax
        mov     dl,2

ce4i8_do4pels_32:

        mov     ah, al
        shr     al, 3
        and     al, 01eh
        xlat    byte ptr [ebx]
        ror     eax,8

        and     al, 0fh
        shl     al, 1
        xlat    byte ptr [ebx]
        ror     eax,8

        mov     al,dh

        mov     ah, al
        shr     al, 3
        and     al, 01eh
        xlat    byte ptr [ebx]
        ror     eax,8

        and     al, 0fh
        shl     al, 1
        xlat    byte ptr [ebx]
        ror     eax,8

        stosd
        dec     dl
        jz      ce4i8_8pels_32
        shr     edx,16
        mov     al,dl
        mov     dl,1
        jmp     short ce4i8_do4pels_32

ce4i8_8pels_32:

        loop    ce4i8_next_pixel_32
        pop     ecx
        and     ecx,3
        jcxz    copy_e4i8_done

ce4i8_next_pixel:
        lodsb
        mov     ah, al
        shr     al, 3
        and     al, 01eh
        xlat    byte ptr [ebx]
        stosb
        mov     al, ah
        and     al, 0fh
        shl     al, 1
        xlat    byte ptr [ebx]
        stosb

        loop    ce4i8_next_pixel

copy_e4i8_done:
        ret


page

;/***************************************************************************
;*
;* FUNCTION NAME = copy_e8i8
;*
;* 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.
;*
;*                  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
;*
;**************************************************************************/

copy_e8i8:

ifndef PALMGR2
@@:
        movsd
        movsd
        loop    @b
else
        push    ebx
        lea     ebx,color_xlate
        mov     eax,0
@@:
        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb

        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb

        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb

        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb

        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb

        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb

        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb

        lodsb
        mov     al,BYTE PTR [ebx+(eax*2)]
        stosb
        loop    @b
        pop     ebx
endif
        ret

page
;/***************************************************************************
;*
;* FUNCTION NAME = copy_e24i8
;*
;* 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.
;*
;*                  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
;*
;**************************************************************************/


copy_e24i8:

ce24i8_next_byte:
        mov     bl, 8                   ; Conversions per destination byte
ce24i8_next_pixel:
        lodsw
        mov     dl, [esi]
        inc     esi
        xor     dh,dh

ifdef PALMGR2
        call    get_color
else
        call    rgb_to_ipc
endif
        stosb                           ; Save C0
        dec     bl
        jz      chk_cx
        jmp     ce24i8_next_pixel

chk_cx:
        dec     cx
        jz      ce24i8_done
        jmp     ce24i8_next_byte        ; complete all the target bytes
ce24i8_done:
        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
;*
;**************************************************************************/

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                    ; 
        shl     al,1                    ;Mul by 2 for word index
        inc     al                      ;Position to mono byte
        xlat    byte ptr [ebx]                  ;Get the actual colors to use
        shr     al,1

        .errnz  MONO_BIT - 00000001b

        rcl     dh,1
        mov     al,ah
        and     al,00001111b
        shl     al,1                    ;Mul by 2 for word index
        inc     al                      ;Position to mono byte
        xlat    byte ptr [ebx]
        shr     al,1

        .errnz  MONO_BIT - 00000001b

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


copy_e8i1:

        lea     ebx,color_xlate

ce8i1_next_dest_byte:

        mov     dh,8                    ;Eight source bytes per dest byte

ce8i1_next_byte:

        xor     eax,eax
        lodsb                           ;Get 1 byte of source data
        shl     eax,1                   ;Mul by 2 for word index
        inc     eax                     ;Position to mono byte
        mov     al,byte ptr [ebx][eax]
        shr     al,1
        rcl     dl,1
        dec     dh
        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
;*
;**************************************************************************/


copy_e24i1:

ce24i1_next_dest_byte:

        mov     bh,8                    ;8 conversion per destination byte

ce24i1_next_byte:

        lodsw
        mov     dl,[esi]
        inc     esi
        MapRGBToMono    <RGB2 PTR [EDI]>,TRASHEDX
        shr     al,1                    ;Get control bits

        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_e4i8_partial
;*
;* DESCRIPTION   = copy external 4 bit packed pixel to internal 8 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
;*
;**************************************************************************/


copy_e4i8_partial:
        shr     cl, 1                   ; Source is pels (nibbles)
        lea     ebx, color_xlate
ce4i8p_next_pixel:
        load_with_seg_check     ; Get 2 bits of source data
        mov     ah, al                  ; save it
        shr     al, 3                   ; high nibble is the first pel
        and     al, 01eh
        xlat    byte ptr [ebx]
        stosb
        mov     al, ah
        and     al, 0fh
        shl     al, 1
        xlat    byte ptr [ebx]
        stosb
        dec     cl
        jne     ce4i8p_next_pixel

        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e8i8_partial
;*
;* DESCRIPTION   = copy external 8 bit packed pixel to internal 8 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
;*
;**************************************************************************/


copy_e8i8_partial:
        lea     ebx, color_xlate
ce8i8p_next_byte:
        load_with_seg_check     ; Get 1 pel of source data
        movzx   eax,al
        shl     eax, 1
        mov     al, byte ptr [ebx][eax]
        stosb
        dec     cl
        jne     ce8i8p_next_byte
        ret


page
;/***************************************************************************
;*
;* PRIVATE ROUTINE copy_e24i8_partial
;*
;* DESCRIPTION   = copy external 24 bit packed pixel to internal 8 plane, partial byte
;*
;*                 The source is copied to all four planes of the destination, with
;*                 color conversion via the actual RGB triplet.
;*
;*                 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
;*
;**************************************************************************/


copy_e24i8_partial:

ce24i8p_next_pixel:
        lodsw
        mov     dl, [esi]
        inc     esi
        xor     dh,dh

ifdef PALMGR2
        call    get_color
else
        call    rgb_to_ipc
endif
        stosb
        dec     cl
        jz      ce24i8p_save_byte
        jmp     ce24i8p_next_pixel      ; process all left over pels

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

copy_e4i1_partial:

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

ce4i1p_next_byte:

        load_with_seg_check             ;Get 2 bits of source data

        mov     ah,al
        shr     al,4
        shl     al,1                    ;Mul by 2 for word index
        inc     al                      ;Position to mono byte
        xlat    byte ptr [ebx]                  ;Get the actual colors to use
        shr     al,1

        rcl     ch,1                    ;Set C0 bit

        dec     cl
        jz      ce4i1p_save_byte

        mov     al,ah
        and     al,00001111b
        shl     al,1                    ;Mul by 2 for word index
        inc     al                      ;Position to mono byte
        xlat    byte ptr [ebx]
        shr     al,1
        rcl     ch,1

        .errnz  MONO_BIT - 00000001b

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

copy_e8i1_partial:

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

ce8i1p_next_byte:

        load_with_seg_check

        movzx   eax,al
        shl     eax,1                   ;Mul by 2 for word index
        inc     eax                     ;Position to mono byte
        mov     al,byte ptr [ebx][eax]
        shr     al,1
        rcl     ch,1

        .errnz  MONO_BIT - 00000001b
        ;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
;*
;**************************************************************************/


copy_e24i1_partial:
        push    ebx

ce24i1p_next_byte:

        lodsw
        mov     dl,[esi]
        inc     esi

ce24i1p_have_source:


ifdef PALMGR2
        call    get_color
else
        call    rgb_to_ipc
endif
        shr     ah,1
        rcl     ch,1
        dec     cl
        jnz     ce24i1p_next_byte

ce24i1p_save_byte:

        mov     al,ch
        pop     ebx
        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
;*
;* 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_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


;/***************************************************************************
;*
;* FUNCTION NAME = get_color
;*
;* DESCRIPTION   = The color is converted from input to ipc.
;*
;*                 Registers Preserved:
;*                       BX,CX,SI,DI,BP,DS,ES
;*                 Registers Destroyed:
;*                       AX,DX
;*
;* INPUT         = DX:AX = color data
;* OUTPUT        = AH:AL = ipc
;*
;* RETURN-NORMAL = NONE
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

ifdef PALMGR2
;/*
;** This maps to RGBToIndexFunction in XGA
;*/

public get_color
get_color::
        ASSUME  edi:NOTHING
        push    edi
        push    ebx
        push    ecx             ;CMVC_53450
        ror     eax,16
        mov     al,dl
        rol     eax,16
        push    eax             ;create "local" variable
        mov     ebx,esp

        mov     edi,pddc

;/*
;** {
;**    if (pdc->DCIColFormat == LCOLF_PALETTE)
;*/

        test    [edi].DDC.ddc_fbClrTbl,DDC_PALETTE
        jz      gc_not_pal
;/*
;**    {
;**        if ( SPad.fbFlags & CONV_BCE_PALETTE )
;*/

        test    fbPal,BCE_PALETTE
        jz      gc_not_bce

;/*
;**        {
;**            return( DirectMapping );
;*/

        jmp     ct_done         ;al already has the value

;/*
;**        {
;*/

gc_not_bce:

;/*
;**        else
;**        {
;**            return( NearestPaletteIndex );
;*/

        INVOKE  NearestPaletteIndex,
                edi,
                RGB2 PTR [ebx]


        jmp     ct_done

;/*
;**        }
;**    }
;*/

gc_not_pal:

;/*
;**    if (fRealizeSupported &
;**        (pdc->DCIColStatus & LCOL_REALIZABLE))
;*/

        test    [edi].DDC.ddc_fbClrTbl,DDC_REALIZABLE
        jz      ct_not_real

;/*
;**    {
;**        return( NearestRealizableIndex );
;*/

        INVOKE  NearestRealizableIndex,
                edi,
                RGB2 PTR [ebx]

        jmp     ct_done

;/*
;**    }
;**
;**    return( NearestDefaultPhysicalIndex );
;*/

ct_not_real:
        INVOKE  NearestDefaultPhysicalIndex,
                edi,
                RGB2 PTR [ebx]

;/*
;** } /* RGBToIndexFunction */
;*/

ct_done:
        add     esp,4           ;CMVC_53450
        pop     ecx             ;CMVC_53450
        pop     ebx
        pop     edi
        ret

endif ;PALMGR2

bmc_ext_to_int  ENDP


        public  eti_1
        public  eti_4
        public  eti_8
        public  eti_24
        public  create_color_table
        public  copy_e1i1_partial
        public  copy_e1i8
        public  copy_e1i8_partial
        public  copy_e4i8
        public  copy_e8i8
        public  copy_e24i8
        public  copy_e4i1
        public  copy_e8i1
        public  copy_e24i1
        public  copy_e4i8_partial
        public  copy_e8i8_partial
        public  copy_e24i8_partial
        public  copy_e4i1_partial
        public  copy_e8i1_partial
        public  copy_e24i1_partial
        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_4_have_proc
        public  eti_8_have_proc
        public  eti_24_not_mono
        public  eti_24_have_proc
        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  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
