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

        .286p
        .xlist
        include cmacros.inc
INCL_GRE_BITMAPS        equ                      1
INCL_GPIBITMAPS         equ                      1
        include pmgre.inc
DINCL_BITMAP            equ                      1
        include driver.inc
        include display.inc                   
        include assert.mac                    
        include bmi2.inc
        include thkmacs.inc
        .286p
        .list


        errcode <INV_SCAN_START,INV_INFO_TABLE,INV_LENGTH_OR_COUNT>

        externA DOSHUGEINCR                       ;Inc to next 64K of huge local segment


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

        externFP DosRequestVDD
        externFP far_rgb_to_ipc
        externFP far_check_bitmap_info

sBegin  Data
        externD  hVideoVDD
sEnd    Data


sBegin  Bitmap
        assumes cs,Bitmap

        externW  BitmapData
        externNP copy_i1e1                        ;Copy as is


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

anpfnPreProc    label   word
        dw      eti_1
        dw      eti_4
        dw      eti_8
        dw      eti_24


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

DDFORMAT_4PLANE equ 1                             ;display driver formats supported

VVDSYSREQ_COPYBITMAP equ 8

VVRECT struc
 vvr_ulDDFormat     dd  ?                         ;display driver format
 vvr_cx             dd  ?                         ;width of DD bitmap buffer
 vvr_cy             dd  ?                         ;height of DD bitmap buffer
 vvr_rcl            dd  4 dup (?)                 ;rectangle requested
 vvr_pbColorXlate   dd  ?                         ;display driver color translation table
VVRECT ends

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


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

        assumes ds,nothing
        assumes es,nothing

cProc   bmc_ext_to_int,<NEAR,PASCAL,PUBLIC,NODATA,NONWIN>,<si,di,ds>

        parmW   npbm                              ; Bitmap
        parmD   pbmi                              ; -> Pointer to info block
        parmD   pBuf                              ; -> buffer of source bits
        parmD   cyScans                           ; Number of scans to copy
        parmD   iStart                            ; First scan to copy

        localW  scans_copied                      ; Number of scanlines copied
        localW  scanline_count                    ; Number of scanlines to copy
        localW  bitmap_width                      ; Width in pixels of the bitmap
        localW  bitmap_height                     ; Height of the bitmap in scans
        localD  lp_bits                           ; Pointer to the actual bits
        localW  width_scan                        ; Width of one scanline in bytes
        localW  next_scan                         ; Index to next scan line
        localW  scans_per_seg                     ; Scanlines per segment
        localW  prev_offset                       ; Offset of last scan, previous segment
        localW  scan_byte_count                  ; # of full bitmap bits per scanline
        localW  full_byte_proc                    ; Routine which xlates full bytes
        localW  partial_byte_flags               ; Flags for a partial byte
        localW  partial_byte_proc                ; Routine which xlates partial bytes
        localW  huge_scans_left                  ; Count of scans left in huge segment
        localW  some_temp
        localW  buffer_adjust                     ; Alignment for each scan of buffer
        localW  temp_byte_count                  ; Work area for conversion routines
        localW  convert_C0                        ; Mono to 4 plane conversion routine
        localW  convert_C1                        ; Mono to 4 plane conversion routine
        localW  convert_C2                        ; Mono to 4 plane conversion routine
        localW  convert_C3                        ; Mono to 4 plane conversion routine
        localW  alignment                         ; Shift to align partial bytes
        localD  scan_length                       ; length of one buffer scanline

        localB  fbsd                              ; sd_fb local copy
        localB  temp_bit_count                    ; Work area for conversion routines
        localW  rgb_size                ; 3 bytes for old format, 4 for new

        localV  color_xlate,256                  ; Color translation table
        localV  vvddrcl,%(size VVRECT)

cBegin
        mov     ds,BitmapData
        assumes ds,Data

ifdef   FIREWALLS
        mov     bx,npbm
        cmp     [bx].bm_sd.sd_usId,SURFACE_IDENT
        jne     bmc_not_a_bitmap
        test    [bx].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     ax,ax
        mov     scans_copied,ax


