|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.