Annotation of ntddk/src/video/displays/vga/i386/special.asm, revision 1.1

1.1     ! root        1:                 page    ,132
        !             2: ;---------------------------Module-Header------------------------------;
        !             3: ; Module Name: special.asm
        !             4: ;
        !             5: ; Copyright (c) 1992 Microsoft Corporation
        !             6: ;-----------------------------------------------------------------------;
        !             7:         title   Special
        !             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:         .data
        !            24: 
        !            25: ;BUGBUG this should be obtained from the surface
        !            26: 
        !            27:         extrn   ulNextScan_global:dword
        !            28: 
        !            29:         .code
        !            30: 
        !            31: _TEXT$01   SEGMENT DWORD USE32 PUBLIC 'CODE'
        !            32:            ASSUME  CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
        !            33: 
        !            34:         .xlist
        !            35:         include stdcall.inc             ;calling convention cmacros
        !            36:         include i386\cmacFLAT.inc       ; FLATland cmacros
        !            37:         include i386\display.inc        ; Display specific structures
        !            38:         include i386\ppc.inc            ; Pack pel conversion structure
        !            39:         include i386\bitblt.inc         ; General definitions
        !            40:         include i386\ropdefs.inc        ; Rop definitions
        !            41:         include i386\egavga.inc         ; EGA register definitions
        !            42:         include i386\strucs.inc
        !            43:         .list
        !            44: 
        !            45: ; Rops we use in this code
        !            46: 
        !            47: ROP_P           equ     0F0h
        !            48: ROP_Pn          equ      0Fh
        !            49: ROP_S           equ     0CCh
        !            50: ROP_DDx         equ       0
        !            51: ROP_DDxn        equ     0FFh
        !            52: ROP_Dn          equ     055h
        !            53: ROP_DPx         equ     05Ah
        !            54: 
        !            55: ; Other values used in this code
        !            56: 
        !            57: fr              equ     [ebp]           ; Access to bitblt frame
        !            58: bptr            equ     byte ptr
        !            59: 
        !            60: ;----------------------------Public Routine----------------------------;
        !            61: ; check_device_special_cases
        !            62: ;
        !            63: ; Check for fast special cases of BLT.
        !            64: ;
        !            65: ; Determine if the BLT is a special case which can be performed with
        !            66: ; static code as opposed to code compiled on the stack, and, if so,
        !            67: ; dispatch to the proper static code.
        !            68: ;
        !            69: ; The parameters needed for the BLT (phase alignment, directions of
        !            70: ; movement, ...) have been computed and saved.  These parameters will
        !            71: ; now be interpreted and a BLT created on the stack.
        !            72: ;
        !            73: ; If the raster op is source copy, both devices are the screen, and the
        !            74: ; phase alignment is 0, then the copy can be performed by the static
        !            75: ; code using the EGA's write mode 1.
        !            76: ;
        !            77: ; If the rasterop is P, Pn, DDx (0), DDxn (1), and the brush is solid
        !            78: ; or grey (for P and Pn), and the destination device is the screen,
        !            79: ; then the operation can be performed by the static code using the EGA's
        !            80: ; write mode 2 (write mode 0 for greys).
        !            81: ;
        !            82: ; Entry:
        !            83: ;       EDI --> pointer to target surface
        !            84: ;       EBP --> frame of BitBLT local variables
        !            85: ;       EGA registers in default state
        !            86: ; Returns:
        !            87: ;       Carry set if BLT was performed with static code.
        !            88: ; Error Returns:
        !            89: ;       Carry clear if BLT was not a special case.
        !            90: ; Registers Destroyed:
        !            91: ;       AX,BX,CX,DX,SI,DI,DS,ES,flags
        !            92: ; Registers Preserved:
        !            93: ;       EBP
        !            94: ; Calls:
        !            95: ;-----------------------------------------------------------------------;
        !            96: 
        !            97: cProc   check_device_special_cases
        !            98: 
        !            99:         xor     cx,cx                       ;This is used, what is it????!!!
        !           100:         mov     dh,fr.the_flags             ;Keep the flags in DH for a while
        !           101:         test    dh,F0_DEST_IS_DEV           ;Is the destination a device?
        !           102:         jz      cdsc_blt_not_special_cased  ;Not device, cannot special case it
        !           103:         mov     edi,fr.dest.next_scan       ;Special case code expects this
        !           104:         mov     al,byte ptr fr.Rop[0]       ;Get the raster op
        !           105:         cmp     al,ROP_S                    ;Is it src copy?
        !           106:         je      cdsc_its_src_copy     ;  Yes, go check it out
        !           107:         cmp     al,ROP_P
        !           108:         je      short cdsc_its_patblt
        !           109: 
        !           110: cdsc_not_s_or_p:
        !           111:         xor     bl,bl                       ;Color for 0 fill
        !           112:         cmp     al,ROP_DDx
        !           113:         je      short cdsc_its_1_or_0
        !           114:         cmp     al,ROP_Pn
        !           115:         je      short cdsc_its_inverse_patblt
        !           116:         cmp     al,ROP_Dn
        !           117:         je      short cdsc_its_dn
        !           118:         cmp     al,ROP_DPx
        !           119:         je      short cdsc_its_dpx
        !           120:         cmp     al,ROP_DDxn
        !           121:         jne     cdsc_blt_not_special_cased
        !           122:         mov     bl,0FFh                     ;Color for 1 fill
        !           123: 
        !           124: ; It's "1" (DDxn) or "0" (DDx)
        !           125: cdsc_its_1_or_0:
        !           126:         mov     fr.brush_accel,SOLID_BRUSH  ;(no brush given for DDx or DDxn)
        !           127:         call    ega_solid_pat
        !           128:         jmp     cdsc_exit
        !           129: 
        !           130: cdsc_its_patblt:
        !           131:         mov     bl,fr.brush_accel       ;Ccolor in lower bits, flags in upper
        !           132:         test    bl,SOLID_BRUSH
        !           133:         jnz     short cdsc_its_a_solid_color
        !           134:         test    bl,GREY_SCALE
        !           135:         jz      short cdsc_not_solid_nor_grey
        !           136:         xor     bl,bl                   ;It's grey.  !!! what is this flag
        !           137:         call    ega_solid_pat
        !           138:         jmp     cdsc_exit
        !           139: 
        !           140: cdsc_not_solid_nor_grey:
        !           141:         call    do_wes_patblt
        !           142:         jmp     cdsc_exit
        !           143: 
        !           144: cdsc_its_inverse_solid_color:
        !           145:         not     bl
        !           146: cdsc_its_a_solid_color:
        !           147:         mov     cx,2
        !           148:         call    do_solid_patcopy        ;color and accl. flags already in BL
        !           149:         jmp     short cdsc_exit
        !           150: 
        !           151: cdsc_its_inverse_patblt:
        !           152:         mov     bl,fr.brush_accel       ;color in lower bits, flags in upper
        !           153:         test    bl,SOLID_BRUSH
        !           154:         jnz     short cdsc_its_inverse_solid_color
        !           155:         test    bl,GREY_SCALE
        !           156:         jz      short cdsc_blt_not_special_cased
        !           157:         mov     bl,-1                   ;It's grey.  !!! What is this flag
        !           158:         call    ega_solid_pat
        !           159:         jmp     short cdsc_exit
        !           160: 
        !           161: cdsc_its_dn:
        !           162:         call    do_wes_invert
        !           163:         jmp     short cdsc_exit
        !           164: 
        !           165: cdsc_its_dpx:
        !           166:         mov     ah,fr.brush_accel       ;color in lower bits, flags in upper
        !           167:         test    ah,SOLID_BRUSH
        !           168:         jnz     cdsc_its_solid_dpx      ;dpx with solid brush
        !           169:         test    ah,GREY_SCALE           ;Otherwise must be a grey brush
        !           170:         jz      short cdsc_blt_not_special_cased
        !           171:         call    do_grey_dpx
        !           172:         jmp     short cdsc_exit
        !           173: 
        !           174: cdsc_its_solid_dpx:
        !           175:         call    do_wes_dpx_solidpat     ;solid color => can special case
        !           176:         jmp     short cdsc_exit
        !           177: 
        !           178: 
        !           179: ;-----------------------------------------------------------------------;
        !           180: ; This is a source copy.  The phase must be zero to special case the
        !           181: ; source copy, and both devices must be the screen.
        !           182: ;
        !           183: ;       errnz      F0_SRC_IS_DEV - 00001000b
        !           184: ;       errnz    F0_SRC_IS_COLOR - 00000100b
        !           185: ;
        !           186: ; its_src_copy:
        !           187: ;       and     dh,F0_SRC_IS_DEV + F0_SRC_IS_COLOR
        !           188: ;       shiftr  dh,2
        !           189: ;       cmp     fr.phase_h,1            ; Gives CF if horizontal phase = zero
        !           190: ;       rcl     dh,1
        !           191: ; Now we have the needed flags in the lower 3 bits of DH
        !           192: ;                                       ; Src=EGA  Src=Color  Phase0
        !           193: ;
        !           194: ;       dw      do_wes_mono_trick       ;    0        0         0
        !           195: ;       dw      blt_not_a_special_case  ;    0        0         1
        !           196: ;       dw      blt_not_a_special_case  ;    0        1         0
        !           197: ;       dw      blt_not_a_special_case  ;    0        1         1
        !           198: ;       dw      do_wes_mono_trick       ;    1        0         0
        !           199: ;       dw      blt_not_a_special_case  ;    1        0         1
        !           200: ;       dw      blt_not_a_special_case  ;    1        1         0
        !           201: ;       dw      ega_src_copy            ;    1        1         1
        !           202: ;-----------------------------------------------------------------------;
        !           203: 
        !           204: cdsc_its_src_copy:
        !           205:         test    dh,F0_SRC_IS_DEV
        !           206:         jnz     short cdsc_exit
        !           207: 
        !           208: cdsc_source_is_memory:
        !           209:         test    dh,F0_SRC_IS_COLOR          ;mono-mem to color-EGA conversion?
        !           210:         jnz     cdsc_blt_not_special_cased  ;color to color, cannot special case it
        !           211:         call    do_wes_mono_trick
        !           212:         jmp     short cdsc_exit
        !           213: 
        !           214: cdsc_blt_not_special_cased:
        !           215:         clc
        !           216:         cRet    check_device_special_cases
        !           217: 
        !           218: cdsc_exit:
        !           219:         stc
        !           220:         cRet    check_device_special_cases
        !           221: 
        !           222: 
        !           223: ;----------------------------Private-Routine----------------------------;
        !           224: ; calc_parms
        !           225: ;
        !           226: ; Calculate the parameters needed for the output functions contained
        !           227: ; in this file.
        !           228: ;
        !           229: ; To avoid conditional jumps we will use some sick optimizations.
        !           230: ; Remember this:
        !           231: ;       adc     ax,-1           ; DEC AX if carry clear
        !           232: ;       sbb     ax,0            ; DEC AX if carry set
        !           233: ;       sbb     ax,-1           ; INC AX if carry clear
        !           234: ;       adc     ax,0            ; INC AX if carry set
        !           235: ;
        !           236: ; Entry:
        !           237: ;       EBP --> BitBLT local frame
        !           238: ; Returns:
        !           239: ;       ESI set to upper left of bitmap or pattern
        !           240: ;       EDI set to upper left
        !           241: ;       EDX = src bitmap width  (if present)
        !           242: ;       ECX = fr.yExt
        !           243: ;       EBX = offset into pattern (if pat present)
        !           244: ;       sets dest_right_edge
        !           245: ;       sets start_mask[0]
        !           246: ;       sets last_mask[0]
        !           247: ;       sets inner_loop_count
        !           248: ; Registers Destroyed:
        !           249: ;       EAX,flags
        !           250: ; Registers Preserved:
        !           251: ;       EBP
        !           252: ; Alters:
        !           253: ;
        !           254: ; Calls:
        !           255: ;       None
        !           256: ;-----------------------------------------------------------------------;
        !           257: 
        !           258:         .errnz  SIZE_PATTERN - 8                ; any power of 2 will work
        !           259: 
        !           260:         align   4
        !           261: calc_parms:
        !           262: 
        !           263: ; Left edge.
        !           264: 
        !           265:         movzx   edi,fr.DestxOrg         ;X origin in pixels, must be positive
        !           266:         mov     ebx,edi
        !           267:         mov     cl,7
        !           268:         and     ecx,edi                 ;Save lower 3 bits
        !           269:         mov     fr.phase_h,cl
        !           270:         shr     edi,3                   ;EDI set for left edge
        !           271:         mov     al,0FFh
        !           272:         shr     al,cl
        !           273:         mov     byte ptr fr.start_mask[0],al
        !           274: 
        !           275: ; Right edge.
        !           276: 
        !           277:         movzx   eax,fr.xExt
        !           278:         add     ebx,eax                 ;Right edge in pixels
        !           279:         mov     cl,7
        !           280:         and     cl,bl                   ;save lower 3 bits
        !           281:         shr     ebx,3                   ;convert to bytes
        !           282:         mov     fr.start_fl,ebx         ;dest_right_edge (reuse stk variable)
        !           283:         mov     al,0FFh
        !           284:         shr     al,cl
        !           285:         not     al
        !           286: 
        !           287: ; Check if the BLT does not cross any byte boundaries.
        !           288: 
        !           289:         sub     ebx,edi                 ;make EBX # bytes including left edge
        !           290:         jnz     crosses_byte_boundary
        !           291:         and     byte ptr fr.start_mask[0],al
        !           292:         xor     al,al
        !           293: 
        !           294: ; There are 2 cases where we get zero for fr.inner_loop_count:
        !           295: ; When the start and end bytes are adjacent and when they are
        !           296: ; the same byte.  In the latter case we get -1 for
        !           297: ; fr.inner_loop_count so INC BX now so it will be zero.
        !           298: 
        !           299:         inc     ebx
        !           300: crosses_byte_boundary:
        !           301: 
        !           302:         cmp     al,0FFh
        !           303:         sbb     al,-1                   ;AL=FF -> AL=0 (put in innerloop)
        !           304:         mov     byte ptr fr.last_mask[0],al
        !           305: 
        !           306: ; Inner loop  --  combine edge bytes into inner loop if they are
        !           307: ; full bytes.
        !           308: 
        !           309:         mov     fr.end_fl,ebx           ;src_right_edge (reuse stk variable)
        !           310:         mov     al,byte ptr fr.start_mask[0]
        !           311:         cmp     al,0FFh
        !           312: 
        !           313: ; If gl_start_mask = FF the carry is clear, otherwise carry is set.
        !           314: ; We want to DEC BX if carry set because we have already included
        !           315: ; the left edge byte in BX, but we shouldn't have included it if
        !           316: ; it's only a partial byte.
        !           317: 
        !           318:         sbb     ebx,0
        !           319:         cmp     al,0FFh
        !           320: 
        !           321: ; If gl_start_mask = FF the carry is clear, otherwise carry is set.
        !           322: ; We want to INC AL (zero it) if it is FF (carry clear) because we
        !           323: ; will do this edge as part of the innerloop.
        !           324: 
        !           325:         sbb     al,-1
        !           326:         mov     byte ptr fr.start_mask[0],al
        !           327:         mov     fr.inner_loop_count,ebx
        !           328:         movzx   eax,fr.DestyOrg
        !           329:         imul    eax,ulNextScan_global
        !           330:         add     edi,eax
        !           331:         mov     esi,fr.pdsurfDst
        !           332:         add     edi,[esi].dsurf_pvBitmapStart
        !           333: 
        !           334: ; The source.
        !           335: 
        !           336:         test    fr.the_flags,F0_SRC_PRESENT
        !           337:         jz      no_source
        !           338:         mov     esi,fr.pdsurfSrc
        !           339:         mov     ecx,[esi].dsurf_lNextScan   ;!!! will this be correct ??
        !           340:         mov     esi,[esi].dsurf_pvBitmapStart
        !           341: 
        !           342: ; Left edge.
        !           343: 
        !           344:         movzx   ebx,fr.SrcxOrg
        !           345:         mov     dl,7
        !           346:         and     dl,bl                   ;get lower 3 bits ( Src Mod 8 )
        !           347:         sub     fr.phase_h,dl           ;phase def'd as Mod8[gl_dest]-
        !           348:         shr     ebx,3                   ;               Mod8[gl_src]
        !           349:         add     esi,ebx                 ;ESI set for left edge
        !           350:         movzx   eax,fr.SrcyOrg
        !           351:         mul     ecx
        !           352:         add     esi,eax
        !           353:         add     fr.end_fl,esi           ;src_right_edge (reuse stack variable)
        !           354:         mov     edx,ecx
        !           355:         jmp     short   no_pattern
        !           356: no_source:
        !           357:         test    fr.the_flags,F0_PAT_PRESENT ; assuming P or S but not both
        !           358:         jz      no_pattern
        !           359:         mov     esi,fr.lpPBrush
        !           360:         movzx   ebx,fr.DestyOrg
        !           361:         and     ebx,SIZE_PATTERN - 1
        !           362: no_pattern:
        !           363:         movzx   ecx,fr.yExt
        !           364:         PLAIN_RET
        !           365: 
        !           366: 
        !           367: ;----------------------------Private-Routine----------------------------;
        !           368: ; ega_solid_pat
        !           369: ;
        !           370: ; EGA special case for solid color pattern copy.
        !           371: ;
        !           372: ; The following routine is invoked instead of generating code for a
        !           373: ; pattern copy.  The actual time involved in executing the pattern
        !           374: ; copy as static code as compared to compiled code is a win.
        !           375: ;
        !           376: ; This code can only be used if the pattern is a solid color or a grey,
        !           377: ; and the operation is to the screen.  In this case, the three bits of
        !           378: ; color stored in the accelerator byte of the brush will be used, or the
        !           379: ; bits of the grey brush.
        !           380: ;
        !           381: ; The logic operations which will invoke this routine are:
        !           382: ;
        !           383: ;       P
        !           384: ;       Pn
        !           385: ;       DDx
        !           386: ;       DDxn
        !           387: ;
        !           388: ; Entry:
        !           389: ;       BL = color to write or xor value for a grey pattern
        !           390: ;       CX = Mode register value (sort of)
        !           391: ;       EBP = BitBLT local variable frame
        !           392: ; Returns:
        !           393: ;       Nothing
        !           394: ; Registers Destroyed:
        !           395: ;       ALL except EBP
        !           396: ; Registers Preserved:
        !           397: ;       EBP
        !           398: ; Calls:
        !           399: ;       None
        !           400: ;-----------------------------------------------------------------------;
        !           401: 
        !           402:         align   4
        !           403: ega_solid_pat:
        !           404: 
        !           405: ; Instead of pushing and popping the destination pointer and adding in
        !           406: ; the fr.dest.Incr, the bias needed for adjusting the pointer at the
        !           407: ; end of a scan line will be computed and used.
        !           408: ;
        !           409: ; Since this is a pattern copy, the fr.dest.Incr will be positive.
        !           410: 
        !           411: ;       mov     esi,edi                 ;Get destination increment
        !           412: ;       sub     esi,1                   ;Adjust for first byte
        !           413:         lea     esi,-1[edi]
        !           414:         sub     esi,fr.inner_loop_count ;Compute number of bytes to copy
        !           415: 
        !           416: ; Put color in Set/Reset if it is a solid color.
        !           417: 
        !           418:         mov     dx,EGA_BASE + GRAF_ADDR
        !           419:         or      cx,cx
        !           420:         jz      not_solid_color
        !           421:         mov     ax,MM_ALL * 256 + GRAF_ENAB_SR
        !           422:         out     dx,ax
        !           423:         mov     ah,bl
        !           424:         mov     al,GRAF_SET_RESET
        !           425:         out     dx,ax
        !           426: not_solid_color:
        !           427:         mov     al,GRAF_BIT_MASK        ;Leave graphics controller pointing
        !           428:         out     dx,al                   ;  to the bitmask register, which
        !           429:         inc     dx                      ;  is where cursor leaves it too
        !           430: 
        !           431: ; Set up for the loop.
        !           432: 
        !           433:         mov     edi,fr.dest.lp_bits     ;--> destination
        !           434:         mov     fr.phase_h,bl           ;Save color to write or grey XOR mask
        !           435: 
        !           436: ega_solid_pat_20:
        !           437:         mov     al,fr.phase_h               ;Get the color to write
        !           438:         test    fr.brush_accel,SOLID_BRUSH  ;Grey scale brush?
        !           439:         jnz     ega_solid_pat_30            ;  No, a solid color
        !           440:         mov     bl,fr.pat_row               ;Get scan of brush
        !           441:         inc     bl                          ;  and update brush pointer
        !           442:         mov     fr.pat_row,bl
        !           443:         dec     bl
        !           444:         and     ebx,00000111b
        !           445:         add     ebx,fr.lpPBrush
        !           446:         xor     al,bptr [ebx]               ;Invert if needed
        !           447: 
        !           448: ega_solid_pat_30:
        !           449:         mov     bl,al
        !           450:         mov     al,bptr fr.start_mask[1]    ;Set bitmask for first byte
        !           451:         out     dx,al
        !           452:         mov     al,bl
        !           453:         xchg    al,[edi]                    ;xchg to load EGA's latches first
        !           454:         inc     edi                         ;PAT_COPY step +X always!
        !           455: 
        !           456:         mov     ecx,fr.inner_loop_count     ;Set count for innerloop
        !           457:         jecxz   ega_solid_pat_40            ;No innerloop or last byte
        !           458:         mov     al,0FFh                     ;Inner loop alters all bits
        !           459:         out     dx,al
        !           460:         mov     al,bl
        !           461:         rep     stosb
        !           462: 
        !           463: ega_solid_pat_40:
        !           464:         mov     al,bptr fr.last_mask[1]     ;Last byte?
        !           465:         or      al,al
        !           466:         jz      ega_solid_pat_50            ;No last byte
        !           467:         out     dx,al
        !           468:         xchg    bl,[edi]
        !           469: 
        !           470: ega_solid_pat_50:
        !           471:         add     edi,esi                     ;--> next destination
        !           472:         dec     fr.yExt                     ;Any more scans to process?
        !           473:         jnz     ega_solid_pat_20            ;  Yes
        !           474:         PLAIN_RET
        !           475: 
        !           476: 
        !           477: ;----------------------------Private-Routine----------------------------;
        !           478: ; do_wes_invert
        !           479: ; do_wes_dpx_solidpat
        !           480: ;
        !           481: ; Entry:
        !           482: ;       EBP --> BitBLT local variable frame
        !           483: ;       AH = color of solid-pat.
        !           484: ; Returns:
        !           485: ;       Nothing
        !           486: ; Registers Destroyed:
        !           487: ;       ALL but EBP
        !           488: ; Registers Preserved:
        !           489: ;       EBP
        !           490: ; Calls:
        !           491: ;       calc_parms
        !           492: ;       edge_invert
        !           493: ;       invert
        !           494: ;-----------------------------------------------------------------------;
        !           495: 
        !           496:         align   4
        !           497: do_wes_invert:
        !           498: 
        !           499:         mov     ah,0Fh                  ; black
        !           500: 
        !           501: do_wes_dpx_solidpat     label near
        !           502: 
        !           503: ; Setup SET_RESET.
        !           504: 
        !           505:         mov     dx,EGA_BASE + GRAF_ADDR
        !           506:         mov     al,GRAF_SET_RESET
        !           507:         out     dx,ax
        !           508:         mov     ax,0F00h + GRAF_ENAB_SR ; enable all planes
        !           509:         out     dx,ax
        !           510: 
        !           511: ; Go to XOR mode.
        !           512: 
        !           513:         mov     ax,GRAF_DATA_ROT + 256 * DR_XOR
        !           514:         out     dx,ax
        !           515: 
        !           516:         call    calc_parms
        !           517:         mov     ah,byte ptr fr.start_mask[0]
        !           518:         or      ah,ah
        !           519:         jz      no_left_invert_edge
        !           520:         push    edi
        !           521:         call    edge_invert
        !           522:         pop     edi
        !           523:         inc     edi
        !           524: 
        !           525: no_left_invert_edge:
        !           526:         mov     ebx,fr.inner_loop_count
        !           527:         or      ebx,ebx
        !           528:         jz      no_inner_invert_loop
        !           529:         movzx   ecx,fr.yExt
        !           530:         push    edi
        !           531:         call    invert
        !           532:         pop     edi
        !           533:         add     edi,fr.inner_loop_count
        !           534: 
        !           535: no_inner_invert_loop:
        !           536:         mov     ah,byte ptr fr.last_mask[0]
        !           537:         or      ah,ah
        !           538:         jz      no_last_invert_edge
        !           539:         movzx   ecx,fr.yExt
        !           540:         call    edge_invert
        !           541: 
        !           542: no_last_invert_edge:
        !           543:         PLAIN_RET
        !           544: 
        !           545: 
        !           546: ;----------------------------Private-Routine----------------------------;
        !           547: ;do_solid_patcopy() is called to copy (PatCopy) a solid brush directly to
        !           548: ;the screen.
        !           549: ;
        !           550: ;Entry:
        !           551: ;   BL      color to write with
        !           552: ;   EDI     fr.dest.next_scan which is equal to width_b
        !           553: ;   EBP     local varible frame
        !           554: ;
        !           555: ;-----------------------------------------------------------------------;
        !           556: 
        !           557:         align   4
        !           558: do_solid_patcopy:
        !           559: 
        !           560:         cmp     fr.inner_loop_count,0   ;if zero, let ega_solid_pat do the work
        !           561:         jne     dsp_do_it
        !           562:         call    ega_solid_pat
        !           563:         PLAIN_RET
        !           564: 
        !           565: dsp_do_it:
        !           566:         sub     eax,eax                 ;accumulate flags in AL
        !           567:         mov     esi,edi                 ;SI: fr.dest.next_scan (must be > 0)
        !           568:         mov     edi,fr.dest.lp_bits     ;EDI-->first byte to write to
        !           569:         mov     bh,bptr fr.start_mask[1]
        !           570:         cmp     ah,bh                   ;is there a left edge?
        !           571:         rcl     al,1                    ;CY if there is an edge to draw
        !           572:         sub     bh,0ffh                 ;is the left edge an entire byte wide?
        !           573:         neg     bh                      ;CY if less than a byte
        !           574:         rcl     al,1                    ;accumulate flag into AL
        !           575:         mov     bh,bptr fr.last_mask[1]
        !           576:         cmp     ah,bh                   ;is there a right edge?
        !           577:         rcl     al,1                    ;CY if there is an edge to draw
        !           578:         sub     bh,0ffh                 ;is right edge an entire byte wide?
        !           579:         neg     bh                      ;CY if less than a byte
        !           580:         rcl     al,1                    ;accumulate flag into AL
        !           581:         test    al,04h                  ;set all pixels in left byte?
        !           582:         jnz     dsp_keep_left_edge      ;no. Do normal stuff
        !           583:         inc     fr.inner_loop_count     ;left edge is an entire byte. INC inner
        !           584:         and     al,0f7h                 ;loop cnt and draw it the fast way
        !           585: 
        !           586: dsp_keep_left_edge:
        !           587:         test    al,01h                  ;set all pixels in right byte?
        !           588:         jnz     dsp_keep_right_edge     ;no. Do normal stuff
        !           589:         inc     fr.inner_loop_count     ;need to set all pixels in right byte.
        !           590:         and     al,0fdh                 ;inc inner loop cnt do it the fast way
        !           591: 
        !           592: dsp_keep_right_edge:
        !           593:         test    al,0ah                  ;any edges to draw?
        !           594:         jz      dsp_draw_core_piece     ;no, just do the main chunk
        !           595: 
        !           596: dsp_draw_edges:
        !           597:         mov     bh,al                   ;save flags in BH
        !           598:         mov     dx,EGA_BASE + GRAF_ADDR
        !           599:         mov     ax,MM_ALL * 256 + GRAF_ENAB_SR
        !           600:         out     dx,ax                   ;enable writing to all planes at once
        !           601:         mov     ah,bl
        !           602:         mov     al,GRAF_SET_RESET
        !           603:         out     dx,ax                   ;program to color value to write
        !           604:         mov     al,GRAF_BIT_MASK        ;Leave graphics controller pointing
        !           605:         out     dx,al                   ;  to the bitmask register, which
        !           606:         inc     dx                      ;  is where cursor leaves it too
        !           607: 
        !           608:         test    bh,08h                  ;need to draw the left edge?
        !           609:         jz      dsp_draw_right_edge
        !           610: 
        !           611:         push    edi                     ;save destination offset
        !           612:         mov     al,bptr fr.start_mask[1]
        !           613:         out     dx,al                   ;get it to the board
        !           614:         movzx   ecx,fr.yExt
        !           615: 
        !           616: dsp_left_edge_draw_loop:
        !           617:         mov     al,bl                   ;copy color index into AL
        !           618:         xchg    al,[edi]                ;load latches, copy color index
        !           619:         add     edi,esi
        !           620:         loop    dsp_left_edge_draw_loop
        !           621:         pop     edi                     ;restore dest offset
        !           622:         inc     edi                     ;update to new draw position
        !           623: 
        !           624: 
        !           625: dsp_draw_right_edge:
        !           626:         test    bh,02h                  ;is there a right edge to draw?
        !           627:         jz      dsp_reset_registers     ;no.  Restore default settings
        !           628:         push    edi                     ;save updated dest offset
        !           629:         add     edi,fr.inner_loop_count ;go to the right hand edge
        !           630:         mov     al,bptr fr.last_mask[1]
        !           631:         out     dx,al                   ;get it to the board
        !           632:         movzx   ecx,fr.yExt
        !           633: 
        !           634: dsp_right_edge_draw_loop:
        !           635:         mov     al,bl                   ;copy color index into AL
        !           636:         xchg    al,[edi]                ;load latches, copy color index
        !           637:         add     edi,esi
        !           638:         loop    dsp_right_edge_draw_loop
        !           639:         pop     edi                     ;restore dest offset
        !           640: 
        !           641: 
        !           642: dsp_reset_registers:
        !           643:         mov     al,0ffh                 ;allow writing to all bits in the byte
        !           644:         out     dx,al                   ;this is the default value
        !           645: 
        !           646: dsp_draw_core_piece:
        !           647:         sub     esi,fr.inner_loop_count ;account for EDI being incr. by stosb
        !           648:         mov     dx,EGA_BASE+SEQ_DATA    ;time to copy pattern to board  DX=3C5h
        !           649:         mov     al,01h
        !           650:         mov     ecx,4
        !           651: 
        !           652: dsp_load_latches_loop:
        !           653:         out     dx,al                   ;select the next plane to write to
        !           654:         shr     bl,1                    ;move plane bit into carry
        !           655:         sbb     ah,ah                   ;expand into AH
        !           656:         mov     [edi],ah                ;copy it to the bit plane
        !           657:         shl     al,1                    ;update plane selector
        !           658:         loop    dsp_load_latches_loop   ;do all 4 planes
        !           659: 
        !           660:         mov     al,MM_ALL               ;to enable all four planes
        !           661:         out     dx,al                   ;enable all planes
        !           662:         mov     dx,EGA_BASE+GRAF_ADDR   ;DX=3CEh
        !           663:         mov     ax,GRAF_BIT_MASK        ;AH=0 ie., copy data from latches, AL=8
        !           664:         out     dx,ax                   ;ignore CPU data on write to board
        !           665: 
        !           666:         mov     al,[edi]                ;load the latches
        !           667:         movzx   eax,fr.yExt             ;initialize loop counter
        !           668:         mov     ebx,fr.inner_loop_count ;initialize rep counter value
        !           669: 
        !           670:         align   4
        !           671: dsp_pat_blt_loop:
        !           672:         mov     ecx,ebx                 ;ECX: repeat count
        !           673:         test    edi,1
        !           674:         jz      short dsp_pat_blt_aligned2
        !           675:         stosb
        !           676:         dec     ecx
        !           677: dsp_pat_blt_aligned2:
        !           678:         shr     ecx,1
        !           679:         rep     stosw
        !           680:         adc     ecx,ecx
        !           681:         rep     stosb
        !           682:         add     edi,esi                 ;point to next scanline
        !           683:         dec     eax
        !           684:         jnz     dsp_pat_blt_loop
        !           685: 
        !           686:         PLAIN_RET
        !           687: 
        !           688: 
        !           689: ;----------------------------Private-Routine----------------------------;
        !           690: ; do_wes_patblt
        !           691: ;
        !           692: ; Entry:
        !           693: ;       EBP --> BitBLT local variable frame
        !           694: ; Returns:
        !           695: ;       Nothing
        !           696: ; Registers Destroyed:
        !           697: ;       All but EBP
        !           698: ; Registers Preserved:
        !           699: ;       EBP
        !           700: ; Calls:
        !           701: ;       calc_parms
        !           702: ;       edge_pat_blt
        !           703: ;       pat_blt
        !           704: ;-----------------------------------------------------------------------;
        !           705: 
        !           706:         align   4
        !           707: do_wes_patblt:
        !           708: 
        !           709:         call    calc_parms
        !           710:         mov     ah,byte ptr fr.start_mask[0]
        !           711:         or      ah,ah
        !           712:         jz      no_left_pat_edge
        !           713:         push    esi
        !           714:         push    ebx
        !           715:         call    edge_pat_blt            ; preserves DI
        !           716:         pop     ebx
        !           717:         pop     esi
        !           718:         inc     edi
        !           719: 
        !           720: no_left_pat_edge:
        !           721:         mov     edx,fr.inner_loop_count
        !           722:         or      edx,edx
        !           723:         jz      no_inner_pat_loop
        !           724:         movzx   ecx,fr.yExt
        !           725:         push    edi
        !           726:         push    esi
        !           727:         push    ebx
        !           728:         call    pat_blt
        !           729:         pop     ebx
        !           730:         pop     esi
        !           731:         pop     edi
        !           732:         add     edi,fr.inner_loop_count
        !           733: 
        !           734: no_inner_pat_loop:
        !           735:         mov     ah,byte ptr fr.last_mask[0]
        !           736:         or      ah,ah
        !           737:         jz      no_last_pat_edge
        !           738:         movzx   ecx,fr.yExt
        !           739:         call    edge_pat_blt
        !           740: 
        !           741: no_last_pat_edge:
        !           742:         PLAIN_RET
        !           743: 
        !           744: 
        !           745: ;----------------------------Private-Routine----------------------------;
        !           746: ; do_wes_mono_trick
        !           747: ;
        !           748: ; Entry:
        !           749: ;       EBP --> BitBLT local variable frame
        !           750: ; Returns:
        !           751: ;       Nothing
        !           752: ; Registers Preserved:
        !           753: ;       EBP
        !           754: ; Registers Destroyed:
        !           755: ;       All but EBP
        !           756: ; Calls:
        !           757: ;       calc_parms
        !           758: ;       left_edge_mono_to_color_blt
        !           759: ;       right_edge_mono_to_color_blt
        !           760: ;       mono_to_color_blt
        !           761: ;-----------------------------------------------------------------------;
        !           762: 
        !           763:         align   4
        !           764: do_wes_mono_trick:
        !           765: 
        !           766:         call    calc_parms
        !           767:         push    edx
        !           768:         mov     ah,byte ptr fr.start_mask[0]
        !           769:         or      ah,ah
        !           770:         jz      no_left_edge
        !           771:         push    edi
        !           772:         push    esi
        !           773:         push    edx
        !           774:         mov     al,fr.phase_h
        !           775:         mov     bx,fr.both_colors
        !           776: ;-      mov     ecx,fr.yExt
        !           777:         call    left_edge_mono_to_color_blt
        !           778:         pop     edx
        !           779:         pop     esi
        !           780:         pop     edi
        !           781:         inc     esi
        !           782:         inc     edi
        !           783: no_left_edge:
        !           784:         mov     ebx,edx
        !           785:         mov     edx,fr.inner_loop_count
        !           786:         mov     ecx,edi                   ; compute/save the right-hand edge
        !           787:         add     ecx,edx
        !           788:         push    ecx
        !           789:         or      edx,edx
        !           790:         jz      no_inner_loop
        !           791:         sub     ebx,edx
        !           792:         movzx   ecx,fr.yExt
        !           793:         mov     al,fr.phase_h
        !           794:         cbw
        !           795:         push    ebp
        !           796:         mov     bp,fr.both_colors
        !           797:         xchg    bp,ax
        !           798:         call    mono_to_color_blt
        !           799:         pop     ebp
        !           800: 
        !           801: no_inner_loop:
        !           802:         pop     edi
        !           803:         pop     edx
        !           804:         mov     ah,byte ptr fr.last_mask[0]
        !           805:         or      ah,ah
        !           806:         jz      no_last_edge
        !           807: 
        !           808:         mov     ecx,fr.inner_loop_count
        !           809:         mov     esi,fr.end_fl           ; src_right_edge (reuse stk variable)
        !           810:         movzx   ecx,fr.yExt
        !           811:         mov     bx,fr.both_colors
        !           812:         mov     al,fr.phase_h
        !           813:         call    right_edge_mono_to_color_blt
        !           814: 
        !           815: no_last_edge:
        !           816:         PLAIN_RET
        !           817: 
        !           818: 
        !           819: ;----------------------------Private-Routine----------------------------;
        !           820: ; mono_to_color_blt
        !           821: ;
        !           822: ; This does phase-0, byte-aligned, mem-mono to ega-color blt.
        !           823: ;
        !           824: ; The Problem: copy to the ega a bitmap where "0"s in the bitmap mean
        !           825: ; color1 and "1"s in the bitmap mean color2, where color1 and color2
        !           826: ; are arbitrary colors.
        !           827: ;
        !           828: ; The solution:
        !           829: ;
        !           830: ;                       plane0  plane1  plane2  plane3
        !           831: ;
        !           832: ; color1                1       1       0       0
        !           833: ; color2                1       0       1       0
        !           834: ; SetResetEnable        1       0       0       1
        !           835: ; SetReset              0       x       x       0
        !           836: ; latches               1       1       0       0       (=color1)
        !           837: ;
        !           838: ; Now with datarot = XOR we get
        !           839: ;
        !           840: ;  when databit=0       1       1       0       0       (=color1)
        !           841: ;  when databit=1       1       0       1       0       (=color2)
        !           842: ;
        !           843: ;
        !           844: ; Entry:
        !           845: ;       BP  = phase ( -7 to 7)   (high byte ignored)
        !           846: ;       AL  = background color ( "1" bits in mono-bitmap )
        !           847: ;       AH  = foreground color
        !           848: ;       EBX = SI wrap
        !           849: ;       ESI = Mono Bitmap first byte
        !           850: ;       EDI = First EGA Byte
        !           851: ;       ECX = Number of scan lines
        !           852: ;       EDX = bytes per scan line
        !           853: ;       GRAF_DATA_ROT = DR_SET
        !           854: ;       All Planes Enabled
        !           855: ; Returns:
        !           856: ;       Nothing
        !           857: ; Registers Destroyed:
        !           858: ;       ALL
        !           859: ; Registers Preserved:
        !           860: ;       None
        !           861: ; Alters:
        !           862: ;       GRAF_SET_RESET
        !           863: ;       GRAF_ENAB_SR
        !           864: ;       GRAF_BIT_MASK
        !           865: ; Calls:
        !           866: ;       None
        !           867: ;-----------------------------------------------------------------------;
        !           868: 
        !           869:         align   4
        !           870: mono_to_color_blt:
        !           871: 
        !           872:         push    ebp                     ; phase
        !           873:         push    edx                     ; bytes per scan line
        !           874:         push    ebx                     ; wrap for SI
        !           875:         mov     ebx,eax                 ; colors
        !           876: 
        !           877: ; First we put the foreground color into the latches.  We do this
        !           878: ; by putting this color into SET_RESET, writing it, then reading it.
        !           879: ; The memory location we will use is the first byte where we will blt.
        !           880: 
        !           881:         mov     dx,EGA_BASE + GRAF_ADDR
        !           882:         mov     al,GRAF_SET_RESET
        !           883:         out     dx,ax
        !           884:         mov     ax,0F00h + GRAF_ENAB_SR
        !           885:         out     dx,ax
        !           886: 
        !           887: ; Set bit mask = FF.
        !           888:         mov     ax,0FF00h + GRAF_BIT_MASK
        !           889:         out     dx,ax
        !           890: 
        !           891: ; Fill the latches.
        !           892:         mov     [edi],al                ; color in SetReset is written, not AL
        !           893:         mov     al,[edi]                ; read to fill latches
        !           894: 
        !           895: ; Go to XOR mode.
        !           896:         mov     ax,GRAF_DATA_ROT + 256 * DR_XOR
        !           897:         out     dx,ax
        !           898: 
        !           899: ; Now setup SET_RESET.
        !           900: 
        !           901:         mov     eax,ebx                 ; restore colors
        !           902:         xor     ah,al                   ; gives 0 where colors match
        !           903:         mov     al,GRAF_SET_RESET
        !           904:         out     dx,ax
        !           905:         not     ah
        !           906:         mov     al,GRAF_ENAB_SR
        !           907:         out     dx,ax                   ; enable Set/Reset where colors match
        !           908: 
        !           909:         pop     ebp                     ; wrap for ESI
        !           910:         pop     edx                     ; bytes per scan
        !           911:         mov     ebx,ulNextScan_global
        !           912:         sub     ebx,edx                 ; BX = wrap
        !           913: 
        !           914:         mov     eax,ecx                 ; loop count
        !           915:         pop     ecx                     ; phase
        !           916:         or      cl,cl
        !           917:         js      phase_neg
        !           918:         jz      phase_zero
        !           919:         dec     esi
        !           920: ;*      dec     ebp
        !           921: pmono_to_color_loop:
        !           922:         push    eax
        !           923:         push    edx
        !           924: pnext_byte:
        !           925:         lodsw
        !           926:         dec     esi
        !           927:         xchg    al,ah
        !           928:         shr     ax,cl
        !           929: ;+      shl     ax,cl
        !           930:         stosb
        !           931:         dec     edx
        !           932:         jnz     pnext_byte
        !           933:         pop     edx
        !           934:         pop     eax
        !           935:         add     edi,ebx
        !           936:         add     esi,ebp
        !           937:         dec     eax
        !           938:         jnz     pmono_to_color_loop
        !           939:         jmp     leave_in_set_mode
        !           940: 
        !           941: phase_zero:
        !           942: zmono_to_color_loop:
        !           943:         mov     ecx,edx
        !           944:         shr     ecx,1
        !           945:         rep     movsw
        !           946:         rcl     ecx,1
        !           947:         rep     movsb
        !           948:         add     edi,ebx
        !           949:         add     esi,ebp
        !           950:         dec     eax
        !           951:         jnz     zmono_to_color_loop
        !           952:         jmp     leave_in_set_mode
        !           953: 
        !           954: phase_neg:
        !           955:         neg     cl                      ; make CX = abs phase
        !           956: nmono_to_color_loop:
        !           957:         push    eax
        !           958:         push    edx
        !           959: nnext_byte:
        !           960:         lodsw
        !           961:         dec     esi
        !           962:         rol     ax,cl
        !           963: ;+      shr     ax,cl
        !           964:         stosb
        !           965:         dec     edx
        !           966:         jnz     nnext_byte
        !           967:         pop     edx
        !           968:         pop     eax
        !           969:         add     edi,ebx
        !           970:         add     esi,ebp
        !           971:         dec     eax
        !           972:         jnz     nmono_to_color_loop
        !           973: 
        !           974: leave_in_set_mode:
        !           975:         mov     dx,EGA_BASE + GRAF_ADDR
        !           976:         mov     ax,GRAF_DATA_ROT + 256 * DR_SET
        !           977:         out     dx,ax
        !           978:         PLAIN_RET
        !           979: 
        !           980: 
        !           981: ;----------------------------Private-Routine----------------------------;
        !           982: ; left_edge_mono_to_color_blt
        !           983: ; right_edge_mono_to_color_blt
        !           984: ;
        !           985: ; This problem here is the same as in mono_to_color_blt, except it
        !           986: ; is complicated by the need to preserve what is already in EGA memory
        !           987: ; for part of the byte which we are writing.
        !           988: ;
        !           989: ; We will set the BIT MASK to preserve these bytes.  We will then read
        !           990: ; the data from memory, and write it to the EGA using an XCHG so the
        !           991: ; latches are filled before the write -- so the appropriate EGA bits
        !           992: ; are preserved.
        !           993: ;
        !           994: ; The method for writing the data involves two passes.  The first pass
        !           995: ; writes the data to some of the planes, the second pass writes NOT the
        !           996: ; data to the other planes.  Depending on the two colors involved we
        !           997: ; may be able to skip one of the two passes.
        !           998: ;
        !           999: ; Define BkColor = the color corresponding to "1" bits in the data.
        !          1000: ; Define TextColor = the color corresponding to "0" bits in the data.
        !          1001: ;
        !          1002: ; We will use the Set/Reset register to take care of the planes where
        !          1003: ; the colors match.  These planes will be ignored in the rest of this
        !          1004: ; comment block.
        !          1005: ;
        !          1006: ; The first pass writes "1"s where the data is "1".  Therefore, the
        !          1007: ; condition for doing the first pass is that the BkColor has a "1"
        !          1008: ; somewhere (ignoring those planes taken care of by Set/Reset).
        !          1009: ; The second pass does whatever planes remain.  We can skip this pass
        !          1010: ; if no planes remain.  To maximize to likelihood of this we make sure
        !          1011: ; that all "Set/Reset" planes are enabled on the first pass (if the
        !          1012: ; first pass occurs).
        !          1013: ;
        !          1014: ; Entry:
        !          1015: ;       AH  = bitmask
        !          1016: ;       AL  = phase (-7 to +7)
        !          1017: ;       BH  = foreground color
        !          1018: ;       BL  = background color
        !          1019: ;       EDX = src bitmap width in bytes
        !          1020: ;       ESI = Mono Bitmap first byte
        !          1021: ;       EDI = First EGA Byte
        !          1022: ;       ECX = Number of scan lines
        !          1023: ;       DATA_ROT = DR_SET
        !          1024: ; Returns:
        !          1025: ;       Nothing
        !          1026: ; Registers Destroyed:
        !          1027: ;       ALL but EBP
        !          1028: ; Registers Preserved:
        !          1029: ;       EBP
        !          1030: ; Alters:
        !          1031: ;       GRAF_SET_RESET
        !          1032: ;       GRAF_BIT_MASK
        !          1033: ;       GRAF_ENAB_SR
        !          1034: ; Calls:
        !          1035: ;       None
        !          1036: ;-----------------------------------------------------------------------;
        !          1037: 
        !          1038: ; Does left edge, which never requires more than 1 byte, and can fault with
        !          1039: ; the 2-byte approach used by the right edge.
        !          1040: 
        !          1041:         align   4
        !          1042: left_edge_mono_to_color_blt:
        !          1043: 
        !          1044:         push    ebp
        !          1045:         push    eax              ; AL = phase
        !          1046:         mov     ebp,edx
        !          1047: 
        !          1048: ; Set bit mask.
        !          1049: 
        !          1050:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1051:         mov     al,GRAF_BIT_MASK
        !          1052:         out     dx,ax
        !          1053: 
        !          1054: ; Put foreground color in Set/Reset and enable planes where colors
        !          1055: ; match.
        !          1056: 
        !          1057:         mov     ah,bh
        !          1058:         mov     al,GRAF_SET_RESET
        !          1059:         out     dx,ax
        !          1060:         xor     ah,bl
        !          1061:         not     ah                      ; gives 1 where colors match
        !          1062:         mov     al,GRAF_ENAB_SR
        !          1063:         out     dx,ax
        !          1064:         mov     dx,EGA_BASE + SEQ_DATA  ; The rest of the OUTs are here.
        !          1065:         mov     al,ah
        !          1066:         not     ah                      ; Gives 1 where colors mismatch.
        !          1067: 
        !          1068: ; The following AND leaves 1 bits in AH for the planes which
        !          1069: ; CANNOT be done on the second pass.  So if this is zero we can
        !          1070: ; skip the first pass.
        !          1071: 
        !          1072:         and     ah,bl                   ; BL = BkColor = color where data is 1
        !          1073:         or      ah,bl                   ; planes to enable
        !          1074:         mov     ebx,ecx                 ; we're done with the colors in BX
        !          1075:         pop     ecx                     ; phase
        !          1076:         jz      short left_skip_first_pass
        !          1077:         or      al,ah                   ; Include "Set/Reset" planes.
        !          1078:         out     dx,al                   ; Enable planes for first pass.
        !          1079: 
        !          1080:         push    ecx
        !          1081:         push    esi
        !          1082:         push    edi
        !          1083:         push    eax
        !          1084:         push    ebx
        !          1085:         or      cl,cl
        !          1086:         js      short left_phase_is_negative1
        !          1087: left_pfirst_pass:
        !          1088:         mov     ah,[esi]
        !          1089:         shr     ah,cl
        !          1090:         xchg    ah,[edi]
        !          1091:         add     esi,ebp
        !          1092:         add     edi,ulNextScan_global
        !          1093:         dec     ebx
        !          1094:         jnz     left_pfirst_pass
        !          1095:         jmp     short left_end_pass_one
        !          1096: 
        !          1097: left_phase_is_negative1:
        !          1098:         neg     cl                      ; make CL = abs phase
        !          1099: left_nfirst_pass:
        !          1100:         mov     ax,[esi]
        !          1101:         rol     ax,cl
        !          1102:         xchg    al,[edi]
        !          1103:         add     esi,ebp
        !          1104:         add     edi,ulNextScan_global
        !          1105:         dec     ebx
        !          1106:         jnz     left_nfirst_pass
        !          1107: left_end_pass_one:
        !          1108:         pop     ebx
        !          1109:         pop     eax
        !          1110:         pop     edi
        !          1111:         pop     esi
        !          1112:         pop     ecx
        !          1113: 
        !          1114: left_skip_first_pass:
        !          1115: 
        !          1116: ; Enable the other planes.
        !          1117: 
        !          1118:         not     ah
        !          1119:         and     ah,MM_ALL
        !          1120:         jz      short left_no_planes_left
        !          1121:         mov     al,ah
        !          1122:         out     dx,al
        !          1123:         or      cl,cl
        !          1124:         js      short left_phase_is_negative2
        !          1125: left_psecond_pass:
        !          1126:         mov     ah,[esi]
        !          1127:         not     ah
        !          1128:         shr     ah,cl
        !          1129:         xchg    ah,[edi]
        !          1130:         add     esi,ebp
        !          1131:         add     edi,ulNextScan_global
        !          1132:         dec     ebx
        !          1133:         jnz     left_psecond_pass
        !          1134:         jmp     short left_no_planes_left
        !          1135: 
        !          1136: left_phase_is_negative2:
        !          1137:         neg     cl                      ; make CL = abs phase
        !          1138: left_nsecond_pass:
        !          1139:         mov     ax,[esi]
        !          1140:         not     ax
        !          1141:         rol     ax,cl
        !          1142:         xchg    al,[edi]
        !          1143:         add     esi,ebp
        !          1144:         add     edi,ulNextScan_global
        !          1145:         dec     ebx
        !          1146:         jnz     left_nsecond_pass
        !          1147: 
        !          1148: left_no_planes_left:
        !          1149:         mov     al,MM_ALL
        !          1150:         out     dx,al
        !          1151:         pop     ebp
        !          1152:         PLAIN_RET
        !          1153: 
        !          1154: ; Does right edge, which may require 2 bytes. 2 bytes are always available,
        !          1155: ; because if there was only 1 byte across, the left edge would handle it,
        !          1156: ; so we don't have to worry about faulting.
        !          1157: 
        !          1158:         align   4
        !          1159: right_edge_mono_to_color_blt:
        !          1160: 
        !          1161:         push    ebp
        !          1162:         push    eax              ; AL = phase
        !          1163:         mov     ebp,edx
        !          1164: 
        !          1165: ; Set bit mask.
        !          1166: 
        !          1167:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1168:         mov     al,GRAF_BIT_MASK
        !          1169:         out     dx,ax
        !          1170: 
        !          1171: ; Put foreground color in Set/Reset and enable planes where colors
        !          1172: ; match.
        !          1173: 
        !          1174:         mov     ah,bh
        !          1175:         mov     al,GRAF_SET_RESET
        !          1176:         out     dx,ax
        !          1177:         xor     ah,bl
        !          1178:         not     ah                      ; gives 1 where colors match
        !          1179:         mov     al,GRAF_ENAB_SR
        !          1180:         out     dx,ax
        !          1181:         mov     dx,EGA_BASE + SEQ_DATA  ; The rest of the OUTs are here.
        !          1182:         mov     al,ah
        !          1183:         not     ah                      ; Gives 1 where colors mismatch.
        !          1184: 
        !          1185: ; The following AND leaves 1 bits in AH for the planes which
        !          1186: ; CANNOT be done on the second pass.  So if this is zero we can
        !          1187: ; skip the first pass.
        !          1188: 
        !          1189:         and     ah,bl                   ; BL = BkColor = color where data is 1
        !          1190:         or      ah,bl                   ; planes to enable
        !          1191:         mov     ebx,ecx                 ; we're done with the colors in BX
        !          1192:         pop     ecx                     ; phase
        !          1193:         jz      short right_skip_first_pass
        !          1194:         or      al,ah                   ; Include "Set/Reset" planes.
        !          1195:         out     dx,al                   ; Enable planes for first pass.
        !          1196: 
        !          1197:         push    ecx
        !          1198:         push    esi
        !          1199:         push    edi
        !          1200:         push    eax
        !          1201:         push    ebx
        !          1202:         or      cl,cl
        !          1203:         js      short right_phase_is_negative1
        !          1204:         dec     esi
        !          1205: right_pfirst_pass:
        !          1206:         mov     ax,[esi]
        !          1207:         ror     ax,cl
        !          1208:         xchg    ah,[edi]
        !          1209:         add     esi,ebp
        !          1210:         add     edi,ulNextScan_global
        !          1211:         dec     ebx
        !          1212:         jnz     right_pfirst_pass
        !          1213:         jmp     short right_end_pass_one
        !          1214: 
        !          1215: right_phase_is_negative1:
        !          1216:         neg     cl                      ; make CL = abs phase
        !          1217: right_nfirst_pass:
        !          1218:         mov     ax,[esi]
        !          1219:         rol     ax,cl
        !          1220:         xchg    al,[edi]
        !          1221:         add     esi,ebp
        !          1222:         add     edi,ulNextScan_global
        !          1223:         dec     ebx
        !          1224:         jnz     right_nfirst_pass
        !          1225: right_end_pass_one:
        !          1226:         pop     ebx
        !          1227:         pop     eax
        !          1228:         pop     edi
        !          1229:         pop     esi
        !          1230:         pop     ecx
        !          1231: 
        !          1232: right_skip_first_pass:
        !          1233: 
        !          1234: ; Enable the other planes.
        !          1235: 
        !          1236:         not     ah
        !          1237:         and     ah,MM_ALL
        !          1238:         jz      short right_no_planes_left
        !          1239:         mov     al,ah
        !          1240:         out     dx,al
        !          1241:         or      cl,cl
        !          1242:         js      short right_phase_is_negative2
        !          1243:         dec     esi
        !          1244: right_psecond_pass:
        !          1245:         mov     ax,[esi]
        !          1246:         not     ax
        !          1247:         ror     ax,cl
        !          1248:         xchg    ah,[edi]
        !          1249:         add     esi,ebp
        !          1250:         add     edi,ulNextScan_global
        !          1251:         dec     ebx
        !          1252:         jnz     right_psecond_pass
        !          1253:         jmp     short right_no_planes_left
        !          1254: 
        !          1255: right_phase_is_negative2:
        !          1256:         neg     cl                      ; make CL = abs phase
        !          1257: right_nsecond_pass:
        !          1258:         mov     ax,[esi]
        !          1259:         not     ax
        !          1260:         rol     ax,cl
        !          1261:         xchg    al,[edi]
        !          1262:         add     esi,ebp
        !          1263:         add     edi,ulNextScan_global
        !          1264:         dec     ebx
        !          1265:         jnz     right_nsecond_pass
        !          1266: 
        !          1267: right_no_planes_left:
        !          1268:         mov     al,MM_ALL
        !          1269:         out     dx,al
        !          1270:         pop     ebp
        !          1271:         PLAIN_RET
        !          1272: 
        !          1273: 
        !          1274: ;----------------------------Private-Routine----------------------------;
        !          1275: ; pat_blt
        !          1276: ;                       XOR mode with data = FF for Pn?
        !          1277: ;
        !          1278: ; This BLTs an arbitrary 8x8 bit pattern (3 or 4 planes deep) to EGA.
        !          1279: ;
        !          1280: ; The method is simple.  Load the latches with the pattern for a
        !          1281: ; particular scan line, then REP STOS this with the BIT MASK = 0
        !          1282: ; so that only the latches get written.  Before putting the pattern
        !          1283: ; for the next scan line into the latches we will do all other scan
        !          1284: ; lines with the same pattern.
        !          1285: ;
        !          1286: ; Entry:
        !          1287: ;       ESI = pattern bytes
        !          1288: ;       EDI = First EGA Byte
        !          1289: ;       ECX = Number of scan lines (yExt)
        !          1290: ;       EBX = offset into pattern
        !          1291: ;       EDX = bytes per scan line (scan_len)
        !          1292: ;       GRAF_DATA_ROT = DR_SET
        !          1293: ;       BIT_MASK = FF
        !          1294: ; Returns:
        !          1295: ;       Nothing
        !          1296: ; Registers Destroyed:
        !          1297: ;       ALL but EBP
        !          1298: ; Registers Preserved:
        !          1299: ;       EBP
        !          1300: ; Alters:
        !          1301: ;       GRAF_BIT_MASK   (leaves it 00)
        !          1302: ; Calls:
        !          1303: ;       None
        !          1304: ;-----------------------------------------------------------------------;
        !          1305: 
        !          1306:         .errnz  SIZE_PATTERN - 8        ; actually any power of 2 is okay.
        !          1307: 
        !          1308:         align   4
        !          1309: pat_blt:
        !          1310: 
        !          1311:         push    ebp
        !          1312:         push    edx                     ; scan_len
        !          1313:         push    ecx                     ; yExt
        !          1314:         mov     ah,11h                  ; left nibble gives carry to end loop
        !          1315: 
        !          1316: ; Set EBP = min(yExt, scans/pattern).
        !          1317: 
        !          1318:         sub     ecx,SIZE_PATTERN        ; SIZE_PATTERN = 8 = yExt of pattern
        !          1319:         sbb     ebp,ebp
        !          1320:         and     ebp,ecx
        !          1321:         add     ebp,SIZE_PATTERN
        !          1322: 
        !          1323:         mov     dx,EGA_BASE + SEQ_DATA
        !          1324: set_next_plane:
        !          1325:         push    ebx
        !          1326:         push    edi
        !          1327: 
        !          1328: ; Enable next plane.
        !          1329: 
        !          1330:         mov     al,MM_ALL
        !          1331:         and     al,ah
        !          1332:         out     dx,al
        !          1333:         mov     ecx,ebp
        !          1334: 
        !          1335: hit_next_byte:
        !          1336:         mov     al,[esi][ebx]           ; Next pattern byte
        !          1337:         inc     ebx
        !          1338:         and     ebx,SIZE_PATTERN - 1
        !          1339:         mov     [edi],al
        !          1340:         add     edi,ulNextScan_global
        !          1341:         loop    hit_next_byte
        !          1342:         add     esi,SIZE_PATTERN
        !          1343:         pop     edi
        !          1344:         pop     ebx
        !          1345:         shl     ah,1
        !          1346:         jnc     set_next_plane
        !          1347: 
        !          1348: ; Set bit mask = 00.
        !          1349: 
        !          1350:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1351:         mov     ax,0000h + GRAF_BIT_MASK
        !          1352:         out     dx,ax
        !          1353: 
        !          1354: ; Enable all planes.
        !          1355: 
        !          1356:         mov     al,MM_ALL
        !          1357:         mov     dx,EGA_BASE + SEQ_DATA
        !          1358:         out     dx,al
        !          1359: 
        !          1360:         mov     ecx,ebp                 ; MIN(yExt,SIZE_PATTERN)
        !          1361:         pop     ebp                     ; yExt
        !          1362:         pop     eax                     ; scan_len
        !          1363:         mov     esi,ulNextScan_global   ; ESI = scan_width
        !          1364: 
        !          1365:         .errnz  (SIZE_PATTERN - 8)
        !          1366:         ;------------------------------------------------;
        !          1367:         ;       mov     ebx,(SIZE_PATTERN - 1) * scan_width
        !          1368:         ;------------------------------------------------;
        !          1369:         lea     ebx,[esi*2+esi]         ; scan_width * 3
        !          1370:         lea     ebx,[ebx+esi*4]         ; scan_width * 7
        !          1371: 
        !          1372:         sub     esi,eax                 ; ESI = scan_width
        !          1373:         add     ebx,esi                 ; EBX = (scan_width * 7) + next_scan
        !          1374: 
        !          1375: pat_blt_next_scan:
        !          1376:         push    ecx
        !          1377:         mov     esi,edi                 ; save ESI
        !          1378:         mov     edx,ebp                 ; save yExt
        !          1379:         mov     cl,[edi]                ; load latches
        !          1380: 
        !          1381: pat_blt_loop:
        !          1382:         mov     ecx,eax                 ; EAX = scan_len
        !          1383:         rep     stosb
        !          1384:         add     edi,ebx                 ; EBX = (scan_width * 7) + next_scan
        !          1385:         sub     ebp,SIZE_PATTERN
        !          1386:         jg      pat_blt_loop
        !          1387: 
        !          1388:         mov     ebp,edx
        !          1389:         dec     ebp
        !          1390:         mov     edi,esi
        !          1391:         add     edi,ulNextScan_global
        !          1392:         pop     ecx
        !          1393:         loop    pat_blt_next_scan
        !          1394: 
        !          1395:         pop     ebp
        !          1396:         PLAIN_RET
        !          1397: 
        !          1398: 
        !          1399: ;----------------------------Private-Routine----------------------------;
        !          1400: ; edge_pat_blt
        !          1401: ;
        !          1402: ; Entry:
        !          1403: ;       AH  = bitmask
        !          1404: ;       ESI = pattern bytes
        !          1405: ;       EDI = First EGA Byte
        !          1406: ;       ECX = Number of scan lines (yExt)
        !          1407: ;       EBX = offset into pattern
        !          1408: ;       DATA_ROT = DR_SET
        !          1409: ; Returns:
        !          1410: ;       Nothing
        !          1411: ; Registers Destroyed:
        !          1412: ;       EAX,ECX,EDX,ESI,flags
        !          1413: ; Registers Preserved:
        !          1414: ;       EBX,EDI,EBP
        !          1415: ; Alters:
        !          1416: ;       GRAF_BIT_MASK   (leaves it FF)
        !          1417: ; Calls:
        !          1418: ;       None
        !          1419: ;-----------------------------------------------------------------------;
        !          1420: 
        !          1421:         align   4
        !          1422: edge_pat_blt:
        !          1423: 
        !          1424:         push    ebp
        !          1425: 
        !          1426: ; Set bit mask.
        !          1427: 
        !          1428:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1429:         mov     al,GRAF_BIT_MASK
        !          1430:         out     dx,ax
        !          1431:         mov     ah,11h                  ; left nibble gives carry to end loop
        !          1432:         mov     dx,EGA_BASE + SEQ_DATA
        !          1433:         sub     si,SIZE_PATTERN
        !          1434:         mov     ebp,ecx
        !          1435: 
        !          1436: enable_next_plane:
        !          1437:         push    ebx
        !          1438:         push    edi
        !          1439:         mov     ecx,ebp                 ; yExt
        !          1440:         mov     al,MM_ALL
        !          1441:         and     al,ah
        !          1442:         out     dx,al
        !          1443:         add     esi,SIZE_PATTERN
        !          1444: 
        !          1445: over_scans:
        !          1446:         mov     al,[ebx][esi]           ; pattern fetch
        !          1447:         inc     ebx
        !          1448:         and     ebx,SIZE_PATTERN - 1    ; 7
        !          1449:         .errnz  SIZE_PATTERN - 8        ; any power of 2 works
        !          1450:         xchg    [edi],al
        !          1451:         add     edi,ulNextScan_global
        !          1452:         loop    over_scans
        !          1453: 
        !          1454:         pop     edi
        !          1455:         pop     ebx
        !          1456:         shl     ah,1
        !          1457:         jnc     enable_next_plane
        !          1458: 
        !          1459: ; Restore bitmask to default.
        !          1460: 
        !          1461:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1462:         mov     ax,0FF00h + GRAF_BIT_MASK
        !          1463:         out     dx,ax
        !          1464: 
        !          1465:         pop     ebp
        !          1466:         PLAIN_RET
        !          1467: 
        !          1468: 
        !          1469: ;----------------------------Private-Routine----------------------------;
        !          1470: ; invert
        !          1471: ;
        !          1472: ; Inverts pixels in a rectangle on the display, by simply writing the
        !          1473: ; memory to itself, letting the EGA hardware perform the XORing.
        !          1474: ;
        !          1475: ; Entry:
        !          1476: ;       EDI = First EGA Byte
        !          1477: ;       ECX = Number of scan lines (yExt)
        !          1478: ;       EBX = scan line length in bytes
        !          1479: ;       DATA_ROT = DR_XOR
        !          1480: ;       GRAF_SET_RESET = color to xor DEST with
        !          1481: ;       GRAF_SR_ENAB = MM_ALL
        !          1482: ; Returns:
        !          1483: ;       Nothing
        !          1484: ; Registers Destroyed:
        !          1485: ;       EAX,ECX,EDX,ESI,EDI,flags
        !          1486: ; Registers Preserved:
        !          1487: ;       EBX,EBP
        !          1488: ; Alters:
        !          1489: ;       GRAF_BIT_MASK   (leaves it FF)
        !          1490: ; Calls:
        !          1491: ;       None
        !          1492: ;-----------------------------------------------------------------------;
        !          1493: 
        !          1494:         align   4
        !          1495: invert:
        !          1496: 
        !          1497: ; Set bit mask.
        !          1498: 
        !          1499:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1500:         mov     ax,0FF00h + GRAF_BIT_MASK
        !          1501:         out     dx,ax
        !          1502:         mov     edx,ulNextScan_global
        !          1503:         sub     edx,ebx
        !          1504:         mov     eax,ecx                 ; save height
        !          1505: 
        !          1506: invert_next_scan:
        !          1507:         mov     esi,edi
        !          1508:         mov     ecx,ebx                 ; scan len in bytes
        !          1509:         rep     movsb
        !          1510:         add     edi,edx
        !          1511:         dec     eax
        !          1512:         jnz     invert_next_scan
        !          1513:         PLAIN_RET
        !          1514: 
        !          1515: 
        !          1516: ;----------------------------Private-Routine----------------------------;
        !          1517: ; edge_invert
        !          1518: ;
        !          1519: ; Inverts one byte on each scan line vertically according to the mask
        !          1520: ; in AH.
        !          1521: ;
        !          1522: ; Entry:
        !          1523: ;       AH  = bitmask
        !          1524: ;       EDI = First EGA Byte
        !          1525: ;       ECX = Number of scan lines (yExt)
        !          1526: ;       DATA_ROT = DR_XOR
        !          1527: ;       GRAF_SET_RESET = color to xor DEST with
        !          1528: ;       GRAF_ENAB_SR = MM_ALL
        !          1529: ; Returns:
        !          1530: ;       Nothing
        !          1531: ; Registers Destroyed:
        !          1532: ;       AL,ECX,EDX,EDI,flags
        !          1533: ; Registers Preserved:
        !          1534: ;       AH,EBX,ESI,EBP
        !          1535: ; Alters:
        !          1536: ;       GRAF_BIT_MASK
        !          1537: ; Calls:
        !          1538: ;       None
        !          1539: ;-----------------------------------------------------------------------;
        !          1540: 
        !          1541:         align   4
        !          1542: edge_invert:
        !          1543: 
        !          1544: ; Set bit mask.
        !          1545: 
        !          1546:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1547:         mov     al,GRAF_BIT_MASK
        !          1548:         out     dx,ax
        !          1549: 
        !          1550: edge_invert_next_scan:
        !          1551:         xchg    [edi],al
        !          1552:         add     edi,ulNextScan_global
        !          1553:         loop    edge_invert_next_scan
        !          1554:         PLAIN_RET
        !          1555: 
        !          1556: 
        !          1557: ;----------------------------Private-Routine----------------------------;
        !          1558: ; edge_grey_dpx
        !          1559: ;
        !          1560: ; Inverts one or two bytes on each scan line vertically according
        !          1561: ; to the grey pattern given, under the passed clipping mask.
        !          1562: ;
        !          1563: ; Entry:
        !          1564: ;       EBX    =  brush index (0-7)
        !          1565: ;       ECX    =  number of scan lines (cyExt)
        !          1566: ;       DL     =  lhs clipping mask
        !          1567: ;       DH     =  rhs clipping mask
        !          1568: ;       ESI   --> base address of brush
        !          1569: ;       EDI   --> rhs EGA
        !          1570: ;       EBP   --> lhs EGA
        !          1571: ; Returns:
        !          1572: ;       Nothing
        !          1573: ; Registers Destroyed:
        !          1574: ;       All
        !          1575: ; Registers Preserved:
        !          1576: ;       None
        !          1577: ; Alters:
        !          1578: ;       None
        !          1579: ; Calls:
        !          1580: ;       None
        !          1581: ;-----------------------------------------------------------------------;
        !          1582: 
        !          1583:         align   4
        !          1584: edge_grey_dpx:
        !          1585: 
        !          1586:         sub     ebp,edi                 ;Compute delta to lhs
        !          1587:         and     ebx,00000111b           ;Make sure brush is valid
        !          1588:         .errnz  SIZE_PATTERN - 8
        !          1589:         or      dh,dh                   ;Dispatch based on one or two edges
        !          1590:         jz      edge_grey_dpx_one_loop
        !          1591: 
        !          1592: edge_grey_dpx_both_loop:
        !          1593:         mov     al,[esi][ebx]           ;Get next byte of brush
        !          1594:         mov     ah,al
        !          1595:         and     al,dl                   ;Mask with lhs clipping mask
        !          1596:         xchg    al,[edi]                ;Invert necessary bits
        !          1597:         inc     ebx                     ;--> next brush byte
        !          1598:         and     bl,00000111b            ;Handle any wrap
        !          1599:         .errnz  SIZE_PATTERN - 8
        !          1600:         and     ah,dh                   ;Mask with rhs clipping mask
        !          1601:         xchg    ah,[edi][ebp]           ;Invert necessary bits
        !          1602:         add     edi,ulNextScan_global   ;--> next destination byte
        !          1603:         loop    edge_grey_dpx_both_loop
        !          1604:         PLAIN_RET
        !          1605: 
        !          1606: edge_grey_dpx_one_loop:
        !          1607:         mov     al,[esi][ebx]           ;Get next byte of brush
        !          1608:         and     al,dl                   ;Mask with lhs clipping mask
        !          1609:         xchg    al,[edi]                ;Invert necessary bits
        !          1610:         inc     ebx                     ;--> next brush byte
        !          1611:         and     bl,00000111b            ;Handle any wrap
        !          1612:         .errnz  SIZE_PATTERN - 8
        !          1613:         add     edi,ulNextScan_global   ;--> next destination byte
        !          1614:         loop    edge_grey_dpx_one_loop
        !          1615:         PLAIN_RET
        !          1616: 
        !          1617: 
        !          1618: ;----------------------------Private-Routine----------------------------;
        !          1619: ; middle_grey_dpx
        !          1620: ;
        !          1621: ; Inverts a rectangle on the display using the passed grey pattern.
        !          1622: ;
        !          1623: ; Entry:
        !          1624: ;       EBX     =  brush index (0-7)
        !          1625: ;       ECX     =  # byte to invert on the scan
        !          1626: ;       EDX     =  EGA_BASE + GRAF_ADDR
        !          1627: ;       ESI    --> base address of brush
        !          1628: ;       EDI    --> starting byte
        !          1629: ;       EBP     =  number of scan lines (cyExt)
        !          1630: ;       DATA_ROT       = DR_XOR
        !          1631: ;       GRAF_SET_RESET = All 1
        !          1632: ;       GRAF_ENAB_SR   = MM_ALL
        !          1633: ; Returns:
        !          1634: ;       Nothing
        !          1635: ; Registers Destroyed:
        !          1636: ;       EAX,ECX,EDX,ESI,EDI,flags
        !          1637: ; Registers Preserved:
        !          1638: ;       EBX,EBP
        !          1639: ; Alters:
        !          1640: ;       GRAF_BIT_MASK   (leaves it FF)
        !          1641: ; Calls:
        !          1642: ;       None
        !          1643: ;-----------------------------------------------------------------------;
        !          1644: 
        !          1645:         align   4
        !          1646: middle_grey_dpx:
        !          1647: 
        !          1648: ;       mov     dx,EGA_BASE + GRAF_ADDR ; Leave the Graphics controller
        !          1649:         mov     al,GRAF_BIT_MASK        ;   address register pointing to
        !          1650:         out     dx,al                   ;   the bitmask register
        !          1651:         inc     edx                     ; --> Graphics controller data register
        !          1652:         .errnz  GRAF_DATA - GRAF_ADDR - 1
        !          1653: 
        !          1654:         mov     ah,bl                   ; Keep brush index here
        !          1655:         mov     ebx,ecx                 ; Save a copy of inner loop count here
        !          1656: 
        !          1657: middle_grey_dpx_loop:
        !          1658:         xchg    eax,ebx
        !          1659:         xchg    bl,bh
        !          1660:         and     ebx,00000111b
        !          1661:         errnz   SIZE_PATTERN-8
        !          1662:         mov     bh,[esi][ebx]           ; Get next byte of brush
        !          1663:         inc     bl                      ; --> byte of the brush
        !          1664:         xchg    bh,bl
        !          1665:         xchg    eax,ebx
        !          1666:         out     dx,al
        !          1667:         mov     ecx,ebx
        !          1668:         push    esi
        !          1669:         mov     esi,edi
        !          1670:         rep     movsb
        !          1671:         pop     esi
        !          1672:         sub     edi,ebx
        !          1673:         add     edi,ulNextScan_global   ;next scan on screen
        !          1674:         dec     ebp
        !          1675:         jnz     middle_grey_dpx_loop
        !          1676:         PLAIN_RET
        !          1677: 
        !          1678: 
        !          1679: ;----------------------------Private-Routine----------------------------;
        !          1680: ; do_grey_dpx
        !          1681: ;
        !          1682: ; This is EGA special cased code for the dpx raster op in the case where
        !          1683: ; the pattern (p) is grey (the same on all planes).  We also come here
        !          1684: ; for the special graying pattern rop.  This is not a normal P,S, and D rop,
        !          1685: ; but a hack for pmwin.  It allows graying of things on the screen, meaning
        !          1686: ; the background color is stuffed everywhere the pattern has a "1" bit.
        !          1687: ;
        !          1688: ; Entry:
        !          1689: ;       EBP --> BitBLT local variable frame
        !          1690: ; Returns:
        !          1691: ;       Nothing
        !          1692: ; Registers Destroyed:
        !          1693: ;       ALL but EBP
        !          1694: ; Registers Preserved:
        !          1695: ;       EBP
        !          1696: ; Calls:
        !          1697: ;       calc_parms
        !          1698: ;       edge_grey_dpx
        !          1699: ;       middle_grey_dpx
        !          1700: ;-----------------------------------------------------------------------;
        !          1701: 
        !          1702:         align   4
        !          1703: do_grey_dpx:
        !          1704: 
        !          1705:         call    calc_parms
        !          1706:         mov     dx,EGA_BASE + GRAF_ADDR
        !          1707:         mov     ax,DR_XOR shl 8 + GRAF_DATA_ROT ; XOR mode for grey dpx
        !          1708:         out     dx,ax
        !          1709:         mov     dl,byte ptr fr.start_mask[0]
        !          1710:         mov     dh,byte ptr fr.last_mask[0]
        !          1711:         or      dx,dx
        !          1712:         jz      do_grey_dpx_middle      ;Only middle bytes exist
        !          1713: 
        !          1714:         mov     eax,edi                 ;Assume we have a left edge
        !          1715:         inc     eax                     ;+1 to get to start of middle bytes
        !          1716:         or      dl,dl                   ;Is there really a left edge?
        !          1717:         jnz     do_grey_dpx_have_lhs    ;  Yes, AX = correct middle byte start
        !          1718:         dec     eax                     ;  No, restore middle byte start
        !          1719:         xchg    dl,dh                   ;  Pretend only a lhs edge
        !          1720:         add     edi,fr.inner_loop_count ;    but make it be the rhs
        !          1721: 
        !          1722: do_grey_dpx_have_lhs:
        !          1723:         push    eax                     ;Save middle bytes start
        !          1724:         push    ebx
        !          1725:         push    ecx
        !          1726:         push    esi
        !          1727:         push    ebp
        !          1728:         add     eax,fr.inner_loop_count ;--> possible rhs
        !          1729:         xchg    eax,ebp
        !          1730:         call    edge_grey_dpx
        !          1731: did_gray_pat_edge:
        !          1732:         pop     ebp
        !          1733:         pop     esi
        !          1734:         pop     ecx
        !          1735:         pop     ebx
        !          1736:         pop     edi                     ;Restore middle bytes start
        !          1737: 
        !          1738: do_grey_dpx_middle:
        !          1739:         mov     eax,fr.inner_loop_count
        !          1740:         or      eax,eax
        !          1741:         jz      do_grey_dpx_exit
        !          1742:         push    ebp
        !          1743:         mov     ebp,ecx
        !          1744:         xchg    eax,ecx
        !          1745:         mov     dx,EGA_BASE + GRAF_ADDR         ;
        !          1746:         mov     ax,MM_ALL shl 8 + GRAF_ENAB_SR  ; Set Set/Reset to all "1" bits
        !          1747:         out     dx,ax                           ; and Enable all planes (for
        !          1748:         .errnz  MM_ALL - 0Fh                    ; grey_dpx)
        !          1749:         mov     al,GRAF_SET_RESET               ;
        !          1750:         out     dx,ax                           ;
        !          1751: 
        !          1752: gray_pat:
        !          1753:         call    middle_grey_dpx
        !          1754:         pop     ebp
        !          1755: 
        !          1756: do_grey_dpx_exit:
        !          1757:         PLAIN_RET
        !          1758: 
        !          1759: 
        !          1760: endProc check_device_special_cases
        !          1761: 
        !          1762: _TEXT$01   ends
        !          1763: 
        !          1764:         end
        !          1765: 

unix.superglobalmegacorp.com

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