Annotation of ntddk/src/video/displays/vga/i386/blt.asm, revision 1.1.1.1

1.1       root        1:         page    ,132
                      2:         title   BitBLT
                      3: ;---------------------------Module-Header------------------------------;
                      4: ; Module Name: blt.asm
                      5: ;
                      6: ; Copyright (c) 1992 Microsoft Corporation
                      7: ;-----------------------------------------------------------------------;
                      8:         .386
                      9: 
                     10: ifndef  DOS_PLATFORM
                     11:         .model  small,c
                     12: else
                     13: ifdef   STD_CALL
                     14:         .model  small,c
                     15: else
                     16:         .model  small,pascal
                     17: endif;  STD_CALL
                     18: endif;  DOS_PLATFORM
                     19: 
                     20:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
                     21:         assume fs:nothing,gs:nothing
                     22: 
                     23:         .code
                     24: 
                     25: _TEXT$02   SEGMENT DWORD USE32 PUBLIC 'CODE'
                     26:            ASSUME  CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
                     27: 
                     28:         .xlist
                     29:         include stdcall.inc         ; calling convention cmacros
                     30: 
                     31:         include i386\cmacFLAT.inc   ; FLATland cmacros
                     32:         include i386\display.inc    ; Display specific structures
                     33:         include i386\ppc.inc        ; Pack pel conversion structure
                     34:         include i386\bitblt.inc     ; General definitions
                     35:         include i386\ropdefs.inc    ; Rop definitions
                     36:         include i386\roptable.inc   ; Raster op tables
                     37:         include i386\egavga.inc     ; EGA register definitions
                     38:         include i386\strucs.inc     ; Structure definitions
                     39:         .list
                     40: 
                     41: 
                     42:         EXTRNP  cblt
                     43:         EXTRNP  check_device_special_cases
                     44:         EXTRNP  packed_pel_comp_y
                     45:         EXTRNP  vDIB4Preprocess
                     46:         EXTRNP  vDIB8Preprocess
                     47: 
                     48: ; The following two bitmask tables are used for fetching
                     49: ; the first and last byte used-bits bitmask.
                     50: 
                     51:         public bitmask_tbl1
                     52: bitmask_tbl1    label   byte
                     53:         db      11111111b               ;Masks for leftmost byte
                     54:         db      01111111b
                     55:         db      00111111b
                     56:         db      00011111b
                     57:         db      00001111b
                     58:         db      00000111b
                     59:         db      00000011b
                     60:         db      00000001b
                     61: 
                     62:         public  bitmask_tbl2
                     63: bitmask_tbl2    label   byte
                     64:         db      10000000b               ;Masks for rightmost byte
                     65:         db      11000000b
                     66:         db      11100000b
                     67:         db      11110000b
                     68:         db      11111000b
                     69:         db      11111100b
                     70:         db      11111110b
                     71:         db      11111111b
                     72: 
                     73: ; phase_tbl1 is used for loading the "used" bits and "saved" bits
                     74: ; bitmasks for cases 1,2,3 where the step direction is left to
                     75: ; right.  If it weren't for the case of zero, this could be done
                     76: ; with a simple rotate of 00FF.   For cases 4,5,6, a simple rotate
                     77: ; can create the mask needed.
                     78: 
                     79:         public  phase_tbl1
                     80: phase_tbl1      label   word
                     81:         db      11111111b,00000000b             ;Used bits, saved bits
                     82:         db      00000001b,11111110b
                     83:         db      00000011b,11111100b
                     84:         db      00000111b,11111000b
                     85:         db      00001111b,11110000b
                     86:         db      00011111b,11100000b
                     87:         db      00111111b,11000000b
                     88:         db      01111111b,10000000b
                     89: 
                     90: ProcName    xxxvCompiledBlt,vCompiledBlt,56
                     91: 
                     92: xxxvCompiledBlt proc uses esi edi ebx,\
                     93:         __pdsurfDst     :ptr,   \
                     94:         __DestxOrg      :dword, \
                     95:         __DestyOrg      :dword, \
                     96:         __pdsurfSrc     :ptr,   \
                     97:         __SrcxOrg       :dword, \
                     98:         __SrcyOrg       :dword, \
                     99:         __xExt          :dword, \
                    100:         __yExt          :dword, \
                    101:         __Rop           :dword, \
                    102:         __lpPBrush      :ptr,   \
                    103:         __bkColor       :dword, \
                    104:         __TextColor     :dword, \
                    105:         __pulXlateVec   :dword, \
                    106:         __pptlBrush     :ptr
                    107: 
                    108:         local       fr[SIZE FRAME]:byte
                    109: 
                    110:         cld                             ;Let's make no assumptions about this!
                    111: 
                    112: ; We be hacking, so copy all the parameters into the local frame right now,
                    113: ; so that the subroutines will have access to them.
                    114: 
                    115:         mov         eax,__pdsurfDst
                    116:         mov         fr.pdsurfDst,eax
                    117:         mov         eax,__DestxOrg
                    118:         mov         fr.DestxOrg,ax
                    119:         mov         eax,__DestyOrg
                    120:         mov         fr.DestyOrg,ax
                    121:         mov         eax,__pdsurfSrc
                    122:         mov         fr.pdsurfSrc,eax
                    123:         mov         eax,__SrcxOrg
                    124:         mov         fr.SrcxOrg,ax
                    125:         mov         eax,__SrcyOrg
                    126:         mov         fr.SrcyOrg,ax
                    127:         mov         eax,__xExt
                    128:         mov         fr.xExt,ax
                    129:         mov         eax,__yExt
                    130:         mov         fr.yExt,ax
                    131:         mov         eax,__Rop
                    132:         mov         fr.Rop,eax
                    133:         mov         eax,__lpPBrush
                    134:         mov         fr.lpPBrush,eax
                    135:         mov         eax,__bkColor
                    136:         mov         fr.bkColor,eax
                    137:         mov         eax,__TextColor
                    138:         mov         fr.TextColor,eax
                    139:         mov         eax,__pulXlateVec
                    140:         mov         fr.ppcBlt.pulXlate,eax
                    141:         mov         eax,__pptlBrush
                    142:         mov         fr.pptlBrush,eax
                    143: 
                    144:         subttl  ROP Preprocessing
                    145:         page
                    146: 
                    147: ;-----------------------------------------------------------------------;
                    148: ; Get the encoded raster operation, and map the raster op if needed.
                    149: ;
                    150: ; To map the ROPS 80h through FFh to 00h through 7Fh, take the
                    151: ; 1's complement of the ROP, and invert the "negate needed" flag.
                    152: ;-----------------------------------------------------------------------;
                    153: 
                    154:         xor     ax,ax                   ;Assume not 80h : FFh
                    155:         mov     bl,byte ptr fr.Rop
                    156:         or      bl,bl                   ;Is this in the second half (80-FF)?
                    157:         jns     parse_10                ;  No, rop index is correct
                    158:         not     bl                      ;  Yes, want the inverse
                    159:         mov     ah,HIGH NEGATE_NEEDED   ;Want to invert the not flag
                    160:         errnz   <LOW NEGATE_NEEDED>
                    161: 
                    162: parse_10:
                    163:         movzx   ebx,bl
                    164:         xor     ax,roptable[ebx*2]      ;Get ROP, maybe toggle negate flag
                    165:         mov     fr.operands,ax          ;Save the encoded raster operation
                    166: 
                    167:         mov     bl,ah                   ;Set fr.the_flags for source and pattern
                    168:         and     bl,HIGH (SOURCE_PRESENT+PATTERN_PRESENT)
                    169:         ror     bl,1
                    170: 
                    171:         errnz    <SOURCE_PRESENT - 0010000000000000b>
                    172:         errnz   <PATTERN_PRESENT - 0100000000000000b>
                    173:         errnz    <F0_SRC_PRESENT - 00010000b>
                    174:         errnz    <F0_PAT_PRESENT - 00100000b>
                    175: 
                    176: parse_end:
                    177: 
                    178: 
                    179: ;-----------------------------------------------------------------------;
                    180: ; pdevice_processing
                    181: ;
                    182: ; Check the required bitmaps for validity, get their parameters
                    183: ; and store the information locally.
                    184: ;
                    185: ;       BL = Initial fr.the_flags
                    186: ;            F0_SRC_PRESENT set if source needed
                    187: ;            F0_PAT_PRESENT set if pattern needed
                    188: ;-----------------------------------------------------------------------;
                    189: 
                    190:         xor     bh,bh                   ;BH = real fr.the_flags
                    191:         mov     fr.ppcBlt.fb,bh          ;No packed pel converison
                    192:         test    bl,F0_SRC_PRESENT       ;Is a source needed?
                    193:         jz      pdevice_decode_dest     ;  No, skip source validation
                    194:         mov     esi,fr.pdsurfSrc        ;Get pointer to source
                    195:         lea     edi,fr.src              ;--> where parameters will go
                    196:         push    ebp
                    197:         lea     ebp,fr.ppcBlt
                    198:         cCall   copy_dev                ;Get all the data
                    199:         pop     ebp
                    200:         test    fr.ppcBlt.fb,PPC_NEEDED ;Will we be converting from packed pel?
                    201:         jz      pdevice_decode_dest     ;  No
                    202:         MovAddr eax,vDIB8Preprocess,0
                    203:         cmp     fr.ppcBlt.iFormat,BMF_8BPP
                    204:         je      short @F
                    205:         MovAddr eax,vDIB4Preprocess,0
                    206: @@:
                    207:         push    ebp                     ;  Yes, do serious messing around
                    208:         lea     ebp,fr                  ;  Needs a frame pointer
                    209:         call    eax
                    210:         pop     ebp
                    211: 
                    212: pdevice_decode_dest:
                    213:         mov     esi,fr.pdsurfDst        ;Get pointer to destination
                    214:         lea     edi,fr.dest             ;--> where parameters will go
                    215:         cCall   copy_dev                ;Get all the data
                    216: 
                    217: ; The pattern fetch code will be based on the color format of the
                    218: ; destination.  If the destination is mono, then a mono fetch will be
                    219: ; performed.  If the destination is color, then a color fetch will be
                    220: ; performed.
                    221: 
                    222:         or      bh,bl                   ;Merge in F0_SRC_PRESENT, F0_PAT_PRESENT
                    223:         test    bh,F0_DEST_IS_COLOR     ;Show color pattern needed if
                    224:         jz      pdevice_chk_color_conv  ;  destination is color
                    225:         or      bh,F0_COLOR_PAT
                    226: 
                    227: ;       Check for color conversion.  If so, then set F0_GAG_CHOKE.
                    228: ;       Color conversion will exist if the source and destination are of
                    229: ;       different color formats.
                    230: 
                    231: pdevice_chk_color_conv:
                    232:         test    bh,F0_SRC_PRESENT       ;Is there a source?
                    233:         jz      pdevice_set_dest_flag   ;  No, cannot be converting.
                    234:         mov     al,bh
                    235:         and     al,F0_SRC_IS_COLOR+F0_DEST_IS_COLOR
                    236:         jz      pdevice_set_src_flag    ;Both are monochrome
                    237:         xor     al,F0_SRC_IS_COLOR+F0_DEST_IS_COLOR
                    238:         jz      pdevice_set_src_flag    ;Both are color
                    239:         or      bh,F0_GAG_CHOKE         ;Mono ==> color or color ==> mono
                    240:         mov     al,fr.bkColor.SPECIAL
                    241:         mov     ah,fr.TextColor.SPECIAL
                    242:         errnz   C0_BIT+C1_BIT+C2_BIT+C3_BIT-0Fh
                    243:         and     ax,0F0Fh
                    244:         mov     fr.both_colors,ax
                    245: 
                    246: ; Setup the scan line update flag in the source device structure.
                    247: ; The source will use a monochrome style update if it is the display,
                    248: ; it is monochrome, or it is color and the destination device is
                    249: ; monochrome.
                    250: 
                    251: pdevice_set_src_flag:
                    252:         mov     al,bh                   ;Set 'Z' if to use color update
                    253:         and     al,F0_SRC_IS_DEV+F0_SRC_IS_COLOR+F0_DEST_IS_COLOR
                    254:         xor     al,F0_SRC_IS_COLOR+F0_DEST_IS_COLOR
                    255:         jnz     pdevice_set_dest_flag   ;Use the mono update
                    256:         or      fr.src.dev_flags,COLOR_UP;Show color scan update
                    257: 
                    258: ; Setup the scan line update flag in the destination device
                    259: ; structure.  The destination will use a monochrome update
                    260: ; if it is monochrome or the display.  It will use a color
                    261: ; update if it is a color bitmap.
                    262: 
                    263: pdevice_set_dest_flag:
                    264:         mov     al,bh                   ;Set 'Z' if to use color destination
                    265:         and     al,F0_DEST_IS_DEV+F0_DEST_IS_COLOR;  update code
                    266:         xor     al,F0_DEST_IS_COLOR
                    267:         jnz     pdevice_proc_end        ;Mono update
                    268:         or      fr.dest.dev_flags,COLOR_UP;Show color scan update
                    269: pdevice_proc_end:
                    270: 
                    271: 
                    272:         push    ebp                     ;Set up pointer to frame variables
                    273:         lea     ebp,fr
                    274:         cCall   pattern_preprocessing
                    275:         pop     ebp
                    276: 
                    277:         subttl  Phase Processing (X)
                    278:         page
                    279: 
                    280: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
                    281: ;       Now the real work comes along:  In which direction will the
                    282: ;       copy be done?  Refer to the 10 possible types of overlap that
                    283: ;       can occur (10 cases, 4 resulting types of action required).
                    284: ;
                    285: ;       If there is no source bitmap involved in this particular BLT,
                    286: ;       then the path followed must allow for this.  This is done by
                    287: ;       setting both the destination and source parameters equal.
                    288: ; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;
                    289: 
                    290: phase_processing:
                    291: phase_processing_x:
                    292:         mov     dx,fr.xExt              ;Get X extent
                    293:         dec     dx                      ;Make X extent inclusive
                    294:         mov     bx,fr.DestxOrg          ;Get destination X origin
                    295:         mov     di,bx
                    296:         and     bx,00000111b            ;Get offset of destination within byte
                    297: 
                    298: ; If there is no source, then just use the pointer to the destination
                    299: ; bitmap and load the same parameters, which will cause the "equality"
                    300: ; path to be followed in the set-up code.  This path is the favored
                    301: ; path for the case of no source bitmap.
                    302: 
                    303:         mov     ax,di                   ;Assume no source needed
                    304:         test    fr.the_flags,F0_SRC_PRESENT;Is a source needed?
                    305:         jz      phase_proc_10           ;  No, just use destination parameters
                    306:         mov     ax,fr.SrcxOrg           ;  Yes, get source origin X
                    307:         mov     fr.first_fetch,FF_TWO_INIT_FETCHES
                    308:                                         ;  Assume two initial fetches (if no
                    309:                                         ;    source, then it will be set = 1
                    310:                                         ;    later)
                    311: phase_proc_10:
                    312:         mov     si,ax
                    313:         and     ax,00000111b            ;Get offset of source within byte
                    314:         cmp     si,di                   ;Which direction will we be moving?
                    315:         jl      phase_proc_30           ;Move from right to left
                    316: 
                    317: ; The starting X of the source rectangle is >= the starting X of
                    318: ; the destination rectangle, therefore we will be moving bytes
                    319: ; starting from the left and stepping right.
                    320: ;
                    321: ; Alternatively, this is the path taken if there is no source
                    322: ; bitmap for the current BLT.
                    323: ;
                    324: ; Rectangle cases: 3,4,5,6,8
                    325: 
                    326:         sub     al,bl                   ;Compute horiz. phase  (source-dest)
                    327:         mov     fr.step_direction,STEPRIGHT ;Set direction of move
                    328:         movzx   ebx,bx
                    329:         mov     ah,[ebx].bitmask_tbl1   ;Get starting byte mask
                    330:         ja      phase_proc_two_fetches  ;Scan line case 2, everything is
                    331:                                         ;  already set for this case.
                    332: 
                    333: ; Scan line cases 1 and 3:
                    334: ;
                    335: ; The correct first byte fetch needs to be set for the beginning
                    336: ; of the outer loop, and the phase must be made into a positive
                    337: ; number.
                    338: ;
                    339: ; This is the path that will be followed if there is no source bitmap
                    340: ; for the current BLT.
                    341: 
                    342:         mov     fr.first_fetch,FF_ONE_INIT_FETCH;Set one initial fetch
                    343:         jmp     short pp_only_one_init_fetch
                    344: 
                    345: ;-----------------------------------------------------------------------;
                    346: ; If we get all the bits we need in the first fetch then a second
                    347: ; (unnecessary) fetch could cause a GP Fault.  So let's examine this:
                    348: ; The number of bits from (SI mod 8) to the end of the byte is the number
                    349: ; of available bits we get on the first fetch.  This is (8 - (SI mod 8)).
                    350: ; If this is greater than or equal to xExt then we have all the bits we
                    351: ; need and we better not do the second fetch (even though the phase
                    352: ; relationship may suggest we need it).
                    353: ;
                    354: ; Conclusion: If (8 - (SI mod 8)) >= xExt then DO NOT make second fetch.
                    355: ;-----------------------------------------------------------------------;
                    356: 
                    357: phase_proc_two_fetches:
                    358:         mov     cx,8
                    359:         sub     cl,bl
                    360:         sub     cl,al
                    361: 
                    362: ; We can save a couple cycles here since xExt - 1 is already in DX.
                    363: ; The condition CX >= xExt is the same as CX > DX.
                    364: 
                    365:         cmp     cx,dx                   ;CX = (SI mod 8), DX = (xExt - 1)
                    366:         jle     pp_second_fetch_really_needed
                    367: 
                    368: 
                    369: ;-----------------------------------------------------------------------;
                    370: ; We are here BECAUSE the xExt is so small that we can get all the bits
                    371: ; on the scanline with a single lodsb (no byte boundary is crossed) AND
                    372: ; the phase relationship indicates that a second initial fetch is needed.
                    373: ;
                    374: ; We will override it and only do one fetch.  However, if we simply
                    375: ; fail to do the second fetch then the phase code will screw us.
                    376: ; It will be expecting the bits to get fetched in the first fetch, saved
                    377: ; after the rotate, and mixed in in the second fetch's phase code.
                    378: ; So after the first fetch the bits have been saved in BH, and ANDed out
                    379: ; of the src data in AL.
                    380: ;
                    381: ; The solution is to set a flag here that tells the phase generation code
                    382: ; not to generate the usual masking part of the phase code.
                    383: ;
                    384: ; Short Bitblt Cases:                   (8 bits or less)
                    385: ;
                    386: ;       1) neither crosses byte boundary.
                    387: ;
                    388: ;          a) phase requires second initial fetch
                    389: ;
                    390: ;             Kill the phase masking.  It will screw us.  There will
                    391: ;             be just one lodsb and one stosb and the first byte mask
                    392: ;             will protect the dest bits that should not get hit.
                    393: ;
                    394: ;          b) phase requires only one initial fetch
                    395: ;
                    396: ;             Phase masking is irrelevant.  Removing it would
                    397: ;             be an optimiztation.
                    398: ;
                    399: ;       2) dest crosses byte boundary, but src does not
                    400: ;
                    401: ;          a) phase requires second initial fetch
                    402: ;
                    403: ;             impossible situation:  the way we determine that a 2nd fetch
                    404: ;             is necessary is if the first fetch does not get enough needed
                    405: ;             bits to satisfy the first dest byte.  Here the first fetch
                    406: ;             gets ALL the bits and the first dest byte needs less than
                    407: ;             ALL because it crosses a byte boundary.
                    408: ;
                    409: ;          b) phase requires only one initial fetch
                    410: ;
                    411: ;             Intervention would be bad.  None is necessary since the 2nd
                    412: ;             initial fetch will not be done.  If we do intervene we will
                    413: ;             cause trouble:  Killing the masking will prevent the
                    414: ;             "saved bits" from being saved.  The first byte masking
                    415: ;             can kill off these bits in AL and they will never
                    416: ;             make it to the second stosb.
                    417: ;
                    418: ;       3) src crosses byte boundary  (dest may or may not)
                    419: ;          (this is known to be untrue at this point)
                    420: ;
                    421: ;          There are bits we need in the second fetch, so a second
                    422: ;          initial fetch can not cause a GP fault.  Therefore do
                    423: ;          everything the same as we would have before.
                    424: ;
                    425: ;
                    426: ; Conclusion:  Intervention to kill the phase masking is
                    427: ;              necessary iff
                    428: ;                 [src does not cross byte boundary] AND
                    429: ;                 dest does not cross byte boundary  AND
                    430: ;                 [phase requires second initial fetch].
                    431: ;              and bad if
                    432: ;                 dest crosses byte boundary, but [src does not]
                    433: ;
                    434: ; Statements in [] are known to be true at this point.
                    435: ;
                    436: ; Solution:
                    437: ;
                    438: ; If we always kill the phase-masking when neither crosses a byte
                    439: ; boundary and never kill it otherwise then everyone will be happy
                    440: ; (regardless of other conditions like whether phase requests a 2nd
                    441: ; initial fetch).
                    442: ;-----------------------------------------------------------------------;
                    443: 
                    444:         mov     fr.first_fetch,FF_ONLY_1_SRC_BYTE
                    445:         .errnz  FF_ONE_INIT_FETCH
                    446: 
                    447: pp_second_fetch_really_needed:
                    448: pp_only_one_init_fetch:
                    449:         mov     ch,ah
                    450: 
                    451: ;-----------------------------------------------------------------------;
                    452: ;       We now have the correct phase and the correct first character fetch
                    453: ;       routine set.  Save the phase and ...
                    454: ;
                    455: ;       currently:   AL = phase
                    456: ;                    BL = dest start mod 8
                    457: ;                    CH = first byte mask
                    458: ;                    DX = inclusive X bit count
                    459: ;                    SI = source X start (if there is a source)
                    460: ;                    DI = destination X start
                    461: ;-----------------------------------------------------------------------;
                    462: 
                    463: phase_proc_20:
                    464:         add     al,8                    ;Phase must be positive
                    465:         and     al,00000111b
                    466: 
                    467: ; To calculate the last byte mask, the inclusive count can be
                    468: ; added to the start X MOD 8 value, and the result taken MOD 8.
                    469: ; This is attractive since this is what is needed later for
                    470: ; calculating the inclusive byte count, so save the result
                    471: ; of the addition for later.
                    472: 
                    473:         add     bx,dx                   ;Add inclusive extent to dest MOD 8
                    474:         mov     dx,bx                   ;Save for innerloop count !!!
                    475:         and     ebx,00000111b           ;Set up bx for a base reg
                    476:         mov     cl,[ebx].bitmask_tbl2   ;Get last byte mask
                    477: 
                    478: ;-----------------------------------------------------------------------;
                    479: ; To avoid GP faults, we must never do an extra fetch we don't need.
                    480: ; When we're ready for the last fetch there may already be enough bits
                    481: ; saved from the previous fetch (which we plan to combine with the bits
                    482: ; in the fetch we are about to do).  If so then we'd better not do this
                    483: ; last fetch (it could cause a GP fault).
                    484: ;
                    485: ; The number of bits we have left from the previous byte is (8 - AL)
                    486: ; AL is the phase.  (1 + BL) is the number of bits we actually need
                    487: ; to write to the final destination byte.
                    488: ;
                    489: ; So if  (8 - AL) >= (1 + BL)  then DO NOT do the last fetch.  This
                    490: ; simplifies:  if  (BL + AL) <= 7  then DO NOT do the last fetch.
                    491: ;-----------------------------------------------------------------------;
                    492: 
                    493:         add     bl,al
                    494:         cmp     bl,7
                    495:         jg      phase_proc_last_fetch_needed
                    496:         or      fr.first_fetch,FF_NO_LAST_FETCH
                    497: phase_proc_last_fetch_needed:
                    498: 
                    499:         mov     bl,al                   ;Compute offset into phase mask table
                    500:         movzx   ebx,bx
                    501:         mov     bx,[ebx*2].phase_tbl1   ;Get the phase mask
                    502: 
                    503: ;       Currently:
                    504: ;               AL = phase
                    505: ;               BX = phase mask
                    506: ;               CL = last byte mask
                    507: ;               CH = first byte mask
                    508: ;               DX = inclusive bit count + dest start MOD 8
                    509: ;               SI = source X start (if there is a source)
                    510: ;               DI = destination starting X
                    511: 
                    512:         jmp     phase_proc_50           ;Finish here
                    513: 
                    514: ; The starting X of the source rectangle is < the X of the destination
                    515: ; rectangle, therefore we will be moving bytes starting from the right
                    516: ; and stepping left.
                    517: ;
                    518: ; This code should never be reached if there is no source bitmap
                    519: ; for the current BLT.
                    520: ;
                    521: ; Rectangle cases: 1,2,7
                    522: 
                    523: phase_proc_30:
                    524:         mov     fr.step_direction,ah    ;Set direction of move
                    525:         errnz   STEPLEFT
                    526:         movzx   ebx,bx
                    527:         mov     cl,[ebx].bitmask_tbl1   ;Get last byte mask
                    528:         push    bx
                    529:         add     ax,dx                   ;Find end of the source
                    530: 
                    531: ; To calculate the first byte mask, the inclusive count is
                    532: ; added to the start MOD 8 value, and the result taken MOD 8.
                    533: ; This is attractive since this is what is needed later for
                    534: ; calculating the inclusive byte count, so save the result
                    535: ; of the addition for later.
                    536: 
                    537:         add     bx,dx                   ;Find end of the destination
                    538:         add     di,dx                   ;Will need to update dest start address
                    539:         add     si,dx                   ;  and source's too
                    540:         mov     dx,bx                   ;Save inclusive bit count + start MOD 8
                    541:         and     ax,00000111b            ;Get source offset within byte
                    542:         and     ebx,00000111b           ;Get dest   offset within byte
                    543:         mov     ch,[ebx].bitmask_tbl2   ;Get start byte mask
                    544:         cmp     al,bl                   ;Compute horiz. phase  (source-dest)
                    545:         jb      pp_double_fetch         ;Scan line case 5, everything is
                    546:                                         ;  already set for this case.
                    547: 
                    548: ; Scan line cases 4 and 6:
                    549: ;
                    550: ; The correct first byte fetch needs to be set for the beginning
                    551: ; of the outer loop
                    552: 
                    553:         mov     fr.first_fetch,FF_ONE_INIT_FETCH;Set initial fetch routine
                    554:         jmp     short pp_one_initial_fetch
                    555: 
                    556: ;-----------------------------------------------------------------------;
                    557: ; If only-one-fetch is already set, then the following is a NOP.
                    558: ; It doesn't seem worth the effort to check and jmp around.
                    559: ;
                    560: ; If we get all the bits we need in the first fetch then a second
                    561: ; (unnecessary) fetch could cause a GP Fault.  So let's examine this:
                    562: ;
                    563: ; (DX + SI) points to the first pel (remember we're stepping left).
                    564: ; So the number of needed bits we get in the first fetch is
                    565: ; ((DX + SI + 1) mod 8).  This is currently equal to AX.
                    566: ; If AX >= xExt then we'd better not do two init fetches.
                    567: ;-----------------------------------------------------------------------;
                    568: 
                    569: pp_double_fetch:
                    570:         dec     fr.xExt
                    571:         cmp     ax,fr.xExt
                    572:         jl      pp_double_fetch_really_needed
                    573:         mov     fr.first_fetch,FF_ONLY_1_SRC_BYTE
                    574:         .errnz  FF_ONE_INIT_FETCH
                    575: pp_double_fetch_really_needed:
                    576:         inc     fr.xExt
                    577: 
                    578: pp_one_initial_fetch:
                    579:         sub     al,bl                   ;Compute horiz. phase  (source-dest)
                    580:         add     al,8                    ;Ensure phase positive
                    581:         and     al,00000111b
                    582: 
                    583: ;-----------------------------------------------------------------------;
                    584: ; To avoid GP faults must never do an extra fetch we don't need.
                    585: ; The last byte fetch is unnecessary if Phase is greater than or equal
                    586: ; to 8 - BL.  Phase is the number of bits we still have from the previous
                    587: ; fetch. 8 - BL is the number of bits we actually need to write to the
                    588: ; final destination byte.  So if AL - (8 - BL) >= 0  skip the last fetch.
                    589: ;-----------------------------------------------------------------------;
                    590: 
                    591:         pop     bx
                    592:         add     bl,al
                    593:         sub     bl,8
                    594:         jl      pp_need_last_fetch
                    595:         or      fr.first_fetch,FF_NO_LAST_FETCH
                    596: pp_need_last_fetch:
                    597: phase_proc_40:
                    598: 
                    599: ;-----------------------------------------------------------------------;
                    600: ;       We now have the correct phase and the correct first character fetch
                    601: ;       routine set.  Generate the phase mask and save it.
                    602: ;
                    603: ;       currently:   AL = phase
                    604: ;                    CH = first byte mask
                    605: ;                    CL = last byte mask
                    606: ;                    DX = inclusive bit count + start MOD 8
                    607: 
                    608:         mov     ah,cl                   ;Save last mask
                    609:         mov     cl,al                   ;Create the phase mask
                    610:         mov     bx,00FFh                ;  by shifting this
                    611:         shl     bx,cl                   ;  according to the phase
                    612:         mov     cl,ah                   ;Restore last mask
                    613: ;       jmp     phase_proc_50           ;Go compute # of bytes to BLT
                    614:         errn$   phase_proc_50
                    615: 
                    616: 
                    617: ; The different processing for the different X directions has been
                    618: ; completed, and the processing which is the same regardless of
                    619: ; the X direction is about to begin.
                    620: ;
                    621: ; The phase mask, the first/last byte masks, the X byte offsets,
                    622: ; and the number of innerloop bytes must be calculated.
                    623: ;
                    624: ;
                    625: ; Nasty stuff coming up here!  We now have to determine how
                    626: ; many bits will be BLTed and how they are aligned within the bytes.
                    627: ; This is how it's done (or how I'm going to do it):
                    628: ;
                    629: ; The number of bits (inclusive number that is) is added to the
                    630: ; start MOD 8 value ( the left side of the rectangle, minimum X
                    631: ; value), then the result is divided by 8. Then:
                    632: ;
                    633: ;
                    634: ;    1) If the result is 0, then only one destination byte is being
                    635: ;       BLTed.  In this case, the start & ending masks will be ANDed
                    636: ;       together, the innerloop count (# of full bytes to BLT) will
                    637: ;       be zeroed, and the fr.last_mask set to all 0's (don't alter any
                    638: ;       bits in last byte which will be the byte following the first
                    639: ;       (and only) byte).
                    640: ;
                    641: ;               |      x x x x x|               |
                    642: ;               |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
                    643: ;                0 1 2 3 4 5 6 7
                    644: ;
                    645: ;               start MOD 8 = 3,  extent-1 = 4
                    646: ;               3+7 DIV 8 = 0, only altering one byte
                    647: ;
                    648: ;
                    649: ;
                    650: ;    2) If the result is 1, then only two bytes will be BLTed.
                    651: ;       In this case, the start and ending masks are valid, and
                    652: ;       all that needs to be done is set the innerloop count to 0.
                    653: ;       (it is true that the last byte could have all bits affected
                    654: ;       the same as if the innerloop count was set to 1 and the
                    655: ;       last byte mask was set to 0, but I don't think there would be
                    656: ;       much time saved special casing this).
                    657: ;
                    658: ;               |  x x x x x x x|x x x x x x x|
                    659: ;               |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
                    660: ;                0 1 2 3 4 5 6 7
                    661: ;
                    662: ;               start MOD 8 = 1,  extent-1 = 14
                    663: ;               3+14 DIV 8 = 1.  There is a first and last
                    664: ;               byte but no innerloop count
                    665: ;
                    666: ;
                    667: ;
                    668: ;    3) If the result is >1, then there is some number of entire
                    669: ;       bytes to be BLted by the innerloop.  In this case the
                    670: ;       number of innerloop bytes will be the result - 1.
                    671: ;
                    672: ;               |              x|x x x x x x x x|x
                    673: ;               |_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|_|
                    674: ;                0 1 2 3 4 5 6 7
                    675: ;
                    676: ;               start MOD 8 = 7,  extent-1 = 9
                    677: ;               7+9  DIV 8 = 2.  There is a first and last
                    678: ;               byte and an innerloop count of 1 (result - 1)
                    679: ;
                    680: ;       Currently:      AL = horizontal phase
                    681: ;                       BX = horizontal phase mask
                    682: ;                       CH = first byte mask
                    683: ;                       CL = last byte mask
                    684: ;                       DX = left side X MOD 8 + inclusive X count
                    685: ;                       SI = source start X
                    686: ;                       DI = dest   start X
                    687: 
                    688: phase_proc_50:
                    689:         mov     fr.phase_h,al           ;Save horizontal phase
                    690:         mov     fr.mask_p,bx            ;Save phase mask
                    691:         shr     dx,3                    ;/8 to get full byte count
                    692:         jnz     phase_proc_60           ;Result is >0, check it out
                    693: 
                    694: ; There will only be one byte affected.  Therefore the two byte masks
                    695: ; must be combined, the last byte mask cleared, and the innerloop
                    696: ; count set to zero.
                    697: 
                    698:         or      fr.first_fetch,FF_ONLY_1_DEST_BYTE
                    699:         and     ch,cl                   ;Combine the two masks
                    700:         xor     cl,cl                   ;Clear out the last byte mask
                    701:         inc     dx                      ;Now just fall through to set
                    702:         errn$   phase_proc_60           ;  the innerloop count to 0!
                    703: 
                    704: phase_proc_60:
                    705:         dec     dx                      ;Dec count (might become 0 just like
                    706:         movzx   edx,dx                  ;  we want), and save it
                    707:         mov     fr.inner_loop_count,edx
                    708:         mov     bl,ch
                    709:         mov     ch,cl                   ;Compute last byte mask
                    710:         not     cl                      ;  and save it
                    711:         mov     fr.last_mask,cx
                    712:         mov     bh,bl                   ;Compute start byte mask
                    713:         not     bl                      ;  and save it
                    714:         mov     fr.start_mask,bx
                    715: 
                    716: ; There may or may not be a source bitmap for the following address
                    717: ; computation.  If there is no source, then the vertical setup code
                    718: ; will be entered with both the source and destination Y's set to the
                    719: ; destination Y and the address calculation skipped.  If there is a
                    720: ; source, then the address calculation will be performed and the
                    721: ; vertical setup code entered with both the source and destination Y's.
                    722: 
                    723: phase_processing_y:
                    724:         shr     di,3                    ;Compute byte offset of destination
                    725:         movzx   edi,di                  ;  and add to current destination
                    726:         add     fr.dest.lp_bits,edi      ;  offset
                    727: 
                    728:         mov     dx,fr.DestyOrg          ;Get destination Y origin
                    729:         mov     ax,dx                   ;Assume no source
                    730:         mov     cl,fr.the_flags
                    731:         test    cl,F0_SRC_PRESENT       ;Is a source needed?
                    732:         jz      phase_proc_70           ;  No, skip source set-up
                    733:         shr     si,3                    ;Compute byte offset of source
                    734:         movzx   esi,si                  ;  and add to current source offset
                    735:         add     fr.src.lp_bits,esi
                    736:         mov     ax,fr.SrcyOrg           ;Get source Y origin
                    737: 
                    738: 
                    739:         subttl  Phase Processing (Y)
                    740:         page
                    741: 
                    742: ; The horizontal parameters have been calculated.  Now the vertical
                    743: ; parameters must be calculated.
                    744: ;
                    745: ; Currently:
                    746: ;         DX = destination Y origin
                    747: ;         AX = source Y origin (destination origin if no source)
                    748: ;         CL = fr.the_flags
                    749: 
                    750: phase_proc_70:
                    751:         mov     bx,fr.yExt              ;Get the Y extent of the BLT
                    752:         dec     bx                      ;Make it inclusive
                    753: 
                    754: 
                    755: ; The BLT will be Y+ if the top of the source is below or equal
                    756: ; to the top of the destination (cases: 1,4,5,7,8).  The BLT
                    757: ; will be Y- if the top of the source is above the top of the
                    758: ; destination (cases: 2,3,6)
                    759: ;
                    760: ;
                    761: ;                 !...................!
                    762: ;                 !D                  !
                    763: ;             ____!             ..x   !
                    764: ;            |S   !               :   !     Start at top of S walking down
                    765: ;            |    !                   !
                    766: ;            |    !...................!
                    767: ;            |                    :
                    768: ;            |____________________:
                    769: ;
                    770: ;
                    771: ;             __________________
                    772: ;            |S                 |
                    773: ;            |    .....................     Start at bottom of S walking up
                    774: ;            |    !D                  !
                    775: ;            |    !             :     !
                    776: ;            |____!           ..x     !
                    777: ;                 !                   !
                    778: ;                 !....................
                    779: 
                    780: 
                    781:         mov     ch,INCREASE             ;Set Y direction for top to bottom
                    782:         cmp     ax,dx                   ;Which direction do we move?
                    783:         jge     phase_proc_80           ;Step down screen (cases: 1,4,5,7,8)
                    784: 
                    785: 
                    786: ; Direction will be from bottom of the screen up (Y-)
                    787: ;
                    788: ; This code will not be executed if there is no source since
                    789: ; both Y's were set to the destination Y.
                    790: 
                    791: 
                    792:         add     dx,bx                   ;Find bottom scan line index for
                    793:         add     ax,bx                   ;  destination and source
                    794:         mov     ch,DECREASE             ;Set pattern increment
                    795: 
                    796: phase_proc_80:
                    797:         mov     fr.pat_row,dl           ;Set pattern row and increment
                    798:         mov     fr.direction,ch
                    799:         sar     ch,1                    ;Map FF==>FF, 01==>00
                    800:         errnz   DECREASE-0FFFFFFFFh
                    801:         errnz   INCREASE-00001h
                    802: 
                    803: 
                    804: ; The Y direction has been computed.  Compute the rest of the
                    805: ; Y parameters.  These include the actual starting address,
                    806: ; the scan line and plane increment values, and whether or not
                    807: ; the extents will cross a 64K boundary.
                    808: ;
                    809: ; Currently:
                    810: ;         DX = Y of starting destination scan
                    811: ;         AX = Y of starting source scan
                    812: ;         CH = BLT direction
                    813: ;                00 = increasing BLT, Y+
                    814: ;                FF = decreasing BLT, Y-
                    815: ;         CL = fr.the_flags
                    816: ;         BX = inclusive Y extent
                    817: 
                    818: 
                    819: phase_proc_90:
                    820:         test    cl,F0_SRC_PRESENT       ;Is a source needed?
                    821:         movsx   ecx,ch                  ;  (Want ECX = +/- 1)
                    822:         jz      phase_proc_100          ;  No, skip source set-up
                    823:         test    fr.ppcBlt.fb,PPC_NEEDED ;Packed pel conversion needed?
                    824:         jz      phase_proc_95           ;  No, use normal setup
                    825:         push    ebp                     ;  Yes, perform packed pel work
                    826:         lea     ebp,fr
                    827:         cCall   packed_pel_comp_y
                    828:         pop     ebp
                    829:         jmp     short phase_proc_100
                    830: 
                    831: phase_proc_95:
                    832:         push    dx                      ;Save destination Y
                    833:         push    ebp                     ;Mustn't trash frame pointer
                    834:         lea     ebp,fr.src              ;--> source data structure
                    835:         cCall   compute_y               ;Process as needed
                    836:         pop     ebp
                    837:         pop     dx                      ;Restore destination Y
                    838: 
                    839: phase_proc_100:
                    840:         push    ebp                     ;Mustn't trash frame pointer
                    841:         mov     ax,dx                   ;Put destination Y in ax
                    842:         lea     ebp,fr.dest             ;--> destination data structure
                    843:         cCall   compute_y
                    844:         pop     ebp                     ;Restore frame pointer
                    845: 
                    846:         push    ebp
                    847:         lea     ebp,fr
                    848:         cCall   check_device_special_cases
                    849:         pop     ebp
                    850:         jc      bitblt_exit             ;C ==> BLT done w/special case
                    851: 
                    852: 
                    853:         subttl  Memory allocation for BLT compilation
                    854:         page
                    855: cblt_allocate:
                    856:         sub     esp,MAX_BLT_SIZE
                    857:         mov     edi,esp
                    858:         mov     fr.blt_addr,edi         ;Save the address for later
                    859:         push    ebp
                    860:         lea     ebp,fr
                    861:         cCall   cblt                    ;compile the BLT onto the stack
                    862:         pop     ebp
                    863: 
                    864: ; The BLT has been created on the stack.  Set up the initial registers,
                    865: ; set the direction flag as needed, and execute the BLT.
                    866: 
                    867:         mov     esi,fr.src.lp_bits      ;--> source device's first byte
                    868:         mov     edi,fr.dest.lp_bits     ;--> destination device's first byte
                    869:         mov     cx,fr.yExt              ;Get count of lines to BLT
                    870:         cld                             ;Assume this is the direction
                    871:         cmp     fr.step_direction,STEPRIGHT ;Stepping to the right?
                    872:         jz      call_blt_do_it          ;  Yes
                    873:         std
                    874: call_blt_do_it:
                    875:         push    ebp                     ;MUST SAVE THIS
                    876:         call    fr.blt_addr             ;Call the FAR process
                    877:         pop     ebp
                    878:         add     esp,MAX_BLT_SIZE        ;Return BLT space
                    879:         errn$   bitblt_exit
                    880: 
                    881: bitblt_exit:
                    882: 
                    883: ; Here we test if the VGA was involved and skip reseting the VGA state if
                    884: ; it was not involved.
                    885: 
                    886:         test    fr.the_flags,F0_DEST_IS_DEV + F0_SRC_IS_DEV
                    887:         jz      ega_not_involved
                    888: 
                    889: ; Restore EGA registers to the default state.
                    890: 
                    891:         mov     dx,EGA_BASE + SEQ_DATA
                    892:         mov     al,MM_ALL
                    893:         out     dx,al
                    894:         mov     dl,GRAF_ADDR
                    895:         mov     ax,0FF00h + GRAF_BIT_MASK
                    896:         out     dx,ax
                    897:         mov     ax,DR_SET shl 8 + GRAF_DATA_ROT
                    898:         out     dx,ax
                    899:         mov     ax,GRAF_ENAB_SR
                    900:         out     dx,ax
                    901: ega_not_involved:
                    902: 
                    903:         mov     eax,1                   ;Clear out error register (good exit)
                    904:         cld                             ;Leave direction cleared
                    905:         cRet    vCompiledBlt
                    906: 
                    907: xxxvCompiledBlt endp
                    908: 
                    909: 
                    910: 
                    911: ;----------------------------Private-Routine----------------------------;
                    912: ; copy_device
                    913: ;
                    914: ; Copy device information to frame.
                    915: ;
                    916: ; Entry:
                    917: ;       ESI = pdsurf
                    918: ;       EDI --> frame DEV structure
                    919: ;       EBP --> PPC structure (for source only)
                    920: ;       BH     =  fr.the_flags, accumulated so far
                    921: ; Returns:
                    922: ;       BH     =  fr.the_flags, accumulated so far
                    923: ;       Carry clear if no error
                    924: ;       EBP --> PPC structure
                    925: ; Error Returns:
                    926: ;       None
                    927: ; Calls:
                    928: ;       None
                    929: ; History:
                    930: ;  Sun 22-Feb-1987 16:29:09 -by-  Walt Moore [waltm]
                    931: ; Created.
                    932: ;-----------------------------------------------------------------------;
                    933: 
                    934: cProc   copy_dev
                    935: 
                    936:         mov     eax,[esi].dsurf_sizlSurf.sizl_cx
                    937:         mov     [edi].width_bits,ax
                    938:         mov     eax,[esi].dsurf_sizlSurf.sizl_cy
                    939:         mov     [edi].height,ax
                    940:         mov     eax,[esi].dsurf_lNextScan
                    941:         mov     [edi].width_b,ax
                    942:         mov     eax,[esi].dsurf_pvBitmapStart
                    943:         mov     [edi].lp_bits,eax
                    944:         mov     eax,[esi].dsurf_lNextPlane
                    945:         mov     [edi].next_plane,eax
                    946:         mov     al,[esi].dsurf_iFormat
                    947:         shl     bh,1
                    948:         cmp     al,BMF_PHYSDEVICE
                    949:         sete    ah
                    950:         or      bh,ah
                    951:         errnz   F0_SRC_IS_DEV-00001000b
                    952:         errnz   F0_DEST_IS_DEV-0000010b
                    953: 
                    954:         shl     bh,1
                    955:         cmp     al,BMF_1BPP
                    956:         je      copy_dev_20             ;Mono, color bit is clear
                    957:         or      bh,F0_DEST_IS_COLOR
                    958:         errnz   F0_SRC_IS_COLOR-00000100b
                    959:         errnz   F0_DEST_IS_COLOR-00000001b
                    960: 
                    961: ; The source may be a packed pel source, which will have to be converted
                    962: 
                    963:         cmp     al,BMF_DEVICE           ;4 plane format
                    964:         je      copy_dev_20             ;  Yes, no packed pel conversion
                    965:         cmp     al,BMF_PHYSDEVICE
                    966:         je      copy_dev_20             ;  ditto
                    967: 
                    968:         mov     [ebp].iFormat,al        ;Save source format
                    969:         mov     [ebp].fb,PPC_NEEDED     ;Show conversion needed
                    970: copy_dev_20:
                    971: 
                    972:         mov     al,bh                   ;Set IS_COLOR and IS_DEVICE
                    973:         and     al,IS_COLOR+IS_DEVICE   ;  flags in the Device Flags
                    974:         errnz   IS_COLOR-F0_DEST_IS_COLOR ;Must be same bits
                    975:         mov     [edi].dev_flags,al
                    976:         cRet    copy_dev
                    977: 
                    978: endProc copy_dev
                    979: 
                    980: 
                    981: ;----------------------------Private-Routine----------------------------;
                    982: ; pattern_preprocessing
                    983: ;
                    984: ; If a pattern is needed, make sure that it isn't a hollow
                    985: ; brush. If it is a hollow brush, then return an error.
                    986: ;
                    987: ; The type of brush to use will be set, and the brush pointer
                    988: ; updated to point to the mono bits if the mono brush will be
                    989: ; used.  The type of brush used will match the destination device.
                    990: ;
                    991: ; If the destination is mono and the source is color, then a mono
                    992: ; brush fetch will be used, with the color brush munged in advance
                    993: ; according to the background/foreground colors passed:
                    994: ;
                    995: ;     All brush pixels which match the background color should be set
                    996: ;     to white (1).  All other brush pixels should be set to black (0).
                    997: ;
                    998: ;     If the physical color is stored as all 1's or 0's for each
                    999: ;     plane, then by XORing the physical color for a plane with the
                   1000: ;     corresponding byte in the brush, and ORing the results, this
                   1001: ;     will give 0's where the color matched, and  1's where the colors
                   1002: ;     didn't match.  Inverting this result will then give 1's where
                   1003: ;     the brush matched the background color and 0's where it did not.
                   1004: ;
                   1005: ; If both the source and destination are color, or the source is mono
                   1006: ; and the destination color, then the color portion of the brush will
                   1007: ; be used.
                   1008: ;
                   1009: ; If both the source and destination are mono, then the monochrome
                   1010: ; portion of the brush will be used.
                   1011: ;
                   1012: ; Entry:
                   1013: ;       BH = fr.the_flags
                   1014: ;       EBP = fr
                   1015: ; Returns:
                   1016: ;       Carry flag clear if no error
                   1017: ; Error Returns:
                   1018: ;       Carry flag set if error (null lpPBrush, or hollow brush)
                   1019: ; Registers Preserved:
                   1020: ;       EBP
                   1021: ; Registers Destroyed:
                   1022: ;       AX,BX,CX,DX,SI,DI,DS,ES,flags
                   1023: ; Calls:
                   1024: ;       None
                   1025: ; History:
                   1026: ;  Sat 15-Aug-1987 18:20:34 -by-  Wesley O. Rupel [wesleyr]
                   1027: ; Added 4-plane support.
                   1028: ;  Sun 22-Feb-1987 16:29:09 -by-  Walt Moore [waltm]
                   1029: ; Created.
                   1030: ;-----------------------------------------------------------------------;
                   1031: 
                   1032: ;------------------------------Pseudo-Code------------------------------;
                   1033: ; {
                   1034: ; }
                   1035: ;-----------------------------------------------------------------------;
                   1036: 
                   1037: cProc   pattern_preprocessing
                   1038: 
                   1039:         mov     [ebp].the_flags,bh      ;Save flag values
                   1040:         test    bh,F0_PAT_PRESENT       ;Pattern required?
                   1041:         jz      pattern_preproc_end     ;  No, skip pattern check
                   1042:         mov     esi,[ebp].lpPBrush      ;--> physical brush
                   1043:         mov     dl,[esi].oem_brush_accel;Save brush accelerator
                   1044:         mov     [ebp].brush_accel,dl    ; in local variable frame
                   1045:         test    dl,SOLID_BRUSH          ;Don't need to rotate a solid brush
                   1046:         jnz     pattern_preproc_end
                   1047: 
                   1048: ; !!! hack-o-ramma.  rotate the brush on the frame for now.
                   1049: 
                   1050:         push    ebx
                   1051:         mov     edx,00000111b
                   1052:         lea     edi,[ebp].a_brush.oem_brush_C0  ;EDI --> temp brush area
                   1053:         mov     [ebp].lpPBrush,edi
                   1054:         mov     ebx,[ebp].pptlBrush
                   1055:         mov     ecx,dword ptr [ebx][0]
                   1056:         and     ecx,edx
                   1057:         mov     ebx,dword ptr [ebx][4]
                   1058:         and     ebx,edx
                   1059:         mov     ch,4
                   1060: 
                   1061: pattern_preproc_color:
                   1062:         lodsb
                   1063:         and     ebx,edx
                   1064:         ror     al,cl
                   1065:         mov     byte ptr [edi][ebx],al
                   1066:         inc     ebx
                   1067: 
                   1068:         lodsb
                   1069:         and     ebx,edx
                   1070:         ror     al,cl
                   1071:         mov     byte ptr [edi][ebx],al
                   1072:         inc     ebx
                   1073: 
                   1074:         lodsb
                   1075:         and     ebx,edx
                   1076:         ror     al,cl
                   1077:         mov     byte ptr [edi][ebx],al
                   1078:         inc     ebx
                   1079: 
                   1080:         lodsb
                   1081:         and     ebx,edx
                   1082:         ror     al,cl
                   1083:         mov     byte ptr [edi][ebx],al
                   1084:         inc     ebx
                   1085: 
                   1086:         lodsb
                   1087:         and     ebx,edx
                   1088:         ror     al,cl
                   1089:         mov     byte ptr [edi][ebx],al
                   1090:         inc     ebx
                   1091: 
                   1092:         lodsb
                   1093:         and     ebx,edx
                   1094:         ror     al,cl
                   1095:         mov     byte ptr [edi][ebx],al
                   1096:         inc     ebx
                   1097: 
                   1098:         lodsb
                   1099:         and     ebx,edx
                   1100:         ror     al,cl
                   1101:         mov     byte ptr [edi][ebx],al
                   1102:         inc     ebx
                   1103: 
                   1104:         lodsb
                   1105:         and     ebx,edx
                   1106:         ror     al,cl
                   1107:         mov     byte ptr [edi][ebx],al
                   1108:         inc     ebx
                   1109: 
                   1110:         add     edi,8
                   1111:         dec     ch
                   1112:         jnz     pattern_preproc_color
                   1113:         pop     ebx
                   1114: 
                   1115: pattern_preproc_end:
                   1116:         clc
                   1117:         cRet    pattern_preprocessing
                   1118: 
                   1119: endProc pattern_preprocessing
                   1120: 
                   1121: 
                   1122: ;----------------------------Private-Routine----------------------------;
                   1123: ; compute_y
                   1124: ;
                   1125: ; Compute y-related parameters.
                   1126: ;
                   1127: ; The parameters related to the Y coordinate and BLT direction
                   1128: ; are computed.  The parameters include:
                   1129: ;
                   1130: ;       a) Index to next scan line
                   1131: ;       b) Starting Y address calculation
                   1132: ;       d) Index to next plane
                   1133: ;
                   1134: ; Entry:
                   1135: ;       EBP --> DEV structure to use (src or dest)
                   1136: ;       AX  =  Y coordinate
                   1137: ;       ECX =  BLT direction
                   1138: ;              0000 = Y+
                   1139: ;              FFFF = Y-
                   1140: ;       BX  =  inclusive Y extent
                   1141: ; Returns:
                   1142: ;       ECX  =  BLT direction
                   1143: ;       EBX  =  inclusive count
                   1144: ; Registers Preserved:
                   1145: ;       EBP
                   1146: ; Registers Destroyed:
                   1147: ;       AX,DX,SI,DI,flags
                   1148: ; Calls:
                   1149: ;       None
                   1150: ; History:
                   1151: ;-----------------------------------------------------------------------;
                   1152: 
                   1153: cProc   compute_y
                   1154: 
                   1155:         movsx   esi,[ebp].width_b       ;Need bmWidthBytes a couple of times
                   1156:         movzx   eax,ax
                   1157:         mul     esi                     ;Compute Y address
                   1158:         add     [ebp].lp_bits,eax
                   1159:         xor     esi,ecx                 ;1's complement if Y-
                   1160:         sub     esi,ecx                 ;2's complement if Y-
                   1161: 
                   1162:         test    [ebp].dev_flags,IS_DEVICE
                   1163:         jnz     compute_y_done
                   1164:         test    [ebp].dev_flags,IS_COLOR
                   1165:         jz      compute_y_done
                   1166: 
                   1167: 
                   1168: ; !!! I need to rewrite how next scan is handled.  Currently, for +Y, next scan is 0,
                   1169: ; !!! and for -Y it is 2* -lNextScan
                   1170: 
                   1171:         add     esi,esi                 ;Assume -Y (comp 2 * -lNextScan)
                   1172:         and     esi,ecx                 ;ESI = 0 if +Y, or 2 * -lNextScan
                   1173: 
                   1174: compute_y_done:
                   1175:         mov     [ebp].next_scan,esi     ;Set index to next scan line
                   1176:         cRet    compute_y               ;All done with device, small bitmaps
                   1177: 
                   1178: endProc compute_y
                   1179: 
                   1180: _TEXT$02   ends
                   1181: 
                   1182:         end
                   1183: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.