Annotation of ntddk/src/video/displays/vga256/i386/monopat.asm, revision 1.1.1.1

1.1       root        1: ;---------------------------Module-Header------------------------------;
                      2: ; Module Name: monopat.asm
                      3: ;
                      4: ; Copyright (c) 1992-1993 Microsoft Corporation.  All rights reserved.
                      5: ;-----------------------------------------------------------------------;
                      6: 
                      7: ;-----------------------------------------------------------------------;
                      8: ; VOID vMonoPat(ppdev, culRcl, prcl, ulMix, prb, pptlBrush)
                      9: ;
                     10: ; Input:
                     11: ;
                     12: ;  ppdev     - surface on which to draw
                     13: ;  culRcl    - number of rectangles
                     14: ;  prcl      - pointer to rectangles
                     15: ;  ulMix     - mix mode (i.e., ROP)
                     16: ;  prb       - pointer to realized brush
                     17: ;  pptlBrush - brush alignment
                     18: ;
                     19: ; Draws two color patterns using the VGA hardware.  If the ROP is a
                     20: ; PATCOPY ROP, we can light 8 pixels on every word write to VGA memory.
                     21: ;
                     22: ; We special case black & white patterns because we can do slightly less
                     23: ; initialization, and we can handle arbitrary ROPs (although if the ROP
                     24: ; has to read video memory, we can only do 4 pixels on every read/write
                     25: ; operation).
                     26: ;
                     27: ;-----------------------------------------------------------------------;
                     28: ;
                     29: ; NOTE: Assumes all rectangles have positive heights and widths.  Will
                     30: ; not work properly if this is not the case.
                     31: ;
                     32: ;-----------------------------------------------------------------------;
                     33: 
                     34: ;-----------------------------------------------------------------------;
                     35: ; Set LOOP_UNROLL_SHIFT to the log2 of the number of times you want loops in
                     36: ; this module unrolled. For example, LOOP_UNROLL_SHIFT of 3 yields 2**3 = 8
                     37: ; times unrolling. This is the only thing you need to change to control
                     38: ; unrolling.
                     39: 
                     40: LOOP_UNROLL_SHIFT equ 2
                     41: 
                     42: ;-----------------------------------------------------------------------;
                     43: 
                     44:         .386
                     45: 
                     46:         .model  small,c
                     47: 
                     48:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
                     49:         assume fs:nothing,gs:nothing
                     50: 
                     51:         .xlist
                     52:         include stdcall.inc             ;calling convention cmacros
                     53:         include i386\strucs.inc
                     54:         include i386\driver.inc
                     55:         include i386\unroll.inc
                     56:         include i386\egavga.inc
                     57:         include i386\ropdefs.inc
                     58: 
                     59:         .list
                     60: 
                     61: ;-----------------------------------------------------------------------;
                     62: 
                     63:         .data
                     64: 
                     65: ; vTrgBlt is used for 2-pass ROPs:
                     66: 
                     67:         EXTRNP          vTrgBlt,24
                     68: 
                     69: ; Tables shared with vgablts.asm:
                     70: 
                     71: extrn   jALUFuncTable:  byte
                     72: extrn   jInvertDest:    byte
                     73: 
                     74: ;-----------------------------------------------------------------------;
                     75: ; Bits for drawing routine look-ups.
                     76: 
                     77: BLOCK_LEFT_EDGE                 equ 010000b
                     78: BLOCK_RIGHT_EDGE                equ 001000b
                     79: BLOCK_MIDDLE_STARTS_UNALIGNED   equ 000100b
                     80: BLOCK_NO_MIDDLE                 equ 000010b
                     81: BLOCK_MIDDLE_ENDS_UNALIGNED     equ 000001b
                     82: 
                     83: ;-----------------------------------------------------------------------;
                     84: ; Table of drawing routines, with the look-up index a 5 bit field as
                     85: ; follows:
                     86: ;
                     87: ; Bit 4 = 1 if a left edge must be drawn
                     88: ; Bit 3 = 1 if a right edge must be drawn
                     89: ; Bit 2 = 1 if middle block starts unaligned word-wise
                     90: ; Bit 1 = 1 if no middle block
                     91: ; Bit 0 = 1 if middle block is an odd number of bytes in length
                     92: 
                     93:         align   4
                     94: gapfnSetTable label dword
                     95:         dd      dual_wide_00_w          ;00000
                     96:         dd      dual_wide_01_w          ;00001
                     97:         dd      0                       ;00010
                     98:         dd      0                       ;00011
                     99:         dd      dual_wide_11_w          ;00100
                    100:         dd      dual_wide_10_w          ;00101
                    101:         dd      0                       ;00110
                    102:         dd      0                       ;00111
                    103:         dd      Block_01000_w           ;01000
                    104:         dd      Block_01001_w           ;01001
                    105:         dd      dual_right_0_w          ;01010
                    106:         dd      dual_right_1_w          ;01011
                    107:         dd      Block_01100_w           ;01100
                    108:         dd      Block_01101_w           ;01101
                    109:         dd      dual_right_1_w          ;01110
                    110:         dd      dual_right_0_w          ;01111
                    111:         dd      Block_10000_w           ;10000
                    112:         dd      Block_10001_w           ;10001
                    113:         dd      dual_left_0_w           ;10010
                    114:         dd      dual_left_0_w           ;10011
                    115:         dd      Block_10100_w           ;10100
                    116:         dd      Block_10101_w           ;10101
                    117:         dd      dual_left_1_w           ;10110
                    118:         dd      dual_left_1_w           ;10111
                    119:         dd      Block_11000_w           ;11000
                    120:         dd      Block_11001_w           ;11001
                    121:         dd      Block_11010_w           ;11010
                    122:         dd      0                       ;11011 - can never happen
                    123:         dd      Block_11100_w           ;11100
                    124:         dd      Block_11101_w           ;11101
                    125:         dd      Block_11110_w           ;11110
                    126:         dd      0                       ;11111 - can never happen
                    127: 
                    128: gapfnROPTable label dword
                    129:         dd      dual_wide_00_rw         ;00000
                    130:         dd      dual_wide_01_rw         ;00001
                    131:         dd      0                       ;00010
                    132:         dd      0                       ;00011
                    133:         dd      dual_wide_11_rw         ;00100
                    134:         dd      dual_wide_10_rw         ;00101
                    135:         dd      0                       ;00110
                    136:         dd      0                       ;00111
                    137:         dd      Block_01000_rw          ;01000
                    138:         dd      Block_01001_rw          ;01001
                    139:         dd      dual_right_0_rw         ;01010
                    140:         dd      dual_right_1_rw         ;01011
                    141:         dd      Block_01100_rw          ;01100
                    142:         dd      Block_01101_rw          ;01101
                    143:         dd      dual_right_1_rw         ;01110
                    144:         dd      dual_right_0_rw         ;01111
                    145:         dd      Block_10000_rw          ;10000
                    146:         dd      Block_10001_rw          ;10001
                    147:         dd      dual_left_0_rw          ;10010
                    148:         dd      dual_left_0_rw          ;10011
                    149:         dd      Block_10100_rw          ;10100
                    150:         dd      Block_10101_rw          ;10101
                    151:         dd      dual_left_1_rw          ;10110
                    152:         dd      dual_left_1_rw          ;10111
                    153:         dd      Block_11000_rw          ;11000
                    154:         dd      Block_11001_rw          ;11001
                    155:         dd      Block_11010_rw          ;11010
                    156:         dd      0                       ;11011 - can never happen
                    157:         dd      Block_11100_rw          ;11100
                    158:         dd      Block_11101_rw          ;11101
                    159:         dd      Block_11110_rw          ;11110
                    160:         dd      0                       ;11111 - can never happen
                    161: 
                    162: gaulForceOffTable label dword
                    163:         dd      0                       ;ignored - there is no mix 0
                    164:         dd      0
                    165:         dd      0ffffffffh
                    166:         dd      0ffffffffh
                    167:         dd      0ffffffffh
                    168:         dd      0ffffffffh
                    169:         dd      0ffffffffh
                    170:         dd      0ffffffffh
                    171:         dd      0ffffffffh
                    172:         dd      0ffffffffh
                    173:         dd      0ffffffffh
                    174:         dd      0
                    175:         dd      0ffffffffh
                    176:         dd      0ffffffffh
                    177:         dd      0ffffffffh
                    178:         dd      0ffffffffh
                    179:         dd      0ffffffffh
                    180: 
                    181: gaulForceOnTable label dword
                    182:         dd      0                       ;ignored - there is no mix 0
                    183:         dd      0
                    184:         dd      0
                    185:         dd      0
                    186:         dd      0
                    187:         dd      0
                    188:         dd      0ffffffffh
                    189:         dd      0
                    190:         dd      0
                    191:         dd      0
                    192:         dd      0
                    193:         dd      0
                    194:         dd      0
                    195:         dd      0
                    196:         dd      0
                    197:         dd      0
                    198:         dd      0ffffffffh
                    199: 
                    200: gaulForceNotTable label dword
                    201:         dd      0                       ;ignored - there is no mix 0
                    202:         dd      0
                    203:         dd      0ffffffffh
                    204:         dd      0ffffffffh
                    205:         dd      0ffffffffh
                    206:         dd      0
                    207:         dd      0
                    208:         dd      0
                    209:         dd      0ffffffffh
                    210:         dd      0
                    211:         dd      0ffffffffh
                    212:         dd      0
                    213:         dd      0ffffffffh
                    214:         dd      0
                    215:         dd      0
                    216:         dd      0
                    217:         dd      0
                    218: 
                    219: ;-----------------------------------------------------------------------;
                    220: 
                    221:         .code
                    222: ;-----------------------------------------------------------------------;
                    223: ; Write thunks (for set ROPs)
                    224: ;-----------------------------------------------------------------------;
                    225: 
                    226:         align   4
                    227: Block_01000_w:
                    228:         push    offset dual_right_0_w
                    229:         jmp     dual_wide_00_w
                    230: 
                    231:         align   4
                    232: Block_01001_w:
                    233:         push    offset dual_right_1_w
                    234:         jmp     dual_wide_01_w
                    235: 
                    236:         align   4
                    237: Block_01100_w:
                    238:         push    offset dual_right_1_w
                    239:         jmp     dual_wide_11_w
                    240: 
                    241:         align   4
                    242: Block_01101_w:
                    243:         push    offset dual_right_0_w
                    244:         jmp     dual_wide_10_w
                    245: 
                    246:         align   4
                    247: Block_11000_w:
                    248:         push    offset dual_right_0_w
                    249: Block_10000_w:
                    250:         push    offset dual_left_0_w
                    251:         jmp     dual_wide_00_w
                    252: 
                    253:         align   4
                    254: Block_11001_w:
                    255:         push    offset dual_right_1_w
                    256: Block_10001_w:
                    257:         push    offset dual_left_0_w
                    258:         jmp     dual_wide_01_w
                    259: 
                    260:         align   4
                    261: Block_11100_w:
                    262:         push    offset dual_right_1_w
                    263: Block_10100_w:
                    264:         push    offset dual_left_1_w
                    265:         jmp     dual_wide_11_w
                    266: 
                    267:         align   4
                    268: Block_11101_w:
                    269:         push    offset dual_right_0_w
                    270: Block_10101_w:
                    271:         push    offset dual_left_1_w
                    272:         jmp     dual_wide_10_w
                    273: 
                    274:         align   4
                    275: Block_11010_w:
                    276:         push    offset dual_right_0_w
                    277:         jmp     dual_left_0_w
                    278: 
                    279:         align   4
                    280: Block_11110_w:
                    281:         push    offset dual_right_1_w
                    282:         jmp     dual_left_1_w
                    283: 
                    284: ;-----------------------------------------------------------------------;
                    285: ; Read/write thunks (for arbitrary ROPs)
                    286: ;-----------------------------------------------------------------------;
                    287: 
                    288: Block_01000_rw:
                    289:         push    offset dual_right_0_rw
                    290:         jmp     dual_wide_00_rw
                    291: 
                    292: Block_01001_rw:
                    293:         push    offset dual_right_1_rw
                    294:         jmp     dual_wide_01_rw
                    295: 
                    296: Block_01100_rw:
                    297:         push    offset dual_right_1_rw
                    298:         jmp     dual_wide_11_rw
                    299: 
                    300: Block_01101_rw:
                    301:         push    offset dual_right_0_rw
                    302:         jmp     dual_wide_10_rw
                    303: 
                    304: Block_11000_rw:
                    305:         push    offset dual_right_0_rw
                    306: Block_10000_rw:
                    307:         push    offset dual_left_0_rw
                    308:         jmp     dual_wide_00_rw
                    309: 
                    310: Block_11001_rw:
                    311:         push    offset dual_right_1_rw
                    312: Block_10001_rw:
                    313:         push    offset dual_left_0_rw
                    314:         jmp     dual_wide_01_rw
                    315: 
                    316: Block_11100_rw:
                    317:         push    offset dual_right_1_rw
                    318: Block_10100_rw:
                    319:         push    offset dual_left_1_rw
                    320:         jmp     dual_wide_11_rw
                    321: 
                    322: Block_11101_rw:
                    323:         push    offset dual_right_0_rw
                    324: Block_10101_rw:
                    325:         push    offset dual_left_1_rw
                    326:         jmp     dual_wide_10_rw
                    327: 
                    328: Block_11010_rw:
                    329:         push    offset dual_right_0_rw
                    330:         jmp     dual_left_0_rw
                    331: 
                    332: Block_11110_rw:
                    333:         push    offset dual_right_1_rw
                    334:         jmp     dual_left_1_rw
                    335: 
                    336: ;-----------------------------------------------------------------------;
                    337: 
                    338: cProc   vMonoPat,24,<         \
                    339:         uses esi edi ebx,     \
                    340:         ppdev:     ptr PDEV,  \
                    341:         culRcl:    dword,     \
                    342:         prcl:      ptr RECTL, \
                    343:         ulMix:     dword,     \
                    344:         prb:       ptr RBRUSH,\
                    345:         pptlBrush: ptr POINTL >
                    346: 
                    347: ; Variables used in block drawers:
                    348: 
                    349:         local ppfnDraw:            ptr   ;pointer to array of draw routines
                    350:         local pfnDraw:             ptr   ;pointer to draw routines
                    351: 
                    352:         local yBrush:              dword ;current y brush alignment
                    353:         local yBrushOrg:           dword ;original y brush alignment
                    354:         local ulMiddleDest:        dword ;bitmap offset to middle
                    355:         local lMiddleDelta:        dword ;delta from end of middle scan to next
                    356:         local ulBlockHeight:       dword ;# of scans to be drawn in block
                    357:         local cwMiddle:            dword ;# of words to be written in middle
                    358: 
                    359:         local ulLeftDest:          dword ;bitmap offset to left edge
                    360:         local ulLeftMask:          dword ;plane mask for left-edge drawing
                    361:         local ulRightDest:         dword ;bitmap offset to right edge
                    362:         local ulRightMask:         dword ;plane mask for right-edge drawing
                    363:         local lDelta:              dword ;delta between scans
                    364: 
                    365:         local ulCurrentDestScan:   dword ;current destination scan
                    366:         local ulLastDestScan:      dword ;last destination scan
                    367: 
                    368:         local ulSaveEsp:           dword ;for when we really need a register
                    369:         local pulPattern:          ptr   ;pointer to working pattern buffer
                    370:                                          ; (to account for brush inversions)
                    371:         local aulPatternBuffer[8]: dword ;pattern buffer
                    372: 
                    373:         local cUnrolledLoops:      dword ;number of unrolled loops to do
                    374:         local pfnUnroll:           ptr   ;points to start point in unroll table
                    375: 
                    376:         mov     esi,pptlBrush
                    377:         mov     edi,prb
                    378:         mov     ecx,[esi].ptl_y
                    379:         mov     yBrushOrg,ecx           ;yBrushOrg = pptlBrush->y
                    380:         mov     ecx,[esi].ptl_x
                    381:         mov     eax,[edi].rb_xBrush
                    382:         and     ecx,7
                    383:         cmp     eax,ecx
                    384:         jne     dual_align_brush        ;only align if we really have to
                    385: 
                    386: dual_done_align_brush:
                    387:         test    [edi].rb_fl,RBRUSH_2COLOR
                    388:         jnz     col2_colors
                    389: 
                    390: ; Set VGA to read mode 1 and write mode 2:
                    391: 
                    392:         mov     esi,ppdev
                    393:         mov     edx,VGA_BASE + GRAF_ADDR
                    394:         mov     ah,byte ptr [esi].pdev_ulrm0_wmX[2]
                    395:         or      ah,M_COLOR_READ
                    396:         mov     al,GRAF_MODE
                    397:         out     dx,ax                   ;write mode 2 to expand pattern bits to
                    398:                                         ; 0 or 0ffh per plane, read mode 1 so
                    399:                                         ; we can read 0xFF from memory always,
                    400:                                         ; for ANDing (because Color Don't Care
                    401:                                         ; is all zeros)
                    402: 
                    403: ;-----------------------------------------------------------------------;
                    404: ; Handle only black/white patterns.
                    405: ;-----------------------------------------------------------------------;
                    406: 
                    407:         lea     eax,[edi].rb_aulPattern
                    408:         mov     pulPattern,eax          ;pulPattern = &pbr.rb_aulPattern[0]
                    409:         lea     eax,gapfnSetTable
                    410:         mov     ppfnDraw,eax            ;ppfnDraw = gapfnSetTable
                    411: 
                    412:         mov     ecx,ulMix
                    413:         and     ecx,0fh
                    414:         cmp     ecx,R2_COPYPEN
                    415:         jne     bw_init_rop             ;do some more work if not copy ROP
                    416: 
                    417: bw_done_init_rop:
                    418: 
                    419:         call    dual_draw_rectangles    ;draw those puppies
                    420: 
                    421: ; All done!  Restore read mode 0, write mode 0:
                    422: 
                    423:         mov     esi,ppdev
                    424:         mov     edx,VGA_BASE + GRAF_ADDR
                    425:         mov     ah,byte ptr [esi].pdev_ulrm0_wmX[0]
                    426:         mov     al,GRAF_MODE
                    427:         out     dx,ax
                    428: 
                    429: ; Enable all planes:
                    430: 
                    431:         mov     edx,VGA_BASE + SEQ_DATA
                    432:         mov     al,MM_ALL
                    433:         out     dx,al
                    434: 
                    435:         cmp     ulMix,R2_COPYPEN
                    436:         jne     short bw_enable_set_mode
                    437:         cRet    vMonoPat
                    438: 
                    439: ; Set ALU function to Set mode (we don't have to bother if we had a
                    440: ; COPYPEN ROP):
                    441: 
                    442: bw_enable_set_mode:
                    443:         mov     eax,GRAF_DATA_ROT + (DR_SET shl 8)
                    444:         mov     edx,VGA_BASE + GRAF_ADDR
                    445:         out     dx,ax
                    446:         cRet    vMonoPat
                    447: 
                    448: ;-----------------------------------------------------------------------;
                    449: ; Draw both black and white and 2 color rectangles.
                    450: ;-----------------------------------------------------------------------;
                    451: 
                    452:         align   4
                    453:         public  dual_draw_rectangles
                    454: dual_draw_rectangles:
                    455: 
                    456:         mov     edi,prcl                ;edi = prcl
                    457:         mov     edx,ppdev
                    458:         mov     eax,[edi].yBottom
                    459:         mov     ebx,[edi].yTop
                    460:         mov     edx,[edx].pdev_lPlanarNextScan
                    461: 
                    462:         mov     lDelta,edx              ;lDelta = ppdev->lPlanarNextScan
                    463:         mov     ulLastDestScan,eax      ;ulLastDestScan = prcl->bottom
                    464:         mov     ulCurrentDestScan,ebx   ;ulCurrentDestScan = prcl->top
                    465: 
                    466:         mov     ecx,edx
                    467:         imul    ecx,ebx
                    468: 
                    469:         sub     ebx,yBrushOrg
                    470:         and     ebx,7
                    471:         mov     yBrush,ebx              ;yBrush = (prcl->top - pptlBrush->y) & 7
                    472:                                         ; (our current index into the pattern
                    473:                                         ; array)
                    474: 
                    475:         mov     ebx,[edi].xLeft
                    476:         shr     ebx,2
                    477:         add     ebx,ecx                 ;ebx = prcl->top * lDelta +
                    478:                                         ; (prcl->left >> 2)
                    479:                                         ; (offset into bitmap of left side)
                    480: 
                    481:         mov     eax,[edi].xRight
                    482:         shr     eax,2
                    483:         add     eax,ecx
                    484:         mov     ulRightDest,eax         ;ulRightDest = prcl->top * lDelta +
                    485:                                         ; (prcl->right >> 2)
                    486:                                         ; (offset into bitmap of right side)
                    487: 
                    488:         xor     esi,esi                 ;zero our flags
                    489: 
                    490:         mov     ecx,[edi].xLeft
                    491:         and     ecx,3
                    492:         jz      short dual_done_left    ;skip if we don't need a left edge
                    493: 
                    494:         mov     esi,0fh                 ;compute the plane mask for the left
                    495:         shl     esi,cl                  ; edge.  we don't use a look-up table
                    496:         mov     ulLeftMask,esi          ; 'cause it won't be in the cache.
                    497: 
                    498:         mov     esi,(BLOCK_LEFT_EDGE shr 2)
                    499:                                         ;set our flag (we soon shift left by 2)
                    500: 
                    501:         mov     ulLeftDest,ebx          ;ulLeftDest = prcl->top * lDelta +
                    502:                                         ; (prcl->left >> 2)
                    503:         inc     ebx                     ;ebx = ulMiddleDest = ulLeftDest + 1
                    504:                                         ; (we have to adjust our offset to
                    505:                                         ; the first whole byte)
                    506: 
                    507: dual_done_left:
                    508:         sub     eax,ebx                 ;eax = cjMiddle =
                    509:                                         ; ulRightDest - ulMiddleDest
                    510:         mov     ulMiddleDest,ebx        ;ulMiddleDest
                    511: 
                    512:         .errnz  (BLOCK_MIDDLE_STARTS_UNALIGNED shr 2) - 1
                    513:         and     ebx,1                   ;set bit if middle doesn't start
                    514:         or      esi,ebx                 ; word aligned (remembering we'll
                    515:                                         ; soon shift flags left by 2)
                    516: 
                    517:         mov     ecx,[edi].xRight
                    518:         and     ecx,3
                    519:         jz      short dual_done_right   ;skip if we don't need a right edge
                    520: 
                    521:         mov     ebx,0f0h                ;compute the plane mask for the right
                    522:         rol     bl,cl                   ; edge.  we don't use a look-up table
                    523:         mov     ulRightMask,ebx         ; 'cause it won't be in the cache.
                    524: 
                    525:         or      esi,(BLOCK_RIGHT_EDGE shr 2)
                    526:                                         ;set our flag (we soon shift left by 2)
                    527: 
                    528: ; If the count of whole bytes is negative, that means that the pattern
                    529: ; starts and ends in the same quadpixel, so we do some more work:
                    530: 
                    531:         cmp     eax,0
                    532:         jge     short dual_done_right
                    533: 
                    534: ; It starts and ends in the same quadpixel:
                    535: 
                    536:         and     esi,not (BLOCK_RIGHT_EDGE shr 2)
                    537:                                         ;turn off right edge
                    538:         and     ebx,ulLeftMask
                    539:         mov     ulLeftMask,ebx
                    540:         xor     eax,eax                 ;we do zero middle bytes
                    541: 
                    542:         align   4
                    543:         public  dual_done_right
                    544: dual_done_right:
                    545:         mov     ebx,ppfnDraw
                    546: 
                    547: ; We're going to do two 'adc esi,esi' instructions here, effectively
                    548: ; shifting our flags left by 2, and setting the low bits:
                    549: 
                    550:         .errnz  (BLOCK_NO_MIDDLE shr 1) - 1
                    551:         cmp     eax,1                   ;shift flags left one, and set low
                    552:         adc     esi,esi                 ; bit if we don't need to do a middle
                    553: 
                    554:         .errnz  (BLOCK_MIDDLE_ENDS_UNALIGNED) - 1
                    555:         shr     eax,1
                    556:         adc     esi,esi                 ;shift flags left one, and set low
                    557:                                         ; bit if the middle isn't an even
                    558:                                         ; number of bytes in length
                    559:         mov     cwMiddle,eax            ;cwMiddle = cjMiddle / 2
                    560: 
                    561:         sub     edx,eax
                    562:         sub     edx,eax
                    563:         mov     lMiddleDelta,edx        ;lMiddleDelta = lDelta - 2 * cwMiddle
                    564: 
                    565:         mov     eax,[ebx+esi*4]
                    566:         mov     pfnDraw,eax             ;pointer to function that draws
                    567:                                         ; everything in the bank
                    568: 
                    569:         mov     ebx,ppdev
                    570:         mov     edi,[edi].yTop
                    571: 
                    572:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yTop
                    573:         jl      short dual_map_init_bank
                    574: 
                    575:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yBottom
                    576:         jl      short dual_init_bank_mapped
                    577: 
                    578: dual_map_init_bank:
                    579:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    580:                 <ebx,edi,JustifyTop>
                    581: 
                    582: dual_init_bank_mapped:
                    583:         mov     eax,ulLastDestScan
                    584:         mov     ebx,[ebx].pdev_rcl1PlanarClip.yBottom
                    585: 
                    586:         sub     eax,ebx
                    587:         sbb     ecx,ecx
                    588:         and     ecx,eax
                    589:         add     ebx,ecx                 ;ebx = min(ulLastDestScan,
                    590:                                         ;      ppdev->rcl1PlanarClip.yBottom)
                    591:         mov     ulCurrentDestScan,ebx
                    592: 
                    593:         sub     ebx,edi
                    594:         mov     ulBlockHeight,ebx       ;ulBlockHeight = ebx - ulCurrentDestScan
                    595: 
                    596: ; Draw everything in this bank:
                    597: 
                    598:         call    pfnDraw
                    599: 
                    600: dual_done_pfnDraw:
                    601:         mov     edi,ulCurrentDestScan
                    602:         cmp     edi,ulLastDestScan
                    603:         jge     short dual_next_rectangle
                    604: 
                    605: ; Get the next bank:
                    606: 
                    607:         mov     ebx,ppdev
                    608:         mov     yBrush,esi              ;make sure we record the new brush
                    609:                                         ; alignment
                    610: 
                    611: ; Map the next bank into window.
                    612: ; Note: EBX, ESI, and EDI are preserved, according to C calling conventions.
                    613: 
                    614:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    615:                 <ebx,edi,JustifyTop>
                    616: 
                    617:         jmp     short dual_init_bank_mapped
                    618: 
                    619: ;-----------------------------------------------------------------------;
                    620: ; Done rectangle.
                    621: ;-----------------------------------------------------------------------;
                    622: 
                    623:         align   4
                    624:         public  dual_next_rectangle
                    625: dual_next_rectangle:
                    626:         add     prcl, size RECTL
                    627:         dec     culRcl
                    628:         jg      dual_draw_rectangles    ;do more rectangles
                    629: 
                    630:         PLAIN_RET                       ;return
                    631: 
                    632: ;-----------------------------------------------------------------------;
                    633: ; Handle x-brush alignment.
                    634: ;-----------------------------------------------------------------------;
                    635: 
                    636:         align   4
                    637:         public  dual_align_brush
                    638: dual_align_brush:
                    639: 
                    640: ; Align the pattern on x.  Remember it in the realized brush, because if
                    641: ; the brush is used again, it's likely to have the same alignment...
                    642: 
                    643:         mov     [edi].rb_xBrush,ecx     ;remember our new alignment
                    644:         sub     ecx,eax                 ;rotate pattern left by
                    645:                                         ; pptlBrush->x - prb->xBrush
                    646: 
                    647: ; We keep each row of the pattern in the low word of each dword.  If the
                    648: ; bits are to appear on the screen as 01234567, the word of our pattern
                    649: ; has the bits 32107654|76543210 -- we're in write mode 3, and when
                    650: ; written as a word, this results in 3210 being written in the first
                    651: ; byte, and 7654 in the second byte.
                    652: ;
                    653: ; For brush alignment, we would want to rotate 01234567 right by 'cl'.
                    654: ; For our funky plaanr format, we just rotate each byte of the word left by
                    655: ; 'cl' to get the desired result.
                    656: 
                    657:         rol     byte ptr [edi][0].rb_aulPattern,cl        ;0
                    658:         rol     byte ptr [edi][1].rb_aulPattern,cl
                    659:         rol     byte ptr [edi][4].rb_aulPattern,cl        ;1
                    660:         rol     byte ptr [edi][5].rb_aulPattern,cl
                    661:         rol     byte ptr [edi][8].rb_aulPattern,cl        ;2
                    662:         rol     byte ptr [edi][9].rb_aulPattern,cl
                    663:         rol     byte ptr [edi][12].rb_aulPattern,cl       ;3
                    664:         rol     byte ptr [edi][13].rb_aulPattern,cl
                    665:         rol     byte ptr [edi][16].rb_aulPattern,cl       ;4
                    666:         rol     byte ptr [edi][17].rb_aulPattern,cl
                    667:         rol     byte ptr [edi][20].rb_aulPattern,cl       ;5
                    668:         rol     byte ptr [edi][21].rb_aulPattern,cl
                    669:         rol     byte ptr [edi][24].rb_aulPattern,cl       ;6
                    670:         rol     byte ptr [edi][25].rb_aulPattern,cl
                    671:         rol     byte ptr [edi][28].rb_aulPattern,cl       ;7
                    672:         rol     byte ptr [edi][29].rb_aulPattern,cl
                    673: 
                    674:         jmp     dual_done_align_brush
                    675: 
                    676: ;-----------------------------------------------------------------------;
                    677: ; Handle arbitrary ROPs for black/white patterns.
                    678: ;-----------------------------------------------------------------------;
                    679: 
                    680: ; Expect:
                    681: ;
                    682: ; ecx = ulMix
                    683: 
                    684:         align   4
                    685:         public  bw_init_rop
                    686: bw_init_rop:
                    687:         cmp     jInvertDest[ecx],0
                    688:         je      short bw_set_that_ALU   ;skip if don't need 2 passes
                    689: 
                    690: ; For some ROPs, we have to invert the destination first, then do another
                    691: ; operation (that is, it's a 2-pass ROP).  We handle the inversion here:
                    692: 
                    693:         cCall   vTrgBlt,<ppdev, culRcl, prcl, R2_NOT, 0, 0>
                    694:         mov     ecx,ulMix
                    695: 
                    696: bw_set_that_ALU:
                    697:         mov     ah,jALUFuncTable[ecx]
                    698:         cmp     ah,DR_SET
                    699:         je      short bw_that_ALU_is_set
                    700:                                         ;we're already in Set mode
                    701: 
                    702:         mov     edx,VGA_BASE + GRAF_ADDR
                    703:         mov     al,GRAF_DATA_ROT
                    704:         out     dx,ax                   ;set the ALU logical function
                    705:         lea     ebx,gapfnROPTable
                    706:         mov     ppfnDraw,ebx
                    707: 
                    708: bw_that_ALU_is_set:
                    709:         lea     esi,aulPatternBuffer
                    710:         mov     pulPattern,esi          ;we're using the temporary buffer
                    711: 
                    712:         mov     ebx,gaulForceOffTable[ecx*4]
                    713:         mov     edx,gaulForceOnTable[ecx*4]
                    714:         mov     esi,gaulForceNotTable[ecx*4]
                    715: 
                    716:         mov     eax,[edi][0].rb_aulPattern      ;0
                    717:         and     eax,ebx
                    718:         or      eax,edx
                    719:         xor     eax,esi
                    720:         mov     [aulPatternBuffer][0],eax
                    721:         mov     eax,[edi][4].rb_aulPattern      ;1
                    722:         and     eax,ebx
                    723:         or      eax,edx
                    724:         xor     eax,esi
                    725:         mov     [aulPatternBuffer][4],eax
                    726:         mov     eax,[edi][8].rb_aulPattern      ;2
                    727:         and     eax,ebx
                    728:         or      eax,edx
                    729:         xor     eax,esi
                    730:         mov     [aulPatternBuffer][8],eax
                    731:         mov     eax,[edi][12].rb_aulPattern     ;3
                    732:         and     eax,ebx
                    733:         or      eax,edx
                    734:         xor     eax,esi
                    735:         mov     [aulPatternBuffer][12],eax
                    736:         mov     eax,[edi][16].rb_aulPattern     ;4
                    737:         and     eax,ebx
                    738:         or      eax,edx
                    739:         xor     eax,esi
                    740:         mov     [aulPatternBuffer][16],eax
                    741:         mov     eax,[edi][20].rb_aulPattern     ;5
                    742:         and     eax,ebx
                    743:         or      eax,edx
                    744:         xor     eax,esi
                    745:         mov     [aulPatternBuffer][20],eax
                    746:         mov     eax,[edi][24].rb_aulPattern     ;6
                    747:         and     eax,ebx
                    748:         or      eax,edx
                    749:         xor     eax,esi
                    750:         mov     [aulPatternBuffer][24],eax
                    751:         mov     eax,[edi][28].rb_aulPattern     ;7
                    752:         and     eax,ebx
                    753:         or      eax,edx
                    754:         xor     eax,esi
                    755:         mov     [aulPatternBuffer][28],eax
                    756: 
                    757:         jmp     bw_done_init_rop
                    758: 
                    759: ;-----------------------------------------------------------------------;
                    760: ; Handle 2-color patterns.
                    761: ;-----------------------------------------------------------------------;
                    762: 
                    763:         align   4
                    764:         public  col2_colors
                    765: col2_colors:
                    766:         lea     eax,[edi].rb_aulPattern
                    767:         mov     pulPattern,eax          ;pulPattern = &pbr.rb_aulPattern[0]
                    768:         lea     eax,gapfnSetTable
                    769:         mov     ppfnDraw,eax            ;ppfnDraw = gapfnSetTable
                    770: 
                    771:         call    col2_first_rectangle
                    772: 
                    773: ; Restore VGA hardware to its default state:
                    774: 
                    775:         mov     edx,VGA_BASE + GRAF_DATA
                    776:         mov     al,0ffh
                    777:         out     dx,al                   ;enable all bits through the Bit Mask
                    778: 
                    779:         mov     esi,ppdev
                    780:         dec     edx                     ;point back to the Graphics Index reg
                    781:         mov     ah,byte ptr [esi].pdev_ulrm0_wmX[0]
                    782:                                         ;write mode 0 setting for Graphics Mode
                    783:         mov     al,GRAF_MODE
                    784:         out     dx,ax                   ;write mode 0, read mode 0
                    785: 
                    786:         mov     eax,GRAF_DATA_ROT + (DR_SET SHL 8)
                    787:         out     dx,ax                   ;replace mode, no rotate
                    788: 
                    789:         mov     edx,VGA_BASE + SEQ_DATA
                    790:         mov     al,MM_ALL
                    791:         out     dx,al                   ;enable all planes
                    792: 
                    793:         cRet    vMonoPat
                    794: 
                    795: ;-----------------------------------------------------------------------;
                    796: ; Handle first rectangle for 2-color patterns.
                    797: ;-----------------------------------------------------------------------;
                    798: 
                    799: ; We have to special case the first rectangle because we have to load
                    800: ; the latches with the background color after mapping the bank but before
                    801: ; doing any drawing.
                    802: 
                    803:         align   4
                    804:         public  col2_first_rectangle
                    805: col2_first_rectangle:
                    806:         mov     edi,prcl                ;edi = prcl
                    807:         mov     edx,ppdev
                    808:         mov     eax,[edi].yBottom
                    809:         mov     ebx,[edi].yTop
                    810:         mov     edx,[edx].pdev_lPlanarNextScan
                    811: 
                    812:         mov     lDelta,edx              ;lDelta = ppdev->lPlanarNextScan
                    813:         mov     ulLastDestScan,eax      ;ulLastDestScan = prcl->bottom
                    814:         mov     ulCurrentDestScan,ebx   ;ulCurrentDestScan = prcl->top
                    815: 
                    816:         mov     ecx,edx
                    817:         imul    ecx,ebx
                    818: 
                    819:         sub     ebx,yBrushOrg
                    820:         and     ebx,7
                    821:         mov     yBrush,ebx              ;yBrush = (prcl->top - pptlBrush->y) & 7
                    822:                                         ; (our current index into the pattern
                    823:                                         ; array)
                    824: 
                    825:         mov     ebx,[edi].xLeft
                    826:         shr     ebx,2
                    827:         add     ebx,ecx                 ;ebx = prcl->top * lDelta +
                    828:                                         ; (prcl->left >> 2)
                    829:                                         ; (offset into bitmap of left side)
                    830: 
                    831:         mov     eax,[edi].xRight
                    832:         shr     eax,2
                    833:         add     eax,ecx
                    834:         mov     ulRightDest,eax         ;ulRightDest = prcl->top * lDelta +
                    835:                                         ; (prcl->right >> 2)
                    836:                                         ; (offset into bitmap of right side)
                    837: 
                    838:         xor     esi,esi                 ;zero our flags
                    839: 
                    840:         mov     ecx,[edi].xLeft
                    841:         and     ecx,3
                    842:         jz      short col2_done_left    ;skip if we don't need a left edge
                    843: 
                    844:         mov     esi,0fh                 ;compute the plane mask for the left
                    845:         shl     esi,cl                  ; edge.  we don't use a look-up table
                    846:         mov     ulLeftMask,esi          ; 'cause it won't be in the cache.
                    847: 
                    848:         mov     esi,(BLOCK_LEFT_EDGE shr 2)
                    849:                                         ;set our flag (we soon shift left by 2)
                    850: 
                    851:         mov     ulLeftDest,ebx          ;ulLeftDest = prcl->top * lDelta +
                    852:                                         ; (prcl->left >> 2)
                    853:         inc     ebx                     ;ebx = ulMiddleDest = ulLeftDest + 1
                    854:                                         ; (we have to adjust our offset to
                    855:                                         ; the first whole byte)
                    856: 
                    857: col2_done_left:
                    858:         sub     eax,ebx                 ;eax = cjMiddle =
                    859:                                         ; ulRightDest - ulMiddleDest
                    860:         mov     ulMiddleDest,ebx        ;ulMiddleDest
                    861: 
                    862:         .errnz  (BLOCK_MIDDLE_STARTS_UNALIGNED shr 2) - 1
                    863:         and     ebx,1                   ;set bit if middle doesn't start
                    864:         or      esi,ebx                 ; word aligned (remembering we'll
                    865:                                         ; soon shift flags left by 2)
                    866: 
                    867:         mov     ecx,[edi].xRight
                    868:         and     ecx,3
                    869:         jz      short col2_done_right   ;skip if we don't need a right edge
                    870: 
                    871:         mov     ebx,0f0h                ;compute the plane mask for the right
                    872:         rol     bl,cl                   ; edge.  we don't use a look-up table
                    873:         mov     ulRightMask,ebx         ; 'cause it won't be in the cache.
                    874: 
                    875:         or      esi,(BLOCK_RIGHT_EDGE shr 2)
                    876:                                         ;set our flag (we soon shift left by 2)
                    877: 
                    878: ; If the count of whole bytes is negative, that means that the pattern
                    879: ; starts and ends in the same quadpixel, so we do some more work:
                    880: 
                    881:         cmp     eax,0
                    882:         jge     short col2_done_right
                    883: 
                    884: ; It starts and ends in the same quadpixel:
                    885: 
                    886:         and     esi,not (BLOCK_RIGHT_EDGE shr 2)
                    887:                                         ;turn off right edge
                    888:         and     ebx,ulLeftMask
                    889:         mov     ulLeftMask,ebx
                    890:         xor     eax,eax                 ;we do zero middle bytes
                    891: 
                    892:         align   4
                    893:         public  col2_done_right
                    894: col2_done_right:
                    895:         mov     ebx,ppfnDraw
                    896: 
                    897: ; We're going to do two 'adc esi,esi' instructions here, effectively
                    898: ; shifting our flags left by 2, and setting the low bits:
                    899: 
                    900:         .errnz  (BLOCK_NO_MIDDLE shr 1) - 1
                    901:         cmp     eax,1                   ;shift flags left one, and set low
                    902:         adc     esi,esi                 ; bit if we don't need to do a middle
                    903: 
                    904:         .errnz  (BLOCK_MIDDLE_ENDS_UNALIGNED) - 1
                    905:         shr     eax,1
                    906:         mov     cwMiddle,eax            ;cwMiddle = cjMiddle / 2
                    907:         adc     esi,esi                 ;shift flags left one, and set low
                    908:                                         ; bit if the middle isn't an even
                    909:                                         ; number of bytes in length
                    910: 
                    911:         sub     edx,eax
                    912:         sub     edx,eax
                    913:         mov     lMiddleDelta,edx        ;lMiddleDelta = lDelta - 2 * cwMiddle
                    914: 
                    915:         mov     eax,[ebx+esi*4]
                    916:         mov     pfnDraw,eax             ;pointer to function that draws
                    917:                                         ; everything in the bank
                    918: 
                    919:         mov     ebx,ppdev
                    920:         test    esi,BLOCK_NO_MIDDLE
                    921:         jz      short col2_have_a_middle
                    922: 
                    923: ;-----------------------------------------;
                    924: 
                    925: ; Handle case where there isn't a whole quadpixel that will be overwritten
                    926: ; by the pattern, and so we don't have a convenient place for loading the
                    927: ; latches.  For this case, we'll use off-screen memory.
                    928: 
                    929:         mov     esi,[ebx].pdev_pbceCache
                    930:         mov     eax,[esi].bce_yCache
                    931: 
                    932:         cmp     eax,[ebx].pdev_rcl1PlanarClip.yTop
                    933:         jl      short col2_no_middle_map_brush_bank
                    934: 
                    935:         cmp     eax,[ebx].pdev_rcl1PlanarClip.yBottom
                    936:         jl      short col2_no_middle_brush_bank_mapped
                    937: 
                    938: col2_no_middle_map_brush_bank:
                    939:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    940:                 <ebx,eax,JustifyBottom>
                    941: 
                    942: col2_no_middle_brush_bank_mapped:
                    943:         mov     ecx,prb                 ;ecx = prb
                    944:         mov     esi,[esi].bce_ulCache
                    945:         add     esi,[ebx].pdev_pvBitmapStart
                    946: 
                    947:         mov     eax,[ecx].rb_ulBkColor
                    948:         mov     [esi],al
                    949:         mov     al,[esi]                ;latches now laoded with bk color
                    950: 
                    951:         mov     edi,[edi].yTop
                    952: 
                    953:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yTop
                    954:         jl      short col2_no_middle_map_init_bank
                    955: 
                    956:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yBottom
                    957:         jl      col2_latches_loaded
                    958: 
                    959: col2_no_middle_map_init_bank:
                    960:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    961:                 <ebx,edi,JustifyTop>
                    962: 
                    963:         mov     ecx,prb                 ;reload ecx = prb
                    964:         jmp     col2_latches_loaded
                    965: 
                    966: ;-----------------------------------------;
                    967: 
                    968: col2_have_a_middle:
                    969:         mov     edi,[edi].yTop
                    970: 
                    971:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yTop
                    972:         jl      short col2_map_init_bank
                    973: 
                    974:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yBottom
                    975:         jl      short col2_init_bank_mapped
                    976: 
                    977: col2_map_init_bank:
                    978:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    979:                 <ebx,edi,JustifyTop>
                    980: 
                    981: col2_init_bank_mapped:
                    982:         mov     ecx,prb                 ;ecx = prb
                    983:         mov     esi,ulMiddleDest
                    984:         add     esi,[ebx].pdev_pvBitmapStart
                    985:                                         ;pointer to the first whole quadpixel
                    986:                                         ; that will be overwritten by the
                    987:                                         ; pattern, and so which is a great
                    988:                                         ; place to use to load the latches
                    989: 
                    990:         mov     eax,[ecx].rb_ulBkColor
                    991:         mov     [esi],al
                    992:         mov     al,[esi]                ;latches now loaded with bk color
                    993: 
                    994: ; Set VGA to read mode 0 and write mode 2:
                    995: 
                    996: col2_latches_loaded:
                    997: 
                    998: ; ebx = ppdev
                    999: ; ecx = prb
                   1000: ; edi = top line of rectangle
                   1001: 
                   1002:         mov     esi,ppdev
                   1003:         mov     edx,VGA_BASE + GRAF_ADDR
                   1004:         mov     ah,byte ptr [esi].pdev_ulrm0_wmX[2]
                   1005:         mov     al,GRAF_MODE
                   1006:         out     dx,ax
                   1007: 
                   1008:         mov     eax,GRAF_DATA_ROT + (DR_XOR SHL 8)
                   1009:         out     dx,ax                   ;XOR to flip latched data to make ~bk
                   1010: 
                   1011:         mov     ah,byte ptr [ecx].rb_ulBkColor
                   1012:         xor     ah,byte ptr [ecx].rb_ulFgColor
                   1013:         mov     al,GRAF_BIT_MASK
                   1014:         out     dx,ax                   ;pass through common fg & bk bits
                   1015:                                         ; unchanged from bk color in latches;
                   1016:                                         ; non-common bits come from XOR in the
                   1017:                                         ; ALUs, flipped from the bk to the fg
                   1018:                                         ; state if the glyph bit for the pixel
                   1019:                                         ; in that plane is 1, still in bk state
                   1020:                                         ; if the glyph bit for that plane is 0
                   1021: 
                   1022: ; All done hardware initialization.  Do rest of this boring stuff:
                   1023: 
                   1024:         mov     eax,ulLastDestScan
                   1025:         mov     ebx,[ebx].pdev_rcl1PlanarClip.yBottom
                   1026: 
                   1027:         sub     eax,ebx
                   1028:         sbb     ecx,ecx
                   1029:         and     ecx,eax
                   1030:         add     ebx,ecx                 ;ebx = min(ulLastDestScan,
                   1031:                                         ;      ppdev->rcl1PlanarClip.yBottom)
                   1032:         mov     ulCurrentDestScan,ebx
                   1033: 
                   1034:         sub     ebx,edi
                   1035:         mov     ulBlockHeight,ebx       ;ulBlockHeight = ebx - ulCurrentDestScan
                   1036: 
                   1037: ; Draw everything in this bank:
                   1038: 
                   1039:         CALL_AND_JUMP   pfnDraw,dual_done_pfnDraw
                   1040: 
                   1041: ;=======================================================================;
                   1042: ;========================= Set Block Drawers ===========================;
                   1043: ;=======================================================================;
                   1044: 
                   1045: ;-----------------------------------------------------------------------;
                   1046: ; dual_wide_11_w
                   1047: ;
                   1048: ; Draws middle words with 1 leading byte and 1 trailing byte.
                   1049: ;
                   1050: ; Input:
                   1051: ;     ppdev         - pointer to physical device structure
                   1052: ;     ulBlockHeight - # of scans to draw
                   1053: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1054: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1055: ;     yBrush        - current y brush alignment
                   1056: ;     cwMiddle      - # of words to draw on each scan
                   1057: ;
                   1058: ; Output:
                   1059: ;     esi           - new y brush alignment
                   1060: ;     ulMiddleDest  - new bitmap offset
                   1061: ;-----------------------------------------------------------------------;
                   1062: 
                   1063:         align   4
                   1064:         public  dual_wide_11_w
                   1065: dual_wide_11_w:
                   1066: 
                   1067: ; We only have to reset which planes are enabled if we do edges too:
                   1068: 
                   1069:         mov     edx,VGA_BASE + SEQ_DATA
                   1070:         mov     al,MM_ALL
                   1071:         out     dx,al
                   1072: 
                   1073: ; Calculate full start addresses:
                   1074: 
                   1075:         mov     ulSaveEsp,esp
                   1076:         mov     edi,ppdev
                   1077:         mov     ebx,ulBlockHeight
                   1078:         mov     esp,pulPattern
                   1079:         mov     edx,lMiddleDelta
                   1080:         add     edx,2                   ;account for first and last
                   1081:                                         ; bytes
                   1082:         mov     esi,yBrush
                   1083:         mov     edi,[edi].pdev_pvBitmapStart
                   1084:         add     edi,ulMiddleDest
                   1085:         inc     edi                     ;align to word
                   1086: 
                   1087:         SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide11,LOOP_UNROLL_SHIFT
                   1088: 
                   1089:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide11,W11,LOOP_UNROLL_COUNT
                   1090: 
                   1091: MONO_WIDE_11_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1092: &ENTRY_LABEL&ENTRY_INDEX&:
                   1093: 
                   1094: ; We aim to overdrive.
                   1095: 
                   1096:         mov     eax,[esp+esi * 4]       ;load pattern for this scan
                   1097:         mov     [edi-1],ah              ;write the first byte
                   1098: 
                   1099:         mov     ecx,cwMiddle
                   1100:         dec     ecx                     ;account for first and last
                   1101:                                         ; bytes
                   1102:         rep     stosw                   ;light 8 pels on every write
                   1103: 
                   1104:         inc     esi                     ;advance to next scan of pattern
                   1105:         and     esi,7
                   1106:         mov     [edi],al                ;write that last byte
                   1107: 
                   1108:         add     edi,edx                 ;advance to next scan
                   1109:         endm    ;-----------------------------------;
                   1110: 
                   1111: ;  EBX = count of unrolled loop iterations
                   1112: ;  EDX = offset from end of scan to start of next
                   1113: ;  ESI = current offset into pattern
                   1114: ;  EDI = target address to which to write
                   1115: ;  ESP = pointer to start of pattern
                   1116: 
                   1117:         align   4
                   1118: dual_wide_11_w_loop:
                   1119:         UNROLL_LOOP     MONO_WIDE_11_W_M,W11,LOOP_UNROLL_COUNT
                   1120:         dec     ebx
                   1121:         jnz     short dual_wide_11_w_loop
                   1122: 
                   1123: ; get ready for next time:
                   1124: 
                   1125:         mov     ecx,ppdev
                   1126:         mov     esp,ulSaveEsp
                   1127:         sub     edi,[ecx].pdev_pvBitmapStart
                   1128:         dec     edi                     ;undo our word alignment
                   1129:         mov     ulMiddleDest,edi
                   1130: 
                   1131:         PLAIN_RET
                   1132: 
                   1133: ;-----------------------------------------------------------------------;
                   1134: ; dual_wide_10_w
                   1135: ;
                   1136: ; Draws middle words with 1 leading byte and 0 trailing bytes.
                   1137: ;
                   1138: ; Input:
                   1139: ;     ppdev         - pointer to physical device structure
                   1140: ;     ulBlockHeight - # of scans to draw
                   1141: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1142: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1143: ;     yBrush        - current y brush alignment
                   1144: ;     cwMiddle      - # of words to draw on each scan
                   1145: ;
                   1146: ; Output:
                   1147: ;     esi           - new y brush alignment
                   1148: ;     ulMiddleDest  - new bitmap offset
                   1149: ;-----------------------------------------------------------------------;
                   1150: 
                   1151:         align   4
                   1152:         public  dual_wide_10_w
                   1153: dual_wide_10_w:
                   1154: 
                   1155: ; We only have to reset which planes are enabled if we do edges too:
                   1156: 
                   1157:         mov     edx,VGA_BASE + SEQ_DATA
                   1158:         mov     al,MM_ALL
                   1159:         out     dx,al
                   1160: 
                   1161: ; Calculate full start addresses:
                   1162: 
                   1163:         mov     ulSaveEsp,esp
                   1164:         mov     edi,ppdev
                   1165:         mov     ebx,ulBlockHeight
                   1166:         mov     esp,pulPattern
                   1167:         mov     edx,lMiddleDelta
                   1168:         mov     esi,yBrush
                   1169:         mov     edi,[edi].pdev_pvBitmapStart
                   1170:         add     edi,ulMiddleDest
                   1171:         inc     edi                             ;align to word
                   1172: 
                   1173:         SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide10,LOOP_UNROLL_SHIFT
                   1174: 
                   1175:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide10,W10,LOOP_UNROLL_COUNT
                   1176: 
                   1177: MONO_WIDE_10_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1178: &ENTRY_LABEL&ENTRY_INDEX&:
                   1179: 
                   1180:         mov     eax,[esp+esi * 4]               ;load pattern for this scan
                   1181:         mov     [edi-1],ah                      ;write the first byte
                   1182: 
                   1183:         mov     ecx,cwMiddle
                   1184:         rep     stosw                           ;light 8 pels on every write
                   1185: 
                   1186:         inc     esi                             ;advance to next scan of pattern
                   1187:         and     esi,7
                   1188: 
                   1189:         add     edi,edx                         ;advance to next scan
                   1190:         endm    ;-----------------------------------;
                   1191: 
                   1192: ;  EBX = count of unrolled loop iterations
                   1193: ;  EDX = offset from end of scan to start of next
                   1194: ;  ESI = current offset into pattern
                   1195: ;  EDI = target address to which to write
                   1196: ;  ESP = pointer to start of pattern
                   1197: 
                   1198:         align   4
                   1199: dual_wide_10_w_loop:
                   1200:         UNROLL_LOOP     MONO_WIDE_10_W_M,W10,LOOP_UNROLL_COUNT
                   1201:         dec     ebx
                   1202:         jnz     short dual_wide_10_w_loop
                   1203: 
                   1204: ; get ready for next time:
                   1205: 
                   1206:         mov     ecx,ppdev
                   1207:         mov     esp,ulSaveEsp
                   1208:         sub     edi,[ecx].pdev_pvBitmapStart
                   1209:         dec     edi                             ;undo our word alignment
                   1210:         mov     ulMiddleDest,edi
                   1211: 
                   1212:         PLAIN_RET
                   1213: 
                   1214: ;-----------------------------------------------------------------------;
                   1215: ; dual_wide_01_w
                   1216: ;
                   1217: ; Draws middle words with 0 leading bytes and 1 trailing byte.
                   1218: ;
                   1219: ; Input:
                   1220: ;     ppdev         - pointer to physical device structure
                   1221: ;     ulBlockHeight - # of scans to draw
                   1222: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1223: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1224: ;     yBrush        - current y brush alignment
                   1225: ;     cwMiddle      - # of words to draw on each scan
                   1226: ;
                   1227: ; Output:
                   1228: ;     esi           - new y brush alignment
                   1229: ;     ulMiddleDest  - new bitmap offset
                   1230: ;-----------------------------------------------------------------------;
                   1231: 
                   1232:         align   4
                   1233:         public  dual_wide_01_w
                   1234: dual_wide_01_w:
                   1235: 
                   1236: ; We only have to reset which planes are enabled if we do edges too:
                   1237: 
                   1238:         mov     edx,VGA_BASE + SEQ_DATA
                   1239:         mov     al,MM_ALL
                   1240:         out     dx,al
                   1241: 
                   1242: ; Calculate full start addresses:
                   1243: 
                   1244:         mov     ulSaveEsp,esp
                   1245:         mov     edi,ppdev
                   1246:         mov     ebx,ulBlockHeight
                   1247:         mov     esp,pulPattern
                   1248:         mov     edx,lMiddleDelta
                   1249:         mov     esi,yBrush
                   1250:         mov     edi,[edi].pdev_pvBitmapStart
                   1251:         add     edi,ulMiddleDest
                   1252: 
                   1253:         SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide01,LOOP_UNROLL_SHIFT
                   1254: 
                   1255:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide01,W01,LOOP_UNROLL_COUNT
                   1256: 
                   1257: MONO_WIDE_01_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1258: &ENTRY_LABEL&ENTRY_INDEX&:
                   1259: 
                   1260:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1261: 
                   1262:         mov     ecx,cwMiddle
                   1263:         rep     stosw                           ;light 8 pels on every write
                   1264: 
                   1265:         inc     esi                             ;advance to next scan of pattern
                   1266:         and     esi,7
                   1267:         mov     [edi],al                        ;write that last byte
                   1268: 
                   1269:         add     edi,edx                         ;advance to next scan
                   1270:         endm    ;-----------------------------------;
                   1271: 
                   1272: ;  EBX = count of unrolled loop iterations
                   1273: ;  EDX = offset from end of scan to start of next
                   1274: ;  ESI = current offset into pattern
                   1275: ;  EDI = target address to which to write
                   1276: ;  ESP = pointer to start of pattern
                   1277: 
                   1278:         align   4
                   1279: dual_wide_01_w_loop:
                   1280:         UNROLL_LOOP     MONO_WIDE_01_W_M,W01,LOOP_UNROLL_COUNT
                   1281:         dec     ebx
                   1282:         jnz     short dual_wide_01_w_loop
                   1283: 
                   1284: ; get ready for next time:
                   1285: 
                   1286:         mov     ecx,ppdev
                   1287:         mov     esp,ulSaveEsp
                   1288:         sub     edi,[ecx].pdev_pvBitmapStart
                   1289:         mov     ulMiddleDest,edi
                   1290: 
                   1291:         PLAIN_RET
                   1292: 
                   1293: ;-----------------------------------------------------------------------;
                   1294: ; dual_wide_00_w
                   1295: ;
                   1296: ; Draws middle words with 0 leading bytes and 1 trailing byte.
                   1297: ;
                   1298: ; Input:
                   1299: ;     ppdev         - pointer to physical device structure
                   1300: ;     ulBlockHeight - # of scans to draw
                   1301: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1302: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1303: ;     yBrush        - current y brush alignment
                   1304: ;     cwMiddle      - # of words to draw on each scan
                   1305: ;
                   1306: ; Output:
                   1307: ;     esi           - new y brush alignment
                   1308: ;     ulMiddleDest  - new bitmap offset
                   1309: ;-----------------------------------------------------------------------;
                   1310: 
                   1311:         align   4
                   1312:         public  dual_wide_00_w
                   1313: dual_wide_00_w:
                   1314: 
                   1315: ; We only have to reset which planes are enabled if we do edges too:
                   1316: 
                   1317:         mov     edx,VGA_BASE + SEQ_DATA
                   1318:         mov     al,MM_ALL
                   1319:         out     dx,al
                   1320: 
                   1321: ; Calculate full start addresses:
                   1322: 
                   1323:         mov     ulSaveEsp,esp
                   1324:         mov     edi,ppdev
                   1325:         mov     ebx,ulBlockHeight
                   1326:         mov     esp,pulPattern
                   1327:         mov     edx,lMiddleDelta
                   1328:         mov     esi,yBrush
                   1329:         mov     edi,[edi].pdev_pvBitmapStart
                   1330:         add     edi,ulMiddleDest
                   1331: 
                   1332:         SET_UP_UNROLL_AND_BRANCH ebx,ecx,pfnMonoWide00,LOOP_UNROLL_SHIFT
                   1333: 
                   1334:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide00,W00,LOOP_UNROLL_COUNT
                   1335: 
                   1336: MONO_WIDE_00_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1337: &ENTRY_LABEL&ENTRY_INDEX&:
                   1338: 
                   1339:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1340: 
                   1341:         mov     ecx,cwMiddle
                   1342:         rep     stosw                           ;light 8 pels on every write
                   1343: 
                   1344:         inc     esi                             ;advance to next scan of pattern
                   1345:         and     esi,7
                   1346: 
                   1347:         add     edi,edx                         ;advance to next scan
                   1348:         endm    ;-----------------------------------;
                   1349: 
                   1350: ;  EBX = count of unrolled loop iterations
                   1351: ;  EDX = offset from end of scan to start of next
                   1352: ;  ESI = current offset into pattern
                   1353: ;  EDI = target address to which to write
                   1354: ;  ESP = pointer to start of pattern
                   1355: 
                   1356:         align   4
                   1357: dual_wide_00_w_loop:
                   1358:         UNROLL_LOOP     MONO_WIDE_00_W_M,W00,LOOP_UNROLL_COUNT
                   1359:         dec     ebx
                   1360:         jnz     short dual_wide_00_w_loop
                   1361: 
                   1362: ; get ready for next time:
                   1363: 
                   1364:         mov     ecx,ppdev
                   1365:         mov     esp,ulSaveEsp
                   1366:         sub     edi,[ecx].pdev_pvBitmapStart
                   1367:         mov     ulMiddleDest,edi
                   1368: 
                   1369:         PLAIN_RET
                   1370: 
                   1371: ;-----------------------------------------------------------------------;
                   1372: ; dual_left_1_w
                   1373: ;
                   1374: ; Draws a left edge when the next byte is not word aligned.
                   1375: ;
                   1376: ; Input:
                   1377: ;     ppdev         - pointer to physical device structure
                   1378: ;     ulBlockHeight - # of scans to draw
                   1379: ;     lDelta        - distance from end of current scan to start of next
                   1380: ;     ulLeftDest    - offset in bitmap at which to start drawing
                   1381: ;     yBrush        - current y brush alignment
                   1382: ;
                   1383: ; Output:
                   1384: ;     esi           - new y brush alignment
                   1385: ;     ulLeftDest    - new bitmap offset
                   1386: ;-----------------------------------------------------------------------;
                   1387: 
                   1388:         align   4
                   1389:         public  dual_left_1_w
                   1390: dual_left_1_w:
                   1391: 
                   1392: ; Set left mask by disabling some planes:
                   1393: 
                   1394:         mov     edx,VGA_BASE + SEQ_DATA
                   1395:         mov     eax,ulLeftMask
                   1396:         out     dx,al
                   1397: 
                   1398: ; Calculate full start addresses:
                   1399: 
                   1400:         mov     edi,ppdev
                   1401:         mov     ebx,ulBlockHeight
                   1402:         mov     ecx,pulPattern
                   1403:         mov     edx,lDelta
                   1404:         mov     esi,yBrush
                   1405:         mov     edi,[edi].pdev_pvBitmapStart
                   1406:         add     edi,ulLeftDest
                   1407: 
                   1408:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft1,LOOP_UNROLL_SHIFT
                   1409: 
                   1410:         UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft1,LEFT_W1,LOOP_UNROLL_COUNT
                   1411: 
                   1412: MONO_LEFT_1_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1413: &ENTRY_LABEL&ENTRY_INDEX&:
                   1414: 
                   1415:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   1416:         mov     [edi],al                        ;write the low byte
                   1417:         inc     esi                             ;advance to next scan of pattern
                   1418:         and     esi,7
                   1419:         add     edi,edx                         ;advance to next scan
                   1420:         endm    ;-----------------------------------;
                   1421: 
                   1422: ;  EBX = count of unrolled loop iterations
                   1423: ;  ECX = pointer to start of pattern
                   1424: ;  EDX = offset to next scan
                   1425: ;  ESI = current offset into pattern
                   1426: ;  EDI = target address to which to write
                   1427: 
                   1428:         align   4
                   1429: dual_left_1_w_loop:
                   1430:         UNROLL_LOOP     MONO_LEFT_1_W_M,LEFT_W1,LOOP_UNROLL_COUNT
                   1431:         dec     ebx
                   1432:         jnz     short dual_left_1_w_loop
                   1433: 
                   1434: ; get ready for next time:
                   1435: 
                   1436:         mov     ecx,ppdev
                   1437:         sub     edi,[ecx].pdev_pvBitmapStart
                   1438:         mov     ulLeftDest,edi
                   1439: 
                   1440:         PLAIN_RET
                   1441: 
                   1442: ;-----------------------------------------------------------------------;
                   1443: ; dual_left_0_w
                   1444: ;
                   1445: ; Draws a left edge when the next byte is word aligned.
                   1446: ;
                   1447: ; Input:
                   1448: ;     ppdev         - pointer to physical device structure
                   1449: ;     ulBlockHeight - # of scans to draw
                   1450: ;     lDelta        - distance from end of current scan to start of next
                   1451: ;     ulLeftDest    - offset in bitmap at which to start drawing
                   1452: ;     yBrush        - current y brush alignment
                   1453: ;
                   1454: ; Output:
                   1455: ;     esi           - new y brush alignment
                   1456: ;     ulLeftDest    - new bitmap offset
                   1457: ;-----------------------------------------------------------------------;
                   1458: 
                   1459:         align   4
                   1460:         public  dual_left_0_w
                   1461: dual_left_0_w:
                   1462: 
                   1463: ; Set left mask by disabling some planes:
                   1464: 
                   1465:         mov     edx,VGA_BASE + SEQ_DATA
                   1466:         mov     eax,ulLeftMask
                   1467:         out     dx,al
                   1468: 
                   1469: ; Calculate full start addresses:
                   1470: 
                   1471:         mov     edi,ppdev
                   1472:         mov     ebx,ulBlockHeight
                   1473:         mov     ecx,pulPattern
                   1474:         mov     edx,lDelta
                   1475:         mov     esi,yBrush
                   1476:         mov     edi,[edi].pdev_pvBitmapStart
                   1477:         add     edi,ulLeftDest
                   1478: 
                   1479:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft0,LOOP_UNROLL_SHIFT
                   1480: 
                   1481:         UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft0,LEFT_W0,LOOP_UNROLL_COUNT
                   1482: 
                   1483: MONO_LEFT_0_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1484: &ENTRY_LABEL&ENTRY_INDEX&:
                   1485: 
                   1486:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   1487:         mov     [edi],ah                        ;write the high byte
                   1488:         inc     esi                             ;advance to next scan of pattern
                   1489:         and     esi,7
                   1490:         add     edi,edx                         ;advance to next scan
                   1491:         endm    ;-----------------------------------;
                   1492: 
                   1493: ;  EBX = count of unrolled loop iterations
                   1494: ;  ECX = pointer to start of pattern
                   1495: ;  EDX = offset to next scan
                   1496: ;  ESI = current offset into pattern
                   1497: ;  EDI = target address to which to write
                   1498: 
                   1499:         align   4
                   1500: dual_left_0_w_loop:
                   1501:         UNROLL_LOOP     MONO_LEFT_0_W_M,LEFT_W0,LOOP_UNROLL_COUNT
                   1502:         dec     ebx
                   1503:         jnz     short dual_left_0_w_loop
                   1504: 
                   1505: ; get ready for next time:
                   1506: 
                   1507:         mov     ecx,ppdev
                   1508:         sub     edi,[ecx].pdev_pvBitmapStart
                   1509:         mov     ulLeftDest,edi
                   1510: 
                   1511:         PLAIN_RET
                   1512: 
                   1513: ;-----------------------------------------------------------------------;
                   1514: ; dual_right_1_w
                   1515: ;
                   1516: ; Draws a right edge when not word aligned.
                   1517: ;
                   1518: ; Input:
                   1519: ;     ppdev         - pointer to physical device structure
                   1520: ;     ulBlockHeight - # of scans to draw
                   1521: ;     lDelta        - distance from end of current scan to start of next
                   1522: ;     ulRightDest   - offset in bitmap at which to start drawing
                   1523: ;     yBrush        - current y brush alignment
                   1524: ;
                   1525: ; Output:
                   1526: ;     esi           - new y brush alignment
                   1527: ;     ulRightDest   - new bitmap offset
                   1528: ;-----------------------------------------------------------------------;
                   1529: 
                   1530:         align   4
                   1531:         public  dual_right_1_w
                   1532: dual_right_1_w:
                   1533: 
                   1534: ; Set right mask by disabling some planes:
                   1535: 
                   1536:         mov     edx,VGA_BASE + SEQ_DATA
                   1537:         mov     eax,ulRightMask
                   1538:         out     dx,al
                   1539: 
                   1540: ; Calculate full start addresses:
                   1541: 
                   1542:         mov     edi,ppdev
                   1543:         mov     ebx,ulBlockHeight
                   1544:         mov     ecx,pulPattern
                   1545:         mov     edx,lDelta
                   1546:         mov     esi,yBrush
                   1547:         mov     edi,[edi].pdev_pvBitmapStart
                   1548:         add     edi,ulRightDest
                   1549: 
                   1550:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight1,LOOP_UNROLL_SHIFT
                   1551: 
                   1552:         UNROLL_LOOP_ENTRY_TABLE pfnMonoRight1,RIGHT_W1,LOOP_UNROLL_COUNT
                   1553: 
                   1554: MONO_RIGHT_1_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1555: &ENTRY_LABEL&ENTRY_INDEX&:
                   1556: 
                   1557:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   1558:         mov     [edi],ah                        ;write the high byte
                   1559:         inc     esi                             ;advance to next scan of pattern
                   1560:         and     esi,7
                   1561:         add     edi,edx                         ;advance to next scan
                   1562:         endm    ;-----------------------------------;
                   1563: 
                   1564: ;  EBX = count of unrolled loop iterations
                   1565: ;  ECX = pointer to start of pattern
                   1566: ;  EDX = offset to next scan
                   1567: ;  ESI = current offset into pattern
                   1568: ;  EDI = target address to which to write
                   1569: 
                   1570:         align   4
                   1571: dual_right_1_w_loop:
                   1572:         UNROLL_LOOP     MONO_RIGHT_1_W_M,RIGHT_W1,LOOP_UNROLL_COUNT
                   1573:         dec     ebx
                   1574:         jnz     short dual_right_1_w_loop
                   1575: 
                   1576: ; get ready for next time:
                   1577: 
                   1578:         mov     ecx,ppdev
                   1579:         sub     edi,[ecx].pdev_pvBitmapStart
                   1580:         mov     ulRightDest,edi
                   1581: 
                   1582:         PLAIN_RET
                   1583: 
                   1584: ;-----------------------------------------------------------------------;
                   1585: ; dual_right_0_w
                   1586: ;
                   1587: ; Draws a right edge when word aligned.
                   1588: ;
                   1589: ; Input:
                   1590: ;     ppdev         - pointer to physical device structure
                   1591: ;     ulBlockHeight - # of scans to draw
                   1592: ;     lDelta        - distance from end of current scan to start of next
                   1593: ;     ulRightDest   - offset in bitmap at which to start drawing
                   1594: ;     yBrush        - current y brush alignment
                   1595: ;
                   1596: ; Output:
                   1597: ;     esi           - new y brush alignment
                   1598: ;     ulRightDest   - new bitmap offset
                   1599: ;-----------------------------------------------------------------------;
                   1600: 
                   1601:         align   4
                   1602:         public  dual_right_0_w
                   1603: dual_right_0_w:
                   1604: 
                   1605: ; Set right mask by disabling some planes:
                   1606: 
                   1607:         mov     edx,VGA_BASE + SEQ_DATA
                   1608:         mov     eax,ulRightMask
                   1609:         out     dx,al
                   1610: 
                   1611: ; Calculate full start addresses:
                   1612: 
                   1613:         mov     edi,ppdev
                   1614:         mov     ebx,ulBlockHeight
                   1615:         mov     ecx,pulPattern
                   1616:         mov     edx,lDelta
                   1617:         mov     esi,yBrush
                   1618:         mov     edi,[edi].pdev_pvBitmapStart
                   1619:         add     edi,ulRightDest
                   1620: 
                   1621:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight0,LOOP_UNROLL_SHIFT
                   1622: 
                   1623:         UNROLL_LOOP_ENTRY_TABLE pfnMonoRight0,RIGHT_W0,LOOP_UNROLL_COUNT
                   1624: 
                   1625: MONO_RIGHT_0_W_M macro ENTRY_LABEL,ENTRY_INDEX
                   1626: &ENTRY_LABEL&ENTRY_INDEX&:
                   1627: 
                   1628:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   1629:         mov     [edi],al                        ;write the low byte
                   1630:         inc     esi                             ;advance to next scan of pattern
                   1631:         and     esi,7
                   1632:         add     edi,edx                         ;advance to next scan
                   1633:         endm    ;-----------------------------------;
                   1634: 
                   1635: ;  EBX = count of unrolled loop iterations
                   1636: ;  ECX = pointer to start of pattern
                   1637: ;  EDX = offset to next scan
                   1638: ;  ESI = current offset into pattern
                   1639: ;  EDI = target address to which to write
                   1640: 
                   1641:         align   4
                   1642: dual_right_0_w_loop:
                   1643:         UNROLL_LOOP     MONO_RIGHT_0_W_M,RIGHT_W0,LOOP_UNROLL_COUNT
                   1644:         dec     ebx
                   1645:         jnz     short dual_right_0_w_loop
                   1646: 
                   1647: ; get ready for next time:
                   1648: 
                   1649:         mov     ecx,ppdev
                   1650:         sub     edi,[ecx].pdev_pvBitmapStart
                   1651:         mov     ulRightDest,edi
                   1652: 
                   1653:         PLAIN_RET
                   1654: 
                   1655: ;=======================================================================;
                   1656: ;========================= ROP Block Drawers ===========================;
                   1657: ;=======================================================================;
                   1658: 
                   1659: ;-----------------------------------------------------------------------;
                   1660: ; dual_wide_11_rw
                   1661: ;
                   1662: ; Draws middle words with 1 leading byte and 1 trailing byte.
                   1663: ;
                   1664: ; Input:
                   1665: ;     ppdev         - pointer to physical device structure
                   1666: ;     ulBlockHeight - # of scans to draw
                   1667: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1668: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1669: ;     yBrush        - current y brush alignment
                   1670: ;     cwMiddle      - # of words to draw on each scan
                   1671: ;
                   1672: ; Output:
                   1673: ;     esi           - new y brush alignment
                   1674: ;     ulMiddleDest  - new bitmap offset
                   1675: ;-----------------------------------------------------------------------;
                   1676: 
                   1677:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_11,RW11,LOOP_UNROLL_COUNT
                   1678: 
                   1679:         align   4
                   1680:         public  dual_wide_11_rw
                   1681: dual_wide_11_rw:
                   1682: 
                   1683: ; We only have to reset which planes are enabled if we do edges too:
                   1684: 
                   1685:         mov     edx,VGA_BASE + SEQ_DATA
                   1686:         mov     al,MM_ALL
                   1687:         out     dx,al
                   1688: 
                   1689:         mov     ulSaveEsp,esp
                   1690:         mov     edi,ppdev
                   1691: 
                   1692:         mov     esp,pulPattern                  ;load those registers
                   1693:         mov     edi,[edi].pdev_pvBitmapStart
                   1694:         add     edi,ulMiddleDest
                   1695:         mov     esi,yBrush
                   1696:         mov     edx,ulBlockHeight
                   1697:         mov     ebx,cwMiddle
                   1698: 
                   1699:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1700:         inc     esi
                   1701:         and     esi,7
                   1702: 
                   1703:         SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_11,LOOP_UNROLL_SHIFT
                   1704: 
                   1705:         mov     pfnUnroll,ecx
                   1706:         mov     cUnrolledLoops,ebx
                   1707: 
                   1708:         jmp     ecx
                   1709: 
                   1710: MONO_RWIDE_11_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   1711: &ENTRY_LABEL&ENTRY_INDEX&:
                   1712:         and     [edi],ah
                   1713:         and     [edi+1],al
                   1714:         add     edi,2                           ;the write will overlap this
                   1715:         endm    ;-----------------------------------;
                   1716: 
                   1717: ;  EAX = pattern for this scan
                   1718: ;  EBX = count of unrolled loop iterations
                   1719: ;  EDX = number of scans to do
                   1720: ;  ESI = current offset into pattern
                   1721: ;  EDI = target address to which to write
                   1722: ;  ESP = pointer to start of pattern
                   1723: 
                   1724:         align   4
                   1725: dual_wide_11_rw_loop:
                   1726:         UNROLL_LOOP     MONO_RWIDE_11_RW_M,RW11,LOOP_UNROLL_COUNT
                   1727:         dec     ebx
                   1728:         jnz     short dual_wide_11_rw_loop
                   1729: 
                   1730:         add     edi,lMiddleDelta
                   1731:         dec     edx
                   1732:         jz      short dual_wide_11_rw_done
                   1733: 
                   1734:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1735:         inc     esi
                   1736:         and     esi,7
                   1737: 
                   1738:         mov     ebx,cUnrolledLoops
                   1739:         jmp     pfnUnroll
                   1740: 
                   1741: dual_wide_11_rw_done:
                   1742:         mov     ecx,ppdev
                   1743:         mov     esp,ulSaveEsp
                   1744:         sub     edi,[ecx].pdev_pvBitmapStart
                   1745:         mov     ulMiddleDest,edi
                   1746: 
                   1747:         PLAIN_RET
                   1748: 
                   1749: ;-----------------------------------------------------------------------;
                   1750: ; dual_wide_10_rw
                   1751: ;
                   1752: ; Draws middle words with 1 leading byte and 0 trailing bytes.
                   1753: ;
                   1754: ; Input:
                   1755: ;     ppdev         - pointer to physical device structure
                   1756: ;     ulBlockHeight - # of scans to draw
                   1757: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1758: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1759: ;     yBrush        - current y brush alignment
                   1760: ;     cwMiddle      - # of words to draw on each scan
                   1761: ;
                   1762: ; Output:
                   1763: ;     esi           - new y brush alignment
                   1764: ;     ulMiddleDest  - new bitmap offset
                   1765: ;-----------------------------------------------------------------------;
                   1766: 
                   1767:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_10,RW10,LOOP_UNROLL_COUNT
                   1768: 
                   1769:         align   4
                   1770:         public  dual_wide_10_rw
                   1771: dual_wide_10_rw:
                   1772: 
                   1773: ; We only have to reset which planes are enabled if we do edges too:
                   1774: 
                   1775:         mov     edx,VGA_BASE + SEQ_DATA
                   1776:         mov     al,MM_ALL
                   1777:         out     dx,al
                   1778: 
                   1779:         mov     ulSaveEsp,esp
                   1780:         mov     edi,ppdev
                   1781: 
                   1782:         mov     esp,pulPattern                  ;load those registers
                   1783:         mov     edi,[edi].pdev_pvBitmapStart
                   1784:         add     edi,ulMiddleDest
                   1785:         mov     esi,yBrush
                   1786:         mov     edx,ulBlockHeight
                   1787:         mov     ebx,cwMiddle
                   1788: 
                   1789:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1790:         inc     esi
                   1791:         and     esi,7
                   1792: 
                   1793:         or      ebx,ebx                         ;have to watch for zero words
                   1794:         jz      short dual_wide_10_rw_only_one_byte
                   1795: 
                   1796:         SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_10,LOOP_UNROLL_SHIFT
                   1797: 
                   1798:         mov     pfnUnroll,ecx
                   1799:         mov     cUnrolledLoops,ebx
                   1800: 
                   1801:         jmp     ecx
                   1802: 
                   1803: dual_wide_10_rw_only_one_byte:
                   1804:         mov     pfnUnroll,offset dual_wide_10_rw_odd_byte
                   1805:         jmp     short dual_wide_10_rw_odd_byte
                   1806: 
                   1807: MONO_RWIDE_10_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   1808: &ENTRY_LABEL&ENTRY_INDEX&:
                   1809:         and     [edi],ah
                   1810:         and     [edi+1],al
                   1811:         add     edi,2                           ;the write will overlap this
                   1812:         endm    ;-----------------------------------;
                   1813: 
                   1814: ;  EAX = pattern for this scan
                   1815: ;  EBX = count of unrolled loop iterations
                   1816: ;  EDX = number of scans to do
                   1817: ;  ESI = current offset into pattern
                   1818: ;  EDI = target address to which to write
                   1819: ;  ESP = pointer to start of pattern
                   1820: 
                   1821:         align   4
                   1822: dual_wide_10_rw_loop:
                   1823:         UNROLL_LOOP     MONO_RWIDE_10_RW_M,RW10,LOOP_UNROLL_COUNT
                   1824:         dec     ebx
                   1825:         jnz     short dual_wide_10_rw_loop
                   1826: 
                   1827: dual_wide_10_rw_odd_byte:
                   1828:         and     [edi],ah                        ;write that odd byte
                   1829: 
                   1830:         add     edi,lMiddleDelta
                   1831:         dec     edx
                   1832:         jz      short dual_wide_10_rw_done
                   1833: 
                   1834:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1835:         inc     esi
                   1836:         and     esi,7
                   1837: 
                   1838:         mov     ebx,cUnrolledLoops
                   1839:         jmp     pfnUnroll
                   1840: 
                   1841: dual_wide_10_rw_done:
                   1842:         mov     ecx,ppdev
                   1843:         mov     esp,ulSaveEsp
                   1844:         sub     edi,[ecx].pdev_pvBitmapStart
                   1845:         mov     ulMiddleDest,edi
                   1846: 
                   1847:         PLAIN_RET
                   1848: 
                   1849: ;-----------------------------------------------------------------------;
                   1850: ; dual_wide_01_rw
                   1851: ;
                   1852: ; Draws middle words with 0 leading bytes and 1 trailing byte.
                   1853: ;
                   1854: ; Input:
                   1855: ;     ppdev         - pointer to physical device structure
                   1856: ;     ulBlockHeight - # of scans to draw
                   1857: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1858: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1859: ;     yBrush        - current y brush alignment
                   1860: ;     cwMiddle      - # of words to draw on each scan
                   1861: ;
                   1862: ; Output:
                   1863: ;     esi           - new y brush alignment
                   1864: ;     ulMiddleDest  - new bitmap offset
                   1865: ;-----------------------------------------------------------------------;
                   1866: 
                   1867:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_01,RW01,LOOP_UNROLL_COUNT
                   1868: 
                   1869:         align   4
                   1870:         public  dual_wide_01_rw
                   1871: dual_wide_01_rw:
                   1872: 
                   1873: ; We only have to reset which planes are enabled if we do edges too:
                   1874: 
                   1875:         mov     edx,VGA_BASE + SEQ_DATA
                   1876:         mov     al,MM_ALL
                   1877:         out     dx,al
                   1878: 
                   1879:         mov     ulSaveEsp,esp
                   1880:         mov     edi,ppdev
                   1881: 
                   1882:         mov     esp,pulPattern                  ;load those registers
                   1883:         mov     edi,[edi].pdev_pvBitmapStart
                   1884:         add     edi,ulMiddleDest
                   1885:         mov     esi,yBrush
                   1886:         mov     edx,ulBlockHeight
                   1887:         mov     ebx,cwMiddle
                   1888: 
                   1889:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1890:         inc     esi
                   1891:         and     esi,7
                   1892: 
                   1893:         or      ebx,ebx
                   1894:         jz      short dual_wide_01_rw_only_one_byte
                   1895: 
                   1896:         SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_01,LOOP_UNROLL_SHIFT
                   1897: 
                   1898:         mov     pfnUnroll,ecx
                   1899:         mov     cUnrolledLoops,ebx
                   1900: 
                   1901:         jmp     ecx
                   1902: 
                   1903: dual_wide_01_rw_only_one_byte:
                   1904:         mov     pfnUnroll,offset dual_wide_01_rw_odd_byte
                   1905:         jmp     short dual_wide_01_rw_odd_byte
                   1906: 
                   1907: MONO_RWIDE_01_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   1908: &ENTRY_LABEL&ENTRY_INDEX&:
                   1909:         and     [edi],al
                   1910:         and     [edi+1],ah
                   1911:         add     edi,2                           ;the write will overlap this
                   1912:         endm    ;-----------------------------------;
                   1913: 
                   1914: ;  EAX = pattern for this scan
                   1915: ;  EBX = count of unrolled loop iterations
                   1916: ;  EDX = number of scans to do
                   1917: ;  ESI = current offset into pattern
                   1918: ;  EDI = target address to which to write
                   1919: ;  ESP = pointer to start of pattern
                   1920: 
                   1921:         align   4
                   1922: dual_wide_01_rw_loop:
                   1923:         UNROLL_LOOP     MONO_RWIDE_01_RW_M,RW01,LOOP_UNROLL_COUNT
                   1924:         dec     ebx
                   1925:         jnz     short dual_wide_01_rw_loop
                   1926: 
                   1927: dual_wide_01_rw_odd_byte:
                   1928:         and     [edi],al                        ;write that odd byte
                   1929: 
                   1930:         add     edi,lMiddleDelta
                   1931:         dec     edx
                   1932:         jz      short dual_wide_01_rw_done
                   1933: 
                   1934:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1935:         inc     esi
                   1936:         and     esi,7
                   1937: 
                   1938:         mov     ebx,cUnrolledLoops
                   1939:         jmp     pfnUnroll
                   1940: 
                   1941: dual_wide_01_rw_done:
                   1942:         mov     ecx,ppdev
                   1943:         mov     esp,ulSaveEsp
                   1944:         sub     edi,[ecx].pdev_pvBitmapStart
                   1945:         mov     ulMiddleDest,edi
                   1946: 
                   1947:         PLAIN_RET
                   1948: 
                   1949: ;-----------------------------------------------------------------------;
                   1950: ; dual_wide_00_rw
                   1951: ;
                   1952: ; Draws middle words with 0 leading bytes and 0 trailing bytes.
                   1953: ;
                   1954: ; Input:
                   1955: ;     ppdev         - pointer to physical device structure
                   1956: ;     ulBlockHeight - # of scans to draw
                   1957: ;     lMiddleDelta  - distance from end of current scan to start of next
                   1958: ;     ulMiddleDest  - offset in bitmap at which to start drawing
                   1959: ;     yBrush        - current y brush alignment
                   1960: ;     cwMiddle      - # of words to draw on each scan
                   1961: ;
                   1962: ; Output:
                   1963: ;     esi           - new y brush alignment
                   1964: ;     ulMiddleDest  - new bitmap offset
                   1965: ;-----------------------------------------------------------------------;
                   1966: 
                   1967:         UNROLL_LOOP_ENTRY_TABLE pfnMonoWide_rw_00,RW00,LOOP_UNROLL_COUNT
                   1968: 
                   1969:         align   4
                   1970:         public  dual_wide_00_rw
                   1971: dual_wide_00_rw:
                   1972: 
                   1973: ; We only have to reset which planes are enabled if we do edges too:
                   1974: 
                   1975:         mov     edx,VGA_BASE + SEQ_DATA
                   1976:         mov     al,MM_ALL
                   1977:         out     dx,al
                   1978: 
                   1979:         mov     ulSaveEsp,esp
                   1980:         mov     edi,ppdev
                   1981: 
                   1982:         mov     esp,pulPattern                  ;load those registers
                   1983:         mov     edi,[edi].pdev_pvBitmapStart
                   1984:         add     edi,ulMiddleDest
                   1985:         mov     esi,yBrush
                   1986:         mov     edx,ulBlockHeight
                   1987:         mov     ebx,cwMiddle
                   1988: 
                   1989:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   1990:         inc     esi
                   1991:         and     esi,7
                   1992: 
                   1993:         SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnMonoWide_rw_00,LOOP_UNROLL_SHIFT
                   1994: 
                   1995:         mov     pfnUnroll,ecx
                   1996:         mov     cUnrolledLoops,ebx
                   1997: 
                   1998:         jmp     ecx
                   1999: 
                   2000: MONO_RWIDE_00_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   2001: &ENTRY_LABEL&ENTRY_INDEX&:
                   2002:         and     [edi],al
                   2003:         and     [edi+1],ah
                   2004:         add     edi,2                           ;the write will overlap this
                   2005:         endm    ;-----------------------------------;
                   2006: 
                   2007: ;  EAX = pattern for this scan
                   2008: ;  EBX = count of unrolled loop iterations
                   2009: ;  EDX = number of scans to do
                   2010: ;  ESI = current offset into pattern
                   2011: ;  EDI = target address to which to write
                   2012: ;  ESP = pointer to start of pattern
                   2013: 
                   2014:         align   4
                   2015: dual_wide_00_rw_loop:
                   2016:         UNROLL_LOOP     MONO_RWIDE_00_RW_M,RW00,LOOP_UNROLL_COUNT
                   2017:         dec     ebx
                   2018:         jnz     short dual_wide_00_rw_loop
                   2019: 
                   2020:         add     edi,lMiddleDelta
                   2021:         dec     edx
                   2022:         jz      short dual_wide_00_rw_done
                   2023: 
                   2024:         mov     eax,[esp+esi*4]                 ;load pattern for this scan
                   2025:         inc     esi
                   2026:         and     esi,7
                   2027: 
                   2028:         mov     ebx,cUnrolledLoops
                   2029:         jmp     pfnUnroll
                   2030: 
                   2031: dual_wide_00_rw_done:
                   2032:         mov     ecx,ppdev
                   2033:         mov     esp,ulSaveEsp
                   2034:         sub     edi,[ecx].pdev_pvBitmapStart
                   2035:         mov     ulMiddleDest,edi
                   2036: 
                   2037:         PLAIN_RET
                   2038: 
                   2039: ;-----------------------------------------------------------------------;
                   2040: ; dual_left_1_rw
                   2041: ;
                   2042: ; Draws a left edge when the next byte is not word aligned.
                   2043: ;
                   2044: ; Input:
                   2045: ;     ppdev         - pointer to physical device structure
                   2046: ;     ulBlockHeight - # of scans to draw
                   2047: ;     lDelta        - distance from end of current scan to start of next
                   2048: ;     ulLeftDest    - offset in bitmap at which to start drawing
                   2049: ;     yBrush        - current y brush alignment
                   2050: ;
                   2051: ; Output:
                   2052: ;     esi           - new y brush alignment
                   2053: ;     ulLeftDest    - new bitmap offset
                   2054: ;-----------------------------------------------------------------------;
                   2055: 
                   2056:         align   4
                   2057:         public  dual_left_1_rw
                   2058: dual_left_1_rw:
                   2059: 
                   2060: ; Set left mask by disabling some planes:
                   2061: 
                   2062:         mov     edx,VGA_BASE + SEQ_DATA
                   2063:         mov     eax,ulLeftMask
                   2064:         out     dx,al
                   2065: 
                   2066: ; Calculate full start addresses:
                   2067: 
                   2068:         mov     edi,ppdev
                   2069:         mov     ebx,ulBlockHeight
                   2070:         mov     ecx,pulPattern
                   2071:         mov     edx,lDelta
                   2072:         mov     esi,yBrush
                   2073:         mov     edi,[edi].pdev_pvBitmapStart
                   2074:         add     edi,ulLeftDest
                   2075: 
                   2076:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft_rw_1,LOOP_UNROLL_SHIFT
                   2077: 
                   2078:         UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft_rw_1,LEFT_RW1,LOOP_UNROLL_COUNT
                   2079: 
                   2080: MONO_LEFT_1_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   2081: &ENTRY_LABEL&ENTRY_INDEX&:
                   2082: 
                   2083:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   2084:         and     [edi],al                        ;write the low byte
                   2085:         inc     esi                             ;advance to next scan of pattern
                   2086:         and     esi,7
                   2087:         add     edi,edx                         ;advance to next scan
                   2088:         endm    ;-----------------------------------;
                   2089: 
                   2090: ;  EBX = count of unrolled loop iterations
                   2091: ;  ECX = pointer to start of pattern
                   2092: ;  EDX = offset to next scan
                   2093: ;  ESI = current offset into pattern
                   2094: ;  EDI = target address to which to write
                   2095: 
                   2096:         align   4
                   2097: dual_left_1_rw_loop:
                   2098:         UNROLL_LOOP     MONO_LEFT_1_RW_M,LEFT_RW1,LOOP_UNROLL_COUNT
                   2099:         dec     ebx
                   2100:         jnz     short dual_left_1_rw_loop
                   2101: 
                   2102: ; get ready for next time:
                   2103: 
                   2104:         mov     ecx,ppdev
                   2105:         sub     edi,[ecx].pdev_pvBitmapStart
                   2106:         mov     ulLeftDest,edi
                   2107: 
                   2108:         PLAIN_RET
                   2109: 
                   2110: ;-----------------------------------------------------------------------;
                   2111: ; dual_left_0_rw
                   2112: ;
                   2113: ; Draws a left edge when the next byte is word aligned.
                   2114: ;
                   2115: ; Input:
                   2116: ;     ppdev         - pointer to physical device structure
                   2117: ;     ulBlockHeight - # of scans to draw
                   2118: ;     lDelta        - distance from end of current scan to start of next
                   2119: ;     ulLeftDest    - offset in bitmap at which to start drawing
                   2120: ;     yBrush        - current y brush alignment
                   2121: ;
                   2122: ; Output:
                   2123: ;     esi           - new y brush alignment
                   2124: ;     ulLeftDest    - new bitmap offset
                   2125: ;-----------------------------------------------------------------------;
                   2126: 
                   2127:         align   4
                   2128:         public  dual_left_0_rw
                   2129: dual_left_0_rw:
                   2130: 
                   2131: ; Set left mask by disabling some planes:
                   2132: 
                   2133:         mov     edx,VGA_BASE + SEQ_DATA
                   2134:         mov     eax,ulLeftMask
                   2135:         out     dx,al
                   2136: 
                   2137: ; Calculate full start addresses:
                   2138: 
                   2139:         mov     edi,ppdev
                   2140:         mov     ebx,ulBlockHeight
                   2141:         mov     ecx,pulPattern
                   2142:         mov     edx,lDelta
                   2143:         mov     esi,yBrush
                   2144:         mov     edi,[edi].pdev_pvBitmapStart
                   2145:         add     edi,ulLeftDest
                   2146: 
                   2147:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoLeft_rw_0,LOOP_UNROLL_SHIFT
                   2148: 
                   2149:         UNROLL_LOOP_ENTRY_TABLE pfnMonoLeft_rw_0,LEFT_RW0,LOOP_UNROLL_COUNT
                   2150: 
                   2151: MONO_LEFT_0_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   2152: &ENTRY_LABEL&ENTRY_INDEX&:
                   2153: 
                   2154:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   2155:         and     [edi],ah                        ;write the high byte
                   2156:         inc     esi                             ;advance to next scan of pattern
                   2157:         and     esi,7
                   2158:         add     edi,edx                         ;advance to next scan
                   2159:         endm    ;-----------------------------------;
                   2160: 
                   2161: ;  EBX = count of unrolled loop iterations
                   2162: ;  ECX = pointer to start of pattern
                   2163: ;  EDX = offset to next scan
                   2164: ;  ESI = current offset into pattern
                   2165: ;  EDI = target address to which to write
                   2166: 
                   2167:         align   4
                   2168: dual_left_0_rw_loop:
                   2169:         UNROLL_LOOP     MONO_LEFT_0_RW_M,LEFT_RW0,LOOP_UNROLL_COUNT
                   2170:         dec     ebx
                   2171:         jnz     short dual_left_0_rw_loop
                   2172: 
                   2173: ; get ready for next time:
                   2174: 
                   2175:         mov     ecx,ppdev
                   2176:         sub     edi,[ecx].pdev_pvBitmapStart
                   2177:         mov     ulLeftDest,edi
                   2178: 
                   2179:         PLAIN_RET
                   2180: 
                   2181: ;-----------------------------------------------------------------------;
                   2182: ; dual_right_1_rw
                   2183: ;
                   2184: ; Draws a right edge when not word aligned.
                   2185: ;
                   2186: ; Input:
                   2187: ;     ppdev         - pointer to physical device structure
                   2188: ;     ulBlockHeight - # of scans to draw
                   2189: ;     lDelta        - distance from end of current scan to start of next
                   2190: ;     ulRightDest   - offset in bitmap at which to start drawing
                   2191: ;     yBrush        - current y brush alignment
                   2192: ;
                   2193: ; Output:
                   2194: ;     esi           - new y brush alignment
                   2195: ;     ulRightDest   - new bitmap offset
                   2196: ;-----------------------------------------------------------------------;
                   2197: 
                   2198:         align   4
                   2199:         public  dual_right_1_rw
                   2200: dual_right_1_rw:
                   2201: 
                   2202: ; Set right mask by disabling some planes:
                   2203: 
                   2204:         mov     edx,VGA_BASE + SEQ_DATA
                   2205:         mov     eax,ulRightMask
                   2206:         out     dx,al
                   2207: 
                   2208: ; Calculate full start addresses:
                   2209: 
                   2210:         mov     edi,ppdev
                   2211:         mov     ebx,ulBlockHeight
                   2212:         mov     ecx,pulPattern
                   2213:         mov     edx,lDelta
                   2214:         mov     esi,yBrush
                   2215:         mov     edi,[edi].pdev_pvBitmapStart
                   2216:         add     edi,ulRightDest
                   2217: 
                   2218:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight_rw_1,LOOP_UNROLL_SHIFT
                   2219: 
                   2220:         UNROLL_LOOP_ENTRY_TABLE pfnMonoRight_rw_1,RIGHT_RW1,LOOP_UNROLL_COUNT
                   2221: 
                   2222: MONO_RIGHT_1_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   2223: &ENTRY_LABEL&ENTRY_INDEX&:
                   2224: 
                   2225:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   2226:         and     [edi],ah                        ;write the high byte
                   2227:         inc     esi                             ;advance to next scan of pattern
                   2228:         and     esi,7
                   2229:         add     edi,edx                         ;advance to next scan
                   2230:         endm    ;-----------------------------------;
                   2231: 
                   2232: ;  EBX = count of unrolled loop iterations
                   2233: ;  ECX = pointer to start of pattern
                   2234: ;  EDX = offset to next scan
                   2235: ;  ESI = current offset into pattern
                   2236: ;  EDI = target address to which to write
                   2237: 
                   2238:         align   4
                   2239: dual_right_1_rw_loop:
                   2240:         UNROLL_LOOP     MONO_RIGHT_1_RW_M,RIGHT_RW1,LOOP_UNROLL_COUNT
                   2241:         dec     ebx
                   2242:         jnz     short dual_right_1_rw_loop
                   2243: 
                   2244: ; get ready for next time:
                   2245: 
                   2246:         mov     ecx,ppdev
                   2247:         sub     edi,[ecx].pdev_pvBitmapStart
                   2248:         mov     ulRightDest,edi
                   2249: 
                   2250:         PLAIN_RET
                   2251: 
                   2252: ;-----------------------------------------------------------------------;
                   2253: ; dual_right_0_rw
                   2254: ;
                   2255: ; Draws a right edge when word aligned.
                   2256: ;
                   2257: ; Input:
                   2258: ;     ppdev         - pointer to physical device structure
                   2259: ;     ulBlockHeight - # of scans to draw
                   2260: ;     lDelta        - distance from end of current scan to start of next
                   2261: ;     ulRightDest   - offset in bitmap at which to start drawing
                   2262: ;     yBrush        - current y brush alignment
                   2263: ;
                   2264: ; Output:
                   2265: ;     esi           - new y brush alignment
                   2266: ;     ulRightDest   - new bitmap offset
                   2267: ;-----------------------------------------------------------------------;
                   2268: 
                   2269:         align   4
                   2270:         public  dual_right_0_rw
                   2271: dual_right_0_rw:
                   2272: 
                   2273: ; Set right mask by disabling some planes:
                   2274: 
                   2275:         mov     edx,VGA_BASE + SEQ_DATA
                   2276:         mov     eax,ulRightMask
                   2277:         out     dx,al
                   2278: 
                   2279: ; Calculate full start addresses:
                   2280: 
                   2281:         mov     edi,ppdev
                   2282:         mov     ebx,ulBlockHeight
                   2283:         mov     ecx,pulPattern
                   2284:         mov     edx,lDelta
                   2285:         mov     esi,yBrush
                   2286:         mov     edi,[edi].pdev_pvBitmapStart
                   2287:         add     edi,ulRightDest
                   2288: 
                   2289:         SET_UP_UNROLL_AND_BRANCH ebx,eax,pfnMonoRight_rw_0,LOOP_UNROLL_SHIFT
                   2290: 
                   2291:         UNROLL_LOOP_ENTRY_TABLE pfnMonoRight_rw_0,RIGHT_RW0,LOOP_UNROLL_COUNT
                   2292: 
                   2293: MONO_RIGHT_0_RW_M macro ENTRY_LABEL,ENTRY_INDEX
                   2294: &ENTRY_LABEL&ENTRY_INDEX&:
                   2295: 
                   2296:         mov     eax,[ecx+esi*4]                 ;load pattern for this scan
                   2297:         and     [edi],al                        ;write the low byte
                   2298:         inc     esi                             ;advance to next scan of pattern
                   2299:         and     esi,7
                   2300:         add     edi,edx                         ;advance to next scan
                   2301:         endm    ;-----------------------------------;
                   2302: 
                   2303: ;  EBX = count of unrolled loop iterations
                   2304: ;  ECX = pointer to start of pattern
                   2305: ;  EDX = offset to next scan
                   2306: ;  ESI = current offset into pattern
                   2307: ;  EDI = target address to which to write
                   2308: 
                   2309:         align   4
                   2310: dual_right_0_rw_loop:
                   2311:         UNROLL_LOOP     MONO_RIGHT_0_RW_M,RIGHT_RW0,LOOP_UNROLL_COUNT
                   2312:         dec     ebx
                   2313:         jnz     short dual_right_0_rw_loop
                   2314: 
                   2315: ; get ready for next time:
                   2316: 
                   2317:         mov     ecx,ppdev
                   2318:         sub     edi,[ecx].pdev_pvBitmapStart
                   2319:         mov     ulRightDest,edi
                   2320: 
                   2321:         PLAIN_RET
                   2322: 
                   2323: ;-----------------------------------------------------------------------;
                   2324: 
                   2325: endProc vMonoPat
                   2326: 
                   2327: ;-----------------------------------------------------------------------;
                   2328: ; BOOL b2ColorBrush(pjBits, pjFgColor, pjBkColor)
                   2329: ;
                   2330: ; Determines if the 8x8x8bpp packed brush pointed to by pjBits has only
                   2331: ; two colors, and if so returns the 1bpp bitmap.
                   2332: ;
                   2333: ; Returns:
                   2334: ;       eax        = 1 if two (or one) color brush, 0 otherwise
                   2335: ;       pjBits     = pointer to packed 1bpp bitmap if a 2-color brush
                   2336: ;       *pjFgColor = foreground color for returned 1bpp bitmap (i.e.,
                   2337: ;                       used to color-expand '1' bits)
                   2338: ;       *pjBkColor = backgroun color for returned 1bpp bitmap (i.e.,
                   2339: ;                       used to color-expand '0' bits)
                   2340: ;-----------------------------------------------------------------------;
                   2341: 
                   2342: cProc   b2ColorBrush,12,<     \
                   2343:         uses esi edi ebx,     \
                   2344:         pjBits:    ptr BYTE,  \
                   2345:         pjFgColor: ptr BYTE,  \
                   2346:         pjBkColor: ptr BYTE   >
                   2347: 
                   2348: ; al = first color
                   2349: ; ah = second color
                   2350: ; ecx = number of unrolled loops
                   2351: 
                   2352:         mov     esi,pjBits
                   2353:         mov     ecx,(BRUSH_SIZE shr 1)
                   2354:         mov     al,[esi]
                   2355: 
                   2356:         align   4
                   2357: b2col_find_2nd_color_loop:
                   2358:         mov     ah,[esi+1]
                   2359:         cmp     ah,al
                   2360:         jne     short b2col_find_consecutive_2nd_color_loop_part_1
                   2361: 
                   2362:         add     esi,2
                   2363:         dec     ecx
                   2364:         jz      short b2col_is_2_colors ;actually, it's only one color
                   2365: 
                   2366:         mov     ah,[esi]
                   2367:         cmp     ah,al
                   2368:         jne     short b2col_find_consecutive_2nd_color_loop_part_2
                   2369:         jmp     short b2col_find_2nd_color_loop
                   2370: 
                   2371: ;------------------------------------;
                   2372: 
                   2373:         align   4
                   2374: b2col_find_consecutive_1st_color_loop_part_1:
                   2375:         add     esi,2
                   2376:         dec     ecx
                   2377:         jz      short b2col_is_2_colors
                   2378: 
                   2379:         mov     bl,[esi]
                   2380:         cmp     bl,ah
                   2381:         je      short b2col_find_consecutive_2nd_color_loop_part_2
                   2382:         cmp     bl,al
                   2383:         jne     short b2col_isnt_2_colors
                   2384: 
                   2385: b2col_find_consecutive_1st_color_loop_part_2:
                   2386:         mov     bl,[esi+1]
                   2387:         cmp     bl,ah
                   2388:         je      short b2col_find_consecutive_2nd_color_loop_part_1
                   2389:         cmp     bl,al
                   2390:         je      short b2col_find_consecutive_1st_color_loop_part_1
                   2391: 
                   2392:         xor     eax,eax
                   2393:         cRet    b2ColorBrush            ;return FALSE
                   2394: 
                   2395: ;------------------------------------;
                   2396: 
                   2397:         align   4
                   2398: b2col_find_consecutive_2nd_color_loop_part_1:
                   2399:         add     esi,2
                   2400:         dec     ecx
                   2401:         jz      short b2col_is_2_colors
                   2402: 
                   2403:         mov     bl,[esi]
                   2404:         cmp     bl,al
                   2405:         je      short b2col_find_consecutive_1st_color_loop_part_2
                   2406:         cmp     bl,ah
                   2407:         jne     short b2col_isnt_2_colors
                   2408: 
                   2409: b2col_find_consecutive_2nd_color_loop_part_2:
                   2410:         mov     bl,[esi+1]
                   2411:         cmp     bl,al
                   2412:         je      short b2col_find_consecutive_1st_color_loop_part_1
                   2413:         cmp     bl,ah
                   2414:         je      short b2col_find_consecutive_2nd_color_loop_part_1
                   2415: 
                   2416: b2col_isnt_2_colors:
                   2417:         xor     eax,eax
                   2418:         cRet    b2ColorBrush            ;return FALSE
                   2419: 
                   2420: ;------------------------------------;
                   2421: 
                   2422:         public  b2col_is_2_colors
                   2423: b2col_is_2_colors:
                   2424: 
                   2425: ; Here, we want the color with the lesser value to be in 'al', and the
                   2426: ; other to be in 'ah'.
                   2427: 
                   2428:         cmp     al,ah
                   2429:         jb      short b2col_ordered_colors
                   2430:         xchg    al,ah
                   2431: 
                   2432: b2col_ordered_colors:
                   2433:         mov     ecx,(BRUSH_SIZE shr 3)
                   2434:         mov     esi,pjBits
                   2435:         mov     edi,esi
                   2436: 
                   2437: ; Colors matching 'al' will get mapped to '1' bits, and colors matching
                   2438: ; 'ah' will get mapped to '0' bits:
                   2439: 
                   2440: b2col_monochrome_bitmap_loop:
                   2441:         cmp     [esi+7],ah
                   2442:         adc     bl,bl
                   2443:         cmp     [esi+6],ah
                   2444:         adc     bl,bl
                   2445:         cmp     [esi+5],ah
                   2446:         adc     bl,bl
                   2447:         cmp     [esi+4],ah
                   2448:         adc     bl,bl
                   2449:         cmp     [esi+3],ah
                   2450:         adc     bl,bl
                   2451:         cmp     [esi+2],ah
                   2452:         adc     bl,bl
                   2453:         cmp     [esi+1],ah
                   2454:         adc     bl,bl
                   2455:         cmp     [esi],ah
                   2456:         adc     bl,bl
                   2457: 
                   2458: ; At this point, where the 8 bytes of the bitmap were ordered 0 1 2 3 4 5 6 7,
                   2459: ; we've got the monochrome byte in 'bl' ordered 7 6 5 4 3 2 1 0.  We want
                   2460: ; the word ordered '3 2 1 0 7 6 5 4 | 7 6 5 4 3 2 1 0' where the lower 4 bits
                   2461: ; of every bit are the planes mask, and the upper 4 bits are ordered to
                   2462: ; facilitate easy rotating.
                   2463: ;
                   2464: ; The word is actually written into a dword in the destination buffer.
                   2465: 
                   2466:         mov     bh,bl
                   2467:         ror     bh,4
                   2468:         mov     [edi],ebx               ;save this dword of monochrome bitmap
                   2469:         add     edi,4
                   2470:         add     esi,8
                   2471:         dec     ecx
                   2472:         jnz     b2col_monochrome_bitmap_loop
                   2473: 
                   2474: ; Aside: because of the way this is written, if the two colors are black
                   2475: ; and white (i.e., 0x00 and 0xff), the foreground color will be black (0x00),
                   2476: ; and the background will be white (0xff).
                   2477: 
                   2478:         mov     esi,pjFgColor
                   2479:         mov     edi,pjBkColor
                   2480:         mov     [esi],al                ;save foreground color
                   2481:         mov     [edi],ah                ;save background color
                   2482:         mov     eax,1
                   2483:         cRet    b2ColorBrush
                   2484: 
                   2485: endProc b2ColorBrush
                   2486: 
                   2487:         end

unix.superglobalmegacorp.com

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