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

1.1       root        1: ;---------------------------Module-Header------------------------------;
                      2: ; Module Name: scroll.asm
                      3: ;
                      4: ; Copyright (c) 1992-1993 Microsoft Corporation
                      5: ;-----------------------------------------------------------------------;
                      6: 
                      7: ;-----------------------------------------------------------------------;
                      8: ; VOID vPlanarCopyBits(ppdev, prclDest, pptlSrc);
                      9: ;
                     10: ; Input:
                     11: ;
                     12: ;  ppdev    - surface on which to copy
                     13: ;  prcldest - pointer to destination rectangle
                     14: ;  pptlsrc  - pointer to source upper left corner
                     15: ;
                     16: ; Performs accelerated SRCCOPY screen-to-screen blts.
                     17: ;
                     18: ;-----------------------------------------------------------------------;
                     19: ;
                     20: ; NOTE: This handles only quad-pixel aligned blits!
                     21: ;
                     22: ; NOTE: Assumes all rectangles have positive heights and widths. Will
                     23: ; not work properly if this is not the case.
                     24: ;
                     25: ;-----------------------------------------------------------------------;
                     26: 
                     27: 
                     28: ;-----------------------------------------------------------------------;
                     29: ; Set LOOP_UNROLL_SHIFT to the log2 of the number of times you want loops in
                     30: ; this module unrolled. For example, LOOP_UNROLL_SHIFT of 3 yields 2**3 = 8
                     31: ; times unrolling. This is the only thing you need to change to control
                     32: ; unrolling.
                     33: 
                     34: LOOP_UNROLL_SHIFT equ 2
                     35: 
                     36: ;-----------------------------------------------------------------------;
                     37: 
                     38:         .386
                     39: 
                     40:         .model  small,c
                     41: 
                     42:         assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
                     43:         assume fs:nothing,gs:nothing
                     44: 
                     45:         .xlist
                     46:         include stdcall.inc             ;calling convention cmacros
                     47:         include i386\strucs.inc
                     48:         include i386\driver.inc
                     49:         include i386\unroll.inc
                     50:         include i386\egavga.inc
                     51: 
                     52:         .list
                     53: 
                     54: ;-----------------------------------------------------------------------;
                     55: 
                     56:         .data
                     57: 
                     58:         EXTRNP          bPuntScreenToScreenCopyBits,20
                     59: 
                     60: ; Bits for block copier tables:
                     61: 
                     62: BLOCK_RIGHT_TO_LEFT     equ 4
                     63: BLOCK_LEFT_EDGE         equ 2
                     64: BLOCK_RIGHT_EDGE        equ 1
                     65: 
                     66: ;-----------------------------------------------------------------------;
                     67: ; Table of block copiers for various horizontal directions, with the
                     68: ; look-up index a 3-bit field as follows:
                     69: ;
                     70: ; Bit 2 (BLOCK_RIGHT_TO_LEFT) = 1 if right-to-left copy
                     71: ; Bit 1 (BLOCK_LEFT_EDGE)     = 1 if left edge must be copied
                     72: ; Bit 0 (BLOCK_RIGHT_EDGE)    = 1 if right edge must be copied
                     73: 
                     74:         align   4
                     75: MasterBlockTable label dword
                     76: 
                     77:         dd      copy_just_middle_block
                     78:         dd      Block_WR
                     79:         dd      Block_LW
                     80:         dd      Block_LWR
                     81: 
                     82:         dd      copy_just_middle_block
                     83:         dd      Block_RW
                     84:         dd      Block_WL
                     85:         dd      Block_RWL
                     86: 
                     87:         align   4
                     88: TopToBottomLoopTable label dword
                     89:         dd      0                               ;Not used - unbanked case
                     90:         dd      top_to_bottom_1RW
                     91:         dd      top_to_bottom_2RW
                     92:         dd      top_to_bottom_2RW
                     93: 
                     94:         align   4
                     95: BottomToTopLoopTable label dword
                     96:         dd      0                               ;Not used - unbanked case
                     97:         dd      bottom_to_top_1RW
                     98:         dd      bottom_to_top_2RW
                     99:         dd      bottom_to_top_2RW
                    100: 
                    101:         align   4
                    102: SetUpForCopyDirection label dword
                    103:         dd      left_to_right_top_to_bottom     ;CD_RIGHTDOWN
                    104:         dd      right_to_left_top_to_bottom     ;CD_LEFTDOWN
                    105:         dd      left_to_right_bottom_to_top     ;CD_RIGHTUP
                    106:         dd      right_to_left_bottom_to_top     ;CD_LEFTUP
                    107: 
                    108: LeftMaskTable label dword
                    109:         dd      01111b
                    110:         dd      01110b
                    111:         dd      01100b
                    112:         dd      01000b
                    113: 
                    114: RightMaskTable label dword
                    115:         dd      00000b
                    116:         dd      00001b
                    117:         dd      00011b
                    118:         dd      00111b
                    119: 
                    120: ;-----------------------------------------------------------------------;
                    121: 
                    122:         .code
                    123: 
                    124:         align   4
                    125: Block_WR:
                    126:         push    offset copy_right_block
                    127:         jmp     copy_middle_block
                    128: 
                    129:         align   4
                    130: Block_LW:
                    131:         push    offset copy_middle_block
                    132:         jmp     copy_left_block
                    133: 
                    134:         align   4
                    135: Block_LWR:
                    136:         push    offset copy_right_block
                    137:         push    offset copy_middle_block
                    138:         jmp     copy_left_block
                    139: 
                    140:         align   4
                    141: Block_RW:
                    142:         push    offset copy_middle_block
                    143:         jmp     copy_right_block
                    144: 
                    145:         align   4
                    146: Block_WL:
                    147:         push    offset copy_left_block
                    148:         jmp     copy_middle_block
                    149: 
                    150:         align   4
                    151: Block_RWL:
                    152:         push    offset copy_left_block
                    153:         push    offset copy_middle_block
                    154:         jmp     copy_right_block
                    155: 
                    156: ;-----------------------------------------------------------------------;
                    157: 
                    158: cProc   vPlanarCopyBits,12,<    \
                    159:         uses esi edi ebx,       \
                    160:         ppdev:    ptr PDEV,     \
                    161:         prclDest: ptr RECTL,    \
                    162:         pptlSrc:  ptr POINTL    >
                    163: 
                    164: ; Variables used in block copiers:
                    165: 
                    166:         local pfnCopyBlocks:       ptr   ;pointer to block copy routines
                    167: 
                    168:         local ulMiddleSrc:         dword ;bitmap offset to 1st source
                    169:         local ulMiddleDest:        dword ;bitmap offset to 1st dest
                    170:         local lMiddleDelta:        dword ;delta from end of middle scan to next
                    171:         local ulBlockHeight:       dword ;number of scans to be copied in block
                    172:         local cjMiddle:            dword ;number of bytes to be copied on scan
                    173: 
                    174:         local ulLeftSrc:           dword ;bitmap offset to left source byte edge
                    175:         local ulLeftDest:          dword ;bitmap offset to left dest byte edge
                    176:         local ulRightSrc:          dword ;bitmap offset to right source byte edge
                    177:         local ulRightDest:         dword ;bitmap offset to right dest byte edge
                    178:         local lDelta:              dword ;delta between scans
                    179: 
                    180:         local ulLeftMask:          dword ;byte mask for left-edge copies
                    181:         local ulRightMask:         dword ;byte mask for right-edge copies
                    182: 
                    183:         local rclDest[size RECTL]: byte  ;left and right values always valid
                    184:         local ptlSrc[size POINTL]: byte  ;x value always valid
                    185: 
                    186:         local ulCurrentSrcScan:    dword ;real current source scan
                    187:         local ulCurrentDestScan:   dword ;real current destination scan
                    188:         local ulLastDestScan:      dword ;last destination scan
                    189: 
                    190: ; Set the bit mask to disable all bits, so we can copy through the latches:
                    191: 
                    192:         mov     edx,VGA_BASE + GRAF_ADDR
                    193:         mov     eax,(0 shl 8) + GRAF_BIT_MASK
                    194:         out     dx,ax
                    195: 
                    196: ; Figure out which direction to do the copies:
                    197: 
                    198:         mov     esi,pptlSrc
                    199:         mov     edi,prclDest
                    200:         mov     eax,[esi].ptl_y
                    201:         cmp     eax,[edi].yTop
                    202:         jl      planar_bottom_to_top
                    203: 
                    204:         mov     eax,[esi].ptl_x
                    205:         cmp     eax,[edi].xLeft
                    206:         jge     short left_to_right_top_to_bottom       ; CD_RIGHTDOWN
                    207:         jmp     right_to_left_top_to_bottom             ; CD_LEFTDOWN
                    208: 
                    209:         align   4
                    210: planar_bottom_to_top:
                    211:         mov     eax,[esi].ptl_x
                    212:         cmp     eax,[edi].xLeft
                    213:         jge     left_to_right_bottom_to_top             ; CD_RIGHTUP
                    214:         jmp     right_to_left_bottom_to_top             ; CD_LEFTUP
                    215: 
                    216:         align   4
                    217: all_done:
                    218: 
                    219: ; Enable bit mask for all bits:
                    220: 
                    221:         mov     edx,VGA_BASE + GRAF_ADDR
                    222:         mov     eax,(0ffh shl 8) + GRAF_BIT_MASK
                    223:         out     dx,ax
                    224: 
                    225: ; Enable writes to all planes and reset direction flag:
                    226: 
                    227:         mov     edx,VGA_BASE + SEQ_DATA
                    228:         mov     al,MM_ALL
                    229:         out     dx,al
                    230: 
                    231:         cld
                    232: 
                    233:         cRet    vPlanarCopyBits
                    234: 
                    235: ;=======================================================================;
                    236: ;==================== Direction Dependent Setup ========================;
                    237: ;=======================================================================;
                    238: 
                    239: ;-----------------------------------------------------------------------;
                    240: ; Set-up code for left-to-right, top-to-bottom copies.
                    241: ;
                    242: ; Input:
                    243: ;       esi - pptlSrc
                    244: ;       edi - prclDest
                    245: ;-----------------------------------------------------------------------;
                    246: 
                    247:         align   4
                    248:         public left_to_right_top_to_bottom
                    249: left_to_right_top_to_bottom:
                    250: 
                    251: ; Need to set-up: ulMiddleSrc, ulMiddleDest, lMiddleDelta, cjMiddle
                    252: ;                 ulLeftSrc, ulLeftDest, ulLeftMask
                    253: ;                 lDelta
                    254: ;                 ulRightSrc, ulRightDest, ulRightMask
                    255: ;                 ulCurrentDestScan, ulLastDestScan
                    256: ;                 pfnCopyBlocks
                    257: ;                 ptlSrc.x, rclDest.left, rclDest.right
                    258: 
                    259: ; lDelta = ppdev->lPlanarScan
                    260: ; ulCurrentSrcScan  = pptl->y
                    261: ; ulLeftSrc         = pptl->y       * lDelta + (pptl->x >> 2)
                    262: ; ulCurrentDestScan = prclDest->top
                    263: ; ulLeftDest        = prclDest->top * lDelta + (prclDest->left >> 2)
                    264: ;
                    265: ; ulMiddleSrc  = ulLeftSrc
                    266: ; ulMiddleDest = ulLeftDest
                    267: ;
                    268: ; cjMiddle = (prclDest->right >> 2) - (prclDest->left >> 2)
                    269: ; if (prclDest->left & 3)
                    270: ;     ulLeftMask = LeftMaskTable[prclDest->left & 3]
                    271: ;     fl |= BLOCK_LEFT_EDGE
                    272: ;     ulMiddleSrc++
                    273: ;     ulMiddleDest++
                    274: ;     cjMiddle--
                    275: ;
                    276: ; lMiddleDelta = lDelta - cjMiddle
                    277: ;
                    278: ; if (prclDest->right & 3)
                    279: ;     ulRightMask = RightMaskTable[prclDest->right & 3]
                    280: ;     fl |= BLOCK_RIGHT_EDGE
                    281: ;     ulRightSrc  = ulMiddleSrc  + cjMiddle
                    282: ;     ulRightDest = ulMiddleDest + cjMiddle
                    283: 
                    284:         mov     edx,ppdev
                    285:         mov     eax,[edi].yBottom
                    286:         mov     edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
                    287:         mov     ulLastDestScan,eax      ;ulLastDestScan = prclDest->bottom
                    288: 
                    289:         mov     ecx,[esi].ptl_y
                    290:         mov     eax,edx
                    291:         mov     ulCurrentSrcScan,ecx    ;ulCurrentSrcScan = pptlSrc->y
                    292:         imul    eax,ecx
                    293:         mov     ecx,[esi].ptl_x
                    294:         mov     ptlSrc.ptl_x,ecx        ;ptlSrc.x = pptlSrc->x
                    295:         shr     ecx,2
                    296:         add     eax,ecx                 ;eax = ulLeftSrc = pptlSrc->y *
                    297:                                         ;  lDelta + (pptlSrc->x >> 2)
                    298: 
                    299:         xor     esi,esi                 ;initialize flags
                    300: 
                    301:         mov     ecx,[edi].yTop
                    302:         mov     ebx,edx
                    303:         mov     ulCurrentDestScan,ecx   ;ulCurrentDestScan = prclDest->top
                    304:         imul    ebx,ecx
                    305:         mov     ecx,[edi].xLeft
                    306:         mov     rclDest.xLeft,ecx       ;rclDest.left = prclDest->left
                    307:         shr     ecx,2
                    308:         add     ebx,ecx                 ;ebx = ulLeftDest = prclDest->top *
                    309:                                         ;  lDelta + (prclDest->left >> 2)
                    310: 
                    311:         mov     edi,[edi].xRight
                    312:         mov     rclDest.xRight,edi
                    313:         shr     edi,2
                    314:         sub     edi,ecx                 ;cjMiddle = (prclDest->right >> 2) -
                    315:                                         ;  (prclDest->left >> 2)
                    316: 
                    317:         mov     ecx,rclDest.xLeft
                    318:         and     ecx,3
                    319:         jz      short l_t_done_left_edge ;skip if we don't need a left edge
                    320: 
                    321:         or      esi,BLOCK_LEFT_EDGE
                    322:         mov     ecx,LeftMaskTable[ecx*4]
                    323:         mov     ulLeftMask,ecx          ;ulLeftMask =
                    324:                                         ;  LeftMaskTable[prclDest->left & 3]
                    325: 
                    326:         mov     ulLeftSrc,eax           ;ulLeftSrc
                    327:         mov     ulLeftDest,ebx          ;ulLeftDest
                    328:         inc     eax
                    329:         inc     ebx
                    330:         dec     edi
                    331: 
                    332: l_t_done_left_edge:
                    333:         mov     ulMiddleSrc,eax         ;ulMiddleSrc
                    334:         mov     ulMiddleDest,ebx        ;ulMiddleDest
                    335: 
                    336:         mov     ecx,rclDest.xRight
                    337:         and     ecx,3
                    338:         jz      short l_t_done_right_edge ;skip if we don't need a right edge
                    339: 
                    340:         or      esi,BLOCK_RIGHT_EDGE
                    341:         mov     ecx,RightMaskTable[ecx*4]
                    342:         mov     ulRightMask,ecx         ;ulRightMask =
                    343:                                         ;  RightMaskTable[prclDest->right & 3]
                    344: 
                    345:         add     eax,edi
                    346:         add     ebx,edi
                    347:         mov     ulRightSrc,eax          ;ulRightSrc = ulMiddleSrc + cjMiddle
                    348:         mov     ulRightDest,ebx         ;ulRightDest = ulMiddleDest + cjMiddle
                    349: 
                    350: ; We special case here blits that are less than 4 pels wide and begin and end
                    351: ; in the same 4-pel quadruple:
                    352: 
                    353:         cmp     edi,0
                    354:         jge     l_t_done_right_edge
                    355: 
                    356: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
                    357: ; fall through the 'middle' copy code), turn off the right-edge flag, and
                    358: ; give ulLeftMask the composite mask:
                    359: 
                    360:         inc     edi
                    361:         xor     esi,BLOCK_RIGHT_EDGE
                    362:         and     ecx,ulLeftMask
                    363:         mov     ulLeftMask,ecx
                    364: 
                    365:         align   4
                    366: l_t_done_right_edge:
                    367:         mov     cjMiddle,edi            ;cjMiddle
                    368: 
                    369:         mov     lDelta,edx              ;lDelta = ppdev->lPlanarNextScan
                    370:         sub     edx,edi
                    371:         mov     lMiddleDelta,edx        ;lMiddleDelta = lDelta - cjMiddle
                    372: 
                    373:         mov     ebx,ppdev
                    374:         mov     eax,MasterBlockTable[esi*4]
                    375:         mov     pfnCopyBlocks,eax       ;copy blocks between video memory
                    376: 
                    377: ; Branch to the appropriate top-to-bottom bank enumeration loop:
                    378: 
                    379:         mov     eax,[ebx].pdev_vbtPlanarType
                    380:         jmp     TopToBottomLoopTable[eax*4]
                    381: 
                    382: ;-----------------------------------------------------------------------;
                    383: ; Set-up code for right-to-left, top-to-bottom copies.
                    384: ;
                    385: ; Input:
                    386: ;       esi - pptlSrc
                    387: ;       edi - prclDest
                    388: ;-----------------------------------------------------------------------;
                    389: 
                    390:         align   4
                    391:         public right_to_left_top_to_bottom
                    392: right_to_left_top_to_bottom:
                    393: 
                    394:         std                             ;copy middle blocks right-to-left
                    395: 
                    396:         mov     edx,ppdev
                    397:         mov     eax,[edi].yBottom
                    398:         mov     edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
                    399:         mov     ulLastDestScan,eax      ;ulLastDestScan = prclDest->bottom
                    400: 
                    401:         mov     ecx,[esi].ptl_y
                    402:         mov     eax,edx
                    403:         mov     ulCurrentSrcScan,ecx    ;ulCurrentSrcScan = pptlSrc->y
                    404:         imul    eax,ecx
                    405:         mov     ecx,[esi].ptl_x
                    406:         mov     ptlSrc.ptl_x,ecx        ;ptlSrc.x = pptlSrc->x
                    407:         add     ecx,[edi].xRight
                    408:         sub     ecx,[edi].xLeft
                    409:         shr     ecx,2
                    410:         add     eax,ecx                 ;eax = ulRightSrc = pptlSrc->y *
                    411:                                         ; lDelta + (pptlSrc->x +
                    412:                                         ; prclDest->right - prclDest->left) / 4
                    413: 
                    414:         mov     esi,BLOCK_RIGHT_TO_LEFT ;initialize flags
                    415: 
                    416:         mov     ecx,[edi].yTop
                    417:         mov     ebx,edx
                    418:         mov     ulCurrentDestScan,ecx   ;ulCurrentDestScan = prclDest->top
                    419:         imul    ebx,ecx
                    420:         mov     ecx,[edi].xRight
                    421:         mov     rclDest.xRight,ecx      ;rclDest.right = prclDest->right
                    422:         shr     ecx,2
                    423:         add     ebx,ecx                 ;ebx = ulRightDest = prclDest->top *
                    424:                                         ; lDelta + prclDest->right / 4
                    425: 
                    426:         mov     edi,[edi].xLeft
                    427:         mov     rclDest.xLeft,edi
                    428:         shr     edi,2
                    429:         neg     edi
                    430:         add     edi,ecx                 ;cjMiddle = prclDest->right / 4 -
                    431:                                         ;  prclDest->left / 4
                    432: 
                    433:         mov     ecx,rclDest.xRight
                    434:         and     ecx,3
                    435:         jz      short r_t_done_right_edge ;skip if we don't need a right edge
                    436: 
                    437:         or      esi,BLOCK_RIGHT_EDGE
                    438:         mov     ecx,RightMaskTable[ecx*4]
                    439:         mov     ulRightMask,ecx         ;ulRightMask =
                    440:                                         ;  RightMaskTable[prclDest->right & 3]
                    441: 
                    442:         mov     ulRightSrc,eax          ;ulRightSrc
                    443:         mov     ulRightDest,ebx         ;ulRightDest
                    444: 
                    445: r_t_done_right_edge:
                    446:         dec     eax
                    447:         dec     ebx
                    448:         mov     ulMiddleSrc,eax         ;ulMiddleSrc
                    449:         mov     ulMiddleDest,ebx        ;ulMiddleDest
                    450: 
                    451:         mov     ecx,rclDest.xLeft
                    452:         and     ecx,3
                    453:         jz      short r_t_done_left_edge ;skip if we don't need a right edge
                    454:         or      esi,BLOCK_LEFT_EDGE
                    455:         mov     ecx,LeftMaskTable[ecx*4]
                    456:         mov     ulLeftMask,ecx          ;ulLeftMask =
                    457:                                         ;  LeftMaskTable[prclDest->left & 3]
                    458: 
                    459:         dec     edi                     ;adjust middle block length because
                    460:                                         ;  we're effectively doing one less
                    461:                                         ;  middle byte
                    462: 
                    463:         sub     eax,edi
                    464:         sub     ebx,edi
                    465:         mov     ulLeftSrc,eax           ;ulLeftSrc = ulMiddleSrc - cjMiddle
                    466:         mov     ulLeftDest,ebx          ;ulLeftDest = ulMiddleDest - cjMiddle
                    467: 
                    468: ; We special case here blits that are less than 4 pels wide and begin and end
                    469: ; in the same 4-pel quadruple:
                    470: 
                    471:         cmp     edi,0
                    472:         jge     r_t_done_left_edge
                    473: 
                    474: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
                    475: ; fall through the 'middle' copy code), turn off the right-edge flag, and
                    476: ; give ulRightMask the composite mask:
                    477: 
                    478:         inc     edi
                    479:         xor     esi,BLOCK_LEFT_EDGE
                    480:         and     ecx,ulRightMask
                    481:         mov     ulRightMask,ecx
                    482: 
                    483:         align   4
                    484: r_t_done_left_edge:
                    485:         mov     cjMiddle,edi            ;cjMiddle
                    486: 
                    487:         mov     lDelta,edx              ;lDelta = ppdev->lPlanarNextScan
                    488:         add     edx,edi
                    489:         mov     lMiddleDelta,edx        ;lMiddleDelta = lDelta + cjMiddle
                    490: 
                    491:         mov     ebx,ppdev
                    492:         mov     eax,MasterBlockTable[esi*4]
                    493:         mov     pfnCopyBlocks,eax       ;copy blocks between video memory
                    494: 
                    495: ; Branch to the appropriate top-to-bottom bank enumeration loop:
                    496: 
                    497:         mov     eax,[ebx].pdev_vbtPlanarType
                    498:         jmp     TopToBottomLoopTable[eax*4]
                    499: 
                    500: ;-----------------------------------------------------------------------;
                    501: ; Set-up code for left-to-right, bottom-to-top copies.
                    502: ;
                    503: ; Input:
                    504: ;       esi - pptlSrc
                    505: ;       edi - prclDest
                    506: ;-----------------------------------------------------------------------;
                    507: 
                    508:         align   4
                    509:         public left_to_right_bottom_to_top
                    510: left_to_right_bottom_to_top:
                    511: 
                    512:         mov     edx,ppdev
                    513:         mov     eax,[edi].yTop
                    514:         mov     edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
                    515:         mov     ulLastDestScan,eax      ;ulLastDestScan = prclDest->top
                    516: 
                    517:         mov     ecx,[esi].ptl_y
                    518:         add     ecx,[edi].yBottom
                    519:         sub     ecx,[edi].yTop
                    520:         mov     eax,edx
                    521:         mov     ulCurrentSrcScan,ecx    ;ulCurrentSrcScan = pptlSrc->y +
                    522:                                         ;  (prclDest->bottom - prclDest->top)
                    523:         dec     ecx
                    524:         imul    eax,ecx
                    525:         mov     ecx,[esi].ptl_x
                    526:         mov     ptlSrc.ptl_x,ecx        ;ptlSrc.x = pptlSrc->x
                    527:         shr     ecx,2
                    528:         add     eax,ecx                 ;eax = ulLeftSrc = (ulCurrentSrcScan - 1)
                    529:                                         ;  * lDelta + (pptlSrc->x >> 2)
                    530: 
                    531:         xor     esi,esi                 ;initialize flags
                    532: 
                    533:         mov     ecx,[edi].yBottom
                    534:         mov     ebx,edx
                    535:         mov     ulCurrentDestScan,ecx   ;ulCurrentDestScan = prclDest->bottom
                    536:         dec     ecx
                    537:         imul    ebx,ecx
                    538:         mov     ecx,[edi].xLeft
                    539:         mov     rclDest.xLeft,ecx       ;rclDest.left = prclDest->left
                    540:         shr     ecx,2
                    541:         add     ebx,ecx                 ;ebx = ulLeftDest = (prclDest->bottom - 1)
                    542:                                         ;  * lDelta + (prclDest->left >> 2)
                    543: 
                    544:         mov     edi,[edi].xRight
                    545:         mov     rclDest.xRight,edi
                    546:         shr     edi,2
                    547:         sub     edi,ecx                 ;cjMiddle = (prclDest->right >> 2) -
                    548:                                         ;  (prclDest->left >> 2)
                    549: 
                    550:         mov     ecx,rclDest.xLeft
                    551:         and     ecx,3
                    552:         jz      short l_b_done_left_edge ;skip if we don't need a left edge
                    553: 
                    554:         or      esi,BLOCK_LEFT_EDGE
                    555:         mov     ecx,LeftMaskTable[ecx*4]
                    556:         mov     ulLeftMask,ecx          ;ulLeftMask =
                    557:                                         ;  LeftMaskTable[prclDest->left & 3]
                    558: 
                    559:         mov     ulLeftSrc,eax           ;ulLeftSrc
                    560:         mov     ulLeftDest,ebx          ;ulLeftDest
                    561:         inc     eax
                    562:         inc     ebx
                    563:         dec     edi
                    564: 
                    565: l_b_done_left_edge:
                    566:         mov     ulMiddleSrc,eax         ;ulMiddleSrc
                    567:         mov     ulMiddleDest,ebx        ;ulMiddleDest
                    568: 
                    569:         mov     ecx,rclDest.xRight
                    570:         and     ecx,3
                    571:         jz      short l_b_done_right_edge ;skip if we don't need a right edge
                    572: 
                    573:         or      esi,BLOCK_RIGHT_EDGE
                    574:         mov     ecx,RightMaskTable[ecx*4]
                    575:         mov     ulRightMask,ecx         ;ulRightMask =
                    576:                                         ;  RightMaskTable[prclDest->right & 3]
                    577: 
                    578:         add     eax,edi
                    579:         add     ebx,edi
                    580:         mov     ulRightSrc,eax          ;ulRightSrc = ulMiddleSrc + cjMiddle
                    581:         mov     ulRightDest,ebx         ;ulRightDest = ulMiddleDest + cjMiddle
                    582: 
                    583: ; We special case here blits that are less than 4 pels wide and begin and end
                    584: ; in the same 4-pel quadruple:
                    585: 
                    586:         cmp     edi,0
                    587:         jge     l_b_done_right_edge
                    588: 
                    589: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
                    590: ; fall through the 'middle' copy code), turn off the right-edge flag, and
                    591: ; give ulLeftMask the composite mask:
                    592: 
                    593:         inc     edi
                    594:         xor     esi,BLOCK_RIGHT_EDGE
                    595:         and     ecx,ulLeftMask
                    596:         mov     ulLeftMask,ecx
                    597: 
                    598:         align   4
                    599: l_b_done_right_edge:
                    600:         mov     cjMiddle,edi            ;cjMiddle
                    601: 
                    602:         neg     edx
                    603:         mov     lDelta,edx              ;lDelta = -ppdev->lPlanarNextScan
                    604:         sub     edx,edi
                    605:         mov     lMiddleDelta,edx        ;lMiddleDelta = lDelta - cjMiddle
                    606: 
                    607:         mov     ebx,ppdev
                    608:         mov     eax,MasterBlockTable[esi*4]
                    609:         mov     pfnCopyBlocks,eax       ;copy blocks between video memory
                    610: 
                    611: ; Branch to the appropriate top-to-bottom bank enumeration loop:
                    612: 
                    613:         mov     eax,[ebx].pdev_vbtPlanarType
                    614:         jmp     BottomToTopLoopTable[eax*4]
                    615: 
                    616: ;-----------------------------------------------------------------------;
                    617: ; Set-up code for right-to-left, bottom-to-top copies.
                    618: ;
                    619: ; Input:
                    620: ;       esi - pptlSrc
                    621: ;       edi - prclDest
                    622: ;-----------------------------------------------------------------------;
                    623: 
                    624:         align   4
                    625:         public right_to_left_bottom_to_top
                    626: right_to_left_bottom_to_top:
                    627: 
                    628:         std                             ;copy middle blocks right-to-left
                    629: 
                    630:         mov     edx,ppdev
                    631:         mov     eax,[edi].yTop
                    632:         mov     edx,[edx].pdev_lPlanarNextScan ;edx = lDelta
                    633:         mov     ulLastDestScan,eax      ;ulLastDestScan = prclDest->top
                    634: 
                    635:         mov     ecx,[esi].ptl_y
                    636:         add     ecx,[edi].yBottom
                    637:         sub     ecx,[edi].yTop
                    638:         mov     eax,edx
                    639:         mov     ulCurrentSrcScan,ecx    ;ulCurrentSrcScan = pptlSrc->y +
                    640:                                         ;  (prclDest->bottom - prclDest->top)
                    641:         dec     ecx
                    642:         imul    eax,ecx
                    643:         mov     ecx,[esi].ptl_x
                    644:         mov     ptlSrc.ptl_x,ecx        ;ptlSrc.x = pptlSrc->x
                    645:         add     ecx,[edi].xRight
                    646:         sub     ecx,[edi].xLeft
                    647:         shr     ecx,2
                    648:         add     eax,ecx                 ;eax = ulRightSrc = (ulCurrentSrcScan
                    649:                                         ; - 1) * lDelta + (pptlSrc->x +
                    650:                                         ; prclDest->right - prclDest->left) / 4
                    651: 
                    652:         mov     esi,BLOCK_RIGHT_TO_LEFT ;initialize flags
                    653: 
                    654:         mov     ecx,[edi].yBottom
                    655:         mov     ebx,edx
                    656:         mov     ulCurrentDestScan,ecx   ;ulCurrentDestScan = prclDest->bottom
                    657:         dec     ecx
                    658:         imul    ebx,ecx
                    659:         mov     ecx,[edi].xRight
                    660:         mov     rclDest.xRight,ecx      ;rclDest.right = prclDest->right
                    661:         shr     ecx,2
                    662:         add     ebx,ecx                 ;ebx = ulRightDest = (ulCurrentDestScan
                    663:                                         ; - 1) * lDelta + prclDest->right / 4
                    664: 
                    665:         mov     edi,[edi].xLeft
                    666:         mov     rclDest.xLeft,edi
                    667:         shr     edi,2
                    668:         neg     edi
                    669:         add     edi,ecx                 ;cjMiddle = prclDest->right / 4 -
                    670:                                         ;  prclDest->left / 4
                    671: 
                    672:         mov     ecx,rclDest.xRight
                    673:         and     ecx,3
                    674:         jz      short r_b_done_right_edge ;skip if we don't need a right edge
                    675: 
                    676:         or      esi,BLOCK_RIGHT_EDGE
                    677:         mov     ecx,RightMaskTable[ecx*4]
                    678:         mov     ulRightMask,ecx         ;ulRightMask =
                    679:                                         ;  RightMaskTable[prclDest->right & 3]
                    680: 
                    681:         mov     ulRightSrc,eax          ;ulRightSrc
                    682:         mov     ulRightDest,ebx         ;ulRightDest
                    683: 
                    684: r_b_done_right_edge:
                    685:         dec     eax
                    686:         dec     ebx
                    687:         mov     ulMiddleSrc,eax         ;ulMiddleSrc
                    688:         mov     ulMiddleDest,ebx        ;ulMiddleDest
                    689: 
                    690:         mov     ecx,rclDest.xLeft
                    691:         and     ecx,3
                    692:         jz      short r_b_done_left_edge ;skip if we don't need a right edge
                    693: 
                    694:         or      esi,BLOCK_LEFT_EDGE
                    695:         mov     ecx,LeftMaskTable[ecx*4]
                    696:         mov     ulLeftMask,ecx          ;ulLeftMask =
                    697:                                         ;  LeftMaskTable[prclDest->left & 3]
                    698: 
                    699:         dec     edi                     ;adjust middle block length because
                    700:                                         ;  we're effectively doing one less
                    701:                                         ;  middle byte
                    702: 
                    703:         sub     eax,edi
                    704:         sub     ebx,edi
                    705:         mov     ulLeftSrc,eax           ;ulLeftSrc = ulMiddleSrc - cjMiddle
                    706:         mov     ulLeftDest,ebx          ;ulLeftDest = ulMiddleDest - cjMiddle
                    707: 
                    708: ; We special case here blits that are less than 4 pels wide and begin and end
                    709: ; in the same 4-pel quadruple:
                    710: 
                    711:         cmp     edi,0
                    712:         jge     r_b_done_left_edge
                    713: 
                    714: ; We make sure the 'middle' count of bytes is zero (we'll just let the code
                    715: ; fall through the 'middle' copy code), turn off the right-edge flag, and
                    716: ; give ulRightMask the composite mask:
                    717: 
                    718:         inc     edi
                    719:         xor     esi,BLOCK_LEFT_EDGE
                    720:         and     ecx,ulRightMask
                    721:         mov     ulRightMask,ecx
                    722: 
                    723:         align   4
                    724: r_b_done_left_edge:
                    725:         mov     cjMiddle,edi            ;cjMiddle
                    726: 
                    727:         neg     edx
                    728:         mov     lDelta,edx              ;lDelta = -ppdev->lPlanarNextScan
                    729:         add     edx,edi
                    730:         mov     lMiddleDelta,edx        ;lMiddleDelta = lDelta + cjMiddle
                    731: 
                    732:         mov     ebx,ppdev
                    733:         mov     eax,MasterBlockTable[esi*4]
                    734:         mov     pfnCopyBlocks,eax       ;copy blocks between video memory
                    735: 
                    736: ; Branch to the appropriate top-to-bottom bank enumeration loop:
                    737: 
                    738:         mov     eax,[ebx].pdev_vbtPlanarType
                    739:         jmp     BottomToTopLoopTable[eax*4]
                    740: 
                    741: ;=======================================================================;
                    742: ;============================= Banking =================================;
                    743: ;=======================================================================;
                    744: 
                    745: ;-----------------------------------------------------------------------;
                    746: ; Banking for 1 R/W adapters, top to bottom.
                    747: ;
                    748: ; Input:
                    749: ;       ulCurrentSrcScan
                    750: ;       ulCurrentDestScan
                    751: ;       ulLastDestScan
                    752: ;       Plus some other stuff for split rasters and block copiers
                    753: ;-----------------------------------------------------------------------;
                    754:         align   4
                    755:         public  top_to_bottom_1RW
                    756: top_to_bottom_1RW:
                    757: 
                    758: ; LATER: Should check to see if there's any chance that the source and
                    759: ;     destination overlap in the same window, so that we can use planar
                    760: ;     copies -- otherwise, it's faster to directly call of to
                    761: ;     bPuntScreenToScreenCopyBits
                    762: 
                    763: ; We're going top to bottom. Map in the source and dest, top-justified.
                    764: 
                    765:         mov     ebx,ppdev
                    766:         mov     edi,ulCurrentDestScan
                    767: 
                    768:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yTop
                    769:         jl      short top_1RW_map_init_bank
                    770: 
                    771:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yBottom
                    772:         jl      short top_1RW_init_bank_mapped
                    773: 
                    774: top_1RW_map_init_bank:
                    775: 
                    776: ; Map bank containing the top destination scan line into window.
                    777: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                    778: 
                    779:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    780:                 <ebx,edi,JustifyTop>
                    781: 
                    782: top_1RW_init_bank_mapped:
                    783: 
                    784:         mov     eax,ulCurrentSrcScan
                    785:         cmp     eax,[ebx].pdev_rcl1PlanarClip.yBottom
                    786: 
                    787:         jl      short top_1RW_do_planar_copy
                    788: 
                    789: ; ulCurrentSrcScan >= ppdev->rcl1PlanarClip.bottom, which means that
                    790: ; the window can't overlap the source and destination at all.  We'll
                    791: ; have to use an intermediate temporary buffer:
                    792: 
                    793: ; ebx = ppdev
                    794: ; eax = ulCurrentSrcScan
                    795: ; edi = ulCurrentDestScan
                    796: 
                    797:         mov     ptlSrc.ptl_y,eax        ;ptlSrc.y = ulCurrentSrcScan
                    798:         mov     rclDest.yTop,edi        ;rclDest.top = ulCurrentDestScan
                    799: 
                    800:         mov     esi,[ebx].pdev_rcl1PlanarClip.yBottom
                    801:         mov     eax,ulLastDestScan
                    802:         sub     eax,esi
                    803:         sbb     ecx,ecx
                    804:         and     ecx,eax
                    805:         add     esi,ecx
                    806:         mov     rclDest.yBottom,esi     ;rclDest.bottom = min(ulLastDestScan,
                    807:                                         ;  ppdev->pdev_rcl1PlanarClip.bottom)
                    808: 
                    809: ; Enable bit mask for all bits:
                    810: 
                    811:         mov     edx,VGA_BASE + GRAF_ADDR
                    812:         mov     eax,(0ffh shl 8) + GRAF_BIT_MASK
                    813:         out     dx,ax
                    814: 
                    815: ; Enable writes to all planes and reset direction flag:
                    816: 
                    817:         mov     edx,VGA_BASE + SEQ_DATA
                    818:         mov     al,MM_ALL
                    819:         out     dx,al
                    820: 
                    821:         pushfd
                    822:         cld
                    823: 
                    824: ; Call our routine that copies bits the slow way, preserving EBX, ESI and EDI
                    825: ; according to C calling conventions:
                    826: 
                    827:         lea     ecx,rclDest
                    828:         lea     edx,ptlSrc
                    829: 
                    830:         cCall   bPuntScreenToScreenCopyBits,<ebx,0,0,ecx,edx>
                    831: 
                    832:         popfd
                    833: 
                    834: ; Set the bit mask to disable all bits, so we can copy through latches again:
                    835: 
                    836:         mov     edx,VGA_BASE + GRAF_ADDR
                    837:         mov     eax,(000h shl 8) + GRAF_BIT_MASK
                    838:         out     dx,ax
                    839: 
                    840: ; Update our position variables:
                    841: 
                    842:         mov     ulCurrentDestScan,esi   ;ulCurrentDestScan = rclDest.bottom
                    843: 
                    844:         sub     esi,edi                 ;ulBlockHeight = rclDest.bottom -
                    845:                                         ;  rclDest.top
                    846: 
                    847:         add     ulCurrentSrcScan,esi    ;ulCurrentSrcScan += ulBlockHeight
                    848: 
                    849: ; We have to adjust the offsets for all our block copiers, according to the
                    850: ; number of scans we copied:
                    851: 
                    852:         mov     edx,lDelta
                    853:         imul    edx,esi                 ;edx = lDelta * ulBlockHeight
                    854:         add     ulLeftSrc,edx
                    855:         add     ulLeftDest,edx
                    856:         add     ulMiddleSrc,edx
                    857:         add     ulMiddleDest,edx
                    858:         add     ulRightSrc,edx
                    859:         add     ulRightDest,edx
                    860: 
                    861:         jmp     short top_1RW_see_if_done
                    862: 
                    863: top_1RW_do_planar_copy:
                    864: 
                    865: ; ebx = ppdev
                    866: ; eax = ulCurrentSrcScan
                    867: ; edi = ulCurrentDestScan
                    868: 
                    869:         mov     ebx,[ebx].pdev_rcl1PlanarClip.yBottom
                    870:         sub     ebx,eax                 ;ebx = ppdev->rcl1PlanarClip.bottom -
                    871:                                         ;  ulCurrentSrcScan
                    872:                                         ;ebx is the available number of scans
                    873:                                         ;  we have in the source
                    874: 
                    875:         mov     edx,ulLastDestScan
                    876:         sub     edx,edi                 ;edx = ulLastDestScan - ulCurrentDestScan
                    877:                                         ;edx is the available number of scans
                    878:                                         ;  in the destination
                    879: 
                    880: ; (Because the source starts lower in the window than the destination,
                    881: ; the bottom of the bank always limits the source number of scans before
                    882: ; it does the destination.)
                    883: 
                    884:         sub     ebx,edx
                    885:         sbb     ecx,ecx
                    886:         and     ecx,ebx
                    887:         add     edx,ecx                 ;edx = min(source available,
                    888:                                         ;  destination available)
                    889:         mov     ulBlockHeight,edx
                    890: 
                    891:         add     eax,edx                 ;We have to adjust our current scans
                    892:         add     edi,edx
                    893:         mov     ulCurrentSrcScan,eax
                    894:         mov     ulCurrentDestScan,edi
                    895: 
                    896: ; Now copy the puppy:
                    897: 
                    898:         call    pfnCopyBlocks
                    899: 
                    900: ; See if we're done:
                    901: 
                    902: top_1RW_see_if_done:
                    903:         mov     edi,ulCurrentDestScan
                    904:         cmp     edi,ulLastDestScan
                    905:         jge     all_done
                    906: 
                    907:         mov     ebx,ppdev
                    908: 
                    909: ; Map bank containing the top destination scan line into window.
                    910: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                    911: 
                    912:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    913:                 <ebx,edi,JustifyTop>
                    914: 
                    915:         jmp     top_1RW_init_bank_mapped
                    916: 
                    917: ;-----------------------------------------------------------------------;
                    918: ; Banking for 1 R/W adapters, bottom to top.
                    919: ;
                    920: ; Input:
                    921: ;       ulCurrentSrcScan  - Actually, 1 more current source scan
                    922: ;       ulCurrentDestScan - Actually, 1 more current destination scan
                    923: ;       ulLastDestScan
                    924: ;       Plus some other stuff for split rasters and block copiers
                    925: ;-----------------------------------------------------------------------;
                    926:         align   4
                    927:         public  bottom_to_top_1RW
                    928: bottom_to_top_1RW:
                    929: 
                    930: ; We're going top to bottom. Map in the source and dest, top-justified.
                    931: 
                    932:         mov     ebx,ppdev
                    933:         mov     edi,ulCurrentDestScan
                    934: 
                    935:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yTop
                    936:         jle     short bot_1RW_map_init_bank
                    937: 
                    938:         cmp     edi,[ebx].pdev_rcl1PlanarClip.yBottom
                    939:         jle     short bot_1RW_init_bank_mapped
                    940: 
                    941: bot_1RW_map_init_bank:
                    942: 
                    943: ; Map bank containing the top destination scan line into window.
                    944: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                    945: 
                    946:         dec     edi
                    947:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                    948:                 <ebx,edi,JustifyTop>
                    949:         inc     edi
                    950: 
                    951: bot_1RW_init_bank_mapped:
                    952: 
                    953:         mov     eax,ulCurrentSrcScan
                    954:         cmp     eax,[ebx].pdev_rcl1PlanarClip.yTop
                    955: 
                    956:         jg      short bot_1RW_do_planar_copy
                    957: 
                    958: ; ulCurrentSrcScan <= ppdev->rcl1PlanarClip.top, which means that
                    959: ; the window can't overlap the source and destination at all.  We'll
                    960: ; have to use an intermediate temporary buffer:
                    961: 
                    962: ; ebx = ppdev
                    963: ; eax = ulCurrentSrcScan
                    964: ; edi = ulCurrentDestScan
                    965: 
                    966:         mov     esi,[ebx].pdev_rcl1PlanarClip.yTop
                    967:         mov     edx,ulLastDestScan
                    968:         cmp     esi,edx
                    969:         jg      @F
                    970:         mov     esi,edx
                    971: @@:
                    972:         mov     rclDest.yTop,esi        ;rclDest.top = max(ulLastDestScan,
                    973:                                         ;  ppdev->rcl1PlanarClip.top)
                    974: 
                    975:         mov     rclDest.yBottom,edi     ;rclDest.bottom = ulCurrentDestScan
                    976:         add     eax,esi
                    977:         sub     eax,edi
                    978:         mov     ptlSrc.ptl_y,eax        ;ptlSrc.y = ulCurrentSrcScan -
                    979:                                         ;  (rclDest.bottom - rclDest.top)
                    980: 
                    981: ; Enable bit mask for all bits:
                    982: 
                    983:         mov     edx,VGA_BASE + GRAF_ADDR
                    984:         mov     eax,(0ffh shl 8) + GRAF_BIT_MASK
                    985:         out     dx,ax
                    986: 
                    987: ; Enable writes to all planes and reset direction flag:
                    988: 
                    989:         mov     edx,VGA_BASE + SEQ_DATA
                    990:         mov     al,MM_ALL
                    991:         out     dx,al
                    992: 
                    993:         pushfd
                    994:         cld
                    995: 
                    996: ; Call our routine that copies bits the slow way, preserving EBX, ESI and EDI
                    997: ; according to C calling conventions:
                    998: 
                    999:         lea     ecx,rclDest
                   1000:         lea     edx,ptlSrc
                   1001: 
                   1002:         cCall   bPuntScreenToScreenCopyBits,<ebx,0,0,ecx,edx>
                   1003: 
                   1004:         popfd
                   1005: 
                   1006: ; Set the bit mask to disable all bits, so we can copy through latches again:
                   1007: 
                   1008:         mov     edx,VGA_BASE + GRAF_ADDR
                   1009:         mov     eax,(000h shl 8) + GRAF_BIT_MASK
                   1010:         out     dx,ax
                   1011: 
                   1012: ; Update our position variables:
                   1013: 
                   1014:         mov     ulCurrentDestScan,esi   ;ulCurrentDestScan = rclDest.top
                   1015: 
                   1016:         sub     edi,esi                 ;ulBlockHeight = rclDest.bottom -
                   1017:                                         ;  rclDest.top
                   1018: 
                   1019:         sub     ulCurrentSrcScan,edi    ;ulCurrentSrcScan -= ulBlockHeight
                   1020: 
                   1021: ; We have to adjust the offsets for all our block copiers, according to the
                   1022: ; number of scans we copied:
                   1023: 
                   1024:         mov     edx,lDelta
                   1025:         imul    edx,edi                 ;edx = lDelta * ulBlockHeight
                   1026:         add     ulLeftSrc,edx
                   1027:         add     ulLeftDest,edx
                   1028:         add     ulMiddleSrc,edx
                   1029:         add     ulMiddleDest,edx
                   1030:         add     ulRightSrc,edx
                   1031:         add     ulRightDest,edx
                   1032: 
                   1033:         jmp     short bot_1RW_see_if_done
                   1034: 
                   1035: bot_1RW_do_planar_copy:
                   1036: 
                   1037: ; ebx = ppdev
                   1038: ; eax = ulCurrentSrcScan
                   1039: ; edi = ulCurrentDestScan
                   1040: 
                   1041:         sub     eax,[ebx].pdev_rcl1PlanarClip.yTop
                   1042:                                         ;eax = ulCurrentSrcScan -
                   1043:                                         ;  ppdev->rcl1PlanarClip.top
                   1044: 
                   1045:         sub     edi,ulLastDestScan      ;edi = ulCurrentDestScan - ulLastDestScan
                   1046:                                         ;edi is the available number of scans
                   1047:                                         ;  in the destination
                   1048: 
                   1049: 
                   1050: ; (Because the source starts higher in the window than the destination,
                   1051: ; the bottom of the bank always limits the source number of scans before
                   1052: ; it does the destination.)
                   1053: 
                   1054:         sub     eax,edi
                   1055:         sbb     ecx,ecx
                   1056:         and     ecx,eax
                   1057:         add     edi,ecx                 ;edi = min(source available,
                   1058:                                         ;  destination available)
                   1059: 
                   1060:         mov     ulBlockHeight,edi
                   1061: 
                   1062:         sub     ulCurrentSrcScan,edi    ;We have to adjust our current scans
                   1063:         sub     ulCurrentDestScan,edi
                   1064: 
                   1065: ; Now copy the puppy:
                   1066: 
                   1067:         call    pfnCopyBlocks
                   1068: 
                   1069: ; See if we're done:
                   1070: 
                   1071: bot_1RW_see_if_done:
                   1072:         mov     edi,ulCurrentDestScan
                   1073:         cmp     edi,ulLastDestScan
                   1074:         jle     all_done
                   1075: 
                   1076:         mov     ebx,ppdev
                   1077: 
                   1078: ; Map bank containing the top destination scan line into window.
                   1079: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1080: 
                   1081:         dec     edi
                   1082:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>, \
                   1083:                 <ebx,edi,JustifyTop>
                   1084:         inc     edi
                   1085: 
                   1086:         jmp     bot_1RW_init_bank_mapped
                   1087: 
                   1088: ;-----------------------------------------------------------------------;
                   1089: ; Banking for 1R/1W or 2R/W adapters, top to bottom.
                   1090: ;
                   1091: ; Input:
                   1092: ;       ulCurrentSrcScan
                   1093: ;       ulCurrentDestScan
                   1094: ;       ulLastDestScan
                   1095: ;       Plus some other stuff for split rasters and block copiers
                   1096: ;-----------------------------------------------------------------------;
                   1097:         align   4
                   1098:         public  top_to_bottom_2RW
                   1099: top_to_bottom_2RW:
                   1100: 
                   1101: ; We're going top to bottom. Map in the destination, top-justified.
                   1102: 
                   1103:         mov     ebx,ppdev
                   1104:         mov     edi,ulCurrentDestScan
                   1105:         mov     esi,ulCurrentSrcScan
                   1106: 
                   1107:         cmp     edi,[ebx].pdev_rcl2PlanarClipD.yTop
                   1108:         jl      short top_2RW_map_init_dest_bank
                   1109: 
                   1110:         cmp     edi,[ebx].pdev_rcl2PlanarClipD.yBottom
                   1111:         jl      short top_2RW_init_dest_bank_mapped
                   1112: 
                   1113: top_2RW_map_init_dest_bank:
                   1114: 
                   1115: ; Map bank containing the top destination scan line into window.
                   1116: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1117: 
                   1118:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1119:                 <ebx,edi,JustifyTop,MapDestBank>
                   1120: 
                   1121: top_2RW_init_dest_bank_mapped:
                   1122: 
                   1123:         cmp     esi,[ebx].pdev_rcl2PlanarClipS.yTop
                   1124:         jl      short top_2RW_map_init_src_bank
                   1125: 
                   1126:         cmp     esi,[ebx].pdev_rcl2PlanarClipS.yBottom
                   1127:         jl      short top_2RW_main_loop
                   1128: 
                   1129: top_2RW_map_init_src_bank:
                   1130: 
                   1131: ; Map bank containing the top source scan line into window.
                   1132: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1133: 
                   1134:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1135:                 <ebx,esi,JustifyTop,MapSourceBank>
                   1136: 
                   1137: top_2RW_main_loop:
                   1138:         mov     ecx,[ebx].pdev_rcl2PlanarClipD.yBottom
                   1139:         mov     edx,ulLastDestScan
                   1140: 
                   1141:         sub     ecx,edx
                   1142:         sbb     eax,eax
                   1143:         and     eax,ecx
                   1144:         add     edx,eax                 ;edx = min(ulLastDestScan,
                   1145:                                         ;  ppdev->rcl2PlanarClipD.bottom)
                   1146: 
                   1147:         mov     ecx,[ebx].pdev_rcl2PlanarClipS.yBottom
                   1148: 
                   1149:         sub     edx,edi                 ;edx = available scans in destination
                   1150:                                         ;  bank
                   1151:         sub     ecx,esi                 ;ecx = available scans in source bank
                   1152: 
                   1153:         sub     ecx,edx
                   1154:         sbb     eax,eax
                   1155:         and     eax,ecx
                   1156:         add     edx,eax
                   1157: 
                   1158:         mov     ulBlockHeight,edx       ;ulBlockHeight = min(source available,
                   1159:                                         ;  dest available)
                   1160: 
                   1161:         add     esi,edx                 ;adjust our currents scans accordingly
                   1162:         add     edi,edx
                   1163:         mov     ulCurrentSrcScan,esi
                   1164:         mov     ulCurrentDestScan,edi
                   1165: 
                   1166: ; Do the actual copy:
                   1167: 
                   1168:         call    pfnCopyBlocks
                   1169: 
                   1170:         mov     edi,ulCurrentDestScan   ;check if done
                   1171:         cmp     edi,ulLastDestScan
                   1172:         jge     all_done
                   1173: 
                   1174:         mov     ebx,ppdev
                   1175: 
                   1176: ; We'll have to map a new source bank, destination bank, or both:
                   1177: 
                   1178:         mov     esi,ulCurrentSrcScan
                   1179:         cmp     edi,[ebx].pdev_rcl2PlanarClipD.yBottom
                   1180:         jl      short top_2RW_map_next_src_bank
                   1181: 
                   1182: ; Map bank containing the top destination scan line into window.
                   1183: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1184: 
                   1185:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1186:                 <ebx,edi,JustifyTop,MapDestBank>
                   1187: 
                   1188:         cmp     esi,[ebx].pdev_rcl2PlanarClipS.yBottom
                   1189:         jl      short top_2RW_main_loop
                   1190: 
                   1191: top_2RW_map_next_src_bank:
                   1192: 
                   1193: ; Map bank containing the top source scan line into window.
                   1194: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1195: 
                   1196:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1197:                 <ebx,esi,JustifyTop,MapSourceBank>
                   1198: 
                   1199:         jmp     short top_2RW_main_loop
                   1200: 
                   1201: ;-----------------------------------------------------------------------;
                   1202: ; Banking for 1R/1W or 2R/W adapters, bottom to top.
                   1203: ;
                   1204: ; Input:
                   1205: ;       ulCurrentSrcScan
                   1206: ;       ulCurrentDestScan
                   1207: ;       ulLastDestScan
                   1208: ;       Plus some other stuff for split rasters and block copiers
                   1209: ;-----------------------------------------------------------------------;
                   1210:         align   4
                   1211:         public  bottom_to_top_2RW
                   1212: bottom_to_top_2RW:
                   1213: 
                   1214: ; We're going bottom to top. Map in the destination, bottom-justified.
                   1215: 
                   1216:         mov     ebx,ppdev
                   1217:         mov     edi,ulCurrentDestScan   ; 1 more than actual destination scan
                   1218:         mov     esi,ulCurrentSrcScan    ; 1 more than actual source scan
                   1219: 
                   1220:         cmp     edi,[ebx].pdev_rcl2PlanarClipD.yTop
                   1221:         jle     short bot_2RW_map_init_dest_bank
                   1222: 
                   1223:         cmp     edi,[ebx].pdev_rcl2PlanarClipD.yBottom
                   1224:         jle     short bot_2RW_init_dest_bank_mapped
                   1225: 
                   1226: bot_2RW_map_init_dest_bank:
                   1227: 
                   1228: ; Map bank containing the top destination scan line into window.
                   1229: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1230: 
                   1231:         dec     edi
                   1232:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1233:                 <ebx,edi,JustifyBottom,MapDestBank>
                   1234:         inc     edi
                   1235: 
                   1236: bot_2RW_init_dest_bank_mapped:
                   1237: 
                   1238:         cmp     esi,[ebx].pdev_rcl2PlanarClipS.yTop
                   1239:         jle     short bot_2RW_map_init_src_bank
                   1240: 
                   1241:         cmp     esi,[ebx].pdev_rcl2PlanarClipS.yBottom
                   1242:         jle     short bot_2RW_main_loop
                   1243: 
                   1244: bot_2RW_map_init_src_bank:
                   1245: 
                   1246: ; Map bank containing the top source scan line into window.
                   1247: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1248: 
                   1249:         dec     esi
                   1250:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1251:                 <ebx,esi,JustifyBottom,MapSourceBank>
                   1252:         inc     esi
                   1253: 
                   1254: bot_2RW_main_loop:
                   1255:         mov     ecx,[ebx].pdev_rcl2PlanarClipD.yTop
                   1256:         mov     edx,ulLastDestScan
                   1257: 
                   1258:         cmp     edx,ecx
                   1259:         jg      @F
                   1260:         mov     edx,ecx                 ;edx = max(ulLastDestScan,
                   1261: @@:                                     ;  ppdev->rcl2PlanarClipD.top)
                   1262: 
                   1263:         sub     edi,edx                 ;edi = available scans in destination
                   1264:                                         ;  bank
                   1265:         sub     esi,[ebx].pdev_rcl2PlanarClipS.yTop
                   1266:                                         ;esi = available scans in source bank
                   1267: 
                   1268:         sub     esi,edi
                   1269:         sbb     eax,eax
                   1270:         and     eax,esi
                   1271:         add     edi,eax
                   1272: 
                   1273:         mov     ulBlockHeight,edi       ;ulBlockHeight = min(source available,
                   1274:                                         ;  dest available)
                   1275: 
                   1276:         sub     ulCurrentSrcScan,edi    ;adjust our current scans
                   1277:         sub     ulCurrentDestScan,edi
                   1278: 
                   1279: ; Do the actual copy:
                   1280: 
                   1281:         call    pfnCopyBlocks
                   1282: 
                   1283:         mov     edi,ulCurrentDestScan   ;check if done
                   1284:         cmp     edi,ulLastDestScan
                   1285:         jle     all_done
                   1286: 
                   1287:         mov     ebx,ppdev
                   1288: 
                   1289: ; We'll have to map a new source bank, destination bank, or both:
                   1290: 
                   1291:         mov     esi,ulCurrentSrcScan
                   1292:         cmp     edi,[ebx].pdev_rcl2PlanarClipD.yTop
                   1293:         jg      short bot_2RW_map_next_src_bank
                   1294: 
                   1295: ; Map bank containing the top destination scan line into window.
                   1296: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1297: 
                   1298:         dec     edi
                   1299:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1300:                 <ebx,edi,JustifyBottom,MapDestBank>
                   1301:         inc     edi
                   1302: 
                   1303:         cmp     esi,[ebx].pdev_rcl2PlanarClipS.yTop
                   1304:         jg      short bot_2RW_main_loop
                   1305: 
                   1306: bot_2RW_map_next_src_bank:
                   1307: 
                   1308: ; Map bank containing the top source scan line into window.
                   1309: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions.
                   1310: 
                   1311:         dec     esi
                   1312:         ptrCall <dword ptr [ebx].pdev_pfnPlanarControl2>, \
                   1313:                 <ebx,esi,JustifyBottom,MapSourceBank>
                   1314:         inc     esi
                   1315: 
                   1316:         jmp     short bot_2RW_main_loop
                   1317: 
                   1318: ;=======================================================================;
                   1319: ;=========================== Block Copiers =============================;
                   1320: ;=======================================================================;
                   1321: 
                   1322: ;-----------------------------------------------------------------------;
                   1323: ; Input:
                   1324: ;       Direction flag  - set to the appropriate direction
                   1325: ;       ulMiddleSrc     - offset in bitmap to source
                   1326: ;       ulMiddleDest    - offset in bitmap to destination
                   1327: ;       lMiddleDelta    - distance from end of current scan to start of next
                   1328: ;       ulBlockHeight   - # of scans to copy
                   1329: ;       cjMiddle        - # of planar bytes to copy on every scan
                   1330: ;
                   1331: ; Output:
                   1332: ;       Advances ulMiddleSrc and ulMiddleDest to next strip
                   1333: ;-----------------------------------------------------------------------;
                   1334: 
                   1335:         align   4
                   1336:         public  copy_middle_block
                   1337: copy_middle_block:
                   1338: 
                   1339: ; We only have to reset which planes are enabled if we do edges too:
                   1340: 
                   1341:         mov     edx,VGA_BASE + SEQ_DATA
                   1342:         mov     al,MM_ALL
                   1343:         out     dx,al
                   1344: 
                   1345:         align   4
                   1346: copy_just_middle_block:
                   1347: 
                   1348: ; Calculate full start addresses:
                   1349: 
                   1350:         mov     edi,ppdev
                   1351:         mov     eax,cjMiddle
                   1352:         mov     ebx,ulBlockHeight
                   1353:         mov     edx,lMiddleDelta
                   1354:         mov     esi,[edi].pdev_pvBitmapStart2WindowS
                   1355:         mov     edi,[edi].pdev_pvBitmapStart2WindowD
                   1356:         add     esi,ulMiddleSrc
                   1357:         add     edi,ulMiddleDest
                   1358: 
                   1359:         SET_UP_UNROLL_VARS ebx,ecx,ebx,pfnCopyMiddleEntry, \
                   1360:                                 LOOP_UNROLL_SHIFT
                   1361: 
                   1362:         jmp     ecx
                   1363: 
                   1364:         UNROLL_LOOP_ENTRY_TABLE pfnCopyMiddleEntry,MIDDLE, \
                   1365:                                 LOOP_UNROLL_COUNT
                   1366: 
                   1367: COPY_MIDDLE macro ENTRY_LABEL,ENTRY_INDEX
                   1368: &ENTRY_LABEL&ENTRY_INDEX&:
                   1369:         mov     ecx,eax
                   1370:         rep     movsb
                   1371:         add     esi,edx
                   1372:         add     edi,edx
                   1373:         endm    ;-----------------------------------;
                   1374: 
                   1375: ;  EAX = # of bytes to copy
                   1376: ;  EBX = count of unrolled loop iterations
                   1377: ;  EDX = offset from end of one scan's fill to start of next
                   1378: ;  ESI = source address from which to copy
                   1379: ;  EDI = target address to which to copy
                   1380: 
                   1381:         align   4
                   1382: middle_loop:
                   1383:         UNROLL_LOOP     COPY_MIDDLE,MIDDLE,LOOP_UNROLL_COUNT
                   1384:         dec     ebx
                   1385:         jnz     middle_loop
                   1386: 
                   1387: ; get ready for next time:
                   1388: 
                   1389:         mov     ecx,ppdev
                   1390:         sub     esi,[ecx].pdev_pvBitmapStart2WindowS
                   1391:         sub     edi,[ecx].pdev_pvBitmapStart2WindowD
                   1392:         mov     ulMiddleSrc,esi
                   1393:         mov     ulMiddleDest,edi
                   1394: 
                   1395:         PLAIN_RET
                   1396: 
                   1397: ;-----------------------------------------------------------------------;
                   1398: ; Input:
                   1399: ;       ulLeftSrc     - offset in bitmap to source
                   1400: ;       ulLeftDest    - offset in bitmap to destination
                   1401: ;       lDelta        - distance from between planar scans
                   1402: ;       ulBlockHeight - # of scans to copy
                   1403: ;
                   1404: ; Output:
                   1405: ;       Advances ulLeftSrc and ulLeftDest to next strip
                   1406: ;-----------------------------------------------------------------------;
                   1407: 
                   1408:         align   4
                   1409:         public  copy_left_block
                   1410: copy_left_block:
                   1411: 
                   1412: ; Set left mask by disabling some planes:
                   1413: 
                   1414:         mov     edx,VGA_BASE + SEQ_DATA
                   1415:         mov     eax,ulLeftMask
                   1416:         out     dx,al
                   1417: 
                   1418: ; Calculate full start addresses:
                   1419: 
                   1420:         mov     ecx,ppdev
                   1421:         mov     ebx,ulBlockHeight
                   1422:         mov     edx,lDelta
                   1423:         mov     esi,[ecx].pdev_pvBitmapStart2WindowS
                   1424:         mov     edi,[ecx].pdev_pvBitmapStart2WindowD
                   1425:         add     esi,ulLeftSrc
                   1426:         add     edi,ulLeftDest
                   1427: 
                   1428:         SET_UP_UNROLL_VARS ebx,eax,ebx,pfnCopyLeftEntry, \
                   1429:                                 LOOP_UNROLL_SHIFT
                   1430: 
                   1431:         jmp     eax
                   1432: 
                   1433:         UNROLL_LOOP_ENTRY_TABLE pfnCopyLeftEntry,LEFT, \
                   1434:                                 LOOP_UNROLL_COUNT
                   1435: 
                   1436: COPY_LEFT macro ENTRY_LABEL,ENTRY_INDEX
                   1437: &ENTRY_LABEL&ENTRY_INDEX&:
                   1438:         mov     al,[esi]
                   1439:         mov     [edi],al
                   1440:         add     esi,edx
                   1441:         add     edi,edx
                   1442:         endm    ;-----------------------------------;
                   1443: 
                   1444: ;  EBX = count of unrolled loop iterations
                   1445: ;  EDX = offset from one scan to next
                   1446: ;  ESI = source address from which to copy
                   1447: ;  EDI = target address to which to copy
                   1448: 
                   1449:         align   4
                   1450: left_loop:
                   1451:         UNROLL_LOOP     COPY_LEFT,LEFT,LOOP_UNROLL_COUNT
                   1452:         dec     ebx
                   1453:         jnz     left_loop
                   1454: 
                   1455: ; get ready for next time:
                   1456: 
                   1457:         sub     esi,[ecx].pdev_pvBitmapStart2WindowS
                   1458:         sub     edi,[ecx].pdev_pvBitmapStart2WindowD
                   1459:         mov     ulLeftSrc,esi
                   1460:         mov     ulLeftDest,edi
                   1461: 
                   1462:         PLAIN_RET
                   1463: 
                   1464: ;-----------------------------------------------------------------------;
                   1465: ; Input:
                   1466: ;       ulRightSrc    - offset in bitmap to source
                   1467: ;       ulRightDest   - offset in bitmap to destination
                   1468: ;       lDelta        - distance from between planar scans
                   1469: ;       ulBlockHeight - # of scans to copy
                   1470: ;
                   1471: ; Output:
                   1472: ;       Advances ulRightSrc and ulRightDest to next strip
                   1473: ;-----------------------------------------------------------------------;
                   1474: 
                   1475:         align   4
                   1476:         public  copy_right_block
                   1477: copy_right_block:
                   1478: 
                   1479: ; Set right mask by disabling some planes:
                   1480: 
                   1481:         mov     edx,VGA_BASE + SEQ_DATA
                   1482:         mov     eax,ulRightMask
                   1483:         out     dx,al
                   1484: 
                   1485: ; Calculate full start addresses:
                   1486: 
                   1487:         mov     ecx,ppdev
                   1488:         mov     ebx,ulBlockHeight
                   1489:         mov     edx,lDelta
                   1490:         mov     esi,[ecx].pdev_pvBitmapStart2WindowS
                   1491:         mov     edi,[ecx].pdev_pvBitmapStart2WindowD
                   1492:         add     esi,ulRightSrc
                   1493:         add     edi,ulRightDest
                   1494: 
                   1495:         SET_UP_UNROLL_VARS ebx,eax,ebx,pfnCopyRightEntry, \
                   1496:                                 LOOP_UNROLL_SHIFT
                   1497: 
                   1498:         jmp     eax
                   1499: 
                   1500:         UNROLL_LOOP_ENTRY_TABLE pfnCopyRightEntry,RIGHT, \
                   1501:                                 LOOP_UNROLL_COUNT
                   1502: 
                   1503: COPY_RIGHT macro ENTRY_LABEL,ENTRY_INDEX
                   1504: &ENTRY_LABEL&ENTRY_INDEX&:
                   1505:         mov     al,[esi]
                   1506:         mov     [edi],al
                   1507:         add     esi,edx
                   1508:         add     edi,edx
                   1509:         endm    ;-----------------------------------;
                   1510: 
                   1511: ;  EBX = count of unrolled loop iterations
                   1512: ;  EDX = offset from one scan to next
                   1513: ;  ESI = source address from which to copy
                   1514: ;  EDI = target address to which to copy
                   1515: 
                   1516:         align   4
                   1517: right_loop:
                   1518:         UNROLL_LOOP     COPY_RIGHT,RIGHT,LOOP_UNROLL_COUNT
                   1519:         dec     ebx
                   1520:         jnz     right_loop
                   1521: 
                   1522: ; get ready for next time:
                   1523: 
                   1524:         sub     esi,[ecx].pdev_pvBitmapStart2WindowS
                   1525:         sub     edi,[ecx].pdev_pvBitmapStart2WindowD
                   1526:         mov     ulRightSrc,esi
                   1527:         mov     ulRightDest,edi
                   1528: 
                   1529:         PLAIN_RET
                   1530: 
                   1531: ;-----------------------------------------------------------------------;
                   1532: 
                   1533: endProc vPlanarCopyBits
                   1534: 
                   1535:         end
                   1536: 

unix.superglobalmegacorp.com

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