|
|
1.1 ! root 1: page ,132 ! 2: ;---------------------------Module-Header------------------------------; ! 3: ; Module Name: special.asm ! 4: ; ! 5: ; Copyright (c) 1992 Microsoft Corporation ! 6: ;-----------------------------------------------------------------------; ! 7: title Special ! 8: .386 ! 9: ! 10: ifndef DOS_PLATFORM ! 11: .model small,c ! 12: else ! 13: ifdef STD_CALL ! 14: .model small,c ! 15: else ! 16: .model small,pascal ! 17: endif; STD_CALL ! 18: endif; DOS_PLATFORM ! 19: ! 20: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT ! 21: assume fs:nothing,gs:nothing ! 22: ! 23: .data ! 24: ! 25: ;BUGBUG this should be obtained from the surface ! 26: ! 27: extrn ulNextScan_global:dword ! 28: ! 29: .code ! 30: ! 31: _TEXT$01 SEGMENT DWORD USE32 PUBLIC 'CODE' ! 32: ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING ! 33: ! 34: .xlist ! 35: include stdcall.inc ;calling convention cmacros ! 36: include i386\cmacFLAT.inc ; FLATland cmacros ! 37: include i386\display.inc ; Display specific structures ! 38: include i386\ppc.inc ; Pack pel conversion structure ! 39: include i386\bitblt.inc ; General definitions ! 40: include i386\ropdefs.inc ; Rop definitions ! 41: include i386\egavga.inc ; EGA register definitions ! 42: include i386\strucs.inc ! 43: .list ! 44: ! 45: ; Rops we use in this code ! 46: ! 47: ROP_P equ 0F0h ! 48: ROP_Pn equ 0Fh ! 49: ROP_S equ 0CCh ! 50: ROP_DDx equ 0 ! 51: ROP_DDxn equ 0FFh ! 52: ROP_Dn equ 055h ! 53: ROP_DPx equ 05Ah ! 54: ! 55: ; Other values used in this code ! 56: ! 57: fr equ [ebp] ; Access to bitblt frame ! 58: bptr equ byte ptr ! 59: ! 60: ;----------------------------Public Routine----------------------------; ! 61: ; check_device_special_cases ! 62: ; ! 63: ; Check for fast special cases of BLT. ! 64: ; ! 65: ; Determine if the BLT is a special case which can be performed with ! 66: ; static code as opposed to code compiled on the stack, and, if so, ! 67: ; dispatch to the proper static code. ! 68: ; ! 69: ; The parameters needed for the BLT (phase alignment, directions of ! 70: ; movement, ...) have been computed and saved. These parameters will ! 71: ; now be interpreted and a BLT created on the stack. ! 72: ; ! 73: ; If the raster op is source copy, both devices are the screen, and the ! 74: ; phase alignment is 0, then the copy can be performed by the static ! 75: ; code using the EGA's write mode 1. ! 76: ; ! 77: ; If the rasterop is P, Pn, DDx (0), DDxn (1), and the brush is solid ! 78: ; or grey (for P and Pn), and the destination device is the screen, ! 79: ; then the operation can be performed by the static code using the EGA's ! 80: ; write mode 2 (write mode 0 for greys). ! 81: ; ! 82: ; Entry: ! 83: ; EDI --> pointer to target surface ! 84: ; EBP --> frame of BitBLT local variables ! 85: ; EGA registers in default state ! 86: ; Returns: ! 87: ; Carry set if BLT was performed with static code. ! 88: ; Error Returns: ! 89: ; Carry clear if BLT was not a special case. ! 90: ; Registers Destroyed: ! 91: ; AX,BX,CX,DX,SI,DI,DS,ES,flags ! 92: ; Registers Preserved: ! 93: ; EBP ! 94: ; Calls: ! 95: ;-----------------------------------------------------------------------; ! 96: ! 97: cProc check_device_special_cases ! 98: ! 99: xor cx,cx ;This is used, what is it????!!! ! 100: mov dh,fr.the_flags ;Keep the flags in DH for a while ! 101: test dh,F0_DEST_IS_DEV ;Is the destination a device? ! 102: jz cdsc_blt_not_special_cased ;Not device, cannot special case it ! 103: mov edi,fr.dest.next_scan ;Special case code expects this ! 104: mov al,byte ptr fr.Rop[0] ;Get the raster op ! 105: cmp al,ROP_S ;Is it src copy? ! 106: je cdsc_its_src_copy ; Yes, go check it out ! 107: cmp al,ROP_P ! 108: je short cdsc_its_patblt ! 109: ! 110: cdsc_not_s_or_p: ! 111: xor bl,bl ;Color for 0 fill ! 112: cmp al,ROP_DDx ! 113: je short cdsc_its_1_or_0 ! 114: cmp al,ROP_Pn ! 115: je short cdsc_its_inverse_patblt ! 116: cmp al,ROP_Dn ! 117: je short cdsc_its_dn ! 118: cmp al,ROP_DPx ! 119: je short cdsc_its_dpx ! 120: cmp al,ROP_DDxn ! 121: jne cdsc_blt_not_special_cased ! 122: mov bl,0FFh ;Color for 1 fill ! 123: ! 124: ; It's "1" (DDxn) or "0" (DDx) ! 125: cdsc_its_1_or_0: ! 126: mov fr.brush_accel,SOLID_BRUSH ;(no brush given for DDx or DDxn) ! 127: call ega_solid_pat ! 128: jmp cdsc_exit ! 129: ! 130: cdsc_its_patblt: ! 131: mov bl,fr.brush_accel ;Ccolor in lower bits, flags in upper ! 132: test bl,SOLID_BRUSH ! 133: jnz short cdsc_its_a_solid_color ! 134: test bl,GREY_SCALE ! 135: jz short cdsc_not_solid_nor_grey ! 136: xor bl,bl ;It's grey. !!! what is this flag ! 137: call ega_solid_pat ! 138: jmp cdsc_exit ! 139: ! 140: cdsc_not_solid_nor_grey: ! 141: call do_wes_patblt ! 142: jmp cdsc_exit ! 143: ! 144: cdsc_its_inverse_solid_color: ! 145: not bl ! 146: cdsc_its_a_solid_color: ! 147: mov cx,2 ! 148: call do_solid_patcopy ;color and accl. flags already in BL ! 149: jmp short cdsc_exit ! 150: ! 151: cdsc_its_inverse_patblt: ! 152: mov bl,fr.brush_accel ;color in lower bits, flags in upper ! 153: test bl,SOLID_BRUSH ! 154: jnz short cdsc_its_inverse_solid_color ! 155: test bl,GREY_SCALE ! 156: jz short cdsc_blt_not_special_cased ! 157: mov bl,-1 ;It's grey. !!! What is this flag ! 158: call ega_solid_pat ! 159: jmp short cdsc_exit ! 160: ! 161: cdsc_its_dn: ! 162: call do_wes_invert ! 163: jmp short cdsc_exit ! 164: ! 165: cdsc_its_dpx: ! 166: mov ah,fr.brush_accel ;color in lower bits, flags in upper ! 167: test ah,SOLID_BRUSH ! 168: jnz cdsc_its_solid_dpx ;dpx with solid brush ! 169: test ah,GREY_SCALE ;Otherwise must be a grey brush ! 170: jz short cdsc_blt_not_special_cased ! 171: call do_grey_dpx ! 172: jmp short cdsc_exit ! 173: ! 174: cdsc_its_solid_dpx: ! 175: call do_wes_dpx_solidpat ;solid color => can special case ! 176: jmp short cdsc_exit ! 177: ! 178: ! 179: ;-----------------------------------------------------------------------; ! 180: ; This is a source copy. The phase must be zero to special case the ! 181: ; source copy, and both devices must be the screen. ! 182: ; ! 183: ; errnz F0_SRC_IS_DEV - 00001000b ! 184: ; errnz F0_SRC_IS_COLOR - 00000100b ! 185: ; ! 186: ; its_src_copy: ! 187: ; and dh,F0_SRC_IS_DEV + F0_SRC_IS_COLOR ! 188: ; shiftr dh,2 ! 189: ; cmp fr.phase_h,1 ; Gives CF if horizontal phase = zero ! 190: ; rcl dh,1 ! 191: ; Now we have the needed flags in the lower 3 bits of DH ! 192: ; ; Src=EGA Src=Color Phase0 ! 193: ; ! 194: ; dw do_wes_mono_trick ; 0 0 0 ! 195: ; dw blt_not_a_special_case ; 0 0 1 ! 196: ; dw blt_not_a_special_case ; 0 1 0 ! 197: ; dw blt_not_a_special_case ; 0 1 1 ! 198: ; dw do_wes_mono_trick ; 1 0 0 ! 199: ; dw blt_not_a_special_case ; 1 0 1 ! 200: ; dw blt_not_a_special_case ; 1 1 0 ! 201: ; dw ega_src_copy ; 1 1 1 ! 202: ;-----------------------------------------------------------------------; ! 203: ! 204: cdsc_its_src_copy: ! 205: test dh,F0_SRC_IS_DEV ! 206: jnz short cdsc_exit ! 207: ! 208: cdsc_source_is_memory: ! 209: test dh,F0_SRC_IS_COLOR ;mono-mem to color-EGA conversion? ! 210: jnz cdsc_blt_not_special_cased ;color to color, cannot special case it ! 211: call do_wes_mono_trick ! 212: jmp short cdsc_exit ! 213: ! 214: cdsc_blt_not_special_cased: ! 215: clc ! 216: cRet check_device_special_cases ! 217: ! 218: cdsc_exit: ! 219: stc ! 220: cRet check_device_special_cases ! 221: ! 222: ! 223: ;----------------------------Private-Routine----------------------------; ! 224: ; calc_parms ! 225: ; ! 226: ; Calculate the parameters needed for the output functions contained ! 227: ; in this file. ! 228: ; ! 229: ; To avoid conditional jumps we will use some sick optimizations. ! 230: ; Remember this: ! 231: ; adc ax,-1 ; DEC AX if carry clear ! 232: ; sbb ax,0 ; DEC AX if carry set ! 233: ; sbb ax,-1 ; INC AX if carry clear ! 234: ; adc ax,0 ; INC AX if carry set ! 235: ; ! 236: ; Entry: ! 237: ; EBP --> BitBLT local frame ! 238: ; Returns: ! 239: ; ESI set to upper left of bitmap or pattern ! 240: ; EDI set to upper left ! 241: ; EDX = src bitmap width (if present) ! 242: ; ECX = fr.yExt ! 243: ; EBX = offset into pattern (if pat present) ! 244: ; sets dest_right_edge ! 245: ; sets start_mask[0] ! 246: ; sets last_mask[0] ! 247: ; sets inner_loop_count ! 248: ; Registers Destroyed: ! 249: ; EAX,flags ! 250: ; Registers Preserved: ! 251: ; EBP ! 252: ; Alters: ! 253: ; ! 254: ; Calls: ! 255: ; None ! 256: ;-----------------------------------------------------------------------; ! 257: ! 258: .errnz SIZE_PATTERN - 8 ; any power of 2 will work ! 259: ! 260: align 4 ! 261: calc_parms: ! 262: ! 263: ; Left edge. ! 264: ! 265: movzx edi,fr.DestxOrg ;X origin in pixels, must be positive ! 266: mov ebx,edi ! 267: mov cl,7 ! 268: and ecx,edi ;Save lower 3 bits ! 269: mov fr.phase_h,cl ! 270: shr edi,3 ;EDI set for left edge ! 271: mov al,0FFh ! 272: shr al,cl ! 273: mov byte ptr fr.start_mask[0],al ! 274: ! 275: ; Right edge. ! 276: ! 277: movzx eax,fr.xExt ! 278: add ebx,eax ;Right edge in pixels ! 279: mov cl,7 ! 280: and cl,bl ;save lower 3 bits ! 281: shr ebx,3 ;convert to bytes ! 282: mov fr.start_fl,ebx ;dest_right_edge (reuse stk variable) ! 283: mov al,0FFh ! 284: shr al,cl ! 285: not al ! 286: ! 287: ; Check if the BLT does not cross any byte boundaries. ! 288: ! 289: sub ebx,edi ;make EBX # bytes including left edge ! 290: jnz crosses_byte_boundary ! 291: and byte ptr fr.start_mask[0],al ! 292: xor al,al ! 293: ! 294: ; There are 2 cases where we get zero for fr.inner_loop_count: ! 295: ; When the start and end bytes are adjacent and when they are ! 296: ; the same byte. In the latter case we get -1 for ! 297: ; fr.inner_loop_count so INC BX now so it will be zero. ! 298: ! 299: inc ebx ! 300: crosses_byte_boundary: ! 301: ! 302: cmp al,0FFh ! 303: sbb al,-1 ;AL=FF -> AL=0 (put in innerloop) ! 304: mov byte ptr fr.last_mask[0],al ! 305: ! 306: ; Inner loop -- combine edge bytes into inner loop if they are ! 307: ; full bytes. ! 308: ! 309: mov fr.end_fl,ebx ;src_right_edge (reuse stk variable) ! 310: mov al,byte ptr fr.start_mask[0] ! 311: cmp al,0FFh ! 312: ! 313: ; If gl_start_mask = FF the carry is clear, otherwise carry is set. ! 314: ; We want to DEC BX if carry set because we have already included ! 315: ; the left edge byte in BX, but we shouldn't have included it if ! 316: ; it's only a partial byte. ! 317: ! 318: sbb ebx,0 ! 319: cmp al,0FFh ! 320: ! 321: ; If gl_start_mask = FF the carry is clear, otherwise carry is set. ! 322: ; We want to INC AL (zero it) if it is FF (carry clear) because we ! 323: ; will do this edge as part of the innerloop. ! 324: ! 325: sbb al,-1 ! 326: mov byte ptr fr.start_mask[0],al ! 327: mov fr.inner_loop_count,ebx ! 328: movzx eax,fr.DestyOrg ! 329: imul eax,ulNextScan_global ! 330: add edi,eax ! 331: mov esi,fr.pdsurfDst ! 332: add edi,[esi].dsurf_pvBitmapStart ! 333: ! 334: ; The source. ! 335: ! 336: test fr.the_flags,F0_SRC_PRESENT ! 337: jz no_source ! 338: mov esi,fr.pdsurfSrc ! 339: mov ecx,[esi].dsurf_lNextScan ;!!! will this be correct ?? ! 340: mov esi,[esi].dsurf_pvBitmapStart ! 341: ! 342: ; Left edge. ! 343: ! 344: movzx ebx,fr.SrcxOrg ! 345: mov dl,7 ! 346: and dl,bl ;get lower 3 bits ( Src Mod 8 ) ! 347: sub fr.phase_h,dl ;phase def'd as Mod8[gl_dest]- ! 348: shr ebx,3 ; Mod8[gl_src] ! 349: add esi,ebx ;ESI set for left edge ! 350: movzx eax,fr.SrcyOrg ! 351: mul ecx ! 352: add esi,eax ! 353: add fr.end_fl,esi ;src_right_edge (reuse stack variable) ! 354: mov edx,ecx ! 355: jmp short no_pattern ! 356: no_source: ! 357: test fr.the_flags,F0_PAT_PRESENT ; assuming P or S but not both ! 358: jz no_pattern ! 359: mov esi,fr.lpPBrush ! 360: movzx ebx,fr.DestyOrg ! 361: and ebx,SIZE_PATTERN - 1 ! 362: no_pattern: ! 363: movzx ecx,fr.yExt ! 364: PLAIN_RET ! 365: ! 366: ! 367: ;----------------------------Private-Routine----------------------------; ! 368: ; ega_solid_pat ! 369: ; ! 370: ; EGA special case for solid color pattern copy. ! 371: ; ! 372: ; The following routine is invoked instead of generating code for a ! 373: ; pattern copy. The actual time involved in executing the pattern ! 374: ; copy as static code as compared to compiled code is a win. ! 375: ; ! 376: ; This code can only be used if the pattern is a solid color or a grey, ! 377: ; and the operation is to the screen. In this case, the three bits of ! 378: ; color stored in the accelerator byte of the brush will be used, or the ! 379: ; bits of the grey brush. ! 380: ; ! 381: ; The logic operations which will invoke this routine are: ! 382: ; ! 383: ; P ! 384: ; Pn ! 385: ; DDx ! 386: ; DDxn ! 387: ; ! 388: ; Entry: ! 389: ; BL = color to write or xor value for a grey pattern ! 390: ; CX = Mode register value (sort of) ! 391: ; EBP = BitBLT local variable frame ! 392: ; Returns: ! 393: ; Nothing ! 394: ; Registers Destroyed: ! 395: ; ALL except EBP ! 396: ; Registers Preserved: ! 397: ; EBP ! 398: ; Calls: ! 399: ; None ! 400: ;-----------------------------------------------------------------------; ! 401: ! 402: align 4 ! 403: ega_solid_pat: ! 404: ! 405: ; Instead of pushing and popping the destination pointer and adding in ! 406: ; the fr.dest.Incr, the bias needed for adjusting the pointer at the ! 407: ; end of a scan line will be computed and used. ! 408: ; ! 409: ; Since this is a pattern copy, the fr.dest.Incr will be positive. ! 410: ! 411: ; mov esi,edi ;Get destination increment ! 412: ; sub esi,1 ;Adjust for first byte ! 413: lea esi,-1[edi] ! 414: sub esi,fr.inner_loop_count ;Compute number of bytes to copy ! 415: ! 416: ; Put color in Set/Reset if it is a solid color. ! 417: ! 418: mov dx,EGA_BASE + GRAF_ADDR ! 419: or cx,cx ! 420: jz not_solid_color ! 421: mov ax,MM_ALL * 256 + GRAF_ENAB_SR ! 422: out dx,ax ! 423: mov ah,bl ! 424: mov al,GRAF_SET_RESET ! 425: out dx,ax ! 426: not_solid_color: ! 427: mov al,GRAF_BIT_MASK ;Leave graphics controller pointing ! 428: out dx,al ; to the bitmask register, which ! 429: inc dx ; is where cursor leaves it too ! 430: ! 431: ; Set up for the loop. ! 432: ! 433: mov edi,fr.dest.lp_bits ;--> destination ! 434: mov fr.phase_h,bl ;Save color to write or grey XOR mask ! 435: ! 436: ega_solid_pat_20: ! 437: mov al,fr.phase_h ;Get the color to write ! 438: test fr.brush_accel,SOLID_BRUSH ;Grey scale brush? ! 439: jnz ega_solid_pat_30 ; No, a solid color ! 440: mov bl,fr.pat_row ;Get scan of brush ! 441: inc bl ; and update brush pointer ! 442: mov fr.pat_row,bl ! 443: dec bl ! 444: and ebx,00000111b ! 445: add ebx,fr.lpPBrush ! 446: xor al,bptr [ebx] ;Invert if needed ! 447: ! 448: ega_solid_pat_30: ! 449: mov bl,al ! 450: mov al,bptr fr.start_mask[1] ;Set bitmask for first byte ! 451: out dx,al ! 452: mov al,bl ! 453: xchg al,[edi] ;xchg to load EGA's latches first ! 454: inc edi ;PAT_COPY step +X always! ! 455: ! 456: mov ecx,fr.inner_loop_count ;Set count for innerloop ! 457: jecxz ega_solid_pat_40 ;No innerloop or last byte ! 458: mov al,0FFh ;Inner loop alters all bits ! 459: out dx,al ! 460: mov al,bl ! 461: rep stosb ! 462: ! 463: ega_solid_pat_40: ! 464: mov al,bptr fr.last_mask[1] ;Last byte? ! 465: or al,al ! 466: jz ega_solid_pat_50 ;No last byte ! 467: out dx,al ! 468: xchg bl,[edi] ! 469: ! 470: ega_solid_pat_50: ! 471: add edi,esi ;--> next destination ! 472: dec fr.yExt ;Any more scans to process? ! 473: jnz ega_solid_pat_20 ; Yes ! 474: PLAIN_RET ! 475: ! 476: ! 477: ;----------------------------Private-Routine----------------------------; ! 478: ; do_wes_invert ! 479: ; do_wes_dpx_solidpat ! 480: ; ! 481: ; Entry: ! 482: ; EBP --> BitBLT local variable frame ! 483: ; AH = color of solid-pat. ! 484: ; Returns: ! 485: ; Nothing ! 486: ; Registers Destroyed: ! 487: ; ALL but EBP ! 488: ; Registers Preserved: ! 489: ; EBP ! 490: ; Calls: ! 491: ; calc_parms ! 492: ; edge_invert ! 493: ; invert ! 494: ;-----------------------------------------------------------------------; ! 495: ! 496: align 4 ! 497: do_wes_invert: ! 498: ! 499: mov ah,0Fh ; black ! 500: ! 501: do_wes_dpx_solidpat label near ! 502: ! 503: ; Setup SET_RESET. ! 504: ! 505: mov dx,EGA_BASE + GRAF_ADDR ! 506: mov al,GRAF_SET_RESET ! 507: out dx,ax ! 508: mov ax,0F00h + GRAF_ENAB_SR ; enable all planes ! 509: out dx,ax ! 510: ! 511: ; Go to XOR mode. ! 512: ! 513: mov ax,GRAF_DATA_ROT + 256 * DR_XOR ! 514: out dx,ax ! 515: ! 516: call calc_parms ! 517: mov ah,byte ptr fr.start_mask[0] ! 518: or ah,ah ! 519: jz no_left_invert_edge ! 520: push edi ! 521: call edge_invert ! 522: pop edi ! 523: inc edi ! 524: ! 525: no_left_invert_edge: ! 526: mov ebx,fr.inner_loop_count ! 527: or ebx,ebx ! 528: jz no_inner_invert_loop ! 529: movzx ecx,fr.yExt ! 530: push edi ! 531: call invert ! 532: pop edi ! 533: add edi,fr.inner_loop_count ! 534: ! 535: no_inner_invert_loop: ! 536: mov ah,byte ptr fr.last_mask[0] ! 537: or ah,ah ! 538: jz no_last_invert_edge ! 539: movzx ecx,fr.yExt ! 540: call edge_invert ! 541: ! 542: no_last_invert_edge: ! 543: PLAIN_RET ! 544: ! 545: ! 546: ;----------------------------Private-Routine----------------------------; ! 547: ;do_solid_patcopy() is called to copy (PatCopy) a solid brush directly to ! 548: ;the screen. ! 549: ; ! 550: ;Entry: ! 551: ; BL color to write with ! 552: ; EDI fr.dest.next_scan which is equal to width_b ! 553: ; EBP local varible frame ! 554: ; ! 555: ;-----------------------------------------------------------------------; ! 556: ! 557: align 4 ! 558: do_solid_patcopy: ! 559: ! 560: cmp fr.inner_loop_count,0 ;if zero, let ega_solid_pat do the work ! 561: jne dsp_do_it ! 562: call ega_solid_pat ! 563: PLAIN_RET ! 564: ! 565: dsp_do_it: ! 566: sub eax,eax ;accumulate flags in AL ! 567: mov esi,edi ;SI: fr.dest.next_scan (must be > 0) ! 568: mov edi,fr.dest.lp_bits ;EDI-->first byte to write to ! 569: mov bh,bptr fr.start_mask[1] ! 570: cmp ah,bh ;is there a left edge? ! 571: rcl al,1 ;CY if there is an edge to draw ! 572: sub bh,0ffh ;is the left edge an entire byte wide? ! 573: neg bh ;CY if less than a byte ! 574: rcl al,1 ;accumulate flag into AL ! 575: mov bh,bptr fr.last_mask[1] ! 576: cmp ah,bh ;is there a right edge? ! 577: rcl al,1 ;CY if there is an edge to draw ! 578: sub bh,0ffh ;is right edge an entire byte wide? ! 579: neg bh ;CY if less than a byte ! 580: rcl al,1 ;accumulate flag into AL ! 581: test al,04h ;set all pixels in left byte? ! 582: jnz dsp_keep_left_edge ;no. Do normal stuff ! 583: inc fr.inner_loop_count ;left edge is an entire byte. INC inner ! 584: and al,0f7h ;loop cnt and draw it the fast way ! 585: ! 586: dsp_keep_left_edge: ! 587: test al,01h ;set all pixels in right byte? ! 588: jnz dsp_keep_right_edge ;no. Do normal stuff ! 589: inc fr.inner_loop_count ;need to set all pixels in right byte. ! 590: and al,0fdh ;inc inner loop cnt do it the fast way ! 591: ! 592: dsp_keep_right_edge: ! 593: test al,0ah ;any edges to draw? ! 594: jz dsp_draw_core_piece ;no, just do the main chunk ! 595: ! 596: dsp_draw_edges: ! 597: mov bh,al ;save flags in BH ! 598: mov dx,EGA_BASE + GRAF_ADDR ! 599: mov ax,MM_ALL * 256 + GRAF_ENAB_SR ! 600: out dx,ax ;enable writing to all planes at once ! 601: mov ah,bl ! 602: mov al,GRAF_SET_RESET ! 603: out dx,ax ;program to color value to write ! 604: mov al,GRAF_BIT_MASK ;Leave graphics controller pointing ! 605: out dx,al ; to the bitmask register, which ! 606: inc dx ; is where cursor leaves it too ! 607: ! 608: test bh,08h ;need to draw the left edge? ! 609: jz dsp_draw_right_edge ! 610: ! 611: push edi ;save destination offset ! 612: mov al,bptr fr.start_mask[1] ! 613: out dx,al ;get it to the board ! 614: movzx ecx,fr.yExt ! 615: ! 616: dsp_left_edge_draw_loop: ! 617: mov al,bl ;copy color index into AL ! 618: xchg al,[edi] ;load latches, copy color index ! 619: add edi,esi ! 620: loop dsp_left_edge_draw_loop ! 621: pop edi ;restore dest offset ! 622: inc edi ;update to new draw position ! 623: ! 624: ! 625: dsp_draw_right_edge: ! 626: test bh,02h ;is there a right edge to draw? ! 627: jz dsp_reset_registers ;no. Restore default settings ! 628: push edi ;save updated dest offset ! 629: add edi,fr.inner_loop_count ;go to the right hand edge ! 630: mov al,bptr fr.last_mask[1] ! 631: out dx,al ;get it to the board ! 632: movzx ecx,fr.yExt ! 633: ! 634: dsp_right_edge_draw_loop: ! 635: mov al,bl ;copy color index into AL ! 636: xchg al,[edi] ;load latches, copy color index ! 637: add edi,esi ! 638: loop dsp_right_edge_draw_loop ! 639: pop edi ;restore dest offset ! 640: ! 641: ! 642: dsp_reset_registers: ! 643: mov al,0ffh ;allow writing to all bits in the byte ! 644: out dx,al ;this is the default value ! 645: ! 646: dsp_draw_core_piece: ! 647: sub esi,fr.inner_loop_count ;account for EDI being incr. by stosb ! 648: mov dx,EGA_BASE+SEQ_DATA ;time to copy pattern to board DX=3C5h ! 649: mov al,01h ! 650: mov ecx,4 ! 651: ! 652: dsp_load_latches_loop: ! 653: out dx,al ;select the next plane to write to ! 654: shr bl,1 ;move plane bit into carry ! 655: sbb ah,ah ;expand into AH ! 656: mov [edi],ah ;copy it to the bit plane ! 657: shl al,1 ;update plane selector ! 658: loop dsp_load_latches_loop ;do all 4 planes ! 659: ! 660: mov al,MM_ALL ;to enable all four planes ! 661: out dx,al ;enable all planes ! 662: mov dx,EGA_BASE+GRAF_ADDR ;DX=3CEh ! 663: mov ax,GRAF_BIT_MASK ;AH=0 ie., copy data from latches, AL=8 ! 664: out dx,ax ;ignore CPU data on write to board ! 665: ! 666: mov al,[edi] ;load the latches ! 667: movzx eax,fr.yExt ;initialize loop counter ! 668: mov ebx,fr.inner_loop_count ;initialize rep counter value ! 669: ! 670: align 4 ! 671: dsp_pat_blt_loop: ! 672: mov ecx,ebx ;ECX: repeat count ! 673: test edi,1 ! 674: jz short dsp_pat_blt_aligned2 ! 675: stosb ! 676: dec ecx ! 677: dsp_pat_blt_aligned2: ! 678: shr ecx,1 ! 679: rep stosw ! 680: adc ecx,ecx ! 681: rep stosb ! 682: add edi,esi ;point to next scanline ! 683: dec eax ! 684: jnz dsp_pat_blt_loop ! 685: ! 686: PLAIN_RET ! 687: ! 688: ! 689: ;----------------------------Private-Routine----------------------------; ! 690: ; do_wes_patblt ! 691: ; ! 692: ; Entry: ! 693: ; EBP --> BitBLT local variable frame ! 694: ; Returns: ! 695: ; Nothing ! 696: ; Registers Destroyed: ! 697: ; All but EBP ! 698: ; Registers Preserved: ! 699: ; EBP ! 700: ; Calls: ! 701: ; calc_parms ! 702: ; edge_pat_blt ! 703: ; pat_blt ! 704: ;-----------------------------------------------------------------------; ! 705: ! 706: align 4 ! 707: do_wes_patblt: ! 708: ! 709: call calc_parms ! 710: mov ah,byte ptr fr.start_mask[0] ! 711: or ah,ah ! 712: jz no_left_pat_edge ! 713: push esi ! 714: push ebx ! 715: call edge_pat_blt ; preserves DI ! 716: pop ebx ! 717: pop esi ! 718: inc edi ! 719: ! 720: no_left_pat_edge: ! 721: mov edx,fr.inner_loop_count ! 722: or edx,edx ! 723: jz no_inner_pat_loop ! 724: movzx ecx,fr.yExt ! 725: push edi ! 726: push esi ! 727: push ebx ! 728: call pat_blt ! 729: pop ebx ! 730: pop esi ! 731: pop edi ! 732: add edi,fr.inner_loop_count ! 733: ! 734: no_inner_pat_loop: ! 735: mov ah,byte ptr fr.last_mask[0] ! 736: or ah,ah ! 737: jz no_last_pat_edge ! 738: movzx ecx,fr.yExt ! 739: call edge_pat_blt ! 740: ! 741: no_last_pat_edge: ! 742: PLAIN_RET ! 743: ! 744: ! 745: ;----------------------------Private-Routine----------------------------; ! 746: ; do_wes_mono_trick ! 747: ; ! 748: ; Entry: ! 749: ; EBP --> BitBLT local variable frame ! 750: ; Returns: ! 751: ; Nothing ! 752: ; Registers Preserved: ! 753: ; EBP ! 754: ; Registers Destroyed: ! 755: ; All but EBP ! 756: ; Calls: ! 757: ; calc_parms ! 758: ; left_edge_mono_to_color_blt ! 759: ; right_edge_mono_to_color_blt ! 760: ; mono_to_color_blt ! 761: ;-----------------------------------------------------------------------; ! 762: ! 763: align 4 ! 764: do_wes_mono_trick: ! 765: ! 766: call calc_parms ! 767: push edx ! 768: mov ah,byte ptr fr.start_mask[0] ! 769: or ah,ah ! 770: jz no_left_edge ! 771: push edi ! 772: push esi ! 773: push edx ! 774: mov al,fr.phase_h ! 775: mov bx,fr.both_colors ! 776: ;- mov ecx,fr.yExt ! 777: call left_edge_mono_to_color_blt ! 778: pop edx ! 779: pop esi ! 780: pop edi ! 781: inc esi ! 782: inc edi ! 783: no_left_edge: ! 784: mov ebx,edx ! 785: mov edx,fr.inner_loop_count ! 786: mov ecx,edi ; compute/save the right-hand edge ! 787: add ecx,edx ! 788: push ecx ! 789: or edx,edx ! 790: jz no_inner_loop ! 791: sub ebx,edx ! 792: movzx ecx,fr.yExt ! 793: mov al,fr.phase_h ! 794: cbw ! 795: push ebp ! 796: mov bp,fr.both_colors ! 797: xchg bp,ax ! 798: call mono_to_color_blt ! 799: pop ebp ! 800: ! 801: no_inner_loop: ! 802: pop edi ! 803: pop edx ! 804: mov ah,byte ptr fr.last_mask[0] ! 805: or ah,ah ! 806: jz no_last_edge ! 807: ! 808: mov ecx,fr.inner_loop_count ! 809: mov esi,fr.end_fl ; src_right_edge (reuse stk variable) ! 810: movzx ecx,fr.yExt ! 811: mov bx,fr.both_colors ! 812: mov al,fr.phase_h ! 813: call right_edge_mono_to_color_blt ! 814: ! 815: no_last_edge: ! 816: PLAIN_RET ! 817: ! 818: ! 819: ;----------------------------Private-Routine----------------------------; ! 820: ; mono_to_color_blt ! 821: ; ! 822: ; This does phase-0, byte-aligned, mem-mono to ega-color blt. ! 823: ; ! 824: ; The Problem: copy to the ega a bitmap where "0"s in the bitmap mean ! 825: ; color1 and "1"s in the bitmap mean color2, where color1 and color2 ! 826: ; are arbitrary colors. ! 827: ; ! 828: ; The solution: ! 829: ; ! 830: ; plane0 plane1 plane2 plane3 ! 831: ; ! 832: ; color1 1 1 0 0 ! 833: ; color2 1 0 1 0 ! 834: ; SetResetEnable 1 0 0 1 ! 835: ; SetReset 0 x x 0 ! 836: ; latches 1 1 0 0 (=color1) ! 837: ; ! 838: ; Now with datarot = XOR we get ! 839: ; ! 840: ; when databit=0 1 1 0 0 (=color1) ! 841: ; when databit=1 1 0 1 0 (=color2) ! 842: ; ! 843: ; ! 844: ; Entry: ! 845: ; BP = phase ( -7 to 7) (high byte ignored) ! 846: ; AL = background color ( "1" bits in mono-bitmap ) ! 847: ; AH = foreground color ! 848: ; EBX = SI wrap ! 849: ; ESI = Mono Bitmap first byte ! 850: ; EDI = First EGA Byte ! 851: ; ECX = Number of scan lines ! 852: ; EDX = bytes per scan line ! 853: ; GRAF_DATA_ROT = DR_SET ! 854: ; All Planes Enabled ! 855: ; Returns: ! 856: ; Nothing ! 857: ; Registers Destroyed: ! 858: ; ALL ! 859: ; Registers Preserved: ! 860: ; None ! 861: ; Alters: ! 862: ; GRAF_SET_RESET ! 863: ; GRAF_ENAB_SR ! 864: ; GRAF_BIT_MASK ! 865: ; Calls: ! 866: ; None ! 867: ;-----------------------------------------------------------------------; ! 868: ! 869: align 4 ! 870: mono_to_color_blt: ! 871: ! 872: push ebp ; phase ! 873: push edx ; bytes per scan line ! 874: push ebx ; wrap for SI ! 875: mov ebx,eax ; colors ! 876: ! 877: ; First we put the foreground color into the latches. We do this ! 878: ; by putting this color into SET_RESET, writing it, then reading it. ! 879: ; The memory location we will use is the first byte where we will blt. ! 880: ! 881: mov dx,EGA_BASE + GRAF_ADDR ! 882: mov al,GRAF_SET_RESET ! 883: out dx,ax ! 884: mov ax,0F00h + GRAF_ENAB_SR ! 885: out dx,ax ! 886: ! 887: ; Set bit mask = FF. ! 888: mov ax,0FF00h + GRAF_BIT_MASK ! 889: out dx,ax ! 890: ! 891: ; Fill the latches. ! 892: mov [edi],al ; color in SetReset is written, not AL ! 893: mov al,[edi] ; read to fill latches ! 894: ! 895: ; Go to XOR mode. ! 896: mov ax,GRAF_DATA_ROT + 256 * DR_XOR ! 897: out dx,ax ! 898: ! 899: ; Now setup SET_RESET. ! 900: ! 901: mov eax,ebx ; restore colors ! 902: xor ah,al ; gives 0 where colors match ! 903: mov al,GRAF_SET_RESET ! 904: out dx,ax ! 905: not ah ! 906: mov al,GRAF_ENAB_SR ! 907: out dx,ax ; enable Set/Reset where colors match ! 908: ! 909: pop ebp ; wrap for ESI ! 910: pop edx ; bytes per scan ! 911: mov ebx,ulNextScan_global ! 912: sub ebx,edx ; BX = wrap ! 913: ! 914: mov eax,ecx ; loop count ! 915: pop ecx ; phase ! 916: or cl,cl ! 917: js phase_neg ! 918: jz phase_zero ! 919: dec esi ! 920: ;* dec ebp ! 921: pmono_to_color_loop: ! 922: push eax ! 923: push edx ! 924: pnext_byte: ! 925: lodsw ! 926: dec esi ! 927: xchg al,ah ! 928: shr ax,cl ! 929: ;+ shl ax,cl ! 930: stosb ! 931: dec edx ! 932: jnz pnext_byte ! 933: pop edx ! 934: pop eax ! 935: add edi,ebx ! 936: add esi,ebp ! 937: dec eax ! 938: jnz pmono_to_color_loop ! 939: jmp leave_in_set_mode ! 940: ! 941: phase_zero: ! 942: zmono_to_color_loop: ! 943: mov ecx,edx ! 944: shr ecx,1 ! 945: rep movsw ! 946: rcl ecx,1 ! 947: rep movsb ! 948: add edi,ebx ! 949: add esi,ebp ! 950: dec eax ! 951: jnz zmono_to_color_loop ! 952: jmp leave_in_set_mode ! 953: ! 954: phase_neg: ! 955: neg cl ; make CX = abs phase ! 956: nmono_to_color_loop: ! 957: push eax ! 958: push edx ! 959: nnext_byte: ! 960: lodsw ! 961: dec esi ! 962: rol ax,cl ! 963: ;+ shr ax,cl ! 964: stosb ! 965: dec edx ! 966: jnz nnext_byte ! 967: pop edx ! 968: pop eax ! 969: add edi,ebx ! 970: add esi,ebp ! 971: dec eax ! 972: jnz nmono_to_color_loop ! 973: ! 974: leave_in_set_mode: ! 975: mov dx,EGA_BASE + GRAF_ADDR ! 976: mov ax,GRAF_DATA_ROT + 256 * DR_SET ! 977: out dx,ax ! 978: PLAIN_RET ! 979: ! 980: ! 981: ;----------------------------Private-Routine----------------------------; ! 982: ; left_edge_mono_to_color_blt ! 983: ; right_edge_mono_to_color_blt ! 984: ; ! 985: ; This problem here is the same as in mono_to_color_blt, except it ! 986: ; is complicated by the need to preserve what is already in EGA memory ! 987: ; for part of the byte which we are writing. ! 988: ; ! 989: ; We will set the BIT MASK to preserve these bytes. We will then read ! 990: ; the data from memory, and write it to the EGA using an XCHG so the ! 991: ; latches are filled before the write -- so the appropriate EGA bits ! 992: ; are preserved. ! 993: ; ! 994: ; The method for writing the data involves two passes. The first pass ! 995: ; writes the data to some of the planes, the second pass writes NOT the ! 996: ; data to the other planes. Depending on the two colors involved we ! 997: ; may be able to skip one of the two passes. ! 998: ; ! 999: ; Define BkColor = the color corresponding to "1" bits in the data. ! 1000: ; Define TextColor = the color corresponding to "0" bits in the data. ! 1001: ; ! 1002: ; We will use the Set/Reset register to take care of the planes where ! 1003: ; the colors match. These planes will be ignored in the rest of this ! 1004: ; comment block. ! 1005: ; ! 1006: ; The first pass writes "1"s where the data is "1". Therefore, the ! 1007: ; condition for doing the first pass is that the BkColor has a "1" ! 1008: ; somewhere (ignoring those planes taken care of by Set/Reset). ! 1009: ; The second pass does whatever planes remain. We can skip this pass ! 1010: ; if no planes remain. To maximize to likelihood of this we make sure ! 1011: ; that all "Set/Reset" planes are enabled on the first pass (if the ! 1012: ; first pass occurs). ! 1013: ; ! 1014: ; Entry: ! 1015: ; AH = bitmask ! 1016: ; AL = phase (-7 to +7) ! 1017: ; BH = foreground color ! 1018: ; BL = background color ! 1019: ; EDX = src bitmap width in bytes ! 1020: ; ESI = Mono Bitmap first byte ! 1021: ; EDI = First EGA Byte ! 1022: ; ECX = Number of scan lines ! 1023: ; DATA_ROT = DR_SET ! 1024: ; Returns: ! 1025: ; Nothing ! 1026: ; Registers Destroyed: ! 1027: ; ALL but EBP ! 1028: ; Registers Preserved: ! 1029: ; EBP ! 1030: ; Alters: ! 1031: ; GRAF_SET_RESET ! 1032: ; GRAF_BIT_MASK ! 1033: ; GRAF_ENAB_SR ! 1034: ; Calls: ! 1035: ; None ! 1036: ;-----------------------------------------------------------------------; ! 1037: ! 1038: ; Does left edge, which never requires more than 1 byte, and can fault with ! 1039: ; the 2-byte approach used by the right edge. ! 1040: ! 1041: align 4 ! 1042: left_edge_mono_to_color_blt: ! 1043: ! 1044: push ebp ! 1045: push eax ; AL = phase ! 1046: mov ebp,edx ! 1047: ! 1048: ; Set bit mask. ! 1049: ! 1050: mov dx,EGA_BASE + GRAF_ADDR ! 1051: mov al,GRAF_BIT_MASK ! 1052: out dx,ax ! 1053: ! 1054: ; Put foreground color in Set/Reset and enable planes where colors ! 1055: ; match. ! 1056: ! 1057: mov ah,bh ! 1058: mov al,GRAF_SET_RESET ! 1059: out dx,ax ! 1060: xor ah,bl ! 1061: not ah ; gives 1 where colors match ! 1062: mov al,GRAF_ENAB_SR ! 1063: out dx,ax ! 1064: mov dx,EGA_BASE + SEQ_DATA ; The rest of the OUTs are here. ! 1065: mov al,ah ! 1066: not ah ; Gives 1 where colors mismatch. ! 1067: ! 1068: ; The following AND leaves 1 bits in AH for the planes which ! 1069: ; CANNOT be done on the second pass. So if this is zero we can ! 1070: ; skip the first pass. ! 1071: ! 1072: and ah,bl ; BL = BkColor = color where data is 1 ! 1073: or ah,bl ; planes to enable ! 1074: mov ebx,ecx ; we're done with the colors in BX ! 1075: pop ecx ; phase ! 1076: jz short left_skip_first_pass ! 1077: or al,ah ; Include "Set/Reset" planes. ! 1078: out dx,al ; Enable planes for first pass. ! 1079: ! 1080: push ecx ! 1081: push esi ! 1082: push edi ! 1083: push eax ! 1084: push ebx ! 1085: or cl,cl ! 1086: js short left_phase_is_negative1 ! 1087: left_pfirst_pass: ! 1088: mov ah,[esi] ! 1089: shr ah,cl ! 1090: xchg ah,[edi] ! 1091: add esi,ebp ! 1092: add edi,ulNextScan_global ! 1093: dec ebx ! 1094: jnz left_pfirst_pass ! 1095: jmp short left_end_pass_one ! 1096: ! 1097: left_phase_is_negative1: ! 1098: neg cl ; make CL = abs phase ! 1099: left_nfirst_pass: ! 1100: mov ax,[esi] ! 1101: rol ax,cl ! 1102: xchg al,[edi] ! 1103: add esi,ebp ! 1104: add edi,ulNextScan_global ! 1105: dec ebx ! 1106: jnz left_nfirst_pass ! 1107: left_end_pass_one: ! 1108: pop ebx ! 1109: pop eax ! 1110: pop edi ! 1111: pop esi ! 1112: pop ecx ! 1113: ! 1114: left_skip_first_pass: ! 1115: ! 1116: ; Enable the other planes. ! 1117: ! 1118: not ah ! 1119: and ah,MM_ALL ! 1120: jz short left_no_planes_left ! 1121: mov al,ah ! 1122: out dx,al ! 1123: or cl,cl ! 1124: js short left_phase_is_negative2 ! 1125: left_psecond_pass: ! 1126: mov ah,[esi] ! 1127: not ah ! 1128: shr ah,cl ! 1129: xchg ah,[edi] ! 1130: add esi,ebp ! 1131: add edi,ulNextScan_global ! 1132: dec ebx ! 1133: jnz left_psecond_pass ! 1134: jmp short left_no_planes_left ! 1135: ! 1136: left_phase_is_negative2: ! 1137: neg cl ; make CL = abs phase ! 1138: left_nsecond_pass: ! 1139: mov ax,[esi] ! 1140: not ax ! 1141: rol ax,cl ! 1142: xchg al,[edi] ! 1143: add esi,ebp ! 1144: add edi,ulNextScan_global ! 1145: dec ebx ! 1146: jnz left_nsecond_pass ! 1147: ! 1148: left_no_planes_left: ! 1149: mov al,MM_ALL ! 1150: out dx,al ! 1151: pop ebp ! 1152: PLAIN_RET ! 1153: ! 1154: ; Does right edge, which may require 2 bytes. 2 bytes are always available, ! 1155: ; because if there was only 1 byte across, the left edge would handle it, ! 1156: ; so we don't have to worry about faulting. ! 1157: ! 1158: align 4 ! 1159: right_edge_mono_to_color_blt: ! 1160: ! 1161: push ebp ! 1162: push eax ; AL = phase ! 1163: mov ebp,edx ! 1164: ! 1165: ; Set bit mask. ! 1166: ! 1167: mov dx,EGA_BASE + GRAF_ADDR ! 1168: mov al,GRAF_BIT_MASK ! 1169: out dx,ax ! 1170: ! 1171: ; Put foreground color in Set/Reset and enable planes where colors ! 1172: ; match. ! 1173: ! 1174: mov ah,bh ! 1175: mov al,GRAF_SET_RESET ! 1176: out dx,ax ! 1177: xor ah,bl ! 1178: not ah ; gives 1 where colors match ! 1179: mov al,GRAF_ENAB_SR ! 1180: out dx,ax ! 1181: mov dx,EGA_BASE + SEQ_DATA ; The rest of the OUTs are here. ! 1182: mov al,ah ! 1183: not ah ; Gives 1 where colors mismatch. ! 1184: ! 1185: ; The following AND leaves 1 bits in AH for the planes which ! 1186: ; CANNOT be done on the second pass. So if this is zero we can ! 1187: ; skip the first pass. ! 1188: ! 1189: and ah,bl ; BL = BkColor = color where data is 1 ! 1190: or ah,bl ; planes to enable ! 1191: mov ebx,ecx ; we're done with the colors in BX ! 1192: pop ecx ; phase ! 1193: jz short right_skip_first_pass ! 1194: or al,ah ; Include "Set/Reset" planes. ! 1195: out dx,al ; Enable planes for first pass. ! 1196: ! 1197: push ecx ! 1198: push esi ! 1199: push edi ! 1200: push eax ! 1201: push ebx ! 1202: or cl,cl ! 1203: js short right_phase_is_negative1 ! 1204: dec esi ! 1205: right_pfirst_pass: ! 1206: mov ax,[esi] ! 1207: ror ax,cl ! 1208: xchg ah,[edi] ! 1209: add esi,ebp ! 1210: add edi,ulNextScan_global ! 1211: dec ebx ! 1212: jnz right_pfirst_pass ! 1213: jmp short right_end_pass_one ! 1214: ! 1215: right_phase_is_negative1: ! 1216: neg cl ; make CL = abs phase ! 1217: right_nfirst_pass: ! 1218: mov ax,[esi] ! 1219: rol ax,cl ! 1220: xchg al,[edi] ! 1221: add esi,ebp ! 1222: add edi,ulNextScan_global ! 1223: dec ebx ! 1224: jnz right_nfirst_pass ! 1225: right_end_pass_one: ! 1226: pop ebx ! 1227: pop eax ! 1228: pop edi ! 1229: pop esi ! 1230: pop ecx ! 1231: ! 1232: right_skip_first_pass: ! 1233: ! 1234: ; Enable the other planes. ! 1235: ! 1236: not ah ! 1237: and ah,MM_ALL ! 1238: jz short right_no_planes_left ! 1239: mov al,ah ! 1240: out dx,al ! 1241: or cl,cl ! 1242: js short right_phase_is_negative2 ! 1243: dec esi ! 1244: right_psecond_pass: ! 1245: mov ax,[esi] ! 1246: not ax ! 1247: ror ax,cl ! 1248: xchg ah,[edi] ! 1249: add esi,ebp ! 1250: add edi,ulNextScan_global ! 1251: dec ebx ! 1252: jnz right_psecond_pass ! 1253: jmp short right_no_planes_left ! 1254: ! 1255: right_phase_is_negative2: ! 1256: neg cl ; make CL = abs phase ! 1257: right_nsecond_pass: ! 1258: mov ax,[esi] ! 1259: not ax ! 1260: rol ax,cl ! 1261: xchg al,[edi] ! 1262: add esi,ebp ! 1263: add edi,ulNextScan_global ! 1264: dec ebx ! 1265: jnz right_nsecond_pass ! 1266: ! 1267: right_no_planes_left: ! 1268: mov al,MM_ALL ! 1269: out dx,al ! 1270: pop ebp ! 1271: PLAIN_RET ! 1272: ! 1273: ! 1274: ;----------------------------Private-Routine----------------------------; ! 1275: ; pat_blt ! 1276: ; XOR mode with data = FF for Pn? ! 1277: ; ! 1278: ; This BLTs an arbitrary 8x8 bit pattern (3 or 4 planes deep) to EGA. ! 1279: ; ! 1280: ; The method is simple. Load the latches with the pattern for a ! 1281: ; particular scan line, then REP STOS this with the BIT MASK = 0 ! 1282: ; so that only the latches get written. Before putting the pattern ! 1283: ; for the next scan line into the latches we will do all other scan ! 1284: ; lines with the same pattern. ! 1285: ; ! 1286: ; Entry: ! 1287: ; ESI = pattern bytes ! 1288: ; EDI = First EGA Byte ! 1289: ; ECX = Number of scan lines (yExt) ! 1290: ; EBX = offset into pattern ! 1291: ; EDX = bytes per scan line (scan_len) ! 1292: ; GRAF_DATA_ROT = DR_SET ! 1293: ; BIT_MASK = FF ! 1294: ; Returns: ! 1295: ; Nothing ! 1296: ; Registers Destroyed: ! 1297: ; ALL but EBP ! 1298: ; Registers Preserved: ! 1299: ; EBP ! 1300: ; Alters: ! 1301: ; GRAF_BIT_MASK (leaves it 00) ! 1302: ; Calls: ! 1303: ; None ! 1304: ;-----------------------------------------------------------------------; ! 1305: ! 1306: .errnz SIZE_PATTERN - 8 ; actually any power of 2 is okay. ! 1307: ! 1308: align 4 ! 1309: pat_blt: ! 1310: ! 1311: push ebp ! 1312: push edx ; scan_len ! 1313: push ecx ; yExt ! 1314: mov ah,11h ; left nibble gives carry to end loop ! 1315: ! 1316: ; Set EBP = min(yExt, scans/pattern). ! 1317: ! 1318: sub ecx,SIZE_PATTERN ; SIZE_PATTERN = 8 = yExt of pattern ! 1319: sbb ebp,ebp ! 1320: and ebp,ecx ! 1321: add ebp,SIZE_PATTERN ! 1322: ! 1323: mov dx,EGA_BASE + SEQ_DATA ! 1324: set_next_plane: ! 1325: push ebx ! 1326: push edi ! 1327: ! 1328: ; Enable next plane. ! 1329: ! 1330: mov al,MM_ALL ! 1331: and al,ah ! 1332: out dx,al ! 1333: mov ecx,ebp ! 1334: ! 1335: hit_next_byte: ! 1336: mov al,[esi][ebx] ; Next pattern byte ! 1337: inc ebx ! 1338: and ebx,SIZE_PATTERN - 1 ! 1339: mov [edi],al ! 1340: add edi,ulNextScan_global ! 1341: loop hit_next_byte ! 1342: add esi,SIZE_PATTERN ! 1343: pop edi ! 1344: pop ebx ! 1345: shl ah,1 ! 1346: jnc set_next_plane ! 1347: ! 1348: ; Set bit mask = 00. ! 1349: ! 1350: mov dx,EGA_BASE + GRAF_ADDR ! 1351: mov ax,0000h + GRAF_BIT_MASK ! 1352: out dx,ax ! 1353: ! 1354: ; Enable all planes. ! 1355: ! 1356: mov al,MM_ALL ! 1357: mov dx,EGA_BASE + SEQ_DATA ! 1358: out dx,al ! 1359: ! 1360: mov ecx,ebp ; MIN(yExt,SIZE_PATTERN) ! 1361: pop ebp ; yExt ! 1362: pop eax ; scan_len ! 1363: mov esi,ulNextScan_global ; ESI = scan_width ! 1364: ! 1365: .errnz (SIZE_PATTERN - 8) ! 1366: ;------------------------------------------------; ! 1367: ; mov ebx,(SIZE_PATTERN - 1) * scan_width ! 1368: ;------------------------------------------------; ! 1369: lea ebx,[esi*2+esi] ; scan_width * 3 ! 1370: lea ebx,[ebx+esi*4] ; scan_width * 7 ! 1371: ! 1372: sub esi,eax ; ESI = scan_width ! 1373: add ebx,esi ; EBX = (scan_width * 7) + next_scan ! 1374: ! 1375: pat_blt_next_scan: ! 1376: push ecx ! 1377: mov esi,edi ; save ESI ! 1378: mov edx,ebp ; save yExt ! 1379: mov cl,[edi] ; load latches ! 1380: ! 1381: pat_blt_loop: ! 1382: mov ecx,eax ; EAX = scan_len ! 1383: rep stosb ! 1384: add edi,ebx ; EBX = (scan_width * 7) + next_scan ! 1385: sub ebp,SIZE_PATTERN ! 1386: jg pat_blt_loop ! 1387: ! 1388: mov ebp,edx ! 1389: dec ebp ! 1390: mov edi,esi ! 1391: add edi,ulNextScan_global ! 1392: pop ecx ! 1393: loop pat_blt_next_scan ! 1394: ! 1395: pop ebp ! 1396: PLAIN_RET ! 1397: ! 1398: ! 1399: ;----------------------------Private-Routine----------------------------; ! 1400: ; edge_pat_blt ! 1401: ; ! 1402: ; Entry: ! 1403: ; AH = bitmask ! 1404: ; ESI = pattern bytes ! 1405: ; EDI = First EGA Byte ! 1406: ; ECX = Number of scan lines (yExt) ! 1407: ; EBX = offset into pattern ! 1408: ; DATA_ROT = DR_SET ! 1409: ; Returns: ! 1410: ; Nothing ! 1411: ; Registers Destroyed: ! 1412: ; EAX,ECX,EDX,ESI,flags ! 1413: ; Registers Preserved: ! 1414: ; EBX,EDI,EBP ! 1415: ; Alters: ! 1416: ; GRAF_BIT_MASK (leaves it FF) ! 1417: ; Calls: ! 1418: ; None ! 1419: ;-----------------------------------------------------------------------; ! 1420: ! 1421: align 4 ! 1422: edge_pat_blt: ! 1423: ! 1424: push ebp ! 1425: ! 1426: ; Set bit mask. ! 1427: ! 1428: mov dx,EGA_BASE + GRAF_ADDR ! 1429: mov al,GRAF_BIT_MASK ! 1430: out dx,ax ! 1431: mov ah,11h ; left nibble gives carry to end loop ! 1432: mov dx,EGA_BASE + SEQ_DATA ! 1433: sub si,SIZE_PATTERN ! 1434: mov ebp,ecx ! 1435: ! 1436: enable_next_plane: ! 1437: push ebx ! 1438: push edi ! 1439: mov ecx,ebp ; yExt ! 1440: mov al,MM_ALL ! 1441: and al,ah ! 1442: out dx,al ! 1443: add esi,SIZE_PATTERN ! 1444: ! 1445: over_scans: ! 1446: mov al,[ebx][esi] ; pattern fetch ! 1447: inc ebx ! 1448: and ebx,SIZE_PATTERN - 1 ; 7 ! 1449: .errnz SIZE_PATTERN - 8 ; any power of 2 works ! 1450: xchg [edi],al ! 1451: add edi,ulNextScan_global ! 1452: loop over_scans ! 1453: ! 1454: pop edi ! 1455: pop ebx ! 1456: shl ah,1 ! 1457: jnc enable_next_plane ! 1458: ! 1459: ; Restore bitmask to default. ! 1460: ! 1461: mov dx,EGA_BASE + GRAF_ADDR ! 1462: mov ax,0FF00h + GRAF_BIT_MASK ! 1463: out dx,ax ! 1464: ! 1465: pop ebp ! 1466: PLAIN_RET ! 1467: ! 1468: ! 1469: ;----------------------------Private-Routine----------------------------; ! 1470: ; invert ! 1471: ; ! 1472: ; Inverts pixels in a rectangle on the display, by simply writing the ! 1473: ; memory to itself, letting the EGA hardware perform the XORing. ! 1474: ; ! 1475: ; Entry: ! 1476: ; EDI = First EGA Byte ! 1477: ; ECX = Number of scan lines (yExt) ! 1478: ; EBX = scan line length in bytes ! 1479: ; DATA_ROT = DR_XOR ! 1480: ; GRAF_SET_RESET = color to xor DEST with ! 1481: ; GRAF_SR_ENAB = MM_ALL ! 1482: ; Returns: ! 1483: ; Nothing ! 1484: ; Registers Destroyed: ! 1485: ; EAX,ECX,EDX,ESI,EDI,flags ! 1486: ; Registers Preserved: ! 1487: ; EBX,EBP ! 1488: ; Alters: ! 1489: ; GRAF_BIT_MASK (leaves it FF) ! 1490: ; Calls: ! 1491: ; None ! 1492: ;-----------------------------------------------------------------------; ! 1493: ! 1494: align 4 ! 1495: invert: ! 1496: ! 1497: ; Set bit mask. ! 1498: ! 1499: mov dx,EGA_BASE + GRAF_ADDR ! 1500: mov ax,0FF00h + GRAF_BIT_MASK ! 1501: out dx,ax ! 1502: mov edx,ulNextScan_global ! 1503: sub edx,ebx ! 1504: mov eax,ecx ; save height ! 1505: ! 1506: invert_next_scan: ! 1507: mov esi,edi ! 1508: mov ecx,ebx ; scan len in bytes ! 1509: rep movsb ! 1510: add edi,edx ! 1511: dec eax ! 1512: jnz invert_next_scan ! 1513: PLAIN_RET ! 1514: ! 1515: ! 1516: ;----------------------------Private-Routine----------------------------; ! 1517: ; edge_invert ! 1518: ; ! 1519: ; Inverts one byte on each scan line vertically according to the mask ! 1520: ; in AH. ! 1521: ; ! 1522: ; Entry: ! 1523: ; AH = bitmask ! 1524: ; EDI = First EGA Byte ! 1525: ; ECX = Number of scan lines (yExt) ! 1526: ; DATA_ROT = DR_XOR ! 1527: ; GRAF_SET_RESET = color to xor DEST with ! 1528: ; GRAF_ENAB_SR = MM_ALL ! 1529: ; Returns: ! 1530: ; Nothing ! 1531: ; Registers Destroyed: ! 1532: ; AL,ECX,EDX,EDI,flags ! 1533: ; Registers Preserved: ! 1534: ; AH,EBX,ESI,EBP ! 1535: ; Alters: ! 1536: ; GRAF_BIT_MASK ! 1537: ; Calls: ! 1538: ; None ! 1539: ;-----------------------------------------------------------------------; ! 1540: ! 1541: align 4 ! 1542: edge_invert: ! 1543: ! 1544: ; Set bit mask. ! 1545: ! 1546: mov dx,EGA_BASE + GRAF_ADDR ! 1547: mov al,GRAF_BIT_MASK ! 1548: out dx,ax ! 1549: ! 1550: edge_invert_next_scan: ! 1551: xchg [edi],al ! 1552: add edi,ulNextScan_global ! 1553: loop edge_invert_next_scan ! 1554: PLAIN_RET ! 1555: ! 1556: ! 1557: ;----------------------------Private-Routine----------------------------; ! 1558: ; edge_grey_dpx ! 1559: ; ! 1560: ; Inverts one or two bytes on each scan line vertically according ! 1561: ; to the grey pattern given, under the passed clipping mask. ! 1562: ; ! 1563: ; Entry: ! 1564: ; EBX = brush index (0-7) ! 1565: ; ECX = number of scan lines (cyExt) ! 1566: ; DL = lhs clipping mask ! 1567: ; DH = rhs clipping mask ! 1568: ; ESI --> base address of brush ! 1569: ; EDI --> rhs EGA ! 1570: ; EBP --> lhs EGA ! 1571: ; Returns: ! 1572: ; Nothing ! 1573: ; Registers Destroyed: ! 1574: ; All ! 1575: ; Registers Preserved: ! 1576: ; None ! 1577: ; Alters: ! 1578: ; None ! 1579: ; Calls: ! 1580: ; None ! 1581: ;-----------------------------------------------------------------------; ! 1582: ! 1583: align 4 ! 1584: edge_grey_dpx: ! 1585: ! 1586: sub ebp,edi ;Compute delta to lhs ! 1587: and ebx,00000111b ;Make sure brush is valid ! 1588: .errnz SIZE_PATTERN - 8 ! 1589: or dh,dh ;Dispatch based on one or two edges ! 1590: jz edge_grey_dpx_one_loop ! 1591: ! 1592: edge_grey_dpx_both_loop: ! 1593: mov al,[esi][ebx] ;Get next byte of brush ! 1594: mov ah,al ! 1595: and al,dl ;Mask with lhs clipping mask ! 1596: xchg al,[edi] ;Invert necessary bits ! 1597: inc ebx ;--> next brush byte ! 1598: and bl,00000111b ;Handle any wrap ! 1599: .errnz SIZE_PATTERN - 8 ! 1600: and ah,dh ;Mask with rhs clipping mask ! 1601: xchg ah,[edi][ebp] ;Invert necessary bits ! 1602: add edi,ulNextScan_global ;--> next destination byte ! 1603: loop edge_grey_dpx_both_loop ! 1604: PLAIN_RET ! 1605: ! 1606: edge_grey_dpx_one_loop: ! 1607: mov al,[esi][ebx] ;Get next byte of brush ! 1608: and al,dl ;Mask with lhs clipping mask ! 1609: xchg al,[edi] ;Invert necessary bits ! 1610: inc ebx ;--> next brush byte ! 1611: and bl,00000111b ;Handle any wrap ! 1612: .errnz SIZE_PATTERN - 8 ! 1613: add edi,ulNextScan_global ;--> next destination byte ! 1614: loop edge_grey_dpx_one_loop ! 1615: PLAIN_RET ! 1616: ! 1617: ! 1618: ;----------------------------Private-Routine----------------------------; ! 1619: ; middle_grey_dpx ! 1620: ; ! 1621: ; Inverts a rectangle on the display using the passed grey pattern. ! 1622: ; ! 1623: ; Entry: ! 1624: ; EBX = brush index (0-7) ! 1625: ; ECX = # byte to invert on the scan ! 1626: ; EDX = EGA_BASE + GRAF_ADDR ! 1627: ; ESI --> base address of brush ! 1628: ; EDI --> starting byte ! 1629: ; EBP = number of scan lines (cyExt) ! 1630: ; DATA_ROT = DR_XOR ! 1631: ; GRAF_SET_RESET = All 1 ! 1632: ; GRAF_ENAB_SR = MM_ALL ! 1633: ; Returns: ! 1634: ; Nothing ! 1635: ; Registers Destroyed: ! 1636: ; EAX,ECX,EDX,ESI,EDI,flags ! 1637: ; Registers Preserved: ! 1638: ; EBX,EBP ! 1639: ; Alters: ! 1640: ; GRAF_BIT_MASK (leaves it FF) ! 1641: ; Calls: ! 1642: ; None ! 1643: ;-----------------------------------------------------------------------; ! 1644: ! 1645: align 4 ! 1646: middle_grey_dpx: ! 1647: ! 1648: ; mov dx,EGA_BASE + GRAF_ADDR ; Leave the Graphics controller ! 1649: mov al,GRAF_BIT_MASK ; address register pointing to ! 1650: out dx,al ; the bitmask register ! 1651: inc edx ; --> Graphics controller data register ! 1652: .errnz GRAF_DATA - GRAF_ADDR - 1 ! 1653: ! 1654: mov ah,bl ; Keep brush index here ! 1655: mov ebx,ecx ; Save a copy of inner loop count here ! 1656: ! 1657: middle_grey_dpx_loop: ! 1658: xchg eax,ebx ! 1659: xchg bl,bh ! 1660: and ebx,00000111b ! 1661: errnz SIZE_PATTERN-8 ! 1662: mov bh,[esi][ebx] ; Get next byte of brush ! 1663: inc bl ; --> byte of the brush ! 1664: xchg bh,bl ! 1665: xchg eax,ebx ! 1666: out dx,al ! 1667: mov ecx,ebx ! 1668: push esi ! 1669: mov esi,edi ! 1670: rep movsb ! 1671: pop esi ! 1672: sub edi,ebx ! 1673: add edi,ulNextScan_global ;next scan on screen ! 1674: dec ebp ! 1675: jnz middle_grey_dpx_loop ! 1676: PLAIN_RET ! 1677: ! 1678: ! 1679: ;----------------------------Private-Routine----------------------------; ! 1680: ; do_grey_dpx ! 1681: ; ! 1682: ; This is EGA special cased code for the dpx raster op in the case where ! 1683: ; the pattern (p) is grey (the same on all planes). We also come here ! 1684: ; for the special graying pattern rop. This is not a normal P,S, and D rop, ! 1685: ; but a hack for pmwin. It allows graying of things on the screen, meaning ! 1686: ; the background color is stuffed everywhere the pattern has a "1" bit. ! 1687: ; ! 1688: ; Entry: ! 1689: ; EBP --> BitBLT local variable frame ! 1690: ; Returns: ! 1691: ; Nothing ! 1692: ; Registers Destroyed: ! 1693: ; ALL but EBP ! 1694: ; Registers Preserved: ! 1695: ; EBP ! 1696: ; Calls: ! 1697: ; calc_parms ! 1698: ; edge_grey_dpx ! 1699: ; middle_grey_dpx ! 1700: ;-----------------------------------------------------------------------; ! 1701: ! 1702: align 4 ! 1703: do_grey_dpx: ! 1704: ! 1705: call calc_parms ! 1706: mov dx,EGA_BASE + GRAF_ADDR ! 1707: mov ax,DR_XOR shl 8 + GRAF_DATA_ROT ; XOR mode for grey dpx ! 1708: out dx,ax ! 1709: mov dl,byte ptr fr.start_mask[0] ! 1710: mov dh,byte ptr fr.last_mask[0] ! 1711: or dx,dx ! 1712: jz do_grey_dpx_middle ;Only middle bytes exist ! 1713: ! 1714: mov eax,edi ;Assume we have a left edge ! 1715: inc eax ;+1 to get to start of middle bytes ! 1716: or dl,dl ;Is there really a left edge? ! 1717: jnz do_grey_dpx_have_lhs ; Yes, AX = correct middle byte start ! 1718: dec eax ; No, restore middle byte start ! 1719: xchg dl,dh ; Pretend only a lhs edge ! 1720: add edi,fr.inner_loop_count ; but make it be the rhs ! 1721: ! 1722: do_grey_dpx_have_lhs: ! 1723: push eax ;Save middle bytes start ! 1724: push ebx ! 1725: push ecx ! 1726: push esi ! 1727: push ebp ! 1728: add eax,fr.inner_loop_count ;--> possible rhs ! 1729: xchg eax,ebp ! 1730: call edge_grey_dpx ! 1731: did_gray_pat_edge: ! 1732: pop ebp ! 1733: pop esi ! 1734: pop ecx ! 1735: pop ebx ! 1736: pop edi ;Restore middle bytes start ! 1737: ! 1738: do_grey_dpx_middle: ! 1739: mov eax,fr.inner_loop_count ! 1740: or eax,eax ! 1741: jz do_grey_dpx_exit ! 1742: push ebp ! 1743: mov ebp,ecx ! 1744: xchg eax,ecx ! 1745: mov dx,EGA_BASE + GRAF_ADDR ; ! 1746: mov ax,MM_ALL shl 8 + GRAF_ENAB_SR ; Set Set/Reset to all "1" bits ! 1747: out dx,ax ; and Enable all planes (for ! 1748: .errnz MM_ALL - 0Fh ; grey_dpx) ! 1749: mov al,GRAF_SET_RESET ; ! 1750: out dx,ax ; ! 1751: ! 1752: gray_pat: ! 1753: call middle_grey_dpx ! 1754: pop ebp ! 1755: ! 1756: do_grey_dpx_exit: ! 1757: PLAIN_RET ! 1758: ! 1759: ! 1760: endProc check_device_special_cases ! 1761: ! 1762: _TEXT$01 ends ! 1763: ! 1764: end ! 1765:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.