|
|
1.1 ! root 1: ;---------------------------Module-Header------------------------------; ! 2: ; Module Name: rleblts.asm ! 3: ; ! 4: ; Copyright (c) 1992 Microsoft Corporation ! 5: ;-----------------------------------------------------------------------; ! 6: .386 ! 7: ! 8: ifndef DOS_PLATFORM ! 9: .model small,c ! 10: else ! 11: ifdef STD_CALL ! 12: .model small,c ! 13: else ! 14: .model small,pascal ! 15: endif; STD_CALL ! 16: endif; DOS_PLATFORM ! 17: ! 18: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT ! 19: assume fs:nothing,gs:nothing ! 20: ! 21: .xlist ! 22: include stdcall.inc ;calling convention cmacros ! 23: include i386\egavga.inc ! 24: include i386\strucs.inc ! 25: .list ! 26: ! 27: .code ! 28: ! 29: ;-------------------------------Macro-----------------------------------; ! 30: ; RleSetUp ! 31: ; ! 32: ; Set the EGA\VGA to write mode 2 (M_COLOR_WRITE). Initialize local vars ! 33: ; ! 34: ; Entry: ! 35: ; None ! 36: ; Returns: ! 37: ; ESI = pointer to the source bitmap ! 38: ; ! 39: ;-----------------------------------------------------------------------; ! 40: ! 41: RleSetUp macro ! 42: ! 43: cld ! 44: ! 45: mov dx,VGA_BASE + GRAF_ADDR ! 46: mov ax,(M_COLOR_WRITE shl 8) + GRAF_MODE ! 47: out dx,ax ! 48: ! 49: mov esi,pRleInfo ! 50: mov edi,[esi].RLE_prctlTrg ! 51: mov eax,[edi].xLeft ! 52: mov xStart,eax ! 53: mov eax,[esi].RLE_xBegin ! 54: mov xCurr,eax ! 55: mov eax,[edi].yBottom ! 56: dec eax ! 57: mov yCurr,eax ! 58: ! 59: mov eax,[esi].RLE_pulTranslate ! 60: mov pulXlate,eax ! 61: mov eax,[esi].RLE_prctlClip ! 62: mov prclClip,eax ! 63: mov eax,[esi].RLE_pjSrcBitsMax ! 64: mov pjSrcEnd,eax ! 65: mov ebx,[esi].RLE_pjTrg ! 66: ! 67: mov pjDst,ebx ! 68: mov esi,[esi].RLE_pjSrcBits ! 69: endm ! 70: ! 71: ;-------------------------------Macro-----------------------------------; ! 72: ; RleDelta ! 73: ; ! 74: ; Handle the Delta case. ! 75: ; ! 76: ; Entry: ! 77: ; ESI = pointer to the horz/vert offset of the source bitmap ! 78: ; Returns: ! 79: ; None ! 80: ; ! 81: ;-----------------------------------------------------------------------; ! 82: ! 83: RleDelta macro dest ! 84: ! 85: lodsw ! 86: movzx ecx,al ! 87: add xCurr,ecx ;x adjustment ! 88: ! 89: movzx eax,ah ! 90: sub yCurr,eax ;y adjustment ! 91: ! 92: mul lNextScan ! 93: sub pjDst,eax ! 94: jmp dest ! 95: endm ! 96: ! 97: ;-------------------------------Macro-----------------------------------; ! 98: ; RleExit ! 99: ; ! 100: ; Prepare the Rle routine to exit. Set the EGA/VGA to default write ! 101: ; mode. Save the current status in the RleInfo so we can continue ! 102: ; from where we left off if a complex clipping is encountered. ! 103: ; ! 104: ; Entry: ! 105: ; ESI = pointer pass the first run above the clipping rect ! 106: ; EBX = yCurr(y value of the first run above the clipping rect) ! 107: ; ECX = xCurr(x value of the first run above the clipping rect) ! 108: ; Returns: ! 109: ; None ! 110: ; ! 111: ;-----------------------------------------------------------------------; ! 112: ! 113: RleExit macro ! 114: ! 115: mov dx,VGA_BASE + GRAF_ADDR ! 116: mov ax,(M_PROC_WRITE shl 8) + GRAF_MODE ! 117: out dx,ax ! 118: ! 119: mov ax,0FF00h + GRAF_BIT_MASK ! 120: out dx,ax ;no mask ! 121: ! 122: mov edi,pRleInfo ;update for next call ! 123: dec esi ! 124: dec esi ! 125: mov [edi].RLE_pjSrcBits,esi ! 126: mov esi,[edi].RLE_prctlTrg ! 127: inc ebx ;make it exclusive ! 128: mov [esi].yBottom,ebx ! 129: mov eax,pjDst ! 130: mov [edi].RLE_pjTrg,eax ! 131: mov [edi].RLE_xBegin,ecx ! 132: endm ! 133: ! 134: ;-------------------------------Macro-----------------------------------; ! 135: ; Clip_Encoded ! 136: ; ! 137: ; Clip the current run in encoded mode against the clipping rect. ! 138: ; ! 139: ; Entry: ! 140: ; AH = pel color of this run ! 141: ; AL = number of pels of this run ! 142: ; Returns: ! 143: ; EAX = left coordinate if no clipping ! 144: ; ECX = left coordinate of the clipped run ! 145: ; EBX = right coordinate of the clipped run ! 146: ; ! 147: ;-----------------------------------------------------------------------; ! 148: ! 149: Clip_Encoded macro done, loop_start ! 150: ! 151: movzx edx,ah ;EDX = pel color ! 152: movzx eax,al ;EAX = number of pels ! 153: mov ecx,xCurr ;ECX = left coordinate ! 154: add xCurr,eax ;compute new x position ! 155: mov ebx,yCurr ! 156: ! 157: ; Check if y is inside the clipping range. ! 158: ! 159: mov edi,prclClip ! 160: cmp ebx,[edi].yTop ! 161: jb done ! 162: cmp ebx,[edi].yBottom ! 163: jae short loop_start ! 164: ! 165: ; Clip to the passed in clip rectangle. ! 166: ! 167: mov eax,ecx ! 168: cmp ecx,[edi].xLeft ! 169: jae short @F ! 170: mov ecx,[edi].xLeft ! 171: ! 172: @@: ! 173: mov ebx,xCurr ! 174: cmp ebx,[edi].xRight ! 175: jbe short @F ! 176: mov ebx,[edi].xRight ! 177: ! 178: @@: ! 179: cmp ebx,ecx ;clipped out if left and right crossed ! 180: jbe short loop_start ! 181: endm ! 182: ! 183: ;-------------------------------Macro-----------------------------------; ! 184: ; Draw_Encoded ! 185: ; ! 186: ; Write the current encoded run to the EGA/VGA. ! 187: ; ! 188: ; Entry: ! 189: ; EBX = right coordinate (exclusive) ! 190: ; ECX = left coordinate (inclusive) ! 191: ; EDX = pel color ! 192: ; Returns: ! 193: ; None ! 194: ; ! 195: ;-----------------------------------------------------------------------; ! 196: ! 197: Draw_Encoded macro loop_start ! 198: ! 199: call comp_masks ;compute bit masks ! 200: ! 201: shl eax,8 ;save right mask in high word ! 202: add edi,pjDst ! 203: ! 204: mov ebx,pulXlate ! 205: mov ebx,[ebx][edx*4] ! 206: ! 207: mov dx,VGA_BASE + GRAF_ADDR ! 208: ! 209: or ah,ah ;AH = left mask ! 210: jz short @F ! 211: ! 212: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits ! 213: out dx,ax ! 214: ! 215: mov al,bl ;write color ! 216: xchg [edi],al ! 217: inc edi ;update destination pointer ! 218: ! 219: @@: ! 220: or ecx,ecx ;ECX = inner loop count ! 221: jz short @F ! 222: ! 223: mov ax,0FF00h + GRAF_BIT_MASK ! 224: out dx,ax ;no mask ! 225: ! 226: mov al,bl ! 227: rep stosb ;write color ! 228: ! 229: @@: ! 230: shr eax,8 ;AH = right mask ! 231: or ah,ah ! 232: jz loop_start ! 233: ! 234: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits ! 235: out dx,ax ! 236: xchg [edi],bl ;write color ! 237: ! 238: jmp loop_start ! 239: endm ! 240: ! 241: ;-------------------------------Macro-----------------------------------; ! 242: ; Clip_Absolute ! 243: ; ! 244: ; Clip the current run in absolute mode against the clipping rect. ! 245: ; Compute initial bit mask and other vars for subsequent loop. ! 246: ; ! 247: ; Entry: ! 248: ; AH = number of pels of this run ! 249: ; Returns: ! 250: ; AL = GRAF_BIT_MASK ! 251: ; AH = bitmap for the first pel ! 252: ; EBX = pulXlate (pointer to the xlate table) ! 253: ; CH = 01000001b ! 254: ; EDI = pointer to destination byte to be altered ! 255: ; loop_count = loop count (number of pels to be altered) ! 256: ; ! 257: ;-----------------------------------------------------------------------; ! 258: ! 259: Clip_Absolute macro done,loop_end,loop_count ! 260: ! 261: movzx eax,ah ;EAX = number of pels ! 262: mov ecx,xCurr ;ECX = left coordinate ! 263: add xCurr,eax ! 264: ! 265: mov ebx,yCurr ! 266: ! 267: ; Check if y is inside the clipping range. ! 268: ! 269: mov edi,prclClip ! 270: cmp ebx,[edi].yTop ! 271: jb done ! 272: cmp ebx,[edi].yBottom ! 273: jae loop_end ! 274: ! 275: ; Check if x is inside the clipping range. ! 276: ! 277: cmp ecx,[edi].xRight ;check if x is in range ! 278: jae loop_end ! 279: ! 280: mov ebx,xCurr ;EBX = right coordinate ! 281: cmp ebx,[edi].xLeft ;can I not jump???!!! ! 282: jbe loop_end ! 283: ! 284: ; Clip to the passed in clip rectangle. ! 285: ! 286: cmp ecx,[edi].xLeft ! 287: mov cPreSrcAdv,0 ! 288: jae short @F ! 289: mov eax,[edi].xLeft ! 290: sub eax,ecx ;diff of left coor and prclClip->xLeft ! 291: mov cPreSrcAdv,eax ! 292: add ecx,eax ;ECX = left coordinate = prclClip->xLeft ! 293: ! 294: @@: ! 295: xor eax,eax ;diff of right coor and prclClip->xRight ! 296: cmp ebx,[edi].xRight ! 297: jbe short @F ! 298: mov eax,ebx ! 299: mov ebx,[edi].xRight ;EBX = right coor = prclClip->xRight ! 300: sub eax,ebx ! 301: ! 302: @@: ! 303: mov cPostSrcAdv,eax ! 304: sub ebx,ecx ;loop count ! 305: ! 306: mov edi,ecx ! 307: shr edi,3 ! 308: add edi,pjDst ;point to the first byte to write ! 309: ! 310: and ecx,00000111b ;Compute bit index for left side ! 311: mov ah,080h ;Compute bit mask ! 312: shr ah,cl ;AL = first pel bit mask ! 313: mov al,GRAF_BIT_MASK ! 314: mov loop_count,bl ;loop count < 0FFh ! 315: mov ch,01000001b ;for later use ! 316: mov ebx,pulXlate ! 317: endm ! 318: ! 319: ;-------------------------------Macro-----------------------------------; ! 320: ; RleEOL ! 321: ; ! 322: ; Handle the End of line case. ! 323: ; ! 324: ; Entry: ! 325: ; None. ! 326: ; Returns: ! 327: ; None. ! 328: ; ! 329: ;-----------------------------------------------------------------------; ! 330: ! 331: RleEOL macro loop_start ! 332: ! 333: mov eax,lNextScan ! 334: sub pjDst,eax ;adjust pjDst ! 335: dec yCurr ;adjust yCurr ! 336: mov eax,xStart ;adjust xCurr ! 337: mov xCurr,eax ! 338: jmp loop_start ! 339: endm ! 340: ! 341: ! 342: ;-------------------------------Macro-----------------------------------; ! 343: ; Set up banking-related variables, and make sure the bank for the ! 344: ; initial (bottom) scan line is mapped in. ! 345: ; ! 346: ; Entry: ! 347: ; None. ! 348: ; Returns: ! 349: ; EBX = pdsurf ! 350: ; ESI = pRleInfo ! 351: ; EDI = RLE_prctlClip ! 352: ; ! 353: ;-------------------------------Macro-----------------------------------; ! 354: ! 355: RleBankSetUp macro ! 356: local map_bank,bank_mapped ! 357: ! 358: mov esi,pRleInfo ! 359: mov ebx,[esi].Rle_pdsurfTrg ! 360: mov pdsurf,ebx ! 361: ! 362: mov eax,[ebx].dsurf_lNextScan ! 363: mov lNextScan,eax ! 364: ! 365: mov edi,[esi].RLE_prctlClip ! 366: mov eax,[edi].yTop ! 367: mov ulTrueClipTop,eax ;we blt until we reach this scan line ! 368: ! 369: ; Map in the bottom scan line of the clip rect. ! 370: ! 371: mov eax,[edi].yBottom ;bottom clip scan, exclusive ! 372: dec eax ;make it inclusive ! 373: cmp eax,[ebx].dsurf_rcl1WindowClip.yTop ! 374: jl short map_bank ! 375: cmp eax,[ebx].dsurf_rcl1WindowClip.yBottom ! 376: jl short bank_mapped ! 377: map_bank: ! 378: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyBottom> ! 379: bank_mapped: ! 380: ! 381: endm ! 382: ! 383: ! 384: ;-------------------------------Macro-----------------------------------; ! 385: ; Set up the screen pointer and clip the clip rect to the current bank. ! 386: ; ! 387: ; Entry: ! 388: ; EBX = pdsurf ! 389: ; ESI = pRleInfo ! 390: ; EDI = RLE_prctlClip ! 391: ; Returns: ! 392: ; None. ! 393: ; ! 394: ;-------------------------------Macro-----------------------------------; ! 395: ! 396: RleBankTop macro ! 397: ! 398: ; Convert the screen pointer from an offset within the bitmap to a virtual ! 399: ; address. ! 400: ! 401: mov eax,[ebx].dsurf_pvBitmapStart ! 402: add [esi].RLE_pjTrg,eax ! 403: ! 404: ; Set the clip rect top to MAX(top_of_bank,top_of_clip), to confine drawing to ! 405: ; this bank. ! 406: ! 407: mov eax,[ebx].dsurf_rcl1WindowClip.yTop ! 408: cmp ulTrueClipTop,eax ! 409: jl short @F ! 410: mov eax,ulTrueClipTop ! 411: @@: ! 412: mov [edi].yTop,eax ! 413: ! 414: endm ! 415: ! 416: ! 417: ;-------------------------------Macro-----------------------------------; ! 418: ; Check whether we've done the last bank spanned by this clip rect; exit ! 419: ; if so, map in the bank and continue if not. ! 420: ; ! 421: ; Entry: ! 422: ; None. ! 423: ; Returns: ! 424: ; EBX = pdsurf ! 425: ; ESI = pRleInfo ! 426: ; EDI = RLE_prctlClip ! 427: ; ! 428: ;-------------------------------Macro-----------------------------------; ! 429: ! 430: RleBankBottom macro loop_top,done ! 431: ! 432: ; Convert the screen pointer back to an offset within the bitmap. ! 433: ! 434: mov ebx,pdsurf ! 435: mov esi,pRleInfo ! 436: mov eax,[ebx].dsurf_pvBitmapStart ! 437: sub [esi].RLE_pjTrg,eax ! 438: ! 439: ; Have we reached the top bank involved in this blt? If so, done; if not, map ! 440: ; it in and blt the next bank. ! 441: ! 442: mov eax,[ebx].dsurf_rcl1WindowClip.yTop ! 443: cmp eax,ulTrueClipTop ! 444: jle &done ! 445: dec eax ;map in the bank above the current one ! 446: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyBottom> ! 447: ! 448: mov edi,[esi].RLE_prctlClip ;for RleBankTop ! 449: ! 450: jmp &loop_top ! 451: ! 452: endm ! 453: ! 454: ! 455: ;--------------------------Public-Routine-------------------------------; ! 456: ; vRle8ToVga ! 457: ; ! 458: ; Write an RLE8 bitmap onto the VGA device. ! 459: ; ! 460: ; Entry: ! 461: ; None. ! 462: ; Returns: ! 463: ; None ! 464: ; ! 465: ;-----------------------------------------------------------------------; ! 466: ! 467: cProc vRle8ToVga,4,< \ ! 468: uses esi edi ebx, \ ! 469: pRleInfo: ptr RLEINFO > ! 470: ! 471: local pjDst :ptr ! 472: local pulXlate :ptr ! 473: local xCurr :dword ! 474: local yCurr :dword ! 475: local xStart :dword ! 476: local cPreSrcAdv :dword ! 477: local cPostSrcAdv :dword ! 478: local prclClip :ptr RECTL ! 479: local pjSrcEnd :ptr ! 480: local pdsurf :ptr DEVSURF ! 481: local ulTrueClipTop :dword ! 482: local lNextScan : dword ! 483: ! 484: RleBankSetUp ;wrap a banking loop around everything ! 485: ! 486: rle8_bank_loop: ! 487: ! 488: RleBankTop ! 489: ! 490: RleSetUp ! 491: ! 492: rle8_loop: ! 493: cmp esi,pjSrcEnd ! 494: jae rle8_done ! 495: lodsw ;fetch a word from src RLE bitmap ! 496: ! 497: or al,al ! 498: jz rle8_escape ! 499: ! 500: rle8_encoded: ! 501: Clip_Encoded rle8_done,rle8_loop ! 502: Draw_Encoded rle8_loop ! 503: ! 504: rle8_escape: ! 505: cmp ah,2 ; First byte is 0, check the second byte. ! 506: ja short rle8_absolute ! 507: jb rle8_end_of_line_or_bitmap ! 508: ! 509: rle8_delta: ! 510: RleDelta rle8_loop ! 511: ! 512: rle8_absolute: ! 513: Clip_Absolute rle8_done,rle8_absolute_advance_src,cl ! 514: add esi,cPreSrcAdv ;advance esi to point to the clipped run ! 515: ! 516: ; I am doing a per pel loop rather than a per byte loop which writes 1 plane ! 517: ; at a time because it appears to me that most of the time we output 2 or ! 518: ; 3 pels per encounter of absolute mode. The logic here is simple and we can ! 519: ; stay with M_COLOR_WRITE mode all the time. ! 520: ! 521: rle8_absolute_loop: ! 522: mov dx,VGA_BASE + GRAF_ADDR ! 523: out dx,ax ;Set bitmask for altered bit ! 524: ! 525: movzx edx,byte ptr [esi] ;grab color for this pel ! 526: inc esi ! 527: ! 528: mov edx,[ebx][edx*4] ! 529: xchg [edi],dl ;write to destination ! 530: ! 531: ror ah,1 ;rotate bit mask for next pel ! 532: cmp ch,ah ;cmp bitmask with 01000001b ! 533: adc edi,0 ;advance edi if bitmask is 10000000b ! 534: ! 535: dec cl ;per pel loop ! 536: jnz short rle8_absolute_loop ! 537: mov eax,cPostSrcAdv ! 538: ! 539: rle8_absolute_advance_src: ! 540: add esi,eax ;advance src ptr for clipped out pels ! 541: bt esi,0 ;add 1 if not word aligned ! 542: adc esi,0 ! 543: jmp rle8_loop ! 544: ! 545: rle8_end_of_line_or_bitmap: ! 546: or ah,ah ! 547: jnz short rle8_end_of_bitmap ! 548: ! 549: rle8_end_of_line: ! 550: ! 551: RleEOL rle8_loop ! 552: ! 553: rle8_done: ! 554: RleExit ! 555: ! 556: RleBankBottom rle8_bank_loop,rle8_exit ;see if there are more banks ! 557: ; to do ! 558: align 4 ! 559: rle8_end_of_bitmap: ! 560: RleExit ! 561: rle8_exit: ! 562: cRet vRle8ToVga ! 563: ! 564: endProc vRle8ToVga ! 565: ! 566: ! 567: ;--------------------------Public-Routine-------------------------------; ! 568: ; vRle4ToVga ! 569: ; ! 570: ; Write an RLE4 bitmap onto the VGA device. ! 571: ; ! 572: ; Entry: ! 573: ; None ! 574: ; Returns: ! 575: ; None ! 576: ; ! 577: ;-----------------------------------------------------------------------; ! 578: ! 579: cProc vRle4ToVga,4,< \ ! 580: uses esi edi ebx, \ ! 581: pRleInfo: ptr RLEINFO > ! 582: ! 583: local pjDst :ptr ! 584: local pulXlate :ptr ! 585: local xCurr :dword ! 586: local yCurr :dword ! 587: local xStart :dword ! 588: local cPreSrcAdv :dword ! 589: local cPostSrcAdv :dword ! 590: local pjDstStart :ptr ! 591: local iPels :dword ! 592: local xMask :dword ! 593: local nPels :byte ! 594: local prclClip :ptr RECTL ! 595: local pjSrcEnd :ptr ! 596: local pdsurf :ptr DEVSURF ! 597: local ulTrueClipTop :dword ! 598: local lNextScan : dword ! 599: ! 600: RleBankSetUp ;wrap a banking loop around everything ! 601: ! 602: rle4_bank_loop: ! 603: ! 604: RleBankTop ! 605: ! 606: RleSetUp ! 607: ! 608: rle4_loop: ! 609: cmp esi,pjSrcEnd ! 610: jae rle4_done ! 611: lodsw ;fetch a word ! 612: ! 613: or al,al ! 614: jz rle4_escape ! 615: ! 616: rle4_encoded: ! 617: Clip_Encoded rle4_done,rle4_loop ! 618: ! 619: mov dh,dl ;separate two colors into dl, dh ! 620: and dl,0Fh ! 621: shr dh,4 ! 622: cmp dh,dl ! 623: jnz short encoded_diff_color ! 624: xor dh,dh ;Draw_Encoded use edx as color index ! 625: Draw_Encoded rle4_loop ! 626: ! 627: encoded_diff_color: ! 628: sub eax,ecx ;-eax = #pels clipped away ! 629: bt eax,0 ! 630: jnc short @F ! 631: xchg dl,dh ;xchg colors if odd #pels clipped ! 632: @@: ! 633: mov iPels,edx ;save color index ! 634: sub ebx,ecx ;Compute extent of interval ! 635: dec ebx ;Make interval inclusive ! 636: mov edi,ecx ;Don't destroy starting X ! 637: shr edi,3 ;/8 for byte address ! 638: add edi,pjDst ! 639: ! 640: and ecx,00000111b ;Compute bit index for first byte ! 641: mov eax,00AAAAAAh ;Compute altered bits mask ! 642: shr eax,cl ;AL = left side altered bytes mask ! 643: ! 644: add ebx,ecx ;Compute bit index for last byte ! 645: mov ecx,ebx ;(save for inner loop count) ! 646: and ecx,00000111b ! 647: mov ch,80h ! 648: sar ch,cl ! 649: and al,ch ;AL = last byte altered bits mask ! 650: ! 651: mov edx,eax ! 652: shr edx,1 ! 653: and dl,ch ;EDX = mask for 2nd pel ! 654: ! 655: mov ecx,ebx ! 656: shr ecx,3 ;Compute inner byte count ! 657: jnz short comp_byte_dont_combine ;loop count + 1 > 0, check it out ! 658: ! 659: ; Only one byte will be affected. Combine first/last masks, set loop count = 0 ! 660: ! 661: mov ebx,eax ! 662: shl eax,16 ;Will use first byte mask only ! 663: and eax,ebx ;AH = first mask. Rest of the bits = 0 ! 664: ! 665: mov ebx,edx ! 666: shl edx,16 ;Will use first byte mask only ! 667: and edx,ebx ;DH = first mask. Rest of the bits = 0 ! 668: inc ecx ;Fall through to set 0 ! 669: ! 670: comp_byte_dont_combine: ! 671: dec ecx ;Dec inner loop count (might become 0) ! 672: ! 673: xchg al,ah ! 674: ror eax,16 ;EAX = last mask:inter mask:first mask:0 ! 675: xchg al,ah ;for first pel ! 676: xchg dl,dh ! 677: ror edx,16 ;EDX = last mask:inter mask:first mask:0 ! 678: xchg dl,dh ;for second pel ! 679: ! 680: mov pjDstStart,edi ! 681: mov xMask,edx ;save mask for the 2nd round ! 682: ! 683: mov ebx,pulXlate ! 684: mov edx,iPels ! 685: shr edx,8 ;index for the first pel ! 686: mov ebx,[ebx][edx*4] ! 687: inc bh ;BH = rle4_encoded_diff_color_loop count ! 688: inc bh ! 689: mov dx,VGA_BASE + GRAF_ADDR ! 690: ;BL = color for first pel ! 691: rle4_encoded_diff_color_loop: ! 692: or ah,ah ;AH = first mask ! 693: jz short encoded_inner_diff_color ! 694: ! 695: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits ! 696: out dx,ax ! 697: ! 698: mov al,bl ! 699: xchg [edi],al ;write color ! 700: encoded_inner_diff_color: ! 701: inc edi ;update destination pointer ! 702: shr eax,8 ;AH = internal mask ! 703: or cl,cl ;ECX = inner loop count ! 704: jz short encoded_last_byte_diff_color ! 705: ! 706: mov ch,cl ;save loop count in ch ! 707: ;loop count always fit in a byte ! 708: mov al,GRAF_BIT_MASK ! 709: out dx,ax ;no mask ! 710: ! 711: encoded_loop_diff_color: ! 712: mov al,bl ! 713: xchg [edi],al ;write color ! 714: inc edi ! 715: dec cl ! 716: jnz encoded_loop_diff_color ! 717: ! 718: encoded_last_byte_diff_color: ! 719: shr eax,8 ;AH = last mask ! 720: or ah,ah ! 721: jz encoded_this_run_maybe_done ! 722: ! 723: mov al,GRAF_BIT_MASK ;Set bitmask for altered bits ! 724: out dx,ax ! 725: ! 726: encoded_write: ! 727: xchg [edi],bl ;write color ! 728: ! 729: encoded_this_run_maybe_done: ! 730: dec bh ! 731: jz rle4_loop ! 732: ! 733: mov edi,pulXlate ! 734: mov eax,iPels ;index of the second pel ! 735: xor ah,ah ! 736: mov bl,byte ptr [edi][eax*4] ! 737: mov edi,pjDstStart ! 738: mov eax,xMask ;load mask ! 739: mov cl,ch ;loop count ! 740: ! 741: jmp rle4_encoded_diff_color_loop ! 742: ! 743: rle4_escape: ! 744: cmp ah,2 ; First byte is 0, check the second byte. ! 745: ja rle4_absolute ! 746: jb rle4_end_of_line_or_bitmap ! 747: ! 748: rle4_delta: ! 749: ! 750: RleDelta rle4_loop ! 751: ! 752: rle4_absolute: ! 753: Clip_Absolute rle4_done,rle4_absolute_advance_src,nPels ! 754: ! 755: ;advance esi to point to the clipped run ! 756: ! 757: mov edx,cPreSrcAdv ;number of pels to advance ! 758: shr edx,1 ;number of bytes ! 759: jnc @F ! 760: ! 761: add esi,edx ;odd number of pels to advance ! 762: movzx edx,byte ptr [esi] ;grab color for prev and this pels ! 763: inc esi ! 764: mov iPels,edx ! 765: ! 766: inc nPels ;inc loop count since we start from 1 ! 767: mov cl,1 ! 768: jmp short absolute_loop ! 769: ! 770: @@: ;even number of pels to advance ! 771: add esi,edx ! 772: ! 773: ; I am doing a per pel loop rather than a per byte loop which writes 1 plane ! 774: ; at a time because it appears to me that most of the time we output 2 or ! 775: ; 3 pels per encounter of absolute mode. The logic here is simple and we can ! 776: ; stay with M_COLOR_WRITE mode all the time. ! 777: ! 778: xor cl,cl ;initialize loop count ! 779: ! 780: absolute_loop: ! 781: mov dx,VGA_BASE + GRAF_ADDR ! 782: out dx,ax ;Set bitmask for altered bit ! 783: ! 784: bt cl,0 ! 785: jc @F ! 786: ! 787: movzx edx,byte ptr [esi] ;grab color for this and next pels ! 788: inc esi ! 789: ! 790: mov iPels,edx ;save for next pel ! 791: shr dl,4 ! 792: jmp short ready_to_draw ! 793: @@: ! 794: mov edx,iPels ;second pel ! 795: and dl,0Fh ;mask out the second pel ! 796: ! 797: ready_to_draw: ! 798: mov edx,[ebx][edx*4] ;look up for VGA color ! 799: xchg [edi],dl ;write to destination ! 800: ! 801: ror ah,1 ;rotate bit mask for next pel ! 802: cmp ch,ah ;cmp bitmask with 01000001b ! 803: adc edi,0 ;advance edi if bitmask is 10000000b ! 804: ! 805: inc cl ! 806: cmp cl,nPels ! 807: jnz short absolute_loop ! 808: ! 809: mov eax,cPostSrcAdv ! 810: ! 811: rle4_absolute_advance_src: ! 812: shr eax,1 ;2 pels for one byte ! 813: add esi,eax ;advance src ptr for clipped out pels ! 814: bt esi,0 ;add 1 if not word aligned ! 815: adc esi,0 ! 816: jmp rle4_loop ! 817: ! 818: ! 819: rle4_end_of_line_or_bitmap: ! 820: or ah,ah ! 821: jnz short rle4_end_of_bitmap ! 822: ! 823: rle4_end_of_line: ! 824: RleEOL rle4_loop ! 825: ! 826: rle4_done: ! 827: RleExit ! 828: ! 829: RleBankBottom rle4_bank_loop,rle4_exit ;see if there are more banks ! 830: ; to do ! 831: align 4 ! 832: rle4_end_of_bitmap: ! 833: RleExit ! 834: rle4_exit: ! 835: cRet vRle4ToVga ! 836: ! 837: endProc vRle4ToVga ! 838: ! 839: ;--------------------------Private-Routine------------------------------; ! 840: ; comp_byte_interval ! 841: ; ! 842: ; An interval will be computed for byte boundaries. ! 843: ; ! 844: ; A first mask and a last mask will be calculated, and possibly ! 845: ; combined into the inner loop count. If no first byte exists, ! 846: ; the start address will be incremented to adjust for it. ! 847: ; ! 848: ; Entry: ! 849: ; EBX = right coordinate (exclusive) ! 850: ; ECX = left coordinate (inclusive) ! 851: ; Returns: ! 852: ; EDI = offset to first byte to be altered in the scan ! 853: ; ECX = inner loop count ! 854: ; AL = first byte mask (possibly 0) ! 855: ; AH = last byte mask (possibly 0) ! 856: ; Error Returns: ! 857: ; None ! 858: ; Registers Preserved: ! 859: ; ES,BP ! 860: ; Registers Destroyed: ! 861: ; AX,BX,CX,DI,FLAGS ! 862: ; Calls: ! 863: ; None ! 864: ; ! 865: ;-----------------------------------------------------------------------; ! 866: ! 867: comp_masks proc ! 868: ! 869: sub ebx,ecx ;Compute extent of interval ! 870: dec ebx ;Make interval inclusive ! 871: mov edi,ecx ;Don't destroy starting X ! 872: shr edi,3 ;/8 for byte address ! 873: ! 874: and ecx,00000111b ;Compute bit index for left side ! 875: mov al,0FFh ;Compute left side altered bits mask ! 876: shr al,cl ;AL = left side altered bytes mask ! 877: ! 878: add ebx,ecx ;Compute bit index for right side ! 879: mov ecx,ebx ;(save for inner loop count) ! 880: and ecx,00000111b ! 881: mov ah,80h ! 882: sar ah,cl ;AH = right side altered bits mask ! 883: ! 884: shr ebx,3 ;Compute inner byte count ! 885: jnz short comp_byte_dont_combine ;loop count + 1 > 0, check it out ! 886: ! 887: ; Only one byte will be affected. Combine first/last masks, set loop count = 0 ! 888: ! 889: and al,ah ;Will use first byte mask only ! 890: xor ah,ah ;Want last byte mask to be 0 ! 891: inc ebx ;Fall through to set 0 ! 892: ! 893: comp_byte_dont_combine: ! 894: dec ebx ;Dec inner loop count (might become 0) ! 895: ! 896: ; If all pixels in the first byte are altered, combine the first byte into the ! 897: ; inner loop and clear the first byte mask. Ditto for the last byte mask. ! 898: ! 899: mov ecx,0FFFFFFFFh ! 900: cmp al,cl ;Set 'C' if not all pixels 1 ! 901: sbb ebx,ecx ;If no 'C', sub -1 (add 1), else sub 0 ! 902: cmp al,cl ;Set 'C' if not all pixels 1 ! 903: sbb al,cl ;If no 'C', sub -1 (add 1), else sub 0 ! 904: ! 905: cmp ah,cl ;Set 'C' if not all pixels 1 ! 906: sbb ebx,ecx ;If no 'C', sub -1 (add 1), else sub 0 ! 907: cmp ah,cl ;Set 'C' if not all pixels 1 ! 908: sbb ah,cl ;If no 'C', sub -1 (add 1), else sub 0 ! 909: ! 910: mov ecx,ebx ;Return inner loop count in ECX ! 911: ! 912: ret ! 913: ! 914: comp_masks endp ! 915: ! 916: end ! 917:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.