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

        .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 njmp.mac
        include assert.mac
        include bmi2.inc
        .list
        .286p


        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 far_check_bitmap_info

sBegin  Bitmap
        assumes cs,Bitmap

        externW  BitmapData

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

anpfnPreProc    label   word
        dw      ite_1
        dw      ite_4
        dw      ite_8
        dw      ite_24

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


temp_color_table label byte
        dd      00000000h                         ;Black
        dd      00000080h                         ;Blue
        dd      00008000h                         ;Green
        dd      00008080h                         ;Cyan
        dd      00800000h                         ;Red
        dd      00800080h                         ;Magenta
        dd      00808000h                         ;Yellow
        dd      00808080h                         ;White
ifdef VGA
        dd      00CCCCCCh                         ;Light Gray
else
        dd      00202020h                         ;Black
endif
        dd      000000FFh                         ;Blue
        dd      0000FF00h                         ;Green
        dd      0000FFFFh                         ;Cyan
        dd      00FF0000h                         ;Red
        dd      00FF00FFh                         ;Magenta
        dd      00FFFF00h                         ;Yellow
        dd      00FFFFFFh                         ;White

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

fixed_color_table label byte
        db      000h,000h,000h                    ;Black
        db      080h,000h,000h                    ;Blue
        db      000h,080h,000h                    ;Green
        db      080h,080h,000h                    ;Cyan
        db      000h,000h,080h                    ;Red
        db      080h,000h,080h                    ;Magenta
        db      000h,080h,080h                    ;Yellow
        db      080h,080h,080h                    ;White
ifdef VGA
        db      0CCh,0CCh,0CCh                    ;Light Gray
else
        db      020h,020h,020h                    ;Black
endif
        db      0FFh,000h,000h                    ;Blue
        db      000h,0FFh,000h                    ;Green
        db      0FFh,0FFh,000h                    ;Cyan
        db      000h,000h,0FFh                    ;Red
        db      0FFh,000h,0FFh                    ;Magenta
        db      000h,0FFh,0FFh                    ;Yellow
        db      0FFh,0FFh,0FFh                    ;White

SIZE_FIXED_COLOR_TABLE  = $-fixed_color_table

fixed_color_table2 label byte
        db      000h,000h,000h,000h               ;Black
        db      080h,000h,000h,000h               ;Blue
        db      000h,080h,000h,000h               ;Green
        db      080h,080h,000h,000h               ;Cyan
        db      000h,000h,080h,000h               ;Red
        db      080h,000h,080h,000h               ;Magenta
        db      000h,080h,080h,000h               ;Yellow
        db      080h,080h,080h,000h               ;White
ifdef VGA
        db      0CCh,0CCh,0CCh,000h               ;Light Gray
else
        db      020h,020h,020h,000h               ;Black
endif
        db      0FFh,000h,000h,000h               ;Blue
        db      000h,0FFh,000h,000h               ;Green
        db      0FFh,0FFh,000h,000h               ;Cyan
        db      000h,000h,0FFh,000h               ;Red
        db      0FFh,000h,0FFh,000h               ;Magenta
        db      000h,0FFh,0FFh,000h               ;Yellow
        db      0FFh,0FFh,0FFh,000h               ;White

SIZE_FIXED_COLOR_TABLE2 = $-fixed_color_table2

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

DEFAULT_VALUE      equ    000000000h

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

        assumes ds,nothing
        assumes es,nothing

cProc   bmc_int_to_ext,<NEAR,PASCAL,PUBLIC,NODATA,NONWIN>,<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
        parmD   DummyParameter1                   ; Used by some drivers, but not EGA

        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                ;# bits to xlate in last source byte
        localW  partial_byte_proc                 ;Routine which xlates partial bytes
        localW  huge_scans_left                   ;Count of scans left in huge segment
        localW  some_temp                         ;Byte count for segment crossings
        localW  buffer_adjust                     ;Alignment for each scan of buffer
        localW  temp_byte_count                   ;Work area for conversion routines
        localW  rgb_size                          ;3 bytes for old format, 4 for new

        localD  scan_length                       ;length of one buffer scanline

        localB  fbsd                              ;Bunch of flags

cBegin
        .386P
        push    esi
        .286P

ifdef   FIREWALLS
        mov     ds,BitmapData
        assumes ds,Data
        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

        mov     ds,BitmapData
        assumes ds,Data
        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     ite_log_error
        mov     bx,PMERR_INV_LENGTH_OR_COUNT
        cmp     cyScans.hi,ax
        je      ite_numbers_ok
