|
|
1.1 ! root 1: ;---------------------------Module-Header------------------------------; ! 2: ; Module Name: restscrn.asm ! 3: ; ! 4: ; Copyright (c) 1992 Microsoft Corporation ! 5: ;-----------------------------------------------------------------------; ! 6: ;-----------------------------------------------------------------------; ! 7: ; VOID vRestoreScreenBitsFromMemory(PDEVSURF pdsurf, PRECTL prcl, ! 8: ; PVOID pjSrcBuffer, ULONG ulRestoreWidthInBytes, ! 9: ; ULONG ulSrcDelta); ! 10: ; Input: ! 11: ; pdsurf - surface to which to copy ! 12: ; prcl - pointer to rectangle to which to copy ! 13: ; pjSrcBuffer - pointer to source memory buffer. Should have the same ! 14: ; dword alignment as the dest rect left edge does in screen ! 15: ; memory ! 16: ; ulRestoreWidthInBytes - # of bytes to restore per scan (including any ! 17: ; partial edges) ! 18: ; ulSrcDelta - distance from end of one source scan to start of next. ! 19: ; together with ulRestoreWidthInBytes, should maintain ! 20: ; dword alignment between source and dest ! 21: ; ! 22: ; Copies a rectangle from a memory buffer to VGA memory. ! 23: ; ! 24: ;-----------------------------------------------------------------------; ! 25: ; ! 26: ; Note: Assumes all rectangles have positive heights and widths. Will not ! 27: ; work properly if this is not the case. ! 28: ; ! 29: ;-----------------------------------------------------------------------; ! 30: ; ! 31: ; Note: The rectangle is restored from interleaved-scan format; all four planes ! 32: ; of one scan are saved together, then all four planes of the next scan, ! 33: ; and so on. This is done for maximum restoration efficiency. Planes are ! 34: ; saved in order 3, 2, 1, 0: ! 35: ; ! 36: ; Scan n, plane 3 ! 37: ; Scan n, plane 2 ! 38: ; Scan n, plane 1 ! 39: ; Scan n, plane 0 ! 40: ; Scan n+1, plane 3 ! 41: ; Scan n+1, plane 2 ! 42: ; Scan n+1, plane 1 ! 43: ; Scan n+1, plane 0 ! 44: ; : ! 45: ; ! 46: ; There may be padding on either edge of the saved bits in the destination ! 47: ; buffer, so that the destination can be dword aligned with the source. ! 48: ; ! 49: ;-----------------------------------------------------------------------; ! 50: ;Additional optimizations: ! 51: ; ! 52: ; Could break out separate scan copy code with and without edge handling. ! 53: ; (Possibly by threading the desired operations, or by having many separate ! 54: ; optimizations.) ! 55: ; ! 56: ; Could handle odd bytes to dword align more efficiently, by having separate ! 57: ; optimizations for various alignment widths, thereby avoiding starting REP ! 58: ; and getting word accesses for 2 and 3 wide cases. Most VGAs are 8 or 16 ! 59: ; bit devices, and for them, using MOVSB/REP MOVSW/MOVSB might actually be ! 60: ; faster, especially because it's easier to break out optimizations. ! 61: ; ! 62: ; Could end all scan handlers with loop bottom code. ! 63: ; ! 64: ; Could do more scans in one plane before doing next plane, to avoid ! 65: ; slow OUTs. This could cause color effects, but that might be avoidable ! 66: ; by scaling the # of scans done per plane to the width of the rectangle. ! 67: ; ! 68: ;-----------------------------------------------------------------------; ! 69: ! 70: ! 71: .386 ! 72: ! 73: ifndef DOS_PLATFORM ! 74: .model small,c ! 75: else ! 76: ifdef STD_CALL ! 77: .model small,c ! 78: else ! 79: .model small,pascal ! 80: endif; STD_CALL ! 81: endif; DOS_PLATFORM ! 82: ! 83: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT ! 84: assume fs:nothing,gs:nothing ! 85: ! 86: .xlist ! 87: include stdcall.inc ;calling convention cmacros ! 88: include i386\egavga.inc ! 89: include i386\strucs.inc ! 90: ! 91: .list ! 92: ! 93: .data ! 94: ! 95: ;-----------------------------------------------------------------------; ! 96: ; Masks used to do left and right edge clipping for various alignments. ! 97: ; Low byte = destination mask, high byte = source mask. ! 98: ;-----------------------------------------------------------------------; ! 99: align 2 ! 100: usLeftMasks label word ! 101: dw 0ff00h, 07f80h, 03fc0h, 01fe0h, 00ff0h, 007f8h, 003fch, 001feh ! 102: ! 103: usRightMasks label word ! 104: dw 0ff00h, 0807fh, 0c03fh, 0e01fh, 0f00fh, 0f807h, 0fc03h, 0fe01h ! 105: ! 106: ;-----------------------------------------------------------------------; ! 107: ; Same as above, but dest masks only, and whole byte case is represented ! 108: ; as 0ffh rather than 0. Used for 1-byte-wide cases. ! 109: ;-----------------------------------------------------------------------; ! 110: jLeftMasks label byte ! 111: db 0ffh, 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0fch, 0feh ! 112: ! 113: jRightMasks label byte ! 114: db 0ffh, 07fh, 03fh, 01fh, 00fh, 007h, 003h, 001h ! 115: ! 116: .code ! 117: ! 118: _TEXT$03 SEGMENT DWORD USE32 PUBLIC 'CODE' ! 119: ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING ! 120: ! 121: ;-----------------------------------------------------------------------; ! 122: ! 123: cProc vRestoreScreenBitsFromMemory,20,< \ ! 124: uses esi edi ebx, \ ! 125: pdsurf:ptr, \ ! 126: prcl:ptr, \ ! 127: pjSrcBuffer:ptr, \ ! 128: ulRestoreWidthInBytes:dword, \ ! 129: ulSrcDelta:dword > ! 130: ! 131: local ulCurrentTopScan :dword ;top scan line to copy to in current ! 132: ; bank ! 133: local ulBottomScan :dword ;bottom scan line of rectangle to which ! 134: ; to copy ! 135: local pjDstStart :dword ;destination address ! 136: local ulDstDelta :dword ;distance from end of dest scan to ! 137: ; start of next ! 138: local ulBlockHeight :dword ;# of scans to copy in block ! 139: local ulLeadingBytes :dword ;# of leading bytes to copy per scan ! 140: local ulMiddleDwords :dword ;# of dwords to copy per scan ! 141: local ulTrailingBytes :dword ;# of trailing bytes to copy per scan ! 142: local pfnCopyVector :dword ;pointer to inner loop routine to copy ! 143: ; from buffer to screen ! 144: local ulLeftMask :dword ;2 byte masks for left edge clipping ! 145: ; (low byte = dest mask, ! 146: ; high byte = src mask) ! 147: local ulRightMask :dword ;2 byte masks for right edge clipping ! 148: ! 149: ;-----------------------------------------------------------------------; ! 150: ; Leave the GC Index pointing to the Read Map for the rest of this routine. ! 151: ;-----------------------------------------------------------------------; ! 152: ! 153: mov edx,VGA_BASE + GRAF_ADDR ! 154: mov al,GRAF_READ_MAP ! 155: out dx,al ! 156: ! 157: ;-----------------------------------------------------------------------; ! 158: ; Set up local variables. ! 159: ;-----------------------------------------------------------------------; ! 160: ! 161: mov edi,prcl ;point to rectangle from which to copy ! 162: mov esi,pdsurf ;point to surface from which to copy ! 163: ! 164: mov eax,[edi].yBottom ! 165: mov ulBottomScan,eax ;bottom scan line of source rect ! 166: ! 167: mov eax,[esi].dsurf_lNextScan ! 168: sub eax,ulRestoreWidthInBytes ! 169: mov ulDstDelta,eax ;distance from end of one scan's bits to save ! 170: ; to start of next scan's in display memory ! 171: ! 172: ;-----------------------------------------------------------------------; ! 173: ; Figure out the left and right clip masks. If either or both edges are ! 174: ; solid, add them into the whole bytes. ! 175: ;-----------------------------------------------------------------------; ! 176: ! 177: mov ebx,[edi].xLeft ! 178: mov ecx,[edi].xRight ! 179: mov edx,ebx ! 180: lea eax,[ecx-1] ! 181: and ebx,0111b ! 182: and ecx,0111b ! 183: ! 184: and edx,not 0111b ! 185: sub eax,edx ! 186: shr eax,3 ;width in bytes - 1 ! 187: ;only 1 byte wide? ! 188: jnz short @F ;no ! 189: ;1 byte wide; special case ! 190: mov al,jLeftMasks[ebx] ;look up left dest mask ! 191: and al,jRightMasks[ecx] ;factor in right dest mask ! 192: mov ah,0ffh ! 193: mov ebx,offset copy_from_buffer_l_whole_only ;assume whole byte ! 194: xor ah,al ;calculate matching dest mask ! 195: ;is this single byte a whole byte? ! 196: jz set_copy_vector ;yes, select whole byte optimization ! 197: ;no, select partial byte optimization ! 198: mov ebx,offset copy_from_buffer_l_partial_only ! 199: mov ulLeftMask,eax ! 200: jmp set_copy_vector ! 201: ! 202: align 4 ! 203: @@: ;more than 1 byte wide ! 204: ! 205: mov edx,ulRestoreWidthInBytes ! 206: ! 207: mov ax,usLeftMasks[ebx*2] ;look up left masks ! 208: mov ulLeftMask,eax ! 209: and al,al ;any left clipping? ! 210: jz short @F ;no, do as part of whole bytes ! 211: dec edx ;yes, don't count as whole byte ! 212: @@: ! 213: ! 214: ! 215: mov ax,usRightMasks[ecx*2] ;look up right masks ! 216: mov ulRightMask,eax ! 217: and al,al ;any right clipping? ! 218: jz short @F ;no, do as part of whole bytes ! 219: dec edx ;yes, don't count as whole byte ! 220: @@: ! 221: ! 222: ;-----------------------------------------------------------------------; ! 223: ; Set up for copying as much as possible via aligned dwords, and ! 224: ; select the most efficient loop for doing the copy, based on the copy ! 225: ; width, and on the necessity for leading and/or trailing bytes to ! 226: ; dword align. ! 227: ;-----------------------------------------------------------------------; ! 228: ! 229: cmp edx,8 ;if it's less than 8 bytes, just do a ! 230: ; straight byte copy. This means we ! 231: ; we only have to start 1 REP per line, ! 232: ; and performing this check guarantees ! 233: ; that we have at least 1 aligned dword ! 234: ; to copy in the dword loops ! 235: jb short copy_all_as_bytes ;do straight byte copy ! 236: mov eax,pjSrcBuffer ! 237: neg eax ! 238: and eax,3 ;# of bytes that have to be done as leading ! 239: ; bytes to dword align with source (note that ! 240: ; for performance, the source should be dword ! 241: ; aligned with the destination) ! 242: jz short copy_no_leading_bytes ;no leading bytes ! 243: ;leading bytes ! 244: mov ulLeadingBytes,eax ! 245: mov ebx,offset copy_from_buffer_l ;assume no trailing bytes ! 246: sub edx,eax ;# of bytes after leading bytes ! 247: mov eax,edx ! 248: shr eax,2 ;# of dwords that can be handled as aligned ! 249: ; dwords ! 250: mov ulMiddleDwords,eax ! 251: and edx,3 ;# of trailing bytes left after aligned dwords ! 252: ; copied ! 253: jz short set_copy_vector ;no trailing bytes ! 254: mov ulTrailingBytes,edx ! 255: mov ebx,offset copy_from_buffer_lt ;there are both leading and ! 256: ; trailing bytes ! 257: jmp short set_copy_vector ! 258: ! 259: align 4 ! 260: copy_no_leading_bytes: ! 261: mov ebx,offset copy_from_buffer ;assume no trailing bytes ! 262: mov eax,edx ! 263: shr eax,2 ;# of dwords that can be handled as aligned ! 264: ; dwords ! 265: mov ulMiddleDwords,eax ! 266: and edx,3 ;# of trailing bytes left after aligned dwords ! 267: ; copied ! 268: jz short set_copy_vector ;no trailing bytes ! 269: mov ulTrailingBytes,edx ! 270: mov ebx,offset copy_from_buffer_t ;there are trailing bytes ! 271: jmp short set_copy_vector ! 272: ! 273: ; It's so narrow that we'll forget about aligned dwords, and just do a straight ! 274: ; byte copy, which we'll handle by treating the entire copy as leading bytes. ! 275: align 4 ! 276: copy_all_as_bytes: ! 277: mov ulLeadingBytes,edx ! 278: mov ebx,offset copy_from_buffer_lonly ! 279: ! 280: set_copy_vector: ! 281: mov pfnCopyVector,ebx ! 282: ! 283: ;-----------------------------------------------------------------------; ! 284: ; Map in the bank containing the top scan to copy, if it's not mapped in ! 285: ; already. ! 286: ;-----------------------------------------------------------------------; ! 287: ! 288: mov eax,[edi].yTop ;top scan line of copy ! 289: mov ulCurrentTopScan,eax ;this will be the copy top in 1st bank ! 290: ! 291: cmp eax,[esi].dsurf_rcl1WindowClip.yTop ;is copy top less than ! 292: ; current bank? ! 293: jl short map_init_bank ;yes, map in proper bank ! 294: cmp eax,[esi].dsurf_rcl1WindowClip.yBottom ;copy top greater than ! 295: ; current bank? ! 296: jl short init_bank_mapped ;no, proper bank already mapped ! 297: map_init_bank: ! 298: ! 299: ; Map in the bank containing the top scan line of the copy. ! 300: ! 301: ptrCall <dword ptr [esi].dsurf_pfnBankControl>,<esi,eax,JustifyTop> ! 302: ! 303: init_bank_mapped: ! 304: ! 305: ;-----------------------------------------------------------------------; ! 306: ; Calculate the initial start address to which to copy. ! 307: ;-----------------------------------------------------------------------; ! 308: ! 309: mov eax,ulCurrentTopScan ;top scan line to copy to in current ! 310: ; bank ! 311: imul [esi].dsurf_lNextScan ;offset of starting scan line in bitmap ! 312: add eax,[esi].dsurf_pvBitmapStart ;start address of scan ! 313: mov ebx,[edi].xLeft ! 314: shr ebx,3 ;convert from pixel to byte address ! 315: add eax,ebx ;start dest address ! 316: mov pjDstStart,eax ! 317: ! 318: ;-----------------------------------------------------------------------; ! 319: ; Loop through and copy all bank blocks spanned by the destination ! 320: ; rectangle. ! 321: ; ! 322: ; Input: ! 323: ; ESI = pdsurf ! 324: ;-----------------------------------------------------------------------; ! 325: ! 326: copy_from_buffer_bank_loop: ! 327: ! 328: ; Copy this bank block to the buffer. ! 329: ! 330: ; Calculate # of scans in this bank. ! 331: ! 332: mov ebx,ulBottomScan ;bottom of dest rectangle ! 333: cmp ebx,[esi].dsurf_rcl1WindowClip.yBottom ! 334: ;which comes first, the bottom of the ! 335: ; dest rect or the bottom of the ! 336: ; current bank? ! 337: jl short @F ;dest bottom comes first, so copy to ! 338: ; that; this is the last bank in copy ! 339: mov ebx,[esi].dsurf_rcl1WindowClip.yBottom ! 340: ;bank bottom comes first; copy to ! 341: ; bottom of bank ! 342: @@: ! 343: sub ebx,ulCurrentTopScan ;# of scans to copy in this bank ! 344: mov ulBlockHeight,ebx ! 345: ! 346: mov esi,pjSrcBuffer ;point to start of source rect ! 347: ! 348: mov dh,VGA_BASE SHR 8 ;leave DH pointing to VGA_BASE ! 349: ! 350: ;-----------------------------------------------------------------------; ! 351: ; Loop through all scans in this block, copying all four planes of each ! 352: ; scan in turn, then doing the next scan. ! 353: ;-----------------------------------------------------------------------; ! 354: copy_to_buffer_scan_loop: ! 355: ! 356: mov bl,MM_C3 ;start by copying to plane 3 ! 357: ! 358: ;-----------------------------------------------------------------------; ! 359: ; Loop through all four planes, copying all scans in this block for each ! 360: ; plane in turn. ! 361: ;-----------------------------------------------------------------------; ! 362: ! 363: copy_to_buffer_plane_loop: ! 364: ! 365: mov dl,SEQ_DATA ! 366: mov al,bl ! 367: out dx,al ;set Map Mask to plane to which we're copying ! 368: ! 369: mov dl,GRAF_DATA ! 370: shr al,1 ! 371: cmp al,3 ! 372: adc al,-1 ! 373: out dx,al ! 374: ! 375: mov edi,pjDstStart ;point to start of dest buffer (scan starts ! 376: ; at same address in all planes) ! 377: jmp pfnCopyVector ;jump to the appropriate loop to copy plane ! 378: ! 379: ;-----------------------------------------------------------------------; ! 380: ; Copy loops, broken out by leading and trailing bytes needed for dword ! 381: ; alignment, plus one loop to perform a straight byte copy. ! 382: ; ! 383: ; Input: ! 384: ; ESI = initial source copy address ! 385: ; EDI = initial dest copy address ! 386: ;-----------------------------------------------------------------------; ! 387: ! 388: ; All bytes can be copied as aligned dwords (no leading or trailing whole ! 389: ; bytes). ! 390: align 4 ! 391: copy_from_buffer: ! 392: ! 393: ; Do the left edge byte, if there's a partial left edge byte. ! 394: ! 395: mov eax,ulLeftMask ;AL = dest mask, AH = source mask ! 396: and al,al ;any left mask? ! 397: jz short @F ;left edge is whole ! 398: and al,[edi] ;mask the dest ! 399: and ah,[esi] ;mask the source ! 400: inc esi ;point to next source byte ! 401: or al,ah ;combine the source and dest ! 402: stosb ;store the new byte ! 403: @@: ! 404: ! 405: ; Do the middle (whole) bytes. ! 406: ! 407: mov ecx,ulMiddleDwords ! 408: rep movsd ! 409: ! 410: ; Do the right edge byte, if there's a partial right edge byte. ! 411: ! 412: mov eax,ulRightMask ;AL = dest mask, AH = source mask ! 413: and al,al ;any left mask? ! 414: jz short @F ;right edge is whole ! 415: and al,[edi] ;mask the dest ! 416: and ah,[esi] ;mask the source ! 417: inc esi ;point to next source byte ! 418: or al,ah ;combine the source and dest ! 419: stosb ;store the new byte ! 420: @@: ! 421: ! 422: jmp copy_from_buffer_scan_done ! 423: ! 424: ; Leading odd whole bytes, but no trailing whole bytes. ! 425: align 4 ! 426: copy_from_buffer_l: ! 427: ! 428: ; Do the left edge byte, if there's a partial left edge byte. ! 429: ! 430: mov eax,ulLeftMask ;AL = dest mask, AH = source mask ! 431: and al,al ;any left mask? ! 432: jz short @F ;left edge is whole ! 433: and al,[edi] ;mask the dest ! 434: and ah,[esi] ;mask the source ! 435: inc esi ;point to next source byte ! 436: or al,ah ;combine the source and dest ! 437: stosb ;store the new byte ! 438: @@: ! 439: ! 440: ; Do the middle (whole) bytes. ! 441: ! 442: mov ecx,ulLeadingBytes ! 443: rep movsb ! 444: mov ecx,ulMiddleDwords ! 445: rep movsd ! 446: ! 447: ; Do the right edge byte, if there's a partial right edge byte. ! 448: ! 449: mov eax,ulRightMask ;AL = dest mask, AH = source mask ! 450: and al,al ;any left mask? ! 451: jz short @F ;right edge is whole ! 452: and al,[edi] ;mask the dest ! 453: and ah,[esi] ;mask the source ! 454: inc esi ;point to next source byte ! 455: or al,ah ;combine the source and dest ! 456: stosb ;store the new byte ! 457: @@: ! 458: ! 459: jmp copy_from_buffer_scan_done ! 460: ! 461: ; Trailing odd whole bytes, but no leading whole bytes. ! 462: align 4 ! 463: copy_from_buffer_t: ! 464: ! 465: ; Do the left edge byte, if there's a partial left edge byte. ! 466: ! 467: mov eax,ulLeftMask ;AL = dest mask, AH = source mask ! 468: and al,al ;any left mask? ! 469: jz short @F ;left edge is whole ! 470: and al,[edi] ;mask the dest ! 471: and ah,[esi] ;mask the source ! 472: inc esi ;point to next source byte ! 473: or al,ah ;combine the source and dest ! 474: stosb ;store the new byte ! 475: @@: ! 476: ! 477: ; Do the middle (whole) bytes. ! 478: ! 479: mov ecx,ulMiddleDwords ! 480: rep movsd ! 481: mov ecx,ulTrailingBytes ! 482: rep movsb ! 483: ! 484: ; Do the right edge byte, if there's a partial right edge byte. ! 485: ! 486: mov eax,ulRightMask ;AL = dest mask, AH = source mask ! 487: and al,al ;any left mask? ! 488: jz short @F ;right edge is whole ! 489: and al,[edi] ;mask the dest ! 490: and ah,[esi] ;mask the source ! 491: inc esi ;point to next source byte ! 492: or al,ah ;combine the source and dest ! 493: stosb ;store the new byte ! 494: @@: ! 495: ! 496: jmp copy_from_buffer_scan_done ! 497: ! 498: ; Only leading whole bytes (straight whole byte copy; no aligned dwords). ! 499: align 4 ! 500: copy_from_buffer_lonly: ! 501: ! 502: ; Do the left edge byte, if there's a partial left edge byte. ! 503: ! 504: mov eax,ulLeftMask ;AL = dest mask, AH = source mask ! 505: and al,al ;any left mask? ! 506: jz short @F ;left edge is whole ! 507: and al,[edi] ;mask the dest ! 508: and ah,[esi] ;mask the source ! 509: inc esi ;point to next source byte ! 510: or al,ah ;combine the source and dest ! 511: stosb ;store the new byte ! 512: @@: ! 513: ! 514: ; Do the middle (whole) bytes. ! 515: ! 516: mov ecx,ulLeadingBytes ! 517: rep movsb ! 518: ! 519: ; Do the right edge byte, if there's a partial right edge byte. ! 520: ! 521: mov eax,ulRightMask ;AL = dest mask, AH = source mask ! 522: and al,al ;any left mask? ! 523: jz short @F ;right edge is whole ! 524: and al,[edi] ;mask the dest ! 525: and ah,[esi] ;mask the source ! 526: inc esi ;point to next source byte ! 527: or al,ah ;combine the source and dest ! 528: stosb ;store the new byte ! 529: @@: ! 530: ! 531: jmp short copy_from_buffer_scan_done ! 532: ! 533: ; Only one masked byte; no whole bytes and no right byte. ! 534: align 4 ! 535: copy_from_buffer_l_partial_only: ! 536: ! 537: mov eax,ulLeftMask ;AL = dest mask, AH = source mask ! 538: and al,[edi] ;mask the dest ! 539: and ah,[esi] ;mask the source ! 540: inc esi ;point to next source byte ! 541: or al,ah ;combine the source and dest ! 542: stosb ;store the new byte ! 543: jmp short copy_from_buffer_scan_done ! 544: ! 545: ; Only one whole byte; no left byte and no right byte. ! 546: align 4 ! 547: copy_from_buffer_l_whole_only: ! 548: ! 549: movsb ;copy the one byte ! 550: jmp short copy_from_buffer_scan_done ! 551: ! 552: ; Leading and trailing odd whole bytes. ! 553: align 4 ! 554: copy_from_buffer_lt: ! 555: ! 556: ; Do the left edge byte, if there's a partial left edge byte. ! 557: ! 558: mov eax,ulLeftMask ;AL = dest mask, AH = source mask ! 559: and al,al ;any left mask? ! 560: jz short @F ;left edge is whole ! 561: and al,[edi] ;mask the dest ! 562: and ah,[esi] ;mask the source ! 563: inc esi ;point to next source byte ! 564: or al,ah ;combine the source and dest ! 565: stosb ;store the new byte ! 566: @@: ! 567: ! 568: ; Do the middle (whole) bytes. ! 569: ! 570: mov ecx,ulLeadingBytes ! 571: rep movsb ! 572: mov ecx,ulMiddleDwords ! 573: rep movsd ! 574: mov ecx,ulTrailingBytes ! 575: rep movsb ! 576: ! 577: ; Do the right edge byte, if there's a partial right edge byte. ! 578: ! 579: mov eax,ulRightMask ;AL = dest mask, AH = source mask ! 580: and al,al ;any left mask? ! 581: jz short @F ;right edge is whole ! 582: and al,[edi] ;mask the dest ! 583: and ah,[esi] ;mask the source ! 584: inc esi ;point to next source byte ! 585: or al,ah ;combine the source and dest ! 586: stosb ;store the new byte ! 587: @@: ! 588: ! 589: copy_from_buffer_scan_done: ! 590: ! 591: add esi,ulSrcDelta ;point to next source scan ! 592: shr bl,1 ;count down planes ! 593: jnz copy_to_buffer_plane_loop ! 594: ! 595: add edi,ulDstDelta ;point to next dest scan ! 596: mov pjDstStart,edi ! 597: dec ulBlockHeight ;count down scans ! 598: jnz copy_to_buffer_scan_loop ! 599: ! 600: ; Remember where we left off, for the next block. ! 601: ! 602: mov pjSrcBuffer,esi ! 603: ! 604: ;-----------------------------------------------------------------------; ! 605: ; See if there are more banks to do ! 606: ;-----------------------------------------------------------------------; ! 607: ! 608: mov esi,pdsurf ! 609: mov eax,[esi].dsurf_rcl1WindowClip.yBottom ;is the copy bottom in ! 610: cmp ulBottomScan,eax ; the current bank? ! 611: jle short copy_from_buffer_banks_done ;yes, so we're done ! 612: ;no, map in the next bank and copy it ! 613: mov ulCurrentTopScan,eax ;remember where the top of the bank ! 614: ; we're about to map in is (same as ! 615: ; bottom of bank we just did) ! 616: mov edx,[esi].dsurf_pvBitmapStart ! 617: sub pjDstStart,edx ;convert from address to offset within bitmap ! 618: ! 619: ptrCall <dword ptr [esi].dsurf_pfnBankControl>,<esi,eax,JustifyTop> ! 620: ;map in the bank ! 621: ! 622: ; Compute the starting address in this bank. ! 623: ; Note that the start of the bitmap will change each time through the ! 624: ; bank loop, because the start of the bitmap is varied to map the ! 625: ; desired scan line to the banking window. ! 626: ! 627: mov eax,[esi].dsurf_pvBitmapStart ! 628: add pjDstStart,eax ;address of next scan to draw ! 629: ! 630: ; Copy the new bank. ! 631: ! 632: jmp copy_from_buffer_bank_loop ! 633: ! 634: ! 635: ;-----------------------------------------------------------------------; ! 636: ; Done with all banks. ! 637: ; ! 638: ; At this point: ! 639: ; DX = VGA_BASE + GRAF_DATA ! 640: ;-----------------------------------------------------------------------; ! 641: align 4 ! 642: copy_from_buffer_banks_done: ! 643: ! 644: mov ax,(MM_ALL shl 8)+SEQ_MAP_MASK ;restore writability for all planes ! 645: mov dx,VGA_BASE+SEQ_ADDR ! 646: out dx,ax ! 647: ! 648: cRet vRestoreScreenBitsFromMemory ;done ! 649: ! 650: ;-----------------------------------------------------------------------; ! 651: ! 652: endProc vRestoreScreenBitsFromMemory ! 653: ! 654: _TEXT$03 ends ! 655: ! 656: end ! 657: ! 658:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.