Annotation of ntddk/src/video/displays/vga256/i386/monopat.asm, revision 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.