ite_log_error:
        xchg    ax,bx
        save_error_code
        mov     ax,-1
ite_get_out:
        jmp     ite_exit

ite_inv_format:
        mov     bx,PMERR_INV_INFO_TABLE
        jmp     ite_log_error

ite_numbers_ok:
        les     bx,pbmi                           ;Validate bitmap info structure
        assumes es,nothing
        xor     cx,cx                             ; only check required fields
        call    far_check_bitmap_info
        jcxz    ite_inv_format

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

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

        mov     di,npbm
        mov     ax,[di].bm_sd.sd_cx              ;Must set height and width before
        mov     bitmap_width,ax                  ;  checking for a null bitmap
        mov     dx,[di].bm_sd.sd_cy              ;Preserve AX and DX until height
        mov     bitmap_height,dx                 ;and width are set below
        .386P
        cmp     es:[bx].bmi2_cbFix,SIZE BITMAPINFOHEADER
        .286P
        jne     ite_new_header
        mov     es:[bx].bmi_cx,ax
        mov     es:[bx].bmi_cy,dx
        mov     rgb_size,(SIZE RGB)
        jmp     ite_done_with_bmi
ite_new_header:                             ; fill in remaining fields
        assumes ds,Data
        push    si                          ; save si
        assert  es:[bx].bmp2_cbFix.hi,E,0   ; cbFix must be valid by this point
        mov     si,es:[bx].bmp2_cbFix.lo
        assert  si,LE,64
        .errnz  (SIZE BITMAPINFOHEADER2)-64
        shr     si,1
        assert  NC
        add     si,DataOFFSET ok_cbFix
        .386P
        movzx   si,[si]
        .286P
        assert  si,NE,0                     ; cbFix not invalid
        add     si,BitmapOFFSET bmi2_fill_point
        .386P
        movzx   si,cs:[si]
        .286P
        add     si,BitmapOFFSET ite_ulIdentifier
        jmp     si
ite_ulIdentifier:
ite_ulColorEncoding:
ite_cSize2:
        .386P
        mov     es:[bx].bmi2_cSize2,DEFAULT_VALUE
ite_cSize1:
        mov     es:[bx].bmi2_cSize1,DEFAULT_VALUE
ite_usRendering:
ite_usRecording:
ite_usReserved:
ite_usUnits:
        mov     es:[bx].bmi2_usUnits,BRU_METRIC
ite_cclrImportant:
        mov     cx,es:[bx].bmi2_cBitCount
        mov     esi,1
        shl     si,cl                             ;24-bpp ==> SI = 0
        mov     es:[bx].bmi2_cclrImportant,esi
        jmp     SHORT ite_already_computed_colors
ite_cclrUsed:
        mov     cx,es:[bx].bmi2_cBitCount
        mov     esi,1
        shl     si,cl                             ;24-bpp ==> SI = 0
ite_already_computed_colors:
        mov     es:[bx].bmi2_cclrUsed,esi
ite_cyResolution:
        mov     es:[bx].bmi2_cyResolution,DEFAULT_VALUE
ite_cxResolution:
        mov     es:[bx].bmi2_cxResolution,DEFAULT_VALUE
ite_cbImage:
        mov     es:[bx].bmi2_cbImage,DEFAULT_VALUE
        .286P
ite_ulCompression:
ite_cBitCount:
        mov     es:[bx].bmi2_cx.lo,ax
        mov     es:[bx].bmi2_cy.lo,dx
        mov     es:[bx].bmi2_cx.hi,0
        mov     es:[bx].bmi2_cy.hi,0
        mov     rgb_size,(SIZE RGB2)
        pop     si                                ; restore si

ite_done_with_bmi:
        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
        njz     ite_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      ite_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

ite_isnt_huge_bitmap:

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

        mov     cx,iStart.lo
        mov     bx,bitmap_height
        cmp     cx,bx                             ;If starting scan is outside bitmap
        jb      @F                                ;  want count to become 0 so we'll
        mov     cx,bx                             ;  exit after color table is set
@@:     sub     bx,cx                             ;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
        add     di,es:[di].bmi2_cbFix.lo         ;ES:DI --> where color table is
        call    si

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

        CPUMode 386

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

        CPUMode 286

        cmp     scanline_count,0
        nje     ite_xfered_all

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


        mov     ax,bitmap_height                 ;Invert the Y coordinate
        sub     ax,iStart.lo
        dec     ax
        xor     dx,dx
        test    fbsd,SD_HUGE
        jz      ite_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

ite_huge_bitmap:
        add     dx,cx                             ;Show in next segment
        sub     ax,bx                             ;See if in this segment
        jnc     ite_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
        jl      ite_finish_y_calc                 ;  we'll skip huge bitmap stuff
        and     fbsd,not SD_HUGE

ite_finish_y_calc:
        add     dx,lp_bits.sel                    ;Source is our bitmap
        mov     ds,dx
        assumes ds,nothing

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

        les     di,pBuf                           ;Dest is user's buffer (this pointer
        assumes es,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,di
        adc     dx,0                              ;DX:AX = last address + 1
        jz      ite_in_segment                    ;Won't cross a segment boundary
        or      fbsd,CAN_CROSS_SEG ;Can cross a segment boundary

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

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

ite_see_about_partial:
        mov     cx,partial_byte_flags             ;Process any partial byte
        jcxz    ite_no_partial_byte
        call    partial_byte_proc

ite_no_partial_byte:
        pop     si
        dec     scanline_count
        jz      ite_xfered_all                    ;Transfered all scans

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

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

        dec     huge_scans_left                   ;Any more scans in this segment?
        jnz     ite_next_scan                     ;  No, don't update bitmap pointer
        mov     ax,ds
        sub     ax,DOSHUGEINCR                    ;We're working from bottom up
        mov     ds,ax
        assumes ds,nothing
        mov     si,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     ite_next_scan


ite_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,di                             ;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      ite_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    si                                ;Save bitmap scan start address
        mov     cx,scan_byte_count                ;If only a last byte exists,
        jcxz    ite_see_about_partial             ;  use the normal code
        mov     some_temp,cx                      ;Save full byte count

ite_looking_to_cross:
        mov     cx,8                              ;Always xlate 8 pixels of data
        call    partial_byte_proc
        dec     some_temp
        jnz     ite_looking_to_cross
        jmp     ite_see_about_partial             ;Finish with partial byte code

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

ite_xfered_all:
        les     bx,pbmi                           ;calculate the number of bytes returned
        assumes es,nothing

        CPUMode 386

        cmp     es:[bx].bmp2_cbFix,bmp2_cbImage
        jbe     short ite_return_val
        mov     ax,es:[bx].bmp2_cBitCount
        mul     es:[bx].bmp2_cx.lo
        add     ax,31                   ;Don't forget 32 bit aligned
        adc     dx,0
        shrd    ax,dx,3
        and     ax,not 3
        mul     scans_copied            ;multiply with the number of scans
        mov     es:[bx].bmp2_cbImage.lo,ax
        mov     es:[bx].bmp2_cbImage.hi,dx

        CPUMode 286

ite_return_val:
        mov     ax,scans_copied                  ;Return number of scans copied
        xor     dx,dx

ite_exit:
        cwd
        fw_zero <cx,es>

        .386P
        pop     esi
        .286P

cEnd

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

        assumes ds,nothing
        assumes es,nothing

ite_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,BitmapOFFSET copy_i1e1        ;Assume monochrome bitmap
        mov     bx,BitmapOFFSET copy_i1e1_partial
        test    fbsd,SD_COLOR                    ;Monochrome source?
        jz      ite_1_have_proc                  ;  Yes

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

        mov     ax,BitmapOFFSET copy_i4e1        ;Color bitmap
        mov     bx,BitmapOFFSET copy_i4e1_partial

ite_1_have_proc:
        mov     full_byte_proc,ax
        mov     partial_byte_proc,bx

;/*
;**       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
                                                  ;  for one bitmap scan
        mov     cx,2                              ;Two color table entries
        call    create_mono_color_table
        ret

ite_1   endp

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

        assumes ds,nothing
        assumes es,nothing

ite_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
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jnz     ite_4_not_mono                    ;Not mono, must be color
        call    create_mono_color_table
        mov     ax,BitmapOFFSET copy_i1e4
        mov     bx,BitmapOFFSET copy_i1e4_partial
        jmp     short ite_4_have_proc

ite_4_not_mono:
        call    create_color_color_table
        mov     ax,BitmapOFFSET copy_i4e4
        mov     bx,BitmapOFFSET copy_i4e4_partial

ite_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

ite_4   endp
page

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

        assumes ds,nothing
        assumes es,nothing

ite_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
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jnz     ite_8_not_mono                    ;Not mono, must be color
        call    create_mono_color_table
        mov     ax,BitmapOFFSET copy_i1e8
        mov     bx,BitmapOFFSET copy_i1e8_partial
        jmp     short ite_8_have_proc

ite_8_not_mono:
        call    create_color_color_table
        mov     ax,BitmapOFFSET copy_i4e8
        mov     bx,BitmapOFFSET copy_i4e8_partial

ite_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 nibble becomes
        mov     bx,ax                             ;  a double word in the destination
        shr     ax,3
        mov     scan_byte_count,ax
        and     bl,11111100b                      ;1 source nibble = 4 dest bytes
        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
        ret

ite_8   endp

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

        assumes ds,nothing
        assumes es,nothing

ite_24  proc    near

        mov     ax,BitmapOFFSET copy_i1e24
        mov     bx,BitmapOFFSET copy_i1e24_partial
        test    fbsd,SD_COLOR                     ;Monochrome source?
        jz      ite_24_have_proc                  ;  Yes

ite_24_not_mono:
        mov     ax,BitmapOFFSET copy_i4e24
        mov     bx,BitmapOFFSET copy_i4e24_partial

ite_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
        add     ax,cx                             ;Need to round up to a double word
        adc     dx,0
        and     al,11111100b
        mov     scan_length.lo,ax                 ;Set # bytes of user buffer required
        mov     scan_length.hi,dx
        and     bx,00000111b                      ;Can have up to 7 bits in the last
        mov     partial_byte_flags,bx             ;  byte to convert
        and     bl,00000011b                      ;Compute number of bytes to pad with
        mov     buffer_adjust,bx
        ret

ite_24  endp

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

        assumes ds,nothing
        assumes es,nothing


create_mono_color_table proc near

        dec     cx
        mov     ax,rgb_size
        mul     cx
        mov     cx,ax
        xor     ax,ax
        shr     cx,1
        rep     stosw
        rcl     cx,1
        rep     stosb
        dec     ax
        stosw
        stosb
        cmp     rgb_size,(size RGB)
        je      cmct_end
        .errnz  (size RGB)-3
        .errnz  (size RGB2)-4
        inc     ax
        stosb

cmct_end:
        ret

create_mono_color_table endp

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

        assumes ds,nothing
        assumes es,nothing

create_color_color_table proc near

        mov     bx,cx                             ;Save total table count
        xchg    ax,si                             ;Don't destroy si

        cmp     rgb_size,(SIZE RGB)
        jne     ccct_new_rgb
        mov     si,BitmapOFFSET fixed_color_table
        mov     cx,(SIZE_FIXED_COLOR_TABLE) shr 2
        .errnz  (SIZE_FIXED_COLOR_TABLE) AND 3
        .386P
        rep     movs dword ptr es:[di], word ptr cs:[si]
        .286P
        jmp     ccct_done_with_fixed_table

ccct_new_rgb:
        assert  rgb_size,E,4
        .errnz  (SIZE RGB2)-4
        mov     si,BitmapOFFSET fixed_color_table2
        mov     cx,(SIZE_FIXED_COLOR_TABLE2) shr 2
        .errnz  (SIZE_FIXED_COLOR_TABLE2) AND 3
        .386P
        rep     movs dword ptr es:[di], word ptr cs:[si]
        .286P

ccct_done_with_fixed_table:
        xchg    ax,si                             ;Restore caller's SI
        sub     bx,16                             ;number of fixed colors
        jle     ccct_exit                         ;All done
        mov     cx,bx
        mov     ax,rgb_size
        mul     cx
        mov     cx,ax
        xor     ax,ax                             ;Fill rest of table with black
        shr     cx,1
        rep     stosw
        rcl     cx,1
        rep     stosb

ccct_exit:
        ret

create_color_color_table endp

page

xlate_1_to_4    label   word

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

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

        assumes ds,nothing
        assumes es,nothing

        public  copy_i1e1

copy_i1e1       proc    near

        xchg    ax,cx                             ;Save count of bytes to mov in AX
        xor     cx,cx
        ror     si,1                              ;Set 'C' if source on odd boundary
        rcl     cx,1                              ;CX = 1 if on odd boundary
        sub     ax,cx
        rol     si,1                              ;Restore initial source address
        rep     movsb                             ;Move possible odd aligned byte
        xchg    ax,cx                             ;Move complete words
        shr     cx,1
        rep     movsw
        rcl     cx,1                              ;Process trailing odd byte
        rep     movsb
        ret

copy_i1e1       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i1e4       proc    near

        mov     dx,00011110b                      ;Mask for bits to convert

ci1e4_next_byte:
        lodsb
        mov     bx,ax
        shr     bl,3
        and     bx,dx
        mov     bx,xlate_1_to_4[bx]
        xchg    ax,bx
        xchg    ah,al
        stosw
        shl     bx,1
        and     bx,dx
        mov     ax,xlate_1_to_4[bx]
        xchg    ah,al
        stosw
        loop    ci1e4_next_byte
        ret

copy_i1e4       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i1e4_partial proc near

        mov     bx,BitmapOFFSET xlate_1_to_4 + 1
        lodsb
        mov     ah,al
        shr     cx,1                              ;/2 for number of iterations
        xor     ch,ch

ci1e4p_next_byte:
        rol     ax,2
        and     al,00000011b
        shl     ax,1                              ;Fetching bytes from a word table
        xlat    cs:[bx]
        call    store_with_seg_check
        loop    ci1e4p_next_byte
        ret

copy_i1e4_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i1e8       proc    near

ci1e8_next_byte:
        lodsb
        xchg    ax,bx
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        shl     bl,1
        sbb     al,al
        shl     bl,1
        sbb     ah,ah
        stosw
        loop    ci1e8_next_byte
        ret

copy_i1e8       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i1e8_partial proc near

        lodsb
        xchg    ax,bx
        xor     ch,ch

ci1e8p_next_byte:
        shl     bl,1
        sbb     al,al
        call    store_with_seg_check
        loop    ci1e8p_next_byte
        ret

copy_i1e8_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i1e24      proc    near

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

copy_i1e24      endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i1e24_partial proc near

        lodsb
        xchg    ax,dx
        xor     ch,ch

ci1e24p_next_byte:
        shl     dl,1
        sbb     ax,ax
        cmp     di,0FFFDh                         ;If within 3 bytes, then will have
        jae     ci1e24p_next_sel                  ;  to update the selector
        stosw
        stosb

ci1e24p_loop_next:
        loop    ci1e24p_next_byte

ci1e24p_no_more_sels:
        ret

ci1e24p_next_sel:
        call    store_with_seg_check
        call    store_with_seg_check
        call    store_with_seg_check
        jmp     ci1e24p_loop_next

copy_i1e24_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i1e1_partial proc near

        lodsb
        errn$   store_with_seg_check

copy_i1e1_partial endp

page

;/***************************************************************************
;*
;* PRIVATE ROUTINE store_with_seg_check
;*
;* DESCRIPTION   = The contents of ES:DI is loaded into AL.  If DI 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         = ES:DI --> destination
;*
;* OUTPUT        = NONE
;*
;* RETURN-NORMAL = ES:DI --> 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

store_with_seg_check proc near

        stosb                                     ;Save the byte
        or      di,di                             ;If not in the next segment
        jnz     swsc_exit                         ;  then skip selector update
        push    ax
        push    dx
        mov     dx,es
        add     dx,DOSHUGEINCR

        lar     ax,dx
        jnz     swsc_no_more_selectors            ;Next selector is invalid

swsc_load_next:
        mov     es,dx
        assumes es,nothing
        pop     dx
        pop     ax
        ret

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

swsc_exit:
        ret

store_with_seg_check endp

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


        assumes ds,nothing
        assumes es,nothing

copy_i4e1       proc  near


        mov     bx,width_scan

ci4e1_next_byte:
        add     si,bx
        shl     bx,1
        mov     dh,[si][bx]                       ;Get C3 color
        shr     bx,1
        mov     dl,[si][bx]                       ;Get C2 color
        mov     ah,[si]                           ;Get C1 color
        sub     si,bx
        lodsb                                     ;Get C0 color, update source pointer
        and     ax,dx                             
        and     al,ah
        stosb
        loop    ci4e1_next_byte
        ret

copy_i4e1       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i4e1_partial proc near


        mov     bx,width_scan
        add     si,bx
        shl     bx,1
        mov     dh,[si][bx]                       ;Get C3 color
        shr     bx,1
        mov     dl,[si][bx]                       ;Get C2 color
        mov     ah,[si]                           ;Get C1 color
        sub     si,bx
        lodsb                                     ;Get C0 color, update source pointer
        and     ax,dx                             
        and     al,ah
        jmp     store_with_seg_check

copy_i4e1_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i4e4       proc near


        mov     bx,width_scan
        push    bp
        mov     bp,cx                             ;Use BP for loop counter

ci4e4_next_byte:
        add     si,bx
        shl     bx,1
        mov     dh,[si][bx]                       ;Get C3 color
        shr     bx,1
        mov     dl,[si][bx]                       ;Get C2 color
        mov     ch,[si]                           ;Get C1 color
        sub     si,bx
        mov     cl,[si]                           ;Get C0 color, update source pointer
        inc     si

        mov     ah,4                              ;Set # bytes to write

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

copy_i4e4       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i4e4_partial proc near


        mov     bx,width_scan
        add     si,bx
        shl     bx,1
        mov     dh,[si][bx]                       ;Get C3 color
        shr     bx,1
        mov     dl,[si][bx]                       ;Get C2 color
        mov     ah,[si]                           ;Get C1 color
        sub     si,bx
        lodsb                                     ;Get C0 color, update source pointer
        xchg    ax,cx
        mov     ah,al
        shr     ah,1                              ;/2 for correct number of iterations

ci4e4p_next_byte:
        shl     dh,1                              ;Collect 1st nibble
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1
        shl     dh,1                              ;Collect 2nd nibble
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1
        call    store_with_seg_check
        dec     ah
        jnz     ci4e4p_next_byte
        ret

copy_i4e4_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i4e8       proc near


        mov     bx,width_scan
        push    bp
        mov     bp,cx                             ;Use BP for loop counter

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

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

copy_i4e8       endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i4e8_partial proc near


        mov     bx,width_scan
        add     si,bx
        shl     bx,1
        mov     dh,[si][bx]                       ;Get C3 color
        shr     bx,1
        mov     dl,[si][bx]                       ;Get C2 color
        mov     ah,[si]                           ;Get C1 color
        sub     si,bx
        lodsb                                     ;Get C0 color, update source pointer
        xchg    ax,cx
        mov     ah,al

ci4e8p_next_byte:
        xor     al,al                             ;Collect and store a nibble
        shl     dh,1
        rcl     al,1
        shl     dl,1
        rcl     al,1
        shl     ch,1
        rcl     al,1
        shl     cl,1
        rcl     al,1
        call    store_with_seg_check
        dec     ah
        jnz     ci4e8p_next_byte
        ret

copy_i4e8_partial endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i4e24      proc near


        mov     temp_byte_count,cx               ;Save # bytes to xlate

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

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

        mov     al,temp_color_table[si][2]
        mov     si,word ptr temp_color_table[si][0]

        xchg    ax,si
        stosw
        xchg    ax,si
        stosb
        dec     ah
        jnz     ci4e24_next_dest_byte
        xchg    si,bx
        dec     temp_byte_count
        jnz     ci4e24_next_byte
        ret

copy_i4e24      endp

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

        assumes ds,nothing
        assumes es,nothing

copy_i4e24_partial proc near



        mov     bx,width_scan
        add     si,bx
        shl     bx,1
        mov     dh,[si][bx]                       ;Get C3 color
        shr     bx,1
        mov     dl,[si][bx]                       ;Get C2 color
        mov     ah,[si]                           ;Get C1 color
        sub     si,bx
        lodsb                                     ;Get C0 color, update source pointer
        xchg    ax,cx
        mov     ah,al                             ;Set number of pixels to xlate
        xchg    si,bx

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

        mov     al,temp_color_table[si][2]
        mov     si,word ptr temp_color_table[si][0]

        cmp     di,0FFFDh
        ja      ci4e24p_next_sel
        xchg    ax,si
        stosw
        xchg    ax,si
        stosb

ci4e24p_loop_next:
        dec     ah
        jnz     ci4e24p_next_byte

ci4e24p_no_more_sels:
        xchg    si,bx
        ret

ci4e24p_next_sel:
        xchg    ax,si
        call    store_with_seg_check
        xchg    al,ah
        call    store_with_seg_check
        xchg    al,ah
        xchg    ax,si
        call    store_with_seg_check
        jmp     ci4e24p_loop_next

copy_i4e24_partial endp

sEnd    Bitmap
end