;/*
;**  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     bx,PMERR_INV_SCAN_START ;The starting scan must be 0-65535
        cmp     iStart.hi,ax
        jne     eti_log_error
        mov     bx,PMERR_INV_LENGTH_OR_COUNT
        cmp     cyScans.hi,ax
        je      eti_numbers_ok
eti_log_error:
        xchg    ax,bx
        save_error_code
        mov     ax,-1
eti_get_out:
        jmp     eti_exit

eti_xfered_all_relay:
        jmp     eti_xfered_all

eti_numbers_ok:
        or      ax,cyScans.lo
        jz      eti_xfered_all_relay
        les     bx,pbmi                           ;Validate bitmap info structure
        assumes es,nothing
        mov     cx,1                              ; signal maximum check
        call    far_check_bitmap_info
        mov     bx,PMERR_INV_INFO_TABLE
        jcxz    eti_log_error

ifdef FIREWALLS
        cmp     ax,6                              ;We should always get back 0,2,4,6
        jbe     @F
eti_cbi_failed:
        rip     text,<check_bitmap_info returned an illegal value>
@@:
        test    al,1
        jnz     eti_cbi_failed
endif
        xchg    ax,bx
        mov     si,anpfnPreProc[bx]              ;Save preprocessor's address

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

        mov     di,npbm
        mov     ax,[di].bm_sd.sd_cx
        mov     bitmap_width,ax
        mov     ax,[di].bm_sd.sd_cy
        mov     bitmap_height,ax
        mov     al,[di].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     ax,[di].bm_sd.sd_pBits.off
        mov     lp_bits.off,ax
        mov     ax,[di].bm_sd.sd_pBits.sel
        mov     lp_bits.sel,ax
        mov     ax,[di].bm_sd.sd_cbScan
        mov     width_scan,ax
        mov     bx,[di].bm_sd.sd_dScan
        mov     next_scan,bx
        test    cl,SD_HUGE
        jz      eti_isnt_huge_bitmap

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

        mov     ax,[di].bm_sd.sd_cySeg            ;# scanlines in a segment
        mov     scans_per_seg,ax
        add     bx,[di].bm_sd.sd_cbFill
        neg     bx
        mov     prev_offset,bx                    ;Save start of last scan in segment

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     cx,iStart.lo
        mov     bx,bitmap_height
        sub     bx,cx                             ;If starting scan is outside bitmap
        jbe     eti_xfered_all_relay              ;  surface, then nothing to copy
                                                  ;Compute number of scans to move
        mov     ax,cyScans.lo
        usmin_ax   bx
        mov     scanline_count,ax
        mov     scans_copied,ax                   ;We will return this value


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

        mov     di,pbmi.off
        assert  es:[di].bmi2_cbFix.hi,E,0
        mov     ax,es:[di].bmi2_cbFix.lo         ;ES:DI --> where color table is
        mov     rgb_size,(SIZE RGB)
        cmp     ax,SIZE BITMAPINFOHEADER
        je      eti_got_rgb_size
ifdef FIREWALLS
        assumes ds,Data
        mov     bx,es:[di].bmp2_cbFix.lo
        assert  bx,LE,64
        .errnz  (SIZE BITMAPINFOHEADER2)-64
        shr     bl,1
        assert  NC
        add     bx,DataOFFSET ok_cbFix
        mov     bl,[bx]
        assert  bl,NE,0
        assert  es:[di].bmp2_cbFix.hi,E,0
endif
        mov     rgb_size,(SIZE RGB2)
eti_got_rgb_size:
        add     di,ax
        call    si


;/*
;**  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     ax,bitmap_height                 ;Invert the Y coordinate
        sub     ax,iStart.lo
        dec     ax

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

        .386p                                     
        sub     edx,edx
        cmp     pBuf.sel,dx
        jne     eti_not_vdd                       ;Normal SetBitmapBits call

        mov     vvddrcl.vvr_ulDDFormat,DDFORMAT_4PLANE
        movzx   ecx,bitmap_height                 ;zero high word of ECX at same time
        mov     vvddrcl.vvr_cy,ecx
        mov     cx,bitmap_width                   ;high word is already zeroed this time
        mov     vvddrcl.vvr_cx,ecx

        mov     vvddrcl.vvr_rcl.rcl_xLeft,edx
        mov     dx,cx                             ;DX == width
        dec     dx
        mov     vvddrcl.vvr_rcl.rcl_xRight,edx
        mov     dx,ax
        mov     vvddrcl.vvr_rcl.rcl_yBottom,edx
        sub     dx,cyScans.lo
        inc     dx
        mov     vvddrcl.vvr_rcl.rcl_yTop,edx

        lea     dx,color_xlate
        flatPtr edx,ss,dx
        mov     vvddrcl.vvr_pbColorXlate,edx

        sub     dx,dx
        farPtr  hvdd,hVideoVDD.hi,hVideoVDD.lo
        mov     cx,pBuf.off                       ;CX == VDM SGID
        farPtr  cbInput,dx,%(size VVRECT)
        lea     ax,vvddrcl
        farPtr  pInput,ss,ax
        farPtr  cbOutput,dx,dx                    
        farPtr  pOutput,lp_bits.sel,lp_bits.off

        cCall   DosRequestVDD,<hvdd,cx,VVDSYSREQ_COPYBITMAP,cbInput,pInput,cbOutput,pOutput>
        .286p

        or      ax,ax                             ;any error?
        jnz     eti_vdd_error                     ;yes
        jmp     eti_xfered_all
eti_vdd_error:
        sub     ax,ax
        jmp     eti_exit                          ;propagate error back to Shield


eti_not_vdd:
        test    fbsd,SD_HUGE
        jz      eti_finish_y_calc


;/*
;**  This is a huge bitmap.  Compute which segment the Y coordinate
;**  is in.  Assuming that no huge bitmap will be bigger than two
;**  or three segments, iteratively computing the value would be
;**  faster than a divide, especially if Y is in the first segment
;*/

        mov     cx,DOSHUGEINCR
        mov     bx,scans_per_seg

eti_huge_bitmap:
        add     dx,cx                             ;Show in next segment
        sub     ax,bx                             ;See if in this segment
        jnc     eti_huge_bitmap                   ;Not in current segment, try next
        sub     dx,cx                             ;Show correct segment
        add     ax,bx                             ;Restore correct Y
        inc     ax
        mov     huge_scans_left,ax                ;# scans left in the segment
        dec     ax                                ;Scan index for addr calculation
        cmp     ax,scanline_count                 ;If all bits are in the same segment
        jle     eti_finish_y_calc                 ;  we'll skip huge bitmap stuff
        and     fbsd,not SD_HUGE

eti_finish_y_calc:
        add     dx,lp_bits.sel                    ;Dest is our bitmap
        mov     es,dx
        assumes es,nothing

        mul     next_scan                         ;Compute offset within the segment
        add     ax,lp_bits.off                    ;Compute segment of the bits
        xchg    ax,di

        lds     si,pBuf                           ;Source is user's buffer (this pointer
        assumes ds,nothing                        ;  will never be loaded again)


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

        mov     cx,scanline_count
        mov     ax,scan_length.hi
        mul     cx
        xchg    ax,bx
        mov     ax,scan_length.lo
        mul     cx
        add     dx,bx                             ;DX:AX = total bytes of buffer needed
        add     ax,si
        adc     dx,0                              ;DX:AX = last address + 1
        jz      eti_in_segment                    ;Won't cross a segment boundary
        or      fbsd,CAN_CROSS_SEG                ;Can cross a segment boundary

eti_next_scan:
        test    fbsd,CAN_CROSS_SEG                ;If buffer might cross a segment
        jnz     eti_might_cross_seg               ;  then go check it out

eti_in_segment:
        push    di                                ;Save bitmap scan start address
        mov     cx,scan_byte_count                ;Set translation procedure loop count
        jcxz    eti_see_about_partial             ;No full bytes!
        call    full_byte_proc                    ;Process all complete bytes

eti_see_about_partial:
        mov     cx,partial_byte_flags             ;Process any partial byte
        jcxz    eti_no_partial_byte
        mov     bx,alignment
        call    partial_byte_proc

eti_no_partial_byte:
        pop     di
        dec     scanline_count
        jz      eti_xfered_all                    ;Transfered all scans

        sub     di,next_scan                      ;--> next bitmap scanline
        add     si,buffer_adjust                  ;Align to dword boundary
        jnc     eti_chk_segment_update            ;don't update segment if no wrap
        mov     ax,ds                             ;otherwise, increment segment
        add     ax,DOSHUGEINCR
        mov     ds,ax
        assumes ds,nothing

eti_chk_segment_update:
        test    fbsd,SD_HUGE                      ;If not a huge bitmap,
        jz      eti_next_scan                     ;  go do next scanline

        dec     huge_scans_left                   ;Any more scans in this segment?
        jnz     eti_next_scan                     ;  No, don't update bitmap pointer
        mov     ax,es
        sub     ax,DOSHUGEINCR                    ;We're working from bottom up
        mov     es,ax
        assumes es,nothing
        mov     di,prev_offset                    ;Offset of last scan, previous segment
        mov     ax,scans_per_seg
        mov     huge_scans_left,ax                ;This many scans in the segment
        jmp     eti_next_scan


eti_might_cross_seg:

;/*
;**  The buffer will cross a segment boundary.  If this scanline will
;**  cross the segment, then we'll process eight bits of bitmap data at a time.
;*/

        mov     ax,si                             ;If the entire scan shows, then
        xor     dx,dx                             ;  we can use the normal code
        add     ax,scan_length.lo
        adc     dx,scan_length.hi                 ;scan_length may be > 64K
        jz      eti_in_segment                    ;It won't cross a segment boundary

;/*
;**  The scan will cross a segment boundary.   We'll take the easy
;**  way out and do the entire scanline one bitmap byte at a time.
;*/

        push    di                                ;Save bitmap scan start address
        mov     cx,scan_byte_count                ;If only a last byte exists,
        jcxz    eti_see_about_partial             ;  use the normal code
        mov     some_temp,cx                      ;Save full byte count

eti_looking_to_cross:
        mov     cx,8                              ;Accumulate 8 dest pixels
        xor     bx,bx                             ;No alignment required
        call    partial_byte_proc
        dec     some_temp
        jnz     eti_looking_to_cross
        jmp     eti_see_about_partial            ;Finish with partial byte code

eti_xfered_all:
        mov     ax,scans_copied                  ;Return number of scans copied

eti_exit:
        cwd
        fw_zero <cx,es>
cEnd

page

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

        assumes ds,nothing
        assumes es,nothing

eti_1   proc    near

        xor     ax,ax
        mov     buffer_adjust,ax                 ;Everything will be dword aligned
        mov     partial_byte_flags,ax            ;Will never have a partial byte
        mov     scan_length.hi,ax                ;Max dest scan size is < 64K

        mov     ax,es:[di][0]                    ;Convert color for all 0 pixels
        mov     dl,es:[di][2]
        call    far_rgb_to_ipc
        mov     cl,al
        add     di,rgb_size
        mov     ax,es:[di][0]                    ;Convert color for all 1 pixels
        mov     dl,es:[di][2]
        call    far_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.
;*/

        shr     cl,4                              ;Align bits for eti_1_get_proc
        shr     al,4
        errnz   MONO_BIT-00010000b
        call    eti_1_get_proc
        mov     bx,BitmapOFFSET copy_e1i1_partial
        jmp     short eti_1_have_proc


eti_1_not_mono:
        call    eti_1_get_proc
        mov     convert_C0,dx
        call    eti_1_get_proc
        mov     convert_C1,dx
        call    eti_1_get_proc
        mov     convert_C2,dx
        call    eti_1_get_proc
        mov     convert_C3,dx
        mov     dx,BitmapOFFSET copy_e1i4
        mov     bx,BitmapOFFSET copy_e1i4_partial

eti_1_have_proc:
        mov     full_byte_proc,dx
        mov     partial_byte_proc,bx             ;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     ax,width_scan                    ;Moving all bytes of the scan
        mov     scan_byte_count,ax
        mov     scan_length.lo,ax                ;Set # bytes of user buffer required
        ret


mono_convert    label   word
        dw      copy_0s                           ;Same color, color is 0
        dw      copy_1s                           ;Same color, color is 1
        dw      copy_inverted                     ;Different colors, inverted
        dw      copy_i1e1                         ;Different colors, as is

eti_1_get_proc:
        shr     cl,1                              ;Short little function to return
        rcl     bx,1                              ;  the function address of the
        shr     al,1                              ;  routine to copy the mono
        rcl     bx,2                              ;  source bits
        and     bx,00000110b
        mov     dx,mono_convert[bx]
        ret

eti_1   endp

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

        assumes ds,nothing
        assumes es,nothing

eti_4   proc    near

        xor     ax,ax
        mov     buffer_adjust,ax                 ;Everything will be dword aligned
        mov     partial_byte_flags,ax            ;Will never have a partial byte
        mov     scan_length.hi,ax                ;Max dest scan size is < 64K
        mov     cx,16                            ;There will be 16 color table entries
        call    create_color_table               ;Create the color table to use
        mov     ax,BitmapOFFSET copy_e4i1
        mov     bx,BitmapOFFSET copy_e4i1_partial
        test    fbsd,SD_COLOR                    ;Monochrome source?
        jz      eti_4_have_proc                  ;It is mono
        mov     ax,BitmapOFFSET copy_e4i4
        mov     bx,BitmapOFFSET copy_e4i4_partial

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

eti_4   endp

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

        assumes ds,nothing
        assumes es,nothing

eti_8   proc    near

        xor     ax,ax                             ;Will not require any buffer adjustment
        mov     buffer_adjust,ax
        mov     scan_length.hi,ax                 ;Max dest scan size is < 64K
        mov     cx,256                            ;There will be 256 color table entries
        call    create_color_table                ;Create the color table to use
        mov     ax,BitmapOFFSET copy_e8i1
        mov     bx,BitmapOFFSET copy_e8i1_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      eti_8_have_proc                   ;It is mono
        mov     ax,BitmapOFFSET copy_e8i4
        mov     bx,BitmapOFFSET copy_e8i4_partial

eti_8_have_proc:
        mov     full_byte_proc,ax
        mov     partial_byte_proc,bx
        mov     ax,bitmap_width                   ;Compute the number of source bytes
        add     ax,3                              ;  to convert. Each dword becomes
        mov     bx,ax                             ;  a nibble in our bitmap
        shr     ax,3
        mov     scan_byte_count,ax
        and     bl,11111100b                      ;4 source bytes = 1 dest nibble
        mov     scan_length.lo,bx                 ;Set # bytes of user buffer required
        and     bx,4                              ;Will either have a partial nibble or
        mov     partial_byte_flags,bx             ;  no extra nibble to xlate
        mov     alignment,bx                      ;Save alignment of last byte
        ret

eti_8   endp

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

        assumes ds,nothing
        assumes es,nothing

eti_24  proc    near

        mov     ax,BitmapOFFSET copy_e24i1
        mov     bx,BitmapOFFSET copy_e24i1_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      eti_24_have_proc                  ;  Yes

eti_24_not_mono:
        mov     ax,BitmapOFFSET copy_e24i4
        mov     bx,BitmapOFFSET copy_e24i4_partial

eti_24_have_proc:
        mov     full_byte_proc,ax
        mov     partial_byte_proc,bx
        mov     cx,3
        mov     ax,bitmap_width                   ;Compute the number of source bytes
        mov     bx,ax                             ;  to convert. Each bit becomes
        shr     ax,cl                             ;  three bytes in the destination
        mov     scan_byte_count,ax
        mov     ax,bx                             ;1 source bit = 3 dest bytes
        mul     cx
        mov     cx,ax                             ;Save original width in bytes
        add     ax,3                              ;Need to round up to a double word
        adc     dx,0                              ;Round(byte) = (byte+(size DWORD - 1))
        and     al,11111100b                      ;              and (~(size DWORD - 1))
        mov     scan_length.lo,ax                 ;Set # bytes of user buffer required
        mov     scan_length.hi,dx

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

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

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

        ret

eti_24  endp

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

        assumes ds,nothing
        assumes es,nothing


create_color_table proc near

        xor     si,si                             ;Index into saved colors

ctt_next_color:
        mov     ax,es:[di][0]
        mov     dl,es:[di][2]
        add     di,rgb_size
        call    far_rgb_to_ipc
        mov     color_xlate[si],al
        inc     si
        loop    ctt_next_color
        ret

create_color_table endp

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

        assumes ds,nothing
        assumes es,nothing

copy_0s proc    near

        xor     ax,ax
        jmp     short copy_0_or_1

copy_0s endp

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

        assumes ds,nothing
        assumes es,nothing

copy_1s proc    near

        mov     ax,0FFFFh
        errn$   copy_0_or_1

copy_1s endp

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

        assumes ds,nothing
        assumes es,nothing

copy_0_or_1     proc    near

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

copy_0_or_1     endp

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

        assumes ds,nothing
        assumes es,nothing

copy_inverted   proc    near

        test    si,1
        jz      ci_first_not_odd
        lodsb
        not     al
        stosb
        dec     cx

ci_first_not_odd:
        shr     cx,1
        jcxz    ci_last_byte

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

ci_last_byte:
        rcl     cx,1
        jcxz    ci_all_done
        lodsb
        not     al
        stosb

ci_all_done:
        ret

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

        assumes ds,nothing
        assumes es,nothing

copy_e1i1_partial proc near

        mov     cx,1                              ;Load one complete source byte
        call    full_byte_proc
        dec     si                                ;Let load_with_seg_check deal with
        jmp     load_with_seg_check               ;  updating the selecotr if needed

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

        assumes ds,nothing
        assumes es,nothing

copy_e1i4       proc near

        push    di

        add     di,width_scan                     ;Start with second plane.
        push    si
        push    di
        push    cx
        call    convert_C1
        pop     cx
        pop     di
        pop     si

        add     di,width_scan
        push    si
        push    di
        push    cx
        call    convert_C2
        pop     cx
        pop     di
        pop     si

        add     di,width_scan
        push    si
        push    cx
        call    convert_C3
        pop     cx
        pop     si

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

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

        assumes ds,nothing
        assumes es,nothing

copy_e1i4_partial proc near

        push    di

        add     di,width_scan
        mov     cx,1                              ;Only want to grab a single byte
        call    convert_C1
        dec     si
        dec     di

        add     di,width_scan
        mov     cx,1
        call    convert_C2
        dec     si
        dec     di

        add     di,width_scan
        mov     cx,1
        call    convert_C3
        dec     si

        pop     di
        mov     cx,1
        call    convert_C0
        dec     si                                ;Let load_with_seg_check deal with
        jmp     load_with_seg_check               ;  updating the selecotr if needed

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

        assumes ds,nothing
        assumes es,nothing

copy_e4i4       proc near

        mov     temp_byte_count,cx

ce4i4_next_dest_byte:
        mov     temp_bit_count,4                  ;Four source bytes per dest byte
        lea     bx,color_xlate

ce4i4_next_byte:
        lodsb                                     ;Get 2 bits worth of source data
        mov     ah,al
        shr     al,4
        xlat    ss:[bx]                           ;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    ss:[bx]                           ;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     bx,width_scan
        mov     es:[di][bx],ch                    ;Save C1
        add     di,bx
        mov     es:[di][bx],dl                    ;Save C2
        shl     bx,1
        mov     es:[di][bx],dh                    ;Save C3
        shr     bx,1
        sub     di,bx
        mov     al,cl
        stosb                                     ;Save C0
        dec     temp_byte_count
        jnz     ce4i4_next_dest_byte
        ret

copy_e4i4       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e8i4       proc near

        mov     temp_byte_count,cx

ce8i4_next_dest_byte:
        mov     ah,8                              ;Eight source bytes per dest byte
        lea     bx,color_xlate

ce8i4_next_byte:
        lodsb                                     ;Get 2 bits of source data
        xlat    ss:[bx]                           ;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     bx,width_scan
        mov     es:[di][bx],ch                    ;Save C1
        add     di,bx
        mov     es:[di][bx],dl                    ;Save C2
        shl     bx,1
        mov     es:[di][bx],dh                    ;Save C3
        shr     bx,1
        sub     di,bx
        mov     al,cl
        stosb                                     ;Save C0
        dec     temp_byte_count
        jnz     ce8i4_next_dest_byte
        ret

copy_e8i4       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e24i4      proc near

        mov     temp_byte_count,cx

ce24i4_next_dest_byte:
        mov     temp_bit_count,8                 ;Conversions per destination byte

ce24i4_next_byte:
        lodsw
        xchg    ax,dx
        lodsb
        xchg    ax,dx
        call    far_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    ax,bx
        mov     bx,width_scan
        mov     es:[di][bx],ah                    ;Save C1
        add     di,bx
        mov     es:[di][bx],cl                    ;Save C2
        shl     bx,1
        mov     es:[di][bx],ch                    ;Save C3
        shr     bx,1
        sub     di,bx
        stosb                                     ;Save C0
        dec     temp_byte_count
        jnz     ce24i4_next_dest_byte
        ret

copy_e24i4      endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e4i1       proc near

        lea     bx,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    ss:[bx]                           ;Get the actual colors to use
        shl     al,4
        errnz   MONO_BIT-00010000b
        rcl     dh,1
        mov     al,ah
        and     al,00001111b
        xlat    ss:[bx]
        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

copy_e4i1       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e8i1       proc near

ce8i1_next_dest_byte:
        mov     ah,8                              ;Eight source bytes per dest byte
        lea     bx,color_xlate

ce8i1_next_byte:
        lodsb                                     ;Get 1 bit of source data
        xlat    ss:[bx]                           ;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

copy_e8i1       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e24i1      proc near

ce24i1_next_dest_byte:
        mov     bh,8                              ;8 conversion per destination byte

ce24i1_next_byte:
        lodsw
        xchg    ax,dx
        lodsb
        xchg    ax,dx
        call    far_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

copy_e24i1      endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e4i4_partial proc near

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

ce4i4p_next_byte:
        call    load_with_seg_check               ;Get 2 bits of source data
        mov     ah,al
        shr     al,4
        xlat    ss:[bx]                           ;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    ss:[bx]
        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     bx                                ;Restore masking and alignment
        call    align_and_store_all
        ret

copy_e4i4_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e8i4_partial proc near

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

ce8i4p_next_byte:
        call    load_with_seg_check               ;Get 2 bits of source data
        xlat    ss:[bx]                           ;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     bx                                ;restore masking and alignment
        call    align_and_store_all
        ret

copy_e8i4_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e24i4_partial proc near

        push    bx                                ;Save masking and alignment control
        xor     ch,ch
        mov     temp_byte_count,cx

ce24i4p_next_byte:
        cmp     si,0FFFCh                         
                                                  
        ja      ce24i4p_next_seg
        lodsw
        xchg    ax,dx
        lodsb
        xchg    ax,dx

ce24i4p_have_source:
        call    far_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     bx                                ;restore masking and alignment
        call    align_and_store_all
        ret

ce24i4p_next_seg:
        call    load_with_seg_check
        xchg    al,ah
        call    load_with_seg_check
        xchg    al,ah
        xchg    dx,ax
        call    load_with_seg_check
        xchg    dx,ax
        jmp     ce24i4p_have_source


copy_e24i4_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e4i1_partial proc near

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

ce4i1p_next_byte:
        call    load_with_seg_check               ;Get 2 bits of source data
        mov     ah,al
        shr     al,4
        xlat    ss:[bx]                           ;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    ss:[bx]
        shl     al,4
        rcl     ch,1
        errnz   MONO_BIT-00010000b
        dec     cl
        jnz     ce4i1p_next_byte

ce4i1p_save_byte:
        mov     al,ch
        mov     bx,dx                             ;Restore masking and alignment control
        call    align_and_store
        ret

copy_e4i1_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e8i1_partial proc near

        mov     dx,bx                             ;Save masking and alignment control
        lea     bx,color_xlate

ce8i1p_next_byte:
        call    load_with_seg_check
        xlat    ss:[bx]
        shl     al,4
        rcl     ch,1
        errnz   MONO_BIT-00010000b
        dec     cl
        jnz     ce8i1p_next_byte

ce8i1p_save_byte:
        mov     al,ch
        mov     bx,dx                             ;Restore masking and alignment control
        call    align_and_store
        ret

copy_e8i1_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_e24i1_partial proc near

ce24i1p_next_byte:
        cmp     si,0FFFDh
        jae     ce24i1p_next_seg
        lodsw
        xchg    ax,dx
        lodsb
        xchg    ax,dx

ce24i1p_have_source:
        call    far_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:
        call    load_with_seg_check
        xchg    al,ah
        call    load_with_seg_check
        xchg    al,ah
        xchg    dx,ax
        call    load_with_seg_check
        xchg    dx,ax
        jmp     ce24i1p_have_source

copy_e24i1_partial endp

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE load_with_seg_check
;*
;* DESCRIPTION   = The contents of DS:SI is loaded into AL.  If SI becomes
;*                 0, then the next destination selector (if it exists) will
;*                 be loaded.
;*                                                                                       
;*                 Registers Preserved:        
;*                       AL,BX,CX,DX,SI,BP,DS,BP
;*                 Registers Destroyed:        
;*                       FLAGS  
;*
;* INPUT         = DS:SI --> destination                                
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = DS:SI --> next destination byte
;*                 CX = 1 if no next segment, to terminate any loop
;*                 AH = 1 if no next segment, to terminate any loop
;* RETURN-ERROR  = NONE
;*
;**************************************************************************/

        assumes ds,nothing
        assumes es,nothing

load_with_seg_check proc near

        lodsb                                     ;Get the byte
        or      si,si                             ;If in the next segment
        jnz     lwsc_exit                         ;  then update to the next selector
        push    ax
        push    dx
        mov     dx,ds
        add     dx,DOSHUGEINCR

        lar     ax,dx
        jnz     lwsc_no_more_selectors            ;Next selector is invalid

lwsc_load_next:
        mov     ds,dx
        assumes ds,nothing
        pop     dx
        pop     ax
        ret

lwsc_no_more_selectors:
        pop     dx
        pop     ax
        mov     cx,1                              ;Set possible loop counters to 1 so
        mov     ah,cl                             ;  they will terminate

lwsc_exit:
        ret

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

        assumes ds,nothing
        assumes es,nothing

align_and_store_all proc near

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

align_and_store_all endp

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

        assumes ds,nothing
        assumes es,nothing

align_and_store proc near

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

align_and_store 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  load_with_seg_check 
        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_huge_bitmap
        public  eti_finish_y_calc
        public  eti_next_scan
        public  eti_in_segment
        public  eti_see_about_partial
        public  eti_no_partial_byte
        public  eti_chk_segment_update
        public  eti_might_cross_seg
        public  eti_looking_to_cross
        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  ce24i4p_next_seg
        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
        public  lwsc_load_next
        public  lwsc_no_more_selectors
        public  lwsc_exit

sEnd    Bitmap
end
