|
|
1.1 ! root 1: page ,132 ! 2: ;-----------------------------Module-Header-----------------------------; ! 3: ; Module Name: POINTER.ASM ! 4: ; ! 5: ; This file contains the pointer shape routines required to draw the ! 6: ; pointer shape on the EGA. ! 7: ; ! 8: ; Copyright (c) 1992 Microsoft Corporation ! 9: ; ! 10: ; Exported Functions: none ! 11: ; ! 12: ; Public Functions: xyCreateMasks ! 13: ; vDrawPointer ! 14: ; vYankPointer ! 15: ; ! 16: ; General Description: ! 17: ; ! 18: ; All display drivers must support a "pointer" for the pointing ! 19: ; device. The pointer is a small graphics image which is allowed ! 20: ; to move around the screen independantly of all other operations ! 21: ; to the screen, and is normally bound to the location of the ! 22: ; pointing device. The pointer is non-destructive in nature, i.e. ! 23: ; the bits underneath the pointer image are not destroyed by the ! 24: ; presence of the pointer image. ! 25: ; ! 26: ; A pointer consists of an AND mask and an XOR mask, which give ! 27: ; combinations of 0's, 1's, display, or inverse display. ! 28: ; ! 29: ; AND XOR | DISPLAY ! 30: ; ---------------------- ! 31: ; 0 0 | 0 ! 32: ; 0 1 | 1 ! 33: ; 1 0 | Display ! 34: ; 1 1 | Not Display ! 35: ; ! 36: ; The pointer also has a "hot spot", which is the pixel of the ! 37: ; pointer image which is to be aligned with the actual pointing ! 38: ; device location. ! 39: ; ! 40: ; ! 41: ; | For a pointer like this, the hot spot ! 42: ; | would normally be the *, which would ! 43: ; ---*--- be aligned with the pointing device ! 44: ; | position ! 45: ; | ! 46: ; ! 47: ; The pointer may be moved to any location on the screen, be ! 48: ; restricted to only a section of the screen, or made invisible. ! 49: ; Part of the pointer may actually be off the edge of the screen, ! 50: ; and in such a case only the visible portion of the pointer ! 51: ; image is displayed. ! 52: ; ! 53: ; ! 54: ; ! 55: ; Logically, the pointer image isn't part of the physical display ! 56: ; surface. When a drawing operation coincides with the pointer ! 57: ; image, the result is the same as if the pointer image wasn't ! 58: ; there. In reality, if the pointer image is part of the display ! 59: ; surface it must be removed from memory before the drawing ! 60: ; operation may occur, and redrawn at a later time. ! 61: ; ! 62: ; This exclusion of the pointer image is the responsibility of ! 63: ; the display driver. If the pointer image is part of physical ! 64: ; display memory, then all output operations must perform a hit ! 65: ; test to determine if the pointer must be removed from display ! 66: ; memory, and set a protection rectangle wherein the pointer must ! 67: ; not be displayed. The actual pointer image drawing routine ! 68: ; must honor this protection rectangle by never drawing the ! 69: ; pointer image within its boundary. ! 70: ; ! 71: ; This code doesn't distinguish between pointers and icons, ! 72: ; they both are the same size, 32 x 32, which comes out square. ! 73: ; ! 74: ; Restrictions: ! 75: ; ! 76: ; All routines herein assume protection either via cli/sti ! 77: ; or a semephore at higher level code. ! 78: ; ! 79: ;-----------------------------------------------------------------------; ! 80: ! 81: .386 ! 82: ! 83: ifndef DOS_PLATFORM ! 84: .model small,c ! 85: else ! 86: ifdef STD_CALL ! 87: .model small,c ! 88: else ! 89: .model small,pascal ! 90: endif; STD_CALL ! 91: endif; DOS_PLATFORM ! 92: ! 93: ASSUME CS: FLAT, DS: FLAT, SS: FLAT, ES: FLAT ! 94: assume FS: NOTHING, GS: NOTHING ! 95: ! 96: .xlist ! 97: include stdcall.inc ! 98: include i386\egavga.inc ! 99: include i386\strucs.inc ! 100: .list ! 101: ! 102: PUBLIC PTR_ROUND_RIGHT ;Pointer exclusion needs these ! 103: PUBLIC PTR_ROUND_LEFT ! 104: PUBLIC PTR_WIDTH_BITS ! 105: PUBLIC PTR_HEIGHT ! 106: ! 107: ! 108: ;-----------------------------------------------------------------------; ! 109: ; The following values allow us to set rounding for cursor exclusion. ! 110: ; These values are applied as an AND mask (for rounding left) and as ! 111: ; an OR mask (for rounding right). ! 112: ;-----------------------------------------------------------------------; ! 113: ! 114: ROUNDING_SIZE EQU 8 ;Round to byte boundaries ! 115: .ERRNZ ROUNDING_SIZE AND 111b ;Must be at least byte boundary ! 116: PTR_ROUND_RIGHT EQU ROUNDING_SIZE-1 ! 117: PTR_ROUND_LEFT EQU -ROUNDING_SIZE ! 118: ! 119: ;-----------------------------------------------------------------------; ! 120: ; The RECT_DATA structure is used for describing the rectangles ! 121: ; which will be manipulated by this code. The fields are: ! 122: ; ! 123: ; rd_ptbSave This is the (X,Y) origin of the given rectangle in ! 124: ; the save area. ! 125: ; ! 126: ; rd_ptlScreen This is the (X,Y) origin of the given rectangle on ! 127: ; the screen. ! 128: ; ! 129: ; rd_sizb This is the extents of the rectangle. ! 130: ; ! 131: ; rd_ptbWork This is the (X,Y) origin of the given rectangle in ! 132: ; the work area. ! 133: ;-----------------------------------------------------------------------; ! 134: ! 135: ifdef DUPS_ARE_LEGAL ! 136: ! 137: RECT_DATA STRUC ! 138: rd_ptbSave DW ((SIZE POINTB)/2) DUP (0) ! 139: rd_ptlScreen DW ((SIZE POINTL)/2) DUP (0) ! 140: rd_sizb DW ((SIZE SIZEB)/2) DUP (0) ! 141: rd_ptbWork DW ((SIZE POINTB)/2) DUP (0) ! 142: RECT_DATA ENDS ! 143: .ERRNZ SIZE POINTB AND 1 ! 144: .ERRNZ SIZE POINTL AND 1 ! 145: .ERRNZ SIZE SIZEB AND 1 ! 146: ! 147: else ! 148: ! 149: RECT_DATA STRUC ! 150: rd_ptbSave dw 0 ; POINTB ! 151: rd_ptlScreen dd 0,0 ; POINTL ! 152: rd_sizb dw 0 ; SIZEB ! 153: rd_ptbWork dw 0 ; POINTB ! 154: RECT_DATA ENDS ! 155: .ERRNZ (SIZE POINTB) - 2 ! 156: .ERRNZ (SIZE POINTL) - 8 ! 157: .ERRNZ (SIZE SIZEB) - 2 ! 158: ! 159: endif ! 160: ! 161: ! 162: ! 163: ;-----------------------------------------------------------------------; ! 164: ; The POINTER_DATA structure is used for describing the actual pointer's ! 165: ; rectangle. It also contains clipping information and control flags. ! 166: ; The fields are: ! 167: ; ! 168: ; pd_rd RECT_DATA structure as defined above ! 169: ; ! 170: ; pd_fb Flags as follows: ! 171: ; ! 172: ; PD_VALID 1 The rectangle contains valid data. ! 173: ; 0 The rectangle data is invalid. ! 174: ; ! 175: ; PD_CLIP_BOTTOM 1 Clip the bottom ! 176: ; 0 No bottom clipping needed ! 177: ; ! 178: ; PD_CLIP_TOP 1 Clip the top ! 179: ; 0 No top clipping needed ! 180: ; ! 181: ; PD_CLIP_LEFT 1 Clip the lhs ! 182: ; 0 No lhs clipping needed ! 183: ; ! 184: ; PD_CLIP_RIGHT 1 Clip the rhs ! 185: ; 0 No rhs clipping needed ! 186: ;-----------------------------------------------------------------------; ! 187: ! 188: ifdef DUPS_ARE_LEGAL ! 189: ! 190: POINTER_DATA STRUC ! 191: pd_rd DW ((SIZE RECT_DATA)/2) DUP (0) ! 192: pd_fb DB 0 ! 193: DB 0 ! 194: POINTER_DATA ENDS ! 195: .ERRNZ SIZE RECT_DATA AND 1 ! 196: ! 197: else ! 198: ! 199: POINTER_DATA struc ! 200: pd_rd dw 0,0,0,0,0,0,0 ; RECT_DATA ! 201: pd_fb db 0 ! 202: db 0 ! 203: POINTER_DATA ends ! 204: .ERRNZ (size POINTER_DATA) - (SIZE RECT_DATA) - 2 ! 205: ! 206: endif ! 207: ! 208: ! 209: PD_CLIP_BOTTOM EQU 10000000b ! 210: PD_CLIP_TOP EQU 01000000b ! 211: PD_CLIP_RIGHT EQU 00100000b ! 212: PD_CLIP_LEFT EQU 00010000b ! 213: PD_VALID EQU 00001000b ! 214: ; EQU 00000100b ! 215: ; EQU 00000010b ! 216: ; EQU 00000001b ! 217: ! 218: PD_CLIPPED EQU PD_CLIP_BOTTOM OR PD_CLIP_TOP OR PD_CLIP_RIGHT OR PD_CLIP_LEFT ! 219: ! 220: ! 221: .DATA ! 222: ! 223: PUBLIC pdPtr1 ! 224: PUBLIC pdPtr2 ! 225: PUBLIC rdFlushX ! 226: PUBLIC rdFlushY ! 227: PUBLIC rdOverlap ! 228: PUBLIC rdReadX ! 229: PUBLIC rdReadY ! 230: PUBLIC rdWork ! 231: ! 232: ! 233: ; Offsets of locations in the EGA/VGA's address ! 234: ; space used both to determine and save the state of the EGA/VGA. ! 235: ; ! 236: ; The actual address within the EGA/VGA's Regen RAM is determined ! 237: ; at init time, and is based on the number of vertical scans. ! 238: ! 239: EXTRN pPtrSave : DWORD ;offset from bitmap start of pointer ! 240: EXTRN pPtrWork : DWORD ; work areas ! 241: ! 242: ; !!! This temp flag is a stupid hack to know if the pointer is color or ! 243: ; !!! mono. Fix it up ! 244: ! 245: ! 246: flPointer dd 0 ! 247: ! 248: ! 249: ! 250: pdPtr1 POINTER_DATA <> ;Old/New pointer's data ! 251: pdPtr2 POINTER_DATA <> ;Old/New pointer's data ! 252: rdFlushX RECT_DATA <> ;Flush from save area to screen ! 253: rdFlushY RECT_DATA <> ;Flush from save area to screen ! 254: rdOverlap RECT_DATA <> ;And from save area to work area ! 255: rdReadX RECT_DATA <> ;Read from screen to save, xor to work ! 256: rdReadY RECT_DATA <> ;Read from screen to save, xor to work ! 257: rdWork RECT_DATA <> ;Xor from work to screen ! 258: ! 259: ! 260: ;-----------------------------------------------------------------------; ! 261: ; siz?Mask contains the width and height of the working portion of ! 262: ; the current AND and XOR mask. Use of this allows us to manipulate ! 263: ; less memory when parts of the pointer won't alter the screen image. ! 264: ;-----------------------------------------------------------------------; ! 265: ! 266: sizbMask SIZEB <WORK_WIDTH,PTR_HEIGHT> ! 267: sizlMask SIZEL <WORK_WIDTH,PTR_HEIGHT> ! 268: ! 269: ! 270: ;-----------------------------------------------------------------------; ! 271: ; sizsMaxDelta is the maximum distance the old and new pointers may ! 272: ; be before they are considered disjoint. ! 273: ;-----------------------------------------------------------------------; ! 274: ! 275: sizlMaxDelta SIZEL <WORK_WIDTH,WORK_HEIGHT> ! 276: ! 277: ! 278: ;-----------------------------------------------------------------------; ! 279: ; ptlBotRightClip is the coordinate where rhs or bottom clipping ! 280: ; will first occur. It is basically the screen width - pointer width. ! 281: ;-----------------------------------------------------------------------; ! 282: ! 283: ptlBotRightClip POINTL <0,0> ! 284: ! 285: ! 286: ;-----------------------------------------------------------------------; ! 287: ; This is the initial origin in the save buffer. ! 288: ;-----------------------------------------------------------------------; ! 289: ! 290: ptbInitOrigin POINTB <0,0> ! 291: ! 292: ! 293: ;-----------------------------------------------------------------------; ! 294: ; ppdOld is the pointer to the old pointer's POINTER_DATA structure ! 295: ;-----------------------------------------------------------------------; ! 296: ! 297: ppdOld DD offset FLAT:pdPtr1 ! 298: ! 299: ! 300: ;-----------------------------------------------------------------------; ! 301: ; ppdNew is the pointer to the new pointer's POINTER_DATA structure ! 302: ;-----------------------------------------------------------------------; ! 303: ! 304: ppdNew DD offset FLAT:pdPtr2 ! 305: ! 306: ! 307: ;-----------------------------------------------------------------------; ! 308: ; pAndXor is the pointer to which AND/XOR mask is to be used. It is ! 309: ; based on the 3 least significant bits of the pointer's X coordinate. ! 310: ; pColor is the pointer to which COLOR mask is to be used. ! 311: ;-----------------------------------------------------------------------; ! 312: ! 313: pAndXor DD -1 ! 314: pColor DD -1 ! 315: ! 316: ! 317: ;-----------------------------------------------------------------------; ! 318: ; The following are the masks which make up the pointer image. There ! 319: ; will be one AND/XOR/COLOR mask pair for each possible alignment. On ! 320: ; move_pointers call, all the alignments will be generated to save time. ! 321: ;-----------------------------------------------------------------------; ! 322: ! 323: public base_and_masks ! 324: public base_xor_masks ! 325: public base_clr_masks ! 326: ! 327: base_and_masks EQU THIS BYTE ! 328: REPT (MASK_LENGTH * 8) ! 329: DB ? ! 330: ENDM ! 331: ! 332: base_xor_masks EQU THIS BYTE ! 333: REPT (MASK_LENGTH * 8) ! 334: DB ? ! 335: ENDM ! 336: ! 337: base_clr_masks EQU THIS BYTE ! 338: REPT (CLR_MASK_LENGTH * 8) ! 339: DB ? ! 340: ENDM ! 341: ! 342: ;-----------------------------------------------------------------------; ! 343: ; pabAndMasks is an array which points to the start of the mask for ! 344: ; each X rotation. It is indexed into using the low 3 bits of the ! 345: ; pointer's X coordinate. ! 346: ;-----------------------------------------------------------------------; ! 347: ! 348: pabAndMasks EQU THIS DWORD ! 349: DD offset FLAT:base_and_masks+(0*MASK_LENGTH) ! 350: DD offset FLAT:base_and_masks+(1*MASK_LENGTH) ! 351: DD offset FLAT:base_and_masks+(2*MASK_LENGTH) ! 352: DD offset FLAT:base_and_masks+(3*MASK_LENGTH) ! 353: DD offset FLAT:base_and_masks+(4*MASK_LENGTH) ! 354: DD offset FLAT:base_and_masks+(5*MASK_LENGTH) ! 355: DD offset FLAT:base_and_masks+(6*MASK_LENGTH) ! 356: DD offset FLAT:base_and_masks+(7*MASK_LENGTH) ! 357: ! 358: ;-----------------------------------------------------------------------; ! 359: ; pabClrMasks is an array which points to the start of the mask for ! 360: ; each X rotation. It is indexed into using the low 3 bits of the ! 361: ; pointer's X coordinate. ! 362: ;-----------------------------------------------------------------------; ! 363: ! 364: pabClrMasks EQU THIS DWORD ! 365: DD offset FLAT:base_clr_masks+(0*CLR_MASK_LENGTH) ! 366: DD offset FLAT:base_clr_masks+(1*CLR_MASK_LENGTH) ! 367: DD offset FLAT:base_clr_masks+(2*CLR_MASK_LENGTH) ! 368: DD offset FLAT:base_clr_masks+(3*CLR_MASK_LENGTH) ! 369: DD offset FLAT:base_clr_masks+(4*CLR_MASK_LENGTH) ! 370: DD offset FLAT:base_clr_masks+(5*CLR_MASK_LENGTH) ! 371: DD offset FLAT:base_clr_masks+(6*CLR_MASK_LENGTH) ! 372: DD offset FLAT:base_clr_masks+(7*CLR_MASK_LENGTH) ! 373: ! 374: ;-----------------------------------------------------------------------; ! 375: ; The following flags and flag bytes are used to control which ! 376: ; rectangles are used for what. ! 377: ; ! 378: ; fbFlush controls which rectangles are to be copied from the save ! 379: ; area to the screen. Valid flags are: ! 380: ; ! 381: ; FB_OLD_PTR, FB_FLUSH_X, FB_FLUSH_Y ! 382: ; ! 383: ; FB_OLD_PTR is mutually exclusive of all other flags ! 384: ; ! 385: ; ! 386: ; fbAndRead controls which rectangles are to be ANDed into the work ! 387: ; area from the screen or save area, and which rectangles are to be ! 388: ; copied from the screen to the save area. Valid flags are: ! 389: ; ! 390: ; FB_NEW_PTR, FB_OVERLAP, FB_READ_X, FB_READ_Y, FB_WORK_RECT, ! 391: ; ! 392: ; FB_NEW_PTR and FB_WORK_RECT are mutually exclusive of all other ! 393: ; flags. Note that FB_OVERLAP doesn't apply when coping into the ! 394: ; save area. ! 395: ; ! 396: ; ! 397: ; fbXor describes which rectangle is to be XORed from the work area ! 398: ; into the screen. Valid flags are: ! 399: ; ! 400: ; FB_NEW_PTR, FB_WORK_RECT ! 401: ; ! 402: ; FB_NEW_PTR and FB_WORK_RECT are mutually exclusive ! 403: ;-----------------------------------------------------------------------; ! 404: ! 405: fbFlush DB 0 ! 406: fbAndRead DB 0 ! 407: fbXor DB 0 ! 408: FB_OLD_PTR EQU 10000000b ! 409: FB_NEW_PTR EQU 01000000b ! 410: FB_FLUSH_X EQU 00100000b ! 411: FB_FLUSH_Y EQU 00010000b ! 412: FB_OVERLAP EQU 00001000b ! 413: FB_READ_X EQU 00000100b ! 414: FB_READ_Y EQU 00000010b ! 415: FB_WORK_RECT EQU 00000001b ! 416: ! 417: ; Temporary work buffer. We copy the masks and color data here before ! 418: ; we decide how to flip them. !!! Costly use of static space. Use frame ! 419: ! 420: public alWorkBuff ! 421: ! 422: ! 423: alWorkBuff EQU THIS DWORD ! 424: REPT (2 * PTR_HEIGHT) ! 425: DD ? ! 426: ENDM ! 427: ! 428: ! 429: ; Table of entry points into and_from_screen inner loop ! 430: ! 431: align 4 ! 432: and_from_screen_entry_table label dword ! 433: dd and_from_screen_width_0 ! 434: dd and_from_screen_width_1 ! 435: dd and_from_screen_width_2 ! 436: dd and_from_screen_width_3 ! 437: dd and_from_screen_width_4 ! 438: dd and_from_screen_width_5 ! 439: ! 440: ! 441: ; Table of entry points into and_from_save inner loop ! 442: ! 443: align 4 ! 444: and_from_save_entry_table label dword ! 445: dd and_from_save_width_0 ! 446: dd and_from_save_width_1 ! 447: dd and_from_save_width_2 ! 448: dd and_from_save_width_3 ! 449: dd and_from_save_width_4 ! 450: dd and_from_save_width_5 ! 451: ! 452: ! 453: ; Table of entry points into cps_do_a_pass inner loop ! 454: ! 455: align 4 ! 456: color_to_screen_entry_table label dword ! 457: dd color_to_screen_width_0 ! 458: dd color_to_screen_width_1 ! 459: dd color_to_screen_width_2 ! 460: dd color_to_screen_width_3 ! 461: dd color_to_screen_width_4 ! 462: dd color_to_screen_width_5 ! 463: ! 464: ;------------------------------------------------------------------------; ! 465: ! 466: .CODE ! 467: ! 468: _TEXT$01 SEGMENT DWORD USE32 PUBLIC 'CODE' ! 469: ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING ! 470: ! 471: ;--------------------------Public-Routine-------------------------------; ! 472: ; xyCreateMasks ! 473: ; ! 474: ; The AND, XOR and COLOR pointer masks are stored in the pointer work ! 475: ; areas. The original mask will be pre-rotated for all eight ! 476: ; possible alignments within a byte. ! 477: ; ! 478: ; As the pointer is copied, it will be processed to see if it ! 479: ; can be made narrower. After it has been copied, it will be ! 480: ; processed to see if it can be made shorter. ! 481: ; ! 482: ; The following table indicates how the XOR/AND bitmap interacts with ! 483: ; the COLOR bitmap for a color system: ! 484: ; ! 485: ; XOR AND COLOR Result ! 486: ; 1 1 x invert screen ! 487: ; 0 0 x use x ! 488: ; 0 1 x transparent ! 489: ; 1 0 x use x ! 490: ; ! 491: ; From the table, we observe that when the AND bits are on, the ! 492: ; corresponding COLOR bits are irrelevant. We preprocess the ! 493: ; COLOR bitmap to mask off these bits. ! 494: ; ! 495: ; When drawing the color pointer, we do the following steps: ! 496: ; 1. XOR the destination with XOR mask. ! 497: ; 2. AND the destination with AND mask. Note the zero bits ! 498: ; would mask off the destination to prepare for the COLOR mask. ! 499: ; 3. OR the destination with the COLOR mask. Note it does not ! 500: ; affect the inverted or transparent bits since we have masked ! 501: ; off the corresponding COLOR bits during preprocessing. ! 502: ; ! 503: ; Entry: ! 504: ; ! 505: ; Returns: ! 506: ; AX = width in pels for exclusion hit test ! 507: ; DX = height in scans for exclusion hit test ! 508: ; Error Returns: ! 509: ; None ! 510: ; Registers Preserved: ! 511: ; BP ! 512: ; Registers Destroyed: ! 513: ; AX,BX,CX,DX,SI,DI,FLAGS ! 514: ; Calls: ! 515: ; create_masks_1_thru_7 ! 516: ; ! 517: ;-----------------------------------------------------------------------; ! 518: ! 519: cProc xyCreateMasks,24,< \ ! 520: USES esi edi ebx, \ ! 521: ppdev:PTR, \ ! 522: pBitsAndXor:PTR, \ ! 523: pBitsColor:PTR, \ ! 524: cyHeight:DWORD, \ ! 525: pulXlate:DWORD, \ ! 526: wFlags:WORD > ! 527: ! 528: local cyScreen:dword ;height of bitmap in scans ! 529: local lNextScan:dword ;width of bitmap in bytes ! 530: local ajColorBits[PTR_WIDTH*PTR_HEIGHT*4]:byte ! 531: local aulXlate[16]:dword ! 532: ! 533: cld ! 534: ! 535: mov ecx,ppdev ! 536: mov eax,[ecx].PDEV_sizlSurf.sizl_cy ! 537: mov cyScreen,eax ! 538: mov ecx,[ecx].PDEV_pdsurf ! 539: mov eax,[ecx].dsurf_lNextScan ! 540: mov lNextScan,eax ! 541: ! 542: cmp pBitsColor,0 ! 543: jne short xycm_have_color ! 544: ; Copy the AND/XOR mask into the work buffer ! 545: ! 546: mov esi,pBitsAndXor ! 547: mov ecx,cyHeight ! 548: mov bx,wFlags ! 549: shl ecx,1 ! 550: mov edi,offset FLAT:alWorkBuff ! 551: rep movsd ;copy AND mask ! 552: jmp short xycm_continue ! 553: ! 554: xycm_have_color: ! 555: ! 556: ; If a color translation vector was given, generate the new bit ! 557: ; conversion array ! 558: ! 559: mov eax,offset FLAT:aulDefBitMapping ! 560: cld ! 561: mov esi,pulXlate ! 562: or esi,esi ! 563: jz have_mapping_array ! 564: lea edi,aulXlate ! 565: mov ecx,16 ! 566: create_next_bit_mapping: ! 567: lodsd ! 568: mov eax,aulDefBitMapping[eax*4] ! 569: stosd ! 570: dec ecx ! 571: jnz create_next_bit_mapping ! 572: lea eax,[edi][-16*4] ! 573: have_mapping_array: ! 574: mov pulXlate,eax ! 575: ! 576: ; Copy the AND mask into the work buffer ! 577: ! 578: mov edi,offset FLAT:alWorkBuff ! 579: test wFlags,PTRI_INVERT ;are masks backwards? ! 580: jz @F ; NO ! 581: mov edi,offset FLAT:alWorkBuff + (4*PTR_HEIGHT) ! 582: @@: ! 583: mov esi,pBitsAndXor ! 584: mov ecx,cyHeight ! 585: rep movsd ;copy AND mask ! 586: ! 587: ; later on we will flip the AND and XOR masks, so we have to mix them ! 588: ; up now else there will be problems later. ! 589: ! 590: mov esi,pBitsColor ;Source color bits ! 591: lea edi,ajColorBits ;Where to store color ! 592: mov ecx,cyHeight ! 593: mov dx,wFlags ! 594: push ebp ! 595: mov ebp,pulXlate ! 596: call vConvertDIBPointer ! 597: pop ebp ! 598: ! 599: xycm_continue: ! 600: mov ebx,cyHeight ! 601: mov dx,wFlags ! 602: cCall vCopyMasks ;Pad and maybe flip masks ! 603: ! 604: ;-----------------------------------------------------------------------; ! 605: ; The image we are copying is PTR_WIDTH bytes wide. We must add an ! 606: ; extra byte to make it WORK_WIDTH wide. The byte we add will depends ! 607: ; on whether this is the AND or the XOR mask. For an AND mask, we add ! 608: ; an FF byte on the end of each scan. For an XOR mask, we add a 00 ! 609: ; byte on the end of each scan. For the COLOR mask, we add a 00 byte on ! 610: ; the end of each scan of all planes. These bytes won't alter anything ! 611: ; on the screen. ! 612: ;-----------------------------------------------------------------------; ! 613: ! 614: mov esi,offset FLAT:alWorkBuff ;ESI --> AND/XOR mask ! 615: ! 616: ;-----------------------------------------------------------------------; ! 617: ; Copy the AND mask over. As we copy it, accumulate the value of ! 618: ; each column of the mask. If the entire column is FF, we may be ! 619: ; able to discard it. ! 620: ;-----------------------------------------------------------------------; ! 621: ! 622: mov edi, offset FLAT:base_and_masks ! 623: mov ecx, PTR_HEIGHT ;Set height for move ! 624: mov ebx, 0FFFFFFFFh ;Accumulate mask columns ! 625: ! 626: move_next_and_mask_scan: ! 627: lodsd ;Move explicit part ! 628: stosd ! 629: and ebx, eax ! 630: mov al, 0FFh ! 631: stosb ! 632: .ERRNZ PTR_WIDTH-4 ! 633: .ERRNZ WORK_WIDTH-5 ! 634: loop move_next_and_mask_scan ! 635: push ebx ;Save AND column mask ! 636: mov edx, offset FLAT:base_and_masks ! 637: mov ecx, (MASK_LENGTH*7)/(WORK_WIDTH*2) ! 638: .ERRNZ (MASK_LENGTH*7) mod (WORK_WIDTH*2) ! 639: cCall create_masks_1_thru_7 ! 640: ! 641: ;-----------------------------------------------------------------------; ! 642: ; Copy the XOR mask over. As we copy it, accumulate the value of ! 643: ; each column of the mask. If the entire column is 00, we may be ! 644: ; able to discard it. ! 645: ;-----------------------------------------------------------------------; ! 646: ! 647: mov edi, offset FLAT:base_xor_masks ! 648: mov ecx, PTR_HEIGHT ;Set height for move ! 649: xor ebx, ebx ;Accumulate columns of the mask ! 650: ! 651: move_next_xor_mask_scan: ! 652: lodsd ;Move explicit part ! 653: stosd ! 654: or ebx, eax ! 655: xor al, al ! 656: stosb ! 657: .ERRNZ PTR_WIDTH-4 ! 658: .ERRNZ WORK_WIDTH-5 ! 659: loop move_next_xor_mask_scan ! 660: push ebx ! 661: mov edx, offset FLAT:base_xor_masks ! 662: mov ecx, (MASK_LENGTH*7)/(WORK_WIDTH*2) ! 663: .ERRNZ (MASK_LENGTH*7) mod (WORK_WIDTH*2) ! 664: cCall create_masks_1_thru_7 ! 665: ! 666: ;-----------------------------------------------------------------------; ! 667: ; The masks have been copied. Compute the number of columns which can ! 668: ; be discarded. To discard a column, all bits of the AND mask for that ! 669: ; column must be 1, and all bits of the XOR mask for the column must be ! 670: ; 0. Since we work with bytes in this code, this must be true for an ! 671: ; entire byte. ! 672: ; ! 673: ; Also note that the columns must be processed right to left. We cannot ! 674: ; throw out a middle column if its neighbors contain data. ! 675: ;-----------------------------------------------------------------------; ! 676: ! 677: ;AND mask, EAX[0] = byte 1, EAX[1] = byte 2 ! 678: ;AND mask, EAX[2] = byte 3, EAX[3] = byte 4 ! 679: ;XOR mask, EBX[0] = byte 1, EBX[1] = byte 2 ! 680: ;XOR mask, EBX[2] = byte 3, EBX[3] = byte 4 ! 681: ! 682: pop ebx ;EBX XOR mask ! 683: pop eax ;EAX AND mask ! 684: ! 685: not eax ! 686: or eax, ebx ;Discard only if both are zero! ! 687: ! 688: mov ebx, WORK_WIDTH ! 689: mov edx, PTR_HEIGHT ;assume full mask ! 690: xor ecx, ecx ! 691: ;check wFlags ! 692: test wFlags, PTRI_ANIMATE ! 693: jnz mp_have_sizes ! 694: ! 695: ; !!! Until conversion of pointer images is handled via bitblt, always ! 696: ; !!! treat color cursors as full size ! 697: cmp pBitsColor,0 ;!!! ! 698: jne mp_have_sizes ;!!! ! 699: ! 700: mov edx,eax ;DX = bytes 1 and 2 ! 701: shr eax,16 ;AX = bytes 3 and 4 ! 702: or ah,ah ;Discard 4th byte of mask? ! 703: jnz @F ; No ! 704: dec ebx ! 705: or al,al ! 706: jnz @F ! 707: dec ebx ! 708: or dh,dh ! 709: jnz @F ! 710: dec ebx ! 711: or dl,dl ! 712: jz move_pointers_done ;AX = DX = 0 for return codes ! 713: @@: ! 714: ! 715: ;-----------------------------------------------------------------------; ! 716: ; Compute the number of rows which can be discarded off the bottom. ! 717: ; To discard a row, all bits of the AND mask for that row must be a ! 718: ; 1, and all bits of the XOR mask for that row must be 0. ! 719: ;-----------------------------------------------------------------------; ! 720: ! 721: .ERRNZ PTR_WIDTH AND 1 ;Must be a word multiple ! 722: ! 723: dec esi ;Post decremnent, not pre decrement ! 724: dec esi ! 725: lea edi, [esi][-PTR_WIDTH*PTR_HEIGHT] ;Last word of AND mask ! 726: mov ecx, (PTR_WIDTH/2)*PTR_HEIGHT ! 727: mov ax, 0FFFFh ;Processing AND mask ! 728: std ! 729: repe scasw ! 730: mov edx, ecx ;Save count ! 731: mov edi, esi ;--> XOR mask ! 732: mov ecx, (PTR_WIDTH/2)*PTR_HEIGHT ! 733: xor eax, eax ;Processing XOR mask ! 734: repe scasw ! 735: cld ;Take care of this while we remember ! 736: cmp ecx, edx ;Want |cx| to be the largest ! 737: ja @F ! 738: xchg ecx, edx ! 739: @@: ! 740: ;-----------------------------------------------------------------------; ! 741: ; CX >> 1 +1 ! 742: ; ! 743: ; 63 31 32 1st word did not match, don't chop any scans ! 744: ; 62 31 32 2nd word did not match, don't chop any scans ! 745: ; 61 30 31 3rd word did not match, chop 1 scan ! 746: ; 60 30 31 4th word did not match, chop 1 scan ! 747: ;-----------------------------------------------------------------------; ! 748: ! 749: .ERRNZ PTR_WIDTH-4 ! 750: ! 751: shr ecx, 1 ! 752: inc ecx ;ECX = working height ! 753: mov edx, PTR_HEIGHT ! 754: sub edx, ecx ;EDX = # scans chopped off bottom ! 755: xchg ecx, edx ;Height in DX for returning ! 756: ! 757: ; EBX = working width of the pointer image in bytes. ECX = amount to ! 758: ; chop of the bottom of the pointer image. EDX = working height of ! 759: ; the pointer image. ! 760: ! 761: mp_have_sizes: ! 762: mov eax, ebx ! 763: mov sizlMask.sizl_cx, eax ! 764: mov sizlMaxDelta.sizl_cx, eax ! 765: mov ah, dl ! 766: mov sizbMask, ax ! 767: ! 768: .ERRNZ sizb_cy-sizb_cx-1 ! 769: ! 770: mov eax, edx ! 771: mov sizlMask.sizl_cy, eax ! 772: mov sizlMaxDelta.sizl_cy, eax ! 773: neg eax ! 774: add eax, cyScreen ! 775: mov ptlBotRightClip.ptl_y, eax ! 776: mov eax, lNextScan ! 777: sub eax, ebx ! 778: mov ptlBotRightClip.ptl_x, eax ! 779: shr ecx, 1 ! 780: mov eax, WORK_WIDTH ! 781: sub eax, ebx ! 782: shr eax, 1 ! 783: mov ah, cl ! 784: mov ptbInitOrigin, ax ! 785: ! 786: .ERRNZ ptb_y-ptb_x-1 ! 787: ! 788: mov eax, ebx ! 789: dec eax ! 790: shl eax, 3 ;Bit count is needed ! 791: ! 792: shl edx, 16 ;Return value in upper word of EAX ! 793: or eax, edx ; is cyPointer, lower word of EAX ! 794: push eax ; is cxPointer. ! 795: ! 796: ;-----------------------------------------------------------------------; ! 797: ; Finally, copy the COLOR mask over. As we copy it, mask off the ! 798: ; corresponding AND bits in the COLOR mask since we do not use that ! 799: ; color bit if the AND bit is on. ! 800: ; ! 801: ; XOR AND COLOR ! 802: ; 1 1 invert screen ! 803: ; 0 0 use color ! 804: ; 0 1 transparent ! 805: ; 1 0 use color ! 806: ; ! 807: ;-----------------------------------------------------------------------; ! 808: ! 809: mov ecx, pBitsColor ! 810: jecxz move_color_pointer_done ;pBitsColor was set to null ! 811: lea esi, ajColorBits ! 812: mov edi, offset FLAT:base_clr_masks ! 813: push ebp ;Need extra loop counter ! 814: mov ebp, BITS_PEL ! 815: ! 816: move_next_color_mask_plane: ! 817: mov ecx, PTR_HEIGHT ;Set height for move ! 818: mov ebx, offset FLAT:base_and_masks ! 819: sub ebx, edi ;make it relative ! 820: ! 821: move_next_color_mask_scan: ! 822: ifdef WITH_AND_MASK ! 823: lodsw ;Copy a scan from the current plane ! 824: mov dx, [ebx][edi] ;Mask off the corresponding AND bits ! 825: not dx ! 826: and ax, dx ! 827: stosw ! 828: lodsw ! 829: mov dx, [ebx][edi] ! 830: not dx ! 831: and ax, dx ! 832: stosw ! 833: else ! 834: movsd ! 835: endif ! 836: xor al, al ! 837: stosb ! 838: ! 839: .ERRNZ PTR_WIDTH-4 ! 840: .ERRNZ WORK_WIDTH-5 ! 841: ! 842: add esi, (BITS_PEL-1)*PTR_WIDTH ! 843: loop move_next_color_mask_scan ! 844: sub esi, (BITS_PEL*PTR_WIDTH*PTR_HEIGHT)-PTR_WIDTH ! 845: dec ebp ! 846: jnz move_next_color_mask_plane ! 847: pop ebp ;Restore register ! 848: ! 849: mov edx, offset FLAT:base_clr_masks ! 850: mov ecx, (CLR_MASK_LENGTH*7)/(WORK_WIDTH*2) ! 851: ! 852: .ERRNZ (CLR_MASK_LENGTH*7) MOD (WORK_WIDTH*2) ! 853: ! 854: cCall create_masks_1_thru_7 ! 855: ! 856: move_color_pointer_done: ! 857: ! 858: pop eax ;return results in EAX ! 859: ! 860: move_pointers_done: ! 861: mp_exit: ! 862: cRet xyCreateMasks ! 863: ! 864: endProc xyCreateMasks ! 865: ! 866: ;-------------------------Private-Routine-------------------------------; ! 867: ; Copy the masks to the work buffer and adjust for use. Two things may ! 868: ; need to be done: ! 869: ; ! 870: ; 1) The masks could be inverted. ! 871: ; 2) The masks may need to be padded out ! 872: ; ! 873: ; Entry: ! 874: ; EBX = number of scan lines in each mask ! 875: ; DX = flags (PTRI_INVERT) ! 876: ; ! 877: ; Returns: ! 878: ; None ! 879: ; ! 880: ; Error Returns: ! 881: ; None ! 882: ; ! 883: ;-----------------------------------------------------------------------; ! 884: ! 885: cProc vCopyMasks ! 886: mov ecx,ebx ;Needed for padding calculations ! 887: test dx,PTRI_INVERT ;are masks backwards? ! 888: jz copy_no_flip ! 889: ! 890: ; This is really annoying. Not only are the masks inverted, but they ! 891: ; are stored in the wrong order. First get the AND and XOR masks into ! 892: ; the correct order. ! 893: ! 894: mov ecx,PTR_HEIGHT ! 895: mov esi,offset FLAT:alWorkBuff ! 896: mov edi,offset FLAT:alWorkBuff + PTR_HEIGHT * 4 ! 897: ! 898: @@: ! 899: mov eax,[esi] ! 900: xchg [edi],eax ! 901: mov [esi],eax ! 902: add esi,4 ! 903: add edi,4 ! 904: loop @B ! 905: ! 906: ; Next, flip them so they are right-side up. ! 907: ! 908: mov ecx,ebx ! 909: mov esi,offset FLAT:alWorkBuff ! 910: cCall vFlipMask ;flip AND mask ! 911: ! 912: mov ecx,ebx ! 913: mov esi,offset FLAT:alWorkBuff + PTR_HEIGHT * 4 ! 914: cCall vFlipMask ;flip XOR mask ! 915: ! 916: ; Now pad out the masks so no junk appears on the screen ! 917: ! 918: copy_no_flip: ! 919: ! 920: mov eax,0FFFFFFFFh ;pad AND mask ! 921: mov ecx,PTR_HEIGHT ! 922: sub ecx,ebx ! 923: mov edi,offset FLAT:alWorkBuff ! 924: lea edi,[edi+4*ebx] ! 925: rep stosd ! 926: ! 927: xor eax,eax ;pad XOR mask ! 928: mov ecx,PTR_HEIGHT ! 929: sub ecx,ebx ! 930: mov edi,offset FLAT:alWorkBuff + PTR_HEIGHT * 4 ! 931: lea edi,[edi+4*ebx] ! 932: rep stosd ! 933: ! 934: cRet vCopyMasks ! 935: ! 936: endProc vCopyMasks ! 937: ! 938: ;-------------------------Private-Routine-------------------------------; ! 939: ; Flip the scans in the buffer ! 940: ; ! 941: ; Entry: ! 942: ; ESI --> start of first scan line ! 943: ; ECX = number of scan lines ! 944: ; ! 945: ; Returns: ! 946: ; None ! 947: ; ! 948: ; Error Returns: ! 949: ; None ! 950: ; ! 951: ;-----------------------------------------------------------------------; ! 952: ! 953: cProc vFlipMask ! 954: lea edi,[esi+4*ecx] ! 955: shr ecx,1 ! 956: ! 957: flip_next_scan: ! 958: sub edi,4 ;decrement target pointer ! 959: ! 960: mov eax,[esi] ;Load ! 961: xchg [edi],eax ;Swap ! 962: mov [esi],eax ;Save ! 963: ! 964: add esi,4 ;increment source pointer ! 965: ! 966: loop flip_next_scan ! 967: ! 968: cRet vFlipMask ! 969: ! 970: endProc vFlipMask ! 971: ! 972: page ! 973: ! 974: ;--------------------------Public-Routine-------------------------------; ! 975: ; create_masks_1_thru_7 ! 976: ; ! 977: ; The pointer shape has been copied into our memory. Now pre-rotate ! 978: ; the pointer for all the different alignments. Simply put: ! 979: ; ! 980: ; pointer image fill byte ! 981: ; ! 982: ; |ABCDEFGH|IJKLMNOP|QRSTUVWX|YZabcdef|00000000| ! 983: ; ! 984: ; becomes this for (x mod 8) = 1 ! 985: ; ! 986: ; |0ABCDEFG|HIJKLMNO|PQRSTUVW|XYZabcde|f0000000| ! 987: ; ! 988: ; and this for (x mod 8) = 2 ! 989: ; ! 990: ; |00ABCDEF|GHIJKLMN|OPQRSTUV|WXYZabcd|ef000000| ! 991: ; ! 992: ; Entry: ! 993: ; EDI --> first byte of mask for phase alignment 1 ! 994: ; EDX --> first byte of mask for phase alignment 0 ! 995: ; ECX = (mask length * 7) / (WORK_WIDTH * 2) ! 996: ; AL = fill value (00 or FF) ! 997: ; Returns: ! 998: ; None ! 999: ; Error Returns: ! 1000: ; None ! 1001: ; Registers Preserved: ! 1002: ; BX,SI,BP ! 1003: ; Registers Destroyed: ! 1004: ; AX,CX,DX,DI ! 1005: ; Calls: ! 1006: ; none ! 1007: ; ! 1008: ;-----------------------------------------------------------------------; ! 1009: ! 1010: cProc create_masks_1_thru_7 ! 1011: ! 1012: ; Since the masks are contiguous, we can do it as one very long loop, ! 1013: ; where the results of rotating the previous mask by one becomes the ! 1014: ; source for the next rotate by one. ! 1015: ! 1016: xchg esi, edx ! 1017: add al, al ;Set initial 'C' value ! 1018: ! 1019: rotate_next_two_scans: ! 1020: lodsw ! 1021: rcr al, 1 ! 1022: rcr ah, 1 ! 1023: stosw ! 1024: ! 1025: lodsw ! 1026: rcr al, 1 ! 1027: rcr ah, 1 ! 1028: stosw ! 1029: ! 1030: lodsw ! 1031: rcr al, 1 ! 1032: rcr ah, 1 ! 1033: stosw ! 1034: ! 1035: lodsw ! 1036: rcr al, 1 ! 1037: rcr ah, 1 ! 1038: stosw ! 1039: ! 1040: lodsw ! 1041: rcr al, 1 ! 1042: rcr ah, 1 ! 1043: stosw ! 1044: ! 1045: loop rotate_next_two_scans ! 1046: ! 1047: .ERRNZ (WORK_WIDTH*2)-10 ! 1048: ! 1049: xchg esi, edx ! 1050: ! 1051: cRet create_masks_1_thru_7 ! 1052: ! 1053: endProc create_masks_1_thru_7 ! 1054: page ! 1055: ! 1056: ;--------------------------Public-Routine-------------------------------; ! 1057: ; vYankPointer ! 1058: ; ! 1059: ; Move the pointer off the right edge of the screen ! 1060: ; ! 1061: ; Returns: ! 1062: ; per vDrawPointer ! 1063: ; Error Returns: ! 1064: ; per vDrawPointer ! 1065: ; Registers Preserved: ! 1066: ; per vDrawPointer ! 1067: ; Registers Destroyed: ! 1068: ; per vDrawPointer ! 1069: ; Calls: ! 1070: ; per vDrawPointer ! 1071: ; Restrictions: ! 1072: ; per vDrawPointer ! 1073: ; ! 1074: ;-----------------------------------------------------------------------; ! 1075: ! 1076: cProc vYankPointer,8,< \ ! 1077: ppdev:ptr PDEV, \ ! 1078: flPtr:DWORD > ! 1079: ! 1080: mov eax,ppdev ! 1081: cCall vDrawPointer,<eax,[eax].PDEV_sizlsurf.sizl_cx, \ ! 1082: [eax].PDEV_sizlsurf.sizl_cy,flPtr> ! 1083: yp_exit: ! 1084: cRet vYankPointer ! 1085: ! 1086: endProc vYankPointer ! 1087: ! 1088: page ! 1089: ! 1090: ;--------------------------Public-Routine-------------------------------; ! 1091: ; vDrawPointer ! 1092: ; ! 1093: ; The pointer shape is drawn on the screen at the given coordinates. ! 1094: ; If it currently is displayed on the screen, it will be removed ! 1095: ; from the old location first. ! 1096: ; ! 1097: ; Entry: ! 1098: ; Returns: ! 1099: ; None ! 1100: ; Error Returns: ! 1101: ; None ! 1102: ; Registers Preserved: ! 1103: ; BP ! 1104: ; Registers Destroyed: ! 1105: ; AX,BX,CX,DX,SI,DI,FLAGS ! 1106: ; Calls: ! 1107: ; compute_rects ! 1108: ; clip_rects ! 1109: ; and_into_work ! 1110: ; copy_things_around ! 1111: ; xor_to_screen ! 1112: ; color_pointer_to_screen ! 1113: ; Restrictions: ! 1114: ; None ! 1115: ; ! 1116: ;-----------------------------------------------------------------------; ! 1117: ! 1118: cProc vDrawPointer,16,< \ ! 1119: USES esi edi ebx, \ ! 1120: ppdev:ptr PDEV, \ ! 1121: ptlX:DWORD, \ ! 1122: ptlY:DWORD, \ ! 1123: flPtr:DWORD > ! 1124: ! 1125: local lNextScan :dword ;width of bitmap in bytes ! 1126: local ulNextSrcScan :dword ;offset to next source scan line ! 1127: local jPostWrapWidth :dword ;post-wrap width ! 1128: local pSaveAddr :dword ;virtual address of save area ! 1129: local jSaveSourceXY :dword ;X and Y coordinates of source point in ! 1130: ; save area ! 1131: local jWorkSourceXY :dword ;X and Y coordinates of source point in ! 1132: ; work area ! 1133: local jNextSaveSourceY :dword ;Y coordinate of start source point in ! 1134: ; save area for next bank ! 1135: local jNextWorkSourceY :dword ;Y coordinate of start source point in ! 1136: ; work area for next bank ! 1137: local pWorkingSave :dword ;save area virtual address ! 1138: local ulScanMinusWorkWidth :dword ;distance to next scan, minus the ! 1139: ; width of the work area ! 1140: local ulCurrentTopScan :dword ;top scan line to which to draw in ! 1141: ; current bank ! 1142: local jScansInBank :dword ;# of scan to do in current bank ! 1143: local cjTotalScans :dword ;# of scans left in operation ! 1144: local ulPtrBankScan :dword ;last scan line in pointer work bank ! 1145: local pdsurf :ptr DEVSURF ;pointer to surface structure to which ! 1146: ; we're drawing ! 1147: ;variables used by cps_do_a_pass ! 1148: local ulDeltaScreen :dword ;offset from one scan to next ! 1149: local ulOffsetSave :dword ;offset in save area ! 1150: local ulOffsetMask :dword ;offset within mask ! 1151: local iPlaneMask :dword ! 1152: ;variables used by ! 1153: ; color_pointer_to_screen ! 1154: local pDest :dword ;pointer to destination address ! 1155: local prclSource :dword ;pointer to source rectangle ! 1156: local cyScreen :dword ;height of screen in scan lines ! 1157: ! 1158: ;-----------------------------------------------------------------------; ! 1159: ! 1160: cld ! 1161: ! 1162: mov ecx,ppdev ! 1163: mov eax,[ecx].PDEV_sizlSurf.sizl_cy ! 1164: mov cyScreen,eax ! 1165: ! 1166: mov ecx,[ecx].PDEV_pdsurf ! 1167: mov pdsurf,ecx ;pointer to target surface ! 1168: ! 1169: mov eax,[ecx].dsurf_ulPtrBankScan ! 1170: mov ulPtrBankScan,eax ;last scan line in pointer work bank ! 1171: ! 1172: mov eax,[ecx].dsurf_lNextScan ! 1173: mov lNextScan,eax ;width of bitmap ! 1174: ! 1175: mov eax, flPtr ! 1176: mov flPointer,eax ;save flags ! 1177: mov edi, ppdNew ;--> new pointer's data goes here ! 1178: mov esi, ppdOld ;--> old pointer's data ! 1179: mov eax, ptlX ;EAX = ptlX ! 1180: mov ebx, eax ! 1181: and ebx, 7 ! 1182: mov edx, pabAndMasks[ebx * 4] ! 1183: mov pAndXor, edx ! 1184: mov edx, pabClrMasks[ebx * 4] ! 1185: mov pColor, edx ! 1186: mov ebx, PD_VALID ;Assume visible ! 1187: sar eax, 3 ;Compute starting byte address (set 'S') ! 1188: mov [edi].pd_rd.rd_ptlScreen.ptl_x, eax ! 1189: ! 1190: ;-----------------------------------------------------------------------; ! 1191: ; Compute any X clipping parameters for the new pointer image. ! 1192: ;-----------------------------------------------------------------------; ! 1193: ! 1194: js clip_lhs_of_pointer ;If X is negative, lhs clipping needed ! 1195: sub eax, ptlBotRightClip.ptl_x ! 1196: jle done_x_clipping ! 1197: mov bh,PD_CLIP_RIGHT ;EAX = amount to clip off rhs ! 1198: jmp finish_x_clip ! 1199: ! 1200: clip_lhs_of_pointer: ! 1201: neg eax ;Want |eax| ! 1202: mov bh, PD_CLIP_LEFT ! 1203: ! 1204: finish_x_clip: ! 1205: cmp eax, sizlMask.sizl_cx ;Width of pointer in bytes ! 1206: jge not_visible ;Clipped away too much ! 1207: or bl, bh ! 1208: done_x_clipping: ! 1209: ! 1210: ;-----------------------------------------------------------------------; ! 1211: ; Compute any Y clipping parameters for the new pointer image. ! 1212: ;-----------------------------------------------------------------------; ! 1213: ! 1214: mov eax, ptlY ! 1215: mov [edi].pd_rd.rd_ptlScreen.ptl_y, eax ! 1216: or eax, eax ! 1217: js clip_top_of_pointer ;If Y is negative, top clipping needed ! 1218: sub eax, ptlBotRightClip.ptl_y ! 1219: jle done_y_clipping ! 1220: mov bh, PD_CLIP_BOTTOM ;AX = amount to clip off bottom ! 1221: jmp finish_y_clip ! 1222: ! 1223: ! 1224: ;-----------------------------------------------------------------------; ! 1225: ; not_visible - the pointer will be totally off the screen. All we ! 1226: ; have to do is to determine if any part of the old pointer is visible ! 1227: ; and remove it if so. ! 1228: ;-----------------------------------------------------------------------; ! 1229: ! 1230: not_visible: ! 1231: test [esi].pd_fb, PD_VALID ! 1232: jz draw_pointer_exit ;No new, no old ! 1233: xor eax, eax ! 1234: mov [edi].pd_fb, al ;Clear PD_VALID flag, clipping flags ! 1235: mov WORD PTR fbAndRead, ax ;Nothing to read/and/xor ! 1236: ! 1237: .ERRNZ fbXor-fbAndRead-1 ! 1238: ! 1239: mov fbFlush, FB_OLD_PTR ;Write old to screen ! 1240: jmp rectangles_been_computed ! 1241: ! 1242: ! 1243: ;-----------------------------------------------------------------------; ! 1244: ; Continue with Y clipping ! 1245: ;-----------------------------------------------------------------------; ! 1246: ! 1247: clip_top_of_pointer: ! 1248: neg eax ;Want |eax| ! 1249: mov bh,PD_CLIP_TOP ! 1250: ! 1251: finish_y_clip: ! 1252: cmp eax, sizlMask.sizl_cy ;Height of pointer in scans ! 1253: jge not_visible ;Clipped away too much ! 1254: or bl, bh ! 1255: ! 1256: done_y_clipping: ! 1257: mov [edi].pd_fb, bl ;Set clipping flags and show valid ! 1258: ! 1259: ;-----------------------------------------------------------------------; ! 1260: ; It looks like some portion of the pointer image will be visible. ! 1261: ; Initialize some of the new pointer's POINTER_DATA structure. ! 1262: ;-----------------------------------------------------------------------; ! 1263: ! 1264: mov ax, sizbMask ;ptbSave will be set by compute_rects ! 1265: mov [edi].pd_rd.rd_sizb, ax ! 1266: ! 1267: .ERRNZ (SIZE SIZEB) - 2 ! 1268: ! 1269: xor ax, ax ! 1270: mov [edi].pd_rd.rd_ptbWork, ax ! 1271: ! 1272: .ERRNZ (SIZE POINTB) - 2 ! 1273: ! 1274: ;-----------------------------------------------------------------------; ! 1275: ; Compute the rectangles describing how things overlap and then clip ! 1276: ; them. ! 1277: ;-----------------------------------------------------------------------; ! 1278: ! 1279: call compute_rects ! 1280: rectangles_been_computed: ! 1281: ! 1282: ;-----------------------------------------------------------------------; ! 1283: ; Set WRITE mode of EGA/VGA ! 1284: ;-----------------------------------------------------------------------; ! 1285: ! 1286: mov dx, EGA_BASE + GRAF_ADDR ! 1287: mov ax, DR_SET SHL 8 + GRAF_DATA_ROT ! 1288: out dx, ax ! 1289: ! 1290: mov ax, M_PROC_WRITE SHL 8 + GRAF_MODE ! 1291: out dx, ax ! 1292: ! 1293: mov ax, 0FF00h + GRAF_BIT_MASK ! 1294: out dx, ax ! 1295: ! 1296: mov ax, GRAF_ENAB_SR ! 1297: out dx, ax ! 1298: ! 1299: mov dl, SEQ_ADDR ! 1300: mov ax, MM_ALL SHL 8 + SEQ_MAP_MASK ! 1301: out dx, ax ! 1302: ! 1303: call clip_rects ! 1304: ! 1305: mov eax,flPointer ;lousy hack ! 1306: or eax,eax ! 1307: jnz draw_color_pointer ;Color pointer? ! 1308: ! 1309: ;-----------------------------------------------------------------------; ! 1310: ; Draw B/W Pointer ! 1311: ;-----------------------------------------------------------------------; ! 1312: ! 1313: ;-----------------------------------------------------------------------; ! 1314: ; AND from the save area and the screen into the work area ! 1315: ;-----------------------------------------------------------------------; ! 1316: ! 1317: mov al, fbAndRead ! 1318: or al, al ! 1319: jz done_and_portion ! 1320: call and_into_work ! 1321: done_and_portion: ! 1322: ! 1323: ;-----------------------------------------------------------------------; ! 1324: ; Copy from save area to the screen and from the screen to the save ! 1325: ; area. ! 1326: ;-----------------------------------------------------------------------; ! 1327: ! 1328: mov ax, WORD PTR fbFlush ;Assume nothing to copy to/from save ! 1329: ! 1330: .ERRNZ fbAndRead-fbFlush-1 ! 1331: ! 1332: or ah, al ! 1333: jz copied_things_around ! 1334: call copy_things_around ! 1335: copied_things_around: ! 1336: ! 1337: ! 1338: ;-----------------------------------------------------------------------; ! 1339: ; XOR from the work area to the screen ! 1340: ;-----------------------------------------------------------------------; ! 1341: ! 1342: mov al, fbXor ! 1343: or al, al ! 1344: jz pointer_drawn ! 1345: call xor_to_screen ! 1346: jmp pointer_drawn ! 1347: ! 1348: ;-----------------------------------------------------------------------; ! 1349: ; Draw Color Pointer ! 1350: ;-----------------------------------------------------------------------; ! 1351: ! 1352: draw_color_pointer: ! 1353: ! 1354: ;-----------------------------------------------------------------------; ! 1355: ; Copy from save area to the screen and from the screen to the save area. ! 1356: ;-----------------------------------------------------------------------; ! 1357: ! 1358: mov ax, WORD PTR fbFlush ;Assume nothing to copy to/from save ! 1359: ! 1360: .ERRNZ fbAndRead-fbFlush-1 ! 1361: ! 1362: or ah, al ! 1363: jz things_copied_around ! 1364: call copy_things_around ! 1365: things_copied_around: ! 1366: ! 1367: ;-----------------------------------------------------------------------; ! 1368: ; Draw color pointer to screen ! 1369: ;-----------------------------------------------------------------------; ! 1370: ! 1371: test fbXor, 0FFh ! 1372: jz pointer_drawn ! 1373: call color_pointer_to_screen ;Planes must all be enabled ! 1374: ! 1375: pointer_drawn: ! 1376: mov eax, ppdNew ! 1377: xchg eax, ppdOld ! 1378: mov ppdNew, eax ! 1379: draw_pointer_exit: ! 1380: ! 1381: ;-----------------------------------------------------------------------; ! 1382: ; Reset WRITE mode of EGA/VGA to WRITE MODE 0, READ MODE 1 ! 1383: ;-----------------------------------------------------------------------; ! 1384: ! 1385: mov al, MM_ALL ;Set Map Mask for all write ! 1386: mov dx, EGA_BASE + SEQ_DATA ! 1387: out dx, al ! 1388: ! 1389: mov dx, EGA_BASE + GRAF_ADDR ! 1390: mov ax, DR_SET SHL 8 + GRAF_DATA_ROT ! 1391: out dx, ax ! 1392: ! 1393: mov ax, M_PROC_WRITE SHL 8 + GRAF_MODE ! 1394: out dx, ax ! 1395: ! 1396: mov ax, 0FF00h + GRAF_BIT_MASK ! 1397: out dx, ax ! 1398: ! 1399: mov ax, GRAF_ENAB_SR ! 1400: out dx, ax ! 1401: ! 1402: cRet vDrawPointer ! 1403: ! 1404: ;-----------------------------------------------------------------------; ! 1405: ; The following routines would be procs, outside the scope of ! 1406: ; vDrawPointer, but then they couldn't access vDrawPointer's stack ! 1407: ; frame, which they need to. ! 1408: ;-----------------------------------------------------------------------; ! 1409: ! 1410: page ! 1411: ! 1412: ;--------------------------Private-Routine------------------------------; ! 1413: ; compute_rects ! 1414: ; ! 1415: ; This routine computes the rectangles which describe what needs to be ! 1416: ; read/ANDed/XORed/written. The rectangles are unclipped. Clipping ! 1417: ; must be performed by a different routine. ! 1418: ; ! 1419: ; Entry: ! 1420: ; AX = 0 ! 1421: ; SI --> currently displayed pointer's rectangle data ! 1422: ; DI --> new pointer's rectangle data ! 1423: ; Returns: ! 1424: ; None ! 1425: ; Error Returns: ! 1426: ; None ! 1427: ; Registers Preserved: ! 1428: ; BP ! 1429: ; Registers Destroyed: ! 1430: ; AX,BX,CX,DX,SI,DI,FLAGS ! 1431: ; Calls: ! 1432: ; None ! 1433: ; ! 1434: ;-----------------------------------------------------------------------; ! 1435: ! 1436: align 4 ! 1437: compute_rects: ! 1438: ! 1439: push ebp ! 1440: ! 1441: mov WORD PTR fbFlush, ax ;Assume nothing to restore to screen ! 1442: ! 1443: .ERRNZ fbAndRead-fbFlush-1 ;Assume nothing to read/And to work ! 1444: ! 1445: mov fbXor, FB_NEW_PTR ;Assume new pointer is XORed to screen ! 1446: test [esi].pd_fb, PD_VALID ! 1447: jz old_pointer_is_invalid ! 1448: ! 1449: ;-----------------------------------------------------------------------; ! 1450: ; There is a pointer currently displayed on the screen. If the new ! 1451: ; pointer is far enough away from the old pointer, then we won't have ! 1452: ; to deal with overlap. ! 1453: ;-----------------------------------------------------------------------; ! 1454: ! 1455: old_pointer_is_valid: ! 1456: mov eax, [edi].pd_rd.rd_ptlScreen.ptl_x ! 1457: sub eax, [esi].pd_rd.rd_ptlScreen.ptl_x ! 1458: mov bl, al ;BL = delta x ! 1459: or eax, eax ;EAX = |EAX| ! 1460: jns @F ! 1461: neg eax ! 1462: @@: ! 1463: cmp eax, sizlMaxDelta.sizl_cx ! 1464: jae rects_are_disjoint ! 1465: mov eax, [edi].pd_rd.rd_ptlScreen.ptl_y ! 1466: sub eax, [esi].pd_rd.rd_ptlScreen.ptl_y ! 1467: mov bh, al ;BH = delta y ! 1468: or eax, eax ;EAX = |EAX| ! 1469: jns @F ! 1470: neg eax ! 1471: @@: ! 1472: cmp eax, sizlMaxDelta.sizl_cy ! 1473: jb rects_overlap ;(or are identical) ! 1474: ! 1475: ;-----------------------------------------------------------------------; ! 1476: ; The rectangles will be disjoint. Set up to restore under the old ! 1477: ; pointer, copy the new rectangle to the save area, and AND it into ! 1478: ; the work area. ! 1479: ;-----------------------------------------------------------------------; ! 1480: ! 1481: rects_are_disjoint: ! 1482: mov fbFlush, FB_OLD_PTR ! 1483: ! 1484: ;-----------------------------------------------------------------------; ! 1485: ; The save area image is invalid, so we won't have to copy it to the ! 1486: ; screen or AND some part of it into the work area. We'll simply want ! 1487: ; to copy the new area to the save area and AND it into the work area. ! 1488: ; This can be treated the same as if the rectangles are identical, ! 1489: ; except we want to reset the origin within the save buffer. ! 1490: ;-----------------------------------------------------------------------; ! 1491: ! 1492: old_pointer_is_invalid: ! 1493: mov ax, ptbInitOrigin ;Reset origin within the save area ! 1494: mov [edi].pd_rd.rd_ptbSave,ax ! 1495: ! 1496: .ERRNZ (SIZE POINTB) - 2 ! 1497: ! 1498: mov fbAndRead, FB_NEW_PTR ;Copy new ptr to save and XOR to work ! 1499: jmp compute_rects_exit ! 1500: ! 1501: ! 1502: ;-----------------------------------------------------------------------; ! 1503: ; The rectangles overlap in some manner. Compute how the rectangles, ! 1504: ; will overlap, setting up the various needed rectangle structures as ! 1505: ; we go. ! 1506: ; ! 1507: ; The only hope we have of computing the overlap rectangle is to ! 1508: ; initialize it to some known state and adjusting it as we process ! 1509: ; dx and dy. We will initialize it to be the upper left hand corner ! 1510: ; of the old pointer rectangle. ! 1511: ; ! 1512: ; Currently: ! 1513: ; AX = old pointer's pd_rd.rd_ptbSave ! 1514: ; BH = dy ! 1515: ; BL = dx (negative) ! 1516: ; SI --> old pointer's rd_ptlScreen ! 1517: ; DI --> new pointer rectangle ! 1518: ;-----------------------------------------------------------------------; ! 1519: ! 1520: rects_overlap: ! 1521: ! 1522: ; Set old pointer's save buffer (X,Y) into the overlap rectangle. ! 1523: ; Also set this as the save buffer origin for the new pointer rectangle. ! 1524: ! 1525: lodsw ! 1526: ! 1527: .ERRNZ pd_rd.rd_ptbSave ! 1528: ! 1529: mov rdOverlap.rd_ptbSave, ax ! 1530: mov [edi].pd_rd.rd_ptbSave, ax ! 1531: mov dx, ax ! 1532: ! 1533: ; Set old pointer's screen (X,Y) into the overlap rectangle as the ! 1534: ; screen origin. ! 1535: ! 1536: lodsd ! 1537: ! 1538: .ERRNZ rd_ptlScreen-rd_ptbSave-2 ! 1539: .ERRNZ ptl_x ! 1540: ! 1541: mov rdOverlap.rd_ptlScreen.ptl_x, eax ! 1542: mov ebp, eax ! 1543: lodsd ! 1544: ! 1545: .ERRNZ ptl_y-ptl_x-4 ! 1546: ! 1547: mov rdOverlap.rd_ptlScreen.ptl_y, eax ! 1548: mov esi, eax ! 1549: ! 1550: ; Set the mask width and height into the overlap rectangle ! 1551: ! 1552: mov ax, sizbMask ! 1553: mov rdOverlap.rd_sizb, ax ! 1554: ! 1555: .ERRNZ sizb_cy-sizb_cx-1 ! 1556: .ERRNZ (SIZE SIZEB) - 2 ! 1557: ! 1558: mov ecx, eax ! 1559: ! 1560: .ERRNZ sizb_cy-sizb_cx-1 ! 1561: ! 1562: ; Set the work buffer origin to be zero ! 1563: ! 1564: xor eax, eax ! 1565: mov rdOverlap.rd_ptbWork, ax ! 1566: ! 1567: ; Show that the overlap rectangle exists and should be ANDed into the ! 1568: ; work area, then dispatch based on dx,dy. ! 1569: ! 1570: mov fbAndRead, FB_OVERLAP ! 1571: or bl, bl ; Dispatch based on dx ! 1572: jg moved_right ! 1573: jl moved_left ! 1574: jmp processed_x_overlap ! 1575: ! 1576: ! 1577: ;-----------------------------------------------------------------------; ! 1578: ; The starting X of the new rectangle is to be set as the new lhs. ! 1579: ; ! 1580: ; * nnnnn $ onononono oooooooo * = start of new rectangle ! 1581: ; o o $ = start of old rectangle ! 1582: ; n | o | n | o ! 1583: ; n | n o | o ! 1584: ; n | o O n o ! 1585: ; n n v o F o ! 1586: ; n R o e n l o ! 1587: ; n e n r o u o ! 1588: ; n a o l n s o ! 1589: ; n d n a o h o ! 1590: ; n o p n o ! 1591: ; n | n o | o ! 1592: ; n | o | n | o ! 1593: ; n | n | o | o ! 1594: ; n o n o ! 1595: ; nnnnnnnn nonononono oooooooo ! 1596: ; ! 1597: ; |-- dx -| |-- dx -| ! 1598: ; |-sizbMask.sizb_cx-| ! 1599: ; ! 1600: ; ! 1601: ; Currently: ! 1602: ; AX = 0 ! 1603: ; BH = dy ! 1604: ; BL = dx (negative) ! 1605: ; CH = buffer height ! 1606: ; CL = buffer width ! 1607: ; DH = old pointer's Y coordinate in save area ! 1608: ; DL = old pointer's X coordinate in save area ! 1609: ; SI = old pointer's Y screen coordinate ! 1610: ; BP = old pointer's X screen coordinate ! 1611: ; DI = --> new pointer's RECT_DATA ! 1612: ;-----------------------------------------------------------------------; ! 1613: ! 1614: moved_left: ! 1615: ! 1616: ; The Read buffer will map into the work area at (0,0). ! 1617: ! 1618: mov rdReadX.rd_ptbWork, ax ! 1619: ! 1620: ; The width of the overlap area is sizbMask.sizb_cx - |dx|. ! 1621: ! 1622: mov al, bl ;BL = dx (which is negative) ! 1623: add al, cl ;CL = sizbMask.sizb_cx ! 1624: mov rdOverlap.rd_sizb.sizb_cx, al ! 1625: ! 1626: ; The flush rectangle's X is ptlScreen.ptl_x + sizbMask.sizb_cx - |dx|. ! 1627: ! 1628: add eax, ebp ;AX = sizbMask.sizb_cx - |dx| ! 1629: mov rdFlushX.rd_ptlScreen.ptl_x, eax ! 1630: ! 1631: ; Compute where in the save buffer the new lhs will map to. We must ! 1632: ; update the new pointer's rectangle to reflect where this origin is. ! 1633: ! 1634: mov eax, edx ;DX = old ptbSave ! 1635: add al, bl ;BL = dx (negative) ! 1636: add ah, bh ;BH = dy ! 1637: and eax, ((SAVE_BUFFER_HEIGHT-1) SHL 8) + SAVE_BUFFER_WIDTH-1 ! 1638: mov [edi].pd_rd.rd_ptbSave.ptb_x, al ! 1639: mov rdReadX.rd_ptbSave, ax ! 1640: ! 1641: .ERRNZ ptb_y-ptb_x-1 ! 1642: ! 1643: ; The origin of the flush rectangle is sizbMask.sizb_cx bytes away ! 1644: ; from the origin of the read rectangle. ! 1645: ! 1646: add al, cl ! 1647: and al, SAVE_BUFFER_WIDTH-1 ;Handle any wrap ! 1648: mov ah, dh ! 1649: mov rdFlushX.rd_ptbSave, ax ! 1650: ! 1651: ; Compute |dx|. This is the width of the read and flush rectangles. ! 1652: ; The height will be set to the working height. |dx| is also the ! 1653: ; overlap rectangle's work area X coordinate. ! 1654: ! 1655: mov al, bl ;BL = dx (negative) ! 1656: neg al ;AL = |dx| ! 1657: mov ah, ch ;CH = sizbMask.sizb_cy ! 1658: mov rdFlushX.rd_sizb, ax ! 1659: mov rdReadX.rd_sizb, ax ! 1660: ! 1661: .ERRNZ sizb_cy-sizb_cx-1 ! 1662: ! 1663: mov rdOverlap.rd_ptbWork.ptb_x, al ! 1664: ! 1665: ; The Read buffer's screen address is the ptlScreen stored in the new ! 1666: ; pointer's RECT_DATA. ! 1667: ! 1668: mov eax, [edi].pd_rd.rd_ptlScreen.ptl_x ! 1669: jmp finish_x_overlap ! 1670: ! 1671: ! 1672: ! 1673: ;-----------------------------------------------------------------------; ! 1674: ; The starting X of the new rectangle is somewhere in the middle ! 1675: ; of the old rectangle. ! 1676: ; ! 1677: ; $ ooooo * onononono nnnnnnn * = start of new rectangle ! 1678: ; o n o n $ = start of old rectangle ! 1679: ; o | o | n | n ! 1680: ; o | n o | n ! 1681: ; o o O n | n ! 1682: ; o F n v o n ! 1683: ; o l o e n R n ! 1684: ; o u n r o e n ! 1685: ; o s o l n a n ! 1686: ; o h n a o d n ! 1687: ; o o p n n ! 1688: ; o | n o | n ! 1689: ; o | o | n | n ! 1690: ; o | n | o | n ! 1691: ; o o n n ! 1692: ; oooooooo nonononono nnnnnnn ! 1693: ; ! 1694: ; |-- dx -| |-- dx -| ! 1695: ; |-sizbMask.sizb_cx-| ! 1696: ; ! 1697: ; ! 1698: ; Currently: ! 1699: ; AX = 0 ! 1700: ; BH = dy ! 1701: ; BL = dx (positive) ! 1702: ; CH = buffer height ! 1703: ; CL = buffer width ! 1704: ; DH = old pointer's Y coordinate in save area ! 1705: ; DL = old pointer's X coordinate in save area ! 1706: ; SI = old pointer's Y screen coordinate ! 1707: ; BP = old pointer's X screen coordinate ! 1708: ; DI = --> new pointer's RECT_DATA ! 1709: ;-----------------------------------------------------------------------; ! 1710: ! 1711: moved_right: ! 1712: ! 1713: ; The screen X origin of the overlap rectangle is the new rectangle's ! 1714: ; X coordinate, or the old rectangle's X coordinate + |dx|. ! 1715: ! 1716: mov al, bl ! 1717: add rdOverlap.rd_ptlScreen.ptl_x, eax ! 1718: ! 1719: ; The width of the read and flush buffers is |dx|. The height is ! 1720: ; just the working height. ! 1721: ! 1722: mov ah, ch ;CH = sizbMask.sizb_cy ! 1723: mov rdFlushX.rd_sizb, ax ! 1724: mov rdReadX.rd_sizb, ax ! 1725: ! 1726: .ERRNZ sizb_cy-sizb_cx-1 ! 1727: ! 1728: ; Compute where the new lhs is in the save area. This will be the lhs ! 1729: ; of both the new rectangle and the overlap area. ! 1730: ! 1731: add al, dl ;DL = ptbSave.ptb_x ! 1732: and al, SAVE_BUFFER_WIDTH-1 ;Handle any wrap ! 1733: mov [edi].pd_rd.rd_ptbSave.ptb_x, al ! 1734: mov rdOverlap.rd_ptbSave.ptb_x, al ! 1735: ! 1736: ; The data to be flushed will come from the lhs of the old rectangle ! 1737: ! 1738: mov eax, edx ! 1739: mov rdFlushX.rd_ptbSave, ax ! 1740: ! 1741: ; The data to be read will go at the old lhs + sizbMask.sizb_cx. The ! 1742: ; Y component will be the new Y. ! 1743: ! 1744: add al, cl ! 1745: add ah, bh ! 1746: and eax, ((SAVE_BUFFER_HEIGHT-1) SHL 8) + SAVE_BUFFER_WIDTH-1 ! 1747: mov rdReadX.rd_ptbSave, ax ! 1748: ! 1749: .ERRNZ ptb_y-ptb_x-1 ! 1750: ! 1751: ; The X screen origin of the flush buffer is the old ptlScreen.ptl_x ! 1752: ! 1753: mov rdFlushX.rd_ptlScreen.ptl_x, ebp ! 1754: ! 1755: ; The width of the overlap rectangle is sizbMask.sizb_cx - |dx|. This ! 1756: ; is also the X offset into the work area of the read rectangle. ! 1757: ; The Y offset is zero. ! 1758: ! 1759: mov al, cl ! 1760: sub al, bl ! 1761: mov rdOverlap.rd_sizb.sizb_cx, al ! 1762: movsx eax, al ! 1763: mov rdReadX.rd_ptbWork, ax ! 1764: ! 1765: .ERRNZ ptb_y-ptb_x-1 ! 1766: ! 1767: ; The screen Y origin of the read rectangle is the new rectangle's Y ! 1768: ; coordinate. The X coordinate can be computed as the old rectangles ! 1769: ; X coordinate + the save width ! 1770: ! 1771: mov al, cl ! 1772: add eax, ebp ! 1773: ! 1774: finish_x_overlap: ! 1775: mov rdReadX.rd_ptlScreen.ptl_x, eax ! 1776: mov eax, [edi].pd_rd.rd_ptlScreen.ptl_y ! 1777: mov rdReadX.rd_ptlScreen.ptl_y, eax ! 1778: ! 1779: ; The Y address of the flush rectangle on the screen is ptlScreen.ptl_y. ! 1780: ! 1781: mov rdFlushX.rd_ptlScreen.ptl_y, esi ! 1782: ! 1783: ; Set the flags to show that there is some form of X overlap. We want ! 1784: ; to show that there is some X rectangle to be read/flushed, and that ! 1785: ; there is some overlap rectangle to be processed. ! 1786: ! 1787: or WORD PTR fbFlush, (FB_READ_X SHL 8) + FB_FLUSH_X ! 1788: ! 1789: .ERRNZ fbAndRead-fbFlush-1 ! 1790: ! 1791: xor eax, eax ! 1792: ! 1793: processed_x_overlap: ! 1794: or bh, bh ! 1795: jg moved_down ! 1796: jz processed_y_overlap_relay ! 1797: ! 1798: ! 1799: ;-----------------------------------------------------------------------; ! 1800: ; The starting Y of the new rectangle is to be set as the new top. ! 1801: ; ! 1802: ; * = start of new rectangle ! 1803: ; $ = start of old rectangle ! 1804: ; ! 1805: ; $ oooooooooooooooooooooooooo --- --- ! 1806: ; o o | | ! 1807: ; o -------- Read ---------- o dy | ! 1808: ; o | | ! 1809: ; * onononononononononononono --- ! 1810: ; n sizbMask.sizb_cy - dy ! 1811: ; n o ! 1812: ; o ------- Overlap -------- n | ! 1813: ; n o | ! 1814: ; o n | ! 1815: ; ononononononononononononon --- --- ! 1816: ; n n | ! 1817: ; n -------- Write --------- n dy ! 1818: ; n n | ! 1819: ; nnnnnnnnnnnnnnnnnnnnnnnnnnnn --- ! 1820: ; ! 1821: ; ! 1822: ; ! 1823: ; Currently: ! 1824: ; AX = 0 ! 1825: ; BH = dy (negative) ! 1826: ; BL = dx ! 1827: ; CH = buffer height ! 1828: ; CL = buffer width ! 1829: ; DH = old pointer's Y coordinate in save area ! 1830: ; DL = old pointer's X coordinate in save area ! 1831: ; SI = old pointer's Y screen coordinate ! 1832: ; BP = old pointer's X screen coordinate ! 1833: ; DI = --> new pointer's RECT_DATA ! 1834: ;-----------------------------------------------------------------------; ! 1835: ! 1836: moved_up: ! 1837: ! 1838: ; The Read buffer will map into the work area at (0,0). ! 1839: ! 1840: mov rdReadY.rd_ptbWork, ax ! 1841: ! 1842: ; The height of the overlap area is sizbMask.sizb_cy - |dy|. ! 1843: ! 1844: mov al, bh ;BH = dy (which is negative) ! 1845: add al, ch ;CH = sizbMask.sizb_cy ! 1846: mov rdOverlap.rd_sizb.sizb_cy, al ! 1847: ! 1848: ; The flush rectangle's Y is ptlScreen.ptl_y + sizbMask.sizb_cy - |dy|. ! 1849: ! 1850: add eax, esi ;EAX = sizbMask.sizb_cy - |dy| ! 1851: mov rdFlushY.rd_ptlScreen.ptl_y, eax ! 1852: ! 1853: ; Compute where in the save buffer the new top will map to. We must ! 1854: ; update the new pointer's rectangle to reflect where this origin is. ! 1855: ! 1856: mov eax, edx ;DX = old ptbSave ! 1857: add ah, bh ;BH = dy (negative) ! 1858: add al, bl ! 1859: and eax, ((SAVE_BUFFER_HEIGHT-1) SHL 8) + SAVE_BUFFER_WIDTH-1 ! 1860: mov [edi].pd_rd.rd_ptbSave.ptb_y, ah ! 1861: mov rdReadY.rd_ptbSave, ax ! 1862: ! 1863: .ERRNZ ptb_y-ptb_x-1 ! 1864: ! 1865: ; The origin of the flush rectangle is sizbMask.sizb_cy scans away ! 1866: ; from the origin of the read rectangle. ! 1867: ! 1868: add ah, ch ! 1869: and ah, SAVE_BUFFER_HEIGHT-1 ;Handle any wrap ! 1870: mov al, dl ! 1871: mov rdFlushY.rd_ptbSave, ax ! 1872: ! 1873: ; Compute |dy|. This is the height of the read and flush rectangles. ! 1874: ; The width will be set to the working width. |dy| is also the ! 1875: ; overlap rectangle's work area Y coordinate. ! 1876: ! 1877: mov ah, bh ;BH = dy ! 1878: neg ah ;Make it |dy| ! 1879: mov al, cl ;CL = sizbMask.sizb_cx ! 1880: mov rdFlushY.rd_sizb, ax ! 1881: mov rdReadY.rd_sizb, ax ! 1882: ! 1883: .ERRNZ sizb_cy-sizb_cx-1 ! 1884: ! 1885: mov rdOverlap.rd_ptbWork.ptb_y, ah ! 1886: ! 1887: ; The Read buffer's screen address is the ptlScreen stored in the new ! 1888: ; pointer's RECT_DATA. ! 1889: ! 1890: mov eax, [edi].pd_rd.rd_ptlScreen.ptl_y ! 1891: jmp finish_y_overlap ! 1892: ! 1893: processed_y_overlap_relay: ! 1894: jmp processed_y_overlap ! 1895: ! 1896: ! 1897: ! 1898: ;-----------------------------------------------------------------------; ! 1899: ; The starting Y of the new rectangle is somewhere in the middle ! 1900: ; of the old rectangle. ! 1901: ; ! 1902: ; * = start of new rectangle ! 1903: ; $ = start of old rectangle ! 1904: ; ! 1905: ; $ oooooooooooooooooooooooooo --- --- ! 1906: ; o o | | ! 1907: ; o -------- Write --------- o dy | ! 1908: ; o | | ! 1909: ; * onononononononononononono --- ! 1910: ; n sizbMask.sizb_cy - dy ! 1911: ; n o ! 1912: ; o ------- Overlap -------- n | ! 1913: ; n o | ! 1914: ; o n | ! 1915: ; ononononononononononononon --- --- ! 1916: ; n n | ! 1917: ; n -------- Read ---------- n dy ! 1918: ; n n | ! 1919: ; nnnnnnnnnnnnnnnnnnnnnnnnnnnn --- ! 1920: ; ! 1921: ; ! 1922: ; Currently: ! 1923: ; AX = 0 ! 1924: ; BH = dy (positive) ! 1925: ; BL = dx ! 1926: ; CH = buffer height ! 1927: ; CL = buffer width ! 1928: ; DH = old pointer's Y coordinate in save area ! 1929: ; DL = old pointer's X coordinate in save area ! 1930: ; SI = old pointer's Y screen coordinate ! 1931: ; BP = old pointer's X screen coordinate ! 1932: ; DI = --> new pointer's RECT_DATA ! 1933: ;-----------------------------------------------------------------------; ! 1934: ! 1935: moved_down: ! 1936: ! 1937: ; The screen Y origin of the overlap rectangle is the new rectangle's ! 1938: ; Y coordinate, or the old rectangle's Y coordinate + |dy|. ! 1939: ! 1940: mov al, bh ! 1941: add rdOverlap.rd_ptlScreen.ptl_y, eax ! 1942: ! 1943: ; Compute where the new top is. This will be both the top of the new ! 1944: ; rectangle and the overlap area. ! 1945: ! 1946: ; mov al, bh ;BH = |dy| ! 1947: add al, dh ;DH = ptbSave.ptb_y ! 1948: and al, SAVE_BUFFER_HEIGHT-1 ;CH = sizbMask.sizb_cy ! 1949: mov [edi].pd_rd.rd_ptbSave.ptb_y, al ! 1950: mov rdOverlap.rd_ptbSave.ptb_y, al ! 1951: ! 1952: ; The height of the read and flush buffers is |dy|. The width is ! 1953: ; just the working width. ! 1954: ! 1955: mov ah, bh ! 1956: mov al, cl ;CL = sizbMask.sizb_cx ! 1957: mov rdFlushY.rd_sizb, ax ! 1958: mov rdReadY.rd_sizb, ax ! 1959: ! 1960: .ERRNZ sizb_cy-sizb_cx-1 ! 1961: ! 1962: ; The data to be flushed will come from the top of the old rectangle ! 1963: ! 1964: mov eax, edx ! 1965: mov rdFlushY.rd_ptbSave, dx ! 1966: ! 1967: ; The data to be read will go at the old top + sizbMask.sizb_cy ! 1968: ! 1969: add ah, ch ! 1970: add al, bl ! 1971: and eax, ((SAVE_BUFFER_HEIGHT-1) SHL 8) + SAVE_BUFFER_WIDTH-1 ! 1972: mov rdReadY.rd_ptbSave, ax ! 1973: ! 1974: .ERRNZ ptb_y-ptb_x-1 ! 1975: ! 1976: ; The Y screen origin of the flush buffer is the old ptlScreen.ptl_y ! 1977: ! 1978: mov rdFlushY.rd_ptlScreen.ptl_y, esi ! 1979: ! 1980: ; The height of the overlap rectangle is sizbMask.sizb_cy - |dy|. ! 1981: ; This is also the Y offset into the work area of the read rectangle. ! 1982: ; The X offset is zero. ! 1983: ! 1984: mov ah, ch ! 1985: sub ah, bh ! 1986: mov rdOverlap.rd_sizb.sizb_cy, ah ! 1987: xor al, al ! 1988: mov rdReadY.rd_ptbWork, ax ! 1989: ! 1990: .ERRNZ ptb_y-ptb_x-1 ! 1991: ! 1992: ; The screen X origin of the read rectangle is the new rectangle's X ! 1993: ; coordinate. The Y coordinate can be computed as the old ! 1994: ; rectangle's Y coordinate + the save height ! 1995: ! 1996: mov al, ch ! 1997: xor ah, ah ! 1998: add eax, esi ! 1999: ! 2000: finish_y_overlap: ! 2001: mov rdReadY.rd_ptlScreen.ptl_y, eax ! 2002: mov eax, [edi].pd_rd.rd_ptlScreen.ptl_x ! 2003: mov rdReadY.rd_ptlScreen.ptl_x, eax ! 2004: ! 2005: ; The X address of the flush rectangle on the screen is ptlScreen.ptl_x. ! 2006: ! 2007: mov rdFlushY.rd_ptlScreen.ptl_x, ebp ! 2008: ! 2009: ; Set the flags to show that there is some form of Y overlap. We want ! 2010: ; to show that there is some Y rectangle to be read/flushed, and that ! 2011: ; there is some overlap rectangle to be processed. ! 2012: ! 2013: or WORD PTR fbFlush, ((FB_READ_Y OR FB_OVERLAP) SHL 8) + FB_FLUSH_Y ! 2014: ! 2015: .ERRNZ fbAndRead-fbFlush-1 ! 2016: ! 2017: ! 2018: ;-----------------------------------------------------------------------; ! 2019: ; We have computed the seperate X and Y componets of the overlap. If ! 2020: ; there was both dx and dy, then we have an L shaped area which we'll ! 2021: ; be reading/writing. In this case, we want to remove the overlapping ! 2022: ; portion of the L. ! 2023: ;-----------------------------------------------------------------------; ! 2024: ! 2025: or bl, bl ! 2026: jz processed_y_overlap ! 2027: ! 2028: ;-----------------------------------------------------------------------; ! 2029: ; We have something which looks like one of the following: ! 2030: ; ! 2031: ; ---------- ---------- ! 2032: ; | flush | | flush | dy > 0 ! 2033: ; | f | | f | ! 2034: ; | l ---------- ---------- l | ----- ! 2035: ; | u | | | | | | u | | ! 2036: ; | s | | | | | | s | limit the "x" rectangles to ! 2037: ; | h | 1 | r | | r | 2 | h | this height ! 2038: ; | | | e | | e | | | | ! 2039: ; ---|------ a | | a ------|--- ----- ! 2040: ; | d | | d | \ ! 2041: ; | read | | read |\ \ ! 2042: ; ---------- ---------- \ \ ! 2043: ; \ \_____ The "x" overlap rectangle ! 2044: ; \ ! 2045: ; \______ The "y" overlap rectangle ! 2046: ; ! 2047: ; ! 2048: ; ! 2049: ; ---------- ---------- dy < 0 ! 2050: ; | read | | read | ! 2051: ; | r | | r | ! 2052: ; | e ------|--- ---|------ e | ----- ! 2053: ; | a | | | | | | a | | ! 2054: ; | d | | f | | f | | d | limit the "x" rectangles to ! 2055: ; | | 3 | l | | l | 4 | | this height ! 2056: ; | | | u | | u | | | | ! 2057: ; ---------- s | | s ---------- ----- ! 2058: ; | h | | h | ! 2059: ; | flush | | flush | ! 2060: ; ---------- ---------- ! 2061: ; ! 2062: ; ! 2063: ; The corners of the L shape are contained in both the X and Y ! 2064: ; rectangles we just created. We'll remove the overlap from the ! 2065: ; X rectangles. To do this, we must subtract |dy| from the height ! 2066: ; stored in the rectangles (which is sizbMask.sizb_cy) and adjust ! 2067: ; X parameters of either the read or flush rectangles. ! 2068: ; ! 2069: ; For cases 1 and 2, we want to adjust X parameters of the flush ! 2070: ; rectangle. For cases 3 and 4, we want to adjust X parameters ! 2071: ; of the read rectangle. ! 2072: ; ! 2073: ; Currently: ! 2074: ; BH = dy ! 2075: ; BL = dx ! 2076: ; CH = buffer height ! 2077: ; CL = buffer width ! 2078: ; DH = old pointer's Y coordinate in save area ! 2079: ; DL = old pointer's X coordinate in save area ! 2080: ; SI = old pointer's Y screen coordinate ! 2081: ; BP = old pointer's X screen coordinate ! 2082: ; DI = --> new pointer's RECT_DATA ! 2083: ;-----------------------------------------------------------------------; ! 2084: ! 2085: mov al, bh ! 2086: mov ebx, offset FLAT:rdFlushX ;Assume cases 1 and 2 ! 2087: or al, al ! 2088: jns @F ! 2089: mov ebx, offset FLAT:rdReadX ;Its cases 3 and 4 ! 2090: neg al ;|dy| ! 2091: add [ebx].rd_ptbWork.ptb_y, al;Move down in the work area too! ! 2092: @@: ! 2093: mov cl, [ebx].rd_ptbSave.ptb_y ! 2094: add cl, al ! 2095: and cl, SAVE_BUFFER_HEIGHT-1 ! 2096: mov [ebx].rd_ptbSave.ptb_y, cl ! 2097: movsx eax, al ! 2098: ! 2099: .ERRNZ (SAVE_BUFFER_HEIGHT-1) AND 80h ! 2100: ! 2101: add [ebx].rd_ptlScreen.ptl_y, eax ! 2102: neg al ! 2103: add al, ch ;sizbMask.sizb_cy - |dy| ! 2104: mov rdFlushX.rd_sizb.sizb_cy, al ! 2105: mov rdReadX.rd_sizb.sizb_cy, al ! 2106: ! 2107: processed_y_overlap: ! 2108: compute_rects_exit: ! 2109: ! 2110: pop ebp ! 2111: ! 2112: PLAIN_RET ! 2113: ! 2114: page ! 2115: ! 2116: ;--------------------------Private-Routine------------------------------; ! 2117: ; clip_rects ! 2118: ; ! 2119: ; This routine clips the rectangles computed by compute_rects. ! 2120: ; ! 2121: ; Entry: ! 2122: ; None ! 2123: ; Returns: ! 2124: ; None ! 2125: ; Error Returns: ! 2126: ; None ! 2127: ; Registers Preserved: ! 2128: ; BP ! 2129: ; Registers Destroyed: ! 2130: ; AX,BX,CX,DX,SI,DI,FLAGS ! 2131: ; Calls: ! 2132: ; do_clipping ! 2133: ; ! 2134: ;-----------------------------------------------------------------------; ! 2135: ! 2136: align 4 ! 2137: clip_rects: ! 2138: ! 2139: mov esi, ppdOld ;--> old POINTER_DATA structure ! 2140: mov dl, [esi].pd_fb ! 2141: test dl, PD_CLIPPED ;Won't be set if PD_VALID isn't set ! 2142: jz old_been_clipped ! 2143: ! 2144: ;-----------------------------------------------------------------------; ! 2145: ; The old pointer needs some form of clipping. This can affect either ! 2146: ; the old pointer's rectangle or rdFlushX and rdFlushY. Since the old ! 2147: ; pointer's rectangle will be discarded after it is restored, we don't ! 2148: ; care if we write over it's contents. ! 2149: ;-----------------------------------------------------------------------; ! 2150: ! 2151: mov edi, esi ;EDI --> rectangle to clip ! 2152: mov bl, fbFlush ;fbFlush tells us which rects to use ! 2153: mov bh, FB_OLD_PTR ! 2154: test bl, bh ! 2155: jnz call_do_clip ;Only have to clip old pointer's rect ! 2156: mov edi, offset FLAT:rdFlushX ! 2157: mov bh, FB_FLUSH_X ! 2158: test bl, bh ! 2159: jz @F ! 2160: call do_clipping ! 2161: @@: ! 2162: mov edi, offset FLAT:rdFlushY ! 2163: mov bh, FB_FLUSH_Y ! 2164: test bl, bh ! 2165: jz @F ! 2166: call_do_clip: ! 2167: call do_clipping ! 2168: @@: ! 2169: mov fbFlush, bl ! 2170: ! 2171: mov edi, offset FLAT:rdOverlap ! 2172: mov bl, fbAndRead ! 2173: mov bh, FB_OVERLAP ! 2174: test bl, bh ! 2175: jz @F ! 2176: call do_clipping ! 2177: mov fbAndRead, bl ! 2178: @@: ! 2179: old_been_clipped: ! 2180: ! 2181: ! 2182: ;-----------------------------------------------------------------------; ! 2183: ; The old pointer rectangle has been clipped. Now see about clipping ! 2184: ; the new pointer rectangle. ! 2185: ;-----------------------------------------------------------------------; ! 2186: ! 2187: mov esi, ppdNew ;--> new POINTER_DATA structure ! 2188: mov dl, [esi].pd_fb ! 2189: test dl, PD_CLIPPED ;Won't be set if PD_VALID isn't set ! 2190: jz new_been_clipped ! 2191: ! 2192: ;-----------------------------------------------------------------------; ! 2193: ; The new rectangle structure needs to be clipped. This presents a ! 2194: ; minor problem in that we don't want to destroy the screen X,Y and ! 2195: ; buffer X,Y of the pointer's POINTER_DATA structure. What we'll do ! 2196: ; instead is to copy it to the rdWork structure and update it there. ! 2197: ; We'll also set up to XOR this to the screen instead of the ! 2198: ; POINTER_DATA structure. ! 2199: ;-----------------------------------------------------------------------; ! 2200: ! 2201: lodsw ! 2202: mov rdWork.rd_ptbSave, ax ! 2203: ! 2204: .ERRNZ rd_ptbSave ! 2205: .ERRNZ (SIZE POINTB) - 2 ! 2206: ! 2207: lodsd ! 2208: mov rdWork.rd_ptlScreen.ptl_x, eax ! 2209: ! 2210: .ERRNZ rd_ptlScreen-rd_ptbSave-2 ! 2211: .ERRNZ ptl_x ! 2212: ! 2213: lodsd ! 2214: mov rdWork.rd_ptlScreen.ptl_y, eax ! 2215: ! 2216: .ERRNZ ptl_y-ptl_x-4 ! 2217: ! 2218: lodsw ! 2219: mov rdWork.rd_sizb, ax ! 2220: ! 2221: .ERRNZ (SIZE SIZEB) - 2 ! 2222: ! 2223: lodsw ! 2224: mov rdWork.rd_ptbWork, ax ! 2225: ! 2226: .ERRNZ (SIZE POINTB) - 2 ! 2227: ! 2228: sub esi,SIZE RECT_DATA ;--> to start of POINTER_DATA ! 2229: ! 2230: .ERRNZ (rd_ptbWork+2)-(SIZE RECT_DATA) ! 2231: ! 2232: ; Perform the clipping for the work area. We know that some part of the ! 2233: ; work area exists, else we wouldn't be here with a valid rectangle. ! 2234: ; If FB_NEW_PTR is set in fbAndRead, then we want to replace it with ! 2235: ; FB_WORK_RECT, else we'll want to process any overlap rectangles. ! 2236: ! 2237: mov edi, offset FLAT:rdWork ! 2238: call do_clipping ! 2239: mov bl, FB_WORK_RECT ! 2240: mov fbXor, bl ! 2241: xchg fbAndRead, bl ;Assume only work rect to and/read ! 2242: test bl, FB_NEW_PTR ! 2243: jnz new_been_clipped ! 2244: ! 2245: mov edi, offset FLAT:rdReadX ! 2246: mov bh, FB_READ_X ! 2247: test bl, bh ! 2248: jz @F ! 2249: call do_clipping ! 2250: @@: ! 2251: mov edi, offset FLAT:rdReadY ! 2252: mov bh, FB_READ_Y ! 2253: test bl, bh ! 2254: jz @F ! 2255: call do_clipping ! 2256: @@: ! 2257: mov fbAndRead, bl ! 2258: ! 2259: new_been_clipped: ! 2260: ! 2261: PLAIN_RET ! 2262: ! 2263: page ! 2264: ! 2265: ;--------------------------Private-Routine------------------------------; ! 2266: ; do_clipping ! 2267: ; ! 2268: ; This routine performs the actual clipping of a rectangle using the ! 2269: ; passed POINTER_DATA and RECT_DATA structures. ! 2270: ; ! 2271: ; Entry: ! 2272: ; BL = flag byte ! 2273: ; BH = bit to clear in BL if rectangle is invisible ! 2274: ; DL = pd_fb for [si] ! 2275: ; SI --> POINTER_DATA structure ! 2276: ; DI --> RECT_DATA structure ! 2277: ; Returns: ! 2278: ; BL updated ! 2279: ; Error Returns: ! 2280: ; None ! 2281: ; Registers Preserved: ! 2282: ; DX,SI,DI,BP ! 2283: ; Registers Destroyed: ! 2284: ; AX,BH,CX ! 2285: ; Calls: ! 2286: ; None ! 2287: ; ! 2288: ;-----------------------------------------------------------------------; ! 2289: ! 2290: ! 2291: align 4 ! 2292: do_clipping: ! 2293: ! 2294: .ERRNZ pd_rd ;Must be at offset 0 ! 2295: ! 2296: xor eax, eax ! 2297: test dl, PD_CLIP_BOTTOM OR PD_CLIP_TOP ! 2298: jz y_clipping_done ! 2299: mov ecx, [edi].rd_ptlScreen.ptl_y ! 2300: js clip_on_bottom_eh? ! 2301: ! 2302: .ERRNZ PD_CLIP_BOTTOM-10000000b ! 2303: ! 2304: ;-----------------------------------------------------------------------; ! 2305: ; Top clipping may have to be performed for this rectangle. ! 2306: ;-----------------------------------------------------------------------; ! 2307: ! 2308: clip_on_top: ! 2309: neg ecx ;If it was negative, then must clip ! 2310: jle y_clipping_done ;Was positive, no clipping needed ! 2311: sub [edi].rd_sizb.sizb_cy, cl ;Compute new height ! 2312: jle clear_visible_bit ;Clipped away, nothing visible ! 2313: add [edi].rd_ptbWork.ptb_y, cl ;Move down in work area ! 2314: add cl, [edi].rd_ptbSave.ptb_y ;Move down in save area ! 2315: and cl, SAVE_BUFFER_HEIGHT-1 ! 2316: mov [edi].rd_ptbSave.ptb_y, cl ! 2317: mov [edi].rd_ptlScreen.ptl_y, eax ! 2318: jmp finish_y_clipping ! 2319: ! 2320: ! 2321: ;-----------------------------------------------------------------------; ! 2322: ; Bottom clipping may have to be performed for this rectangle. ! 2323: ;-----------------------------------------------------------------------; ! 2324: ! 2325: clip_on_bottom_eh?: ! 2326: mov al, [edi].rd_sizb.sizb_cy ! 2327: add ecx, eax ! 2328: sub ecx, cyScreen ! 2329: jle finish_y_clipping ;EAX = amount to clip if positive ! 2330: sub al, cl ;Compute new height ! 2331: jle clear_visible_bit ;Clipped away, nothing visible ! 2332: mov [edi].rd_sizb.sizb_cy, al ! 2333: finish_y_clipping: ! 2334: xor eax, eax ! 2335: y_clipping_done: ! 2336: ! 2337: ! 2338: test dl, PD_CLIP_LEFT OR PD_CLIP_RIGHT ! 2339: jz x_clipping_done ! 2340: mov ecx, [edi].rd_ptlScreen.ptl_x ! 2341: test dl, PD_CLIP_RIGHT ! 2342: jnz clip_on_rhs ! 2343: ! 2344: ;-----------------------------------------------------------------------; ! 2345: ; lhs clipping may have to be performed for this rectangle. ! 2346: ;-----------------------------------------------------------------------; ! 2347: ! 2348: clip_on_lhs: ! 2349: neg ecx ;If it was negative, then must clip ! 2350: jle x_clipping_done ;Was positive, no clipping needed ! 2351: sub [edi].rd_sizb.sizb_cx, cl ;Compute new width ! 2352: jle clear_visible_bit ;Clipped away, nothing visible ! 2353: add [edi].rd_ptbWork.ptb_x, cl;Move right in work area ! 2354: add cl, [edi].rd_ptbSave.ptb_x;Move right in save area ! 2355: and cl, SAVE_BUFFER_WIDTH-1 ! 2356: mov [edi].rd_ptbSave.ptb_x, cl ! 2357: mov [edi].rd_ptlScreen.ptl_x, eax ! 2358: jmp x_clipping_done ! 2359: ! 2360: ! 2361: ;-----------------------------------------------------------------------; ! 2362: ; rhs clipping may have to be performed for this rectangle. ! 2363: ;-----------------------------------------------------------------------; ! 2364: ! 2365: clip_on_rhs: ! 2366: mov al,[edi].rd_sizb.sizb_cx ! 2367: add ecx,eax ! 2368: sub ecx,lNextScan ! 2369: jle x_clipping_done ;EAX = amount to clip if positive ! 2370: sub al,cl ;Compute new height ! 2371: jle clear_visible_bit ;Clipped away, nothing visible ! 2372: mov [edi].rd_sizb.sizb_cx, al ! 2373: x_clipping_done: ! 2374: xor bh,bh ;0 to cancel following XOR ! 2375: ! 2376: clear_visible_bit: ! 2377: xor bl,bh ;Update visible bit ! 2378: PLAIN_RET ! 2379: ! 2380: page ! 2381: ! 2382: ;--------------------------Private-Routine------------------------------; ! 2383: ; xor_to_screen ! 2384: ; ! 2385: ; The work area is XORed with the XOR mask and placed on the screen ! 2386: ; ! 2387: ; Entry: ! 2388: ; AL = fbXor ! 2389: ; Returns: ! 2390: ; None ! 2391: ; Error Returns: ! 2392: ; No error return. ! 2393: ; Registers Preserved: ! 2394: ; BP ! 2395: ; Registers Destroyed: ! 2396: ; AX,BX,CX,DX,SI,DI,FLAGS ! 2397: ; Calls: ! 2398: ; None ! 2399: ; ! 2400: ;-----------------------------------------------------------------------; ! 2401: ! 2402: .ERRNZ pd_rd ;Must be at offset 0 ! 2403: ! 2404: align 4 ! 2405: xor_to_screen: ! 2406: xor ebx, ebx ;Zero will be useful soon ! 2407: shr al, 1 ;Set 'C' to FB_WORK_RECT bit ! 2408: ! 2409: .ERRNZ FB_WORK_RECT-00000001b ! 2410: ! 2411: ;-----------------------------------------------------------------------; ! 2412: ; Program the EGA for XOR mode. This will be done using M_PROC_WRITE, ! 2413: ; M_DATA_READ, DR_XOR, and setting GRAF_BIT_MASK to FF. The normal ! 2414: ; sequence of events will have left the bitmask register with 00h and ! 2415: ; the mode register in AND mode. ! 2416: ;-----------------------------------------------------------------------; ! 2417: ! 2418: mov dx, EGA_BASE + GRAF_ADDR ! 2419: mov ax, 0FF00h + GRAF_BIT_MASK ! 2420: out dx, ax ;Enable all bits ! 2421: mov ax, DR_XOR SHL 8 + GRAF_DATA_ROT ! 2422: out dx, ax ! 2423: ! 2424: ;-----------------------------------------------------------------------; ! 2425: ; Compute the offset from the start of the work area and the XOR mask ! 2426: ; (its the same value). If we're to use the new pointer's rectangle, ! 2427: ; then this offset is zero. ! 2428: ;-----------------------------------------------------------------------; ! 2429: ! 2430: mov esi,ppdNew ;assume new pointer is in use ! 2431: jnc have_xor_mask_offset ;EBX = 0 is offset ! 2432: ! 2433: .ERRNZ FB_WORK_RECT-00000001b ! 2434: .ERRE FB_NEW_PTR-00000001b ! 2435: ! 2436: mov esi,offset FLAT:rdWork ;The work area (we be clipping) ! 2437: movzx eax,WORD PTR [esi].rd_ptbWork ;Get origin in work area ! 2438: xchg ah, bl ;BX = ptbWork.ptb_y, AX = ptbWork.ptb_x ! 2439: add eax,ebx ;*1 + X component ! 2440: add ebx,ebx ;*2 ! 2441: add ebx,ebx ;*4 ! 2442: add ebx,eax ;*5 + X = start from work/mask ! 2443: ! 2444: .ERRNZ WORK_WIDTH-5 ! 2445: ! 2446: have_xor_mask_offset: ! 2447: ! 2448: ! 2449: ; Map the proper bank into the destination window for the top destination ! 2450: ; scan line. ! 2451: ! 2452: mov edi,pdsurf ! 2453: mov edx,[esi].rd_ptlScreen.ptl_y ! 2454: mov ulCurrentTopScan,edx ;remember where the top dest scan is ! 2455: cmp edx,[edi].dsurf_rcl2WindowClipD.yTop ;is xor top less than ! 2456: ; current dest bank? ! 2457: jl short xts_map_init_bank ;yes, map in proper bank ! 2458: cmp edx,[edi].dsurf_rcl2WindowClipD.yBottom ;xor top greater than ! 2459: ; current dest bank? ! 2460: jl short xts_init_bank_mapped ;no, proper bank already mapped ! 2461: xts_map_init_bank: ! 2462: ! 2463: ; Map bank containing the top destination (screen) scan line into dest window. ! 2464: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 2465: ! 2466: ptrCall <dword ptr [edi].dsurf_pfnBankControl2Window>, \ ! 2467: <edi,edx,JustifyTop,MapDestBank> ! 2468: ! 2469: xts_init_bank_mapped: ! 2470: ! 2471: ! 2472: ; Map the cursor bank into the source window. ! 2473: ! 2474: mov edx,ulPtrBankScan ;scan line at end of cursor work bank ! 2475: cmp edx,[edi].dsurf_rcl2WindowClipS.yTop ;is cursor scan less than ! 2476: ; current source bank? ! 2477: jl short xts_map_ptr_bank ;yes, map in proper bank ! 2478: cmp edx,[edi].dsurf_rcl2WindowClipS.yBottom ;cursor scan greater ! 2479: ; than current source ! 2480: ; bank? ! 2481: jl short xts_ptr_bank_mapped ;no, proper bank already mapped ! 2482: xts_map_ptr_bank: ! 2483: ! 2484: ; Map cursor work bank into source window. ! 2485: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 2486: ! 2487: ptrCall <dword ptr [edi].dsurf_pfnBankControl2Window>, \ ! 2488: <edi,edx,JustifyBottom,MapSourceBank> ! 2489: ! 2490: xts_ptr_bank_mapped: ! 2491: ! 2492: ! 2493: ; Compute the screen address of this rectangle and get its size ! 2494: ! 2495: mov ecx,[edi].dsurf_pvBitmapStart2WindowD ;start of screen bitmap ! 2496: mov edi,lNextScan ;width of screen bitmap ! 2497: imul edi,[esi].rd_ptlScreen.ptl_y ;offset of dest start in screen ! 2498: add edi,[esi].rd_ptlScreen.ptl_x ; buffer ! 2499: add edi,ecx ;virtual address of dest start ! 2500: ! 2501: mov cx,[esi].rd_sizb ;CH = scans to copy ! 2502: ; CL = bytes across to copy ! 2503: ! 2504: .ERRNZ sizb_cy-sizb_cx-1 ! 2505: ! 2506: ;-----------------------------------------------------------------------; ! 2507: ; To save incrementing the work area pointer (BX), subtract the XOR ! 2508: ; mask pointer off of it. Then use [BX][SI] for addressing into the ! 2509: ; XOR mask. As SI is incremented, BX will effectively be incremented. ! 2510: ; We could not do this if the XOR mask and the work area were different ! 2511: ; widths. ! 2512: ; ! 2513: ; Finish computing the pointer to the XOR mask and the delta from the ! 2514: ; XOR mask to the work area. ! 2515: ;-----------------------------------------------------------------------; ! 2516: ! 2517: mov esi,pAndXor ;set address of XOR mask ! 2518: lea esi,[esi][ebx][base_xor_masks-base_and_masks] ! 2519: add ebx,pPtrWork ;start src offset in bitmap ! 2520: mov eax,pdsurf ! 2521: add ebx,[eax].dsurf_pvBitmapStart2WindowS ;start src virtual addr ! 2522: sub ebx,esi ;fudge back so we get away with one ! 2523: ; increment ! 2524: ! 2525: ; Calculate the number of scans we'll do in this bank. ! 2526: ! 2527: mov edx,[eax].dsurf_rcl2WindowClipD.yBottom ! 2528: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 2529: ; the initial bank ! 2530: sub eax,eax ! 2531: mov al,ch ;total # of scans to copy ! 2532: cmp eax,edx ;can we handle all remaining scans in ! 2533: ; this bank? ! 2534: jb short @F ;yes ! 2535: mov eax,edx ;no, so we'll do the whole bank's worth ! 2536: @@: ! 2537: add ulCurrentTopScan,eax ;set top scan for next bank ! 2538: sub ch,al ;count this bank's scans off total ! 2539: mov byte ptr cjTotalScans,ch ;remember # of scans after this bank ! 2540: mov ch,al ;# of scans to do in this bank ! 2541: ! 2542: ; Compute the delta to the start of the next scanline of the XOR mask ! 2543: ; and the work area, and the next scan of the screen ! 2544: ! 2545: sub eax,eax ! 2546: mov al,cl ;width to copy in bytes ! 2547: mov edx,WORK_WIDTH ! 2548: sub edx,eax ;offset from end of one source scan to ! 2549: mov ulNextSrcScan,edx ; start of next ! 2550: add edx,lNextScan ;offset from end of one dest scan to ! 2551: sub edx,WORK_WIDTH ; start of next ! 2552: ! 2553: lea eax,[eax*4] ! 2554: neg eax ! 2555: add eax,offset FLAT:xor_to_screen_width_0 ! 2556: ! 2557: push ebp ;remember stack frame pointer ! 2558: mov ebp,ulNextSrcScan ;offset to next XOR scan ! 2559: jmp eax ! 2560: ! 2561: .ERRNZ WORK_WIDTH-5 ! 2562: ;-----------------------------------------------------------------------; ! 2563: ; Register usage for the loop will be: ! 2564: ; ! 2565: ; AX = loop starting address ! 2566: ; BX = offset off [si] to the work area ! 2567: ; CH = height ! 2568: ; DX = delta to next scan of the destination ! 2569: ; SI --> XOR mask ! 2570: ; DI --> Destination ! 2571: ; BP = offset to next byte of XOR mask, next scan of work area ! 2572: ;-----------------------------------------------------------------------; ! 2573: ! 2574: align 4 ! 2575: xor_to_screen_width_5: ! 2576: cmp al, [ebx][esi] ;Load latches from work area ! 2577: movsb ;XOR to the screen ! 2578: xor_to_screen_width_4: ! 2579: cmp al, [ebx][esi] ! 2580: movsb ! 2581: xor_to_screen_width_3: ! 2582: cmp al, [ebx][esi] ! 2583: movsb ! 2584: xor_to_screen_width_2: ! 2585: cmp al, [ebx][esi] ! 2586: movsb ! 2587: xor_to_screen_width_1: ! 2588: cmp al, [ebx][esi] ! 2589: movsb ! 2590: xor_to_screen_width_0: ! 2591: ! 2592: .ERRNZ xor_to_screen_width_0-xor_to_screen_width_1-4 ! 2593: .ERRNZ xor_to_screen_width_1-xor_to_screen_width_2-4 ! 2594: .ERRNZ xor_to_screen_width_2-xor_to_screen_width_3-4 ! 2595: .ERRNZ xor_to_screen_width_3-xor_to_screen_width_4-4 ! 2596: .ERRNZ xor_to_screen_width_4-xor_to_screen_width_5-4 ! 2597: ! 2598: add esi, ebp ;--> next scan's XOR mask, work addr ! 2599: add edi, edx ;--> next scan's destination ! 2600: dec ch ;count down lines in this bank ! 2601: jz short @F ;no more lines in this bank ! 2602: jmp eax ;do the next line in this bank ! 2603: ! 2604: align 4 ! 2605: @@: ;done with bank ! 2606: pop ebp ;retrieve stack frame pointer ! 2607: cmp byte ptr cjTotalScans,0 ;more lines (in next dest bank)? ! 2608: jz short xts_done ;no, we're done ! 2609: ;advance to next dest bank and continue ! 2610: ; XORing ! 2611: push eax ;preserve entry vector ! 2612: push edx ;preserve dest next scan ! 2613: mov eax,pdsurf ! 2614: sub edi,[eax].dsurf_pvBitmapStart2WindowD ! 2615: ;calculate the destination offset ! 2616: ; within the bitmap, because the start ! 2617: ; address is about to move ! 2618: mov edx,ulCurrentTopScan ! 2619: ! 2620: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 2621: ! 2622: ptrCall <dword ptr [eax].dsurf_pfnBankControl2Window>, \ ! 2623: <eax,edx,JustifyTop,MapDestBank> ;map in the next dest bank ! 2624: ! 2625: mov eax,pdsurf ! 2626: add edi,[eax].dsurf_pvBitmapStart2WindowD ! 2627: ;add back in the bitmap start address ! 2628: ; to yield the virtual dest address ! 2629: mov edx,[eax].dsurf_rcl2WindowClipD.yBottom ! 2630: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 2631: ; the new bank ! 2632: sub eax,eax ! 2633: mov al,byte ptr cjTotalScans ;remaining scan count ! 2634: cmp eax,edx ;can we handle all remaining scans in ! 2635: ; this bank? ! 2636: jb short @F ;yes ! 2637: mov eax,edx ;no, so we'll do the whole bank's worth ! 2638: @@: ! 2639: add ulCurrentTopScan,eax ;set top scan for next bank ! 2640: sub byte ptr cjTotalScans,al ;count this bank's scans off total ! 2641: mov ch,al ;# of scans to do in this bank ! 2642: ! 2643: pop edx ;restore dest next scan ! 2644: pop eax ;restore entry vector ! 2645: ! 2646: push ebp ;remember stack frame pointer ! 2647: mov ebp,ulNextSrcScan ;offset to next XOR scan ! 2648: jmp eax ;do the next block of scans ! 2649: ! 2650: xts_done: ! 2651: PLAIN_RET ! 2652: ! 2653: page ! 2654: ;--------------------------Private-Routine------------------------------; ! 2655: ; color_pointer_to_screen ! 2656: ; ! 2657: ; The color pointer is output to the screen using AND/XOR/COLOR masks. ! 2658: ; ! 2659: ; Entry: ! 2660: ; None ! 2661: ; Returns: ! 2662: ; None ! 2663: ; Error Returns: ! 2664: ; No error return. ! 2665: ; Registers Preserved: ! 2666: ; BP ! 2667: ; Registers Destroyed: ! 2668: ; AX,BX,CX,DX,SI,DI,FLAGS ! 2669: ; Calls: ! 2670: ; None ! 2671: ; ! 2672: ;-----------------------------------------------------------------------; ! 2673: ! 2674: align 4 ! 2675: color_pointer_to_screen: ! 2676: ! 2677: .ERRNZ pd_rd ;Must be at offset 0 ! 2678: ! 2679: ; Set up variables that don't change from plane to plane in the outer loop ! 2680: ! 2681: mov esi,ppdNew ! 2682: test fbXor,FB_WORK_RECT ! 2683: jz short cps_have_pointer_rect ! 2684: mov esi,offset FLAT:rdWork ;the work area (we be clipping) ! 2685: cps_have_pointer_rect: ! 2686: mov prclSource,esi ! 2687: ! 2688: ; Map the proper bank into the destination window for the top destination ! 2689: ; scan line. ! 2690: ! 2691: mov ebx,pdsurf ! 2692: mov edx,[esi].rd_ptlScreen.ptl_y ! 2693: mov ulCurrentTopScan,edx ;remember where the top dest scan is ! 2694: cmp edx,[ebx].dsurf_rcl2WindowClipD.yTop ;is copy top less than ! 2695: ; current dest bank? ! 2696: jl short cpts_map_init_bank ;yes, map in proper bank ! 2697: cmp edx,[ebx].dsurf_rcl2WindowClipD.yBottom ;copy top greater than ! 2698: ; current dest bank? ! 2699: jl short cpts_init_bank_mapped ;no, proper bank already mapped ! 2700: cpts_map_init_bank: ! 2701: ! 2702: ; Map bank containing the top destination (screen) scan line into dest window. ! 2703: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 2704: ! 2705: ptrCall <dword ptr [ebx].dsurf_pfnBankControl2Window>, \ ! 2706: <ebx,edx,JustifyTop,MapDestBank> ! 2707: ! 2708: cpts_init_bank_mapped: ! 2709: ! 2710: ! 2711: ; Map the cursor bank into the source window. ! 2712: ! 2713: mov edx,ulPtrBankScan ;scan line at end of cursor work bank ! 2714: cmp edx,[ebx].dsurf_rcl2WindowClipS.yTop ;is cursor scan less than ! 2715: ; current source bank? ! 2716: jl short cpts_map_ptr_bank ;yes, map in proper bank ! 2717: cmp edx,[ebx].dsurf_rcl2WindowClipS.yBottom ;cursor scan greater ! 2718: ; than current source ! 2719: ; bank? ! 2720: jl short cpts_ptr_bank_mapped ;no, proper bank already mapped ! 2721: cpts_map_ptr_bank: ! 2722: ! 2723: ; Map cursor work bank into source window. ! 2724: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 2725: ! 2726: ptrCall <dword ptr [ebx].dsurf_pfnBankControl2Window>, \ ! 2727: <ebx,edx,JustifyBottom,MapSourceBank> ! 2728: ! 2729: cpts_ptr_bank_mapped: ! 2730: ! 2731: ! 2732: ; Offset to next screen scan, minus the width of the work area, will ! 2733: ; come in handy in the inner loop. ! 2734: ! 2735: mov eax,lNextScan ;width of screen bitmap ! 2736: mov edi,eax ;set aside for computing the screen address ! 2737: sub eax,WORK_WIDTH ! 2738: mov ulScanMinusWorkWidth,eax ! 2739: ! 2740: ; Compute the screen address of the rectangle in this bank ! 2741: ! 2742: imul edi,[esi].rd_ptlScreen.ptl_y ;offset of dest start in screen ! 2743: add edi,[esi].rd_ptlScreen.ptl_x ; buffer ! 2744: add edi,[ebx].dsurf_pvBitmapStart2WindowD ;virtual address of dest ! 2745: ; start ! 2746: mov pDest,edi ! 2747: ! 2748: ; Remember the save source point. ! 2749: ! 2750: sub eax,eax ! 2751: mov ax,word ptr [esi].rd_ptbSave ! 2752: mov jSaveSourceXY,eax ! 2753: mov byte ptr jNextSaveSourceY,ah ! 2754: ! 2755: ! 2756: ; Remember the work source point. ! 2757: ! 2758: mov ax,word ptr [esi].rd_ptbWork ! 2759: mov jWorkSourceXY,eax ! 2760: mov byte ptr jNextWorkSourceY,ah ! 2761: ! 2762: ! 2763: ; Calculate the number of scans we'll do in this bank. ! 2764: ! 2765: mov edx,[ebx].dsurf_rcl2WindowClipD.yBottom ! 2766: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 2767: ; the initial bank ! 2768: mov ch,byte ptr [esi].rd_sizb+1 ;total # of scans to copy ! 2769: sub eax,eax ! 2770: mov al,ch ! 2771: cmp eax,edx ;can we handle all remaining scans in ! 2772: ; this bank? ! 2773: jb short @F ;yes ! 2774: mov eax,edx ;no, so we'll do the whole bank's worth ! 2775: @@: ! 2776: add ulCurrentTopScan,eax ;set top scan for next bank ! 2777: add byte ptr jNextSaveSourceY,al ;top save source scan for next bank ! 2778: add byte ptr jNextWorkSourceY,al ;top work source scan for next bank ! 2779: sub ch,al ;count this bank's scans off total ! 2780: mov byte ptr cjTotalScans,ch ;remember # of scans after this bank ! 2781: mov byte ptr jScansInBank,al ;# of scans to do in this bank ! 2782: ! 2783: ; Set the virtual address of the save area ! 2784: ! 2785: mov eax,[ebx].dsurf_pvBitmapStart2WindowS ;start of source bitmap ! 2786: add eax,pPtrSave ;virtual address of save area ! 2787: mov pWorkingSave,eax ! 2788: ! 2789: ; Loop through banks that this cursor spans ! 2790: ! 2791: cpts_bank_loop: ! 2792: ! 2793: ; Initial plane is plane 3 ! 2794: ! 2795: mov iPlaneMask,MM_C3 ! 2796: ! 2797: ;-----------------------------------------------------------------------; ! 2798: ; Program the VGA for SET mode. This will be done using M_PROC_WRITE, ! 2799: ; M_DATA_READ, DR_SET, and setting GRAF_BIT_MASK to FF. The normal ! 2800: ; sequence of events will have left the bitmask register with 00h and ! 2801: ; the mode register in AND mode. ! 2802: ;-----------------------------------------------------------------------; ! 2803: ! 2804: mov dx,EGA_BASE + GRAF_ADDR ! 2805: mov ax,0FF00h + GRAF_BIT_MASK ! 2806: out dx,ax ;enable all bits ! 2807: mov ax,DR_SET SHL 8 + GRAF_DATA_ROT ! 2808: out dx,ax ! 2809: mov al,GRAF_READ_MAP ! 2810: out dx,al ;leave the GC Index pointing to the Read Map reg ! 2811: ! 2812: cps_do_next_plane: ! 2813: ! 2814: ; Set write plane enable register to the ONE plane we will alter ! 2815: ! 2816: mov al,byte ptr iPlaneMask ;set Map Mask ! 2817: mov dx,EGA_BASE + SEQ_DATA ! 2818: out dx,al ! 2819: ! 2820: ; Set read plane to plane to read from ! 2821: ! 2822: shr al,1 ;map plane into ReadMask ! 2823: cmp al,100b ;set Carry if not C3 (plane 3) ! 2824: adc al,-1 ;sub 1 only if C3 ! 2825: mov dl,GRAF_DATA ! 2826: out dx,al ! 2827: ! 2828: mov esi,prclSource ;point to source rect ! 2829: mov edi,pDest ;point to initial dest byte ! 2830: ! 2831: mov eax,jSaveSourceXY ! 2832: mov edx,jWorkSourceXY ! 2833: ! 2834: .ERRNZ ptb_y-ptb_x-1 ! 2835: ! 2836: mov cl,byte ptr [esi].rd_sizb ! 2837: ! 2838: .ERRNZ sizb_cy-sizb_cx-1 ! 2839: ! 2840: mov bl,al ;see if save area is contiguous ! 2841: add bl,cl ! 2842: sub bl,SAVE_BUFFER_WIDTH ;BL = is overhang ! 2843: jle short call_cps_do_a_pass ;no overhang ! 2844: ! 2845: sub cl,bl ;set X extent for pass 1 ! 2846: mov bh,cl ;need it for pass 2 ! 2847: mov ch,byte ptr jScansInBank ;# of scans to do in this bank ! 2848: push ebx ! 2849: call cps_do_a_pass ;process first half ! 2850: pop ebx ! 2851: ! 2852: mov esi,prclSource ;point to source rect ! 2853: mov edi,pDest ;point to initial dest byte ! 2854: ! 2855: mov eax,jSaveSourceXY ! 2856: mov edx,jWorkSourceXY ! 2857: ! 2858: .ERRNZ ptb_y-ptb_x-1 ! 2859: ! 2860: mov cl,byte ptr [esi].rd_sizb ! 2861: ! 2862: .ERRNZ sizb_cy-sizb_cx-1 ! 2863: ! 2864: add dl,bh ;move right in work area ! 2865: mov cl,bl ;set new extent ! 2866: xor al,al ;X origin in save area is 0 ! 2867: movzx ebx,bh ;move right in destination area ! 2868: add edi,ebx ! 2869: ! 2870: call_cps_do_a_pass: ! 2871: mov ch,byte ptr jScansInBank ;# of scans to do in this bank ! 2872: call cps_do_a_pass ;process second half (or the whole ! 2873: ; color cursor, if no overhang) ! 2874: ! 2875: shr iPlaneMask,1 ! 2876: jnc cps_do_next_plane ! 2877: ! 2878: .ERRNZ MM_C0-00000001b ! 2879: .ERRNZ MM_C1-00000010b ! 2880: .ERRNZ MM_C2-00000100b ! 2881: .ERRNZ MM_C3-00001000b ! 2882: ! 2883: ;we've done all planes in this bank ! 2884: cmp byte ptr cjTotalScans,0 ;more lines (in next dest bank)? ! 2885: jz short cpts_done ;no, we're done ! 2886: ;advance to next dest bank and continue ! 2887: ; XORing ! 2888: ! 2889: ; Advance the source Y coordinates to match the bank advance we're about to do. ! 2890: ! 2891: mov al,byte ptr jNextSaveSourceY ! 2892: mov byte ptr jSaveSourceXY+1,al ! 2893: mov al,byte ptr jNextWorkSourceY ! 2894: mov byte ptr jWorkSourceXY+1,al ! 2895: ! 2896: ; Advance to the next dest bank. ! 2897: ! 2898: mov ebx,pdsurf ! 2899: mov edx,ulCurrentTopScan ! 2900: ! 2901: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 2902: ! 2903: ptrCall <dword ptr [ebx].dsurf_pfnBankControl2Window>, \ ! 2904: <ebx,edx,JustifyTop,MapDestBank> ;map in the next dest bank ! 2905: ! 2906: ; Compute the screen start address of the rectangle in this bank ! 2907: ! 2908: mov esi,prclSource ;point to source rect ! 2909: mov edi,lNextScan ;width of screen bitmap ! 2910: imul edi,ulCurrentTopScan ;offset of dest start in screen ! 2911: add edi,[esi].rd_ptlScreen.ptl_x ; buffer ! 2912: add edi,[ebx].dsurf_pvBitmapStart2WindowD ;virtual address of dest ! 2913: ; start ! 2914: mov pDest,edi ! 2915: ! 2916: mov edx,[ebx].dsurf_rcl2WindowClipD.yBottom ! 2917: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 2918: ; the new bank ! 2919: sub eax,eax ! 2920: mov al,byte ptr cjTotalScans ;remaining scan count ! 2921: cmp eax,edx ;can we handle all remaining scans in ! 2922: ; this bank? ! 2923: jb short @F ;yes ! 2924: mov eax,edx ;no, so we'll do the whole bank's worth ! 2925: @@: ! 2926: add ulCurrentTopScan,eax ;set top scan for next bank ! 2927: add byte ptr jNextSaveSourceY,al ;top save source scan for next bank ! 2928: add byte ptr jNextWorkSourceY,al ;top work source scan for next bank ! 2929: sub byte ptr cjTotalScans,al ;count this bank's scans off total ! 2930: mov byte ptr jScansInBank,al ;# of scans to do in this bank ! 2931: ! 2932: jmp cpts_bank_loop ;do the next block of scans ! 2933: ! 2934: cpts_done: ! 2935: PLAIN_RET ! 2936: ! 2937: page ! 2938: ;--------------------------Private-Routine------------------------------; ! 2939: ; cps_do_a_pass ! 2940: ; ! 2941: ; Output one plane of the color pointer to the screen using ! 2942: ; AND/XOR/COLOR masks. Does not handle bank spanning; that is taken care ! 2943: ; of in color_pointer_to_screen. ! 2944: ; ! 2945: ; Entry: ! 2946: ; AH = ptbSave.ptb_y, AL = ptbSave.ptb_x ! 2947: ; DH = ptbWork.ptb_y, DL = ptbWork.ptb_x ! 2948: ; CL = x bytes to process ! 2949: ; CH = y scans to process ! 2950: ; EDI --> Destination (screen area) ! 2951: ; EBP = stack frame ! 2952: ; VGA set up to enable writes to proper plane ! 2953: ; Returns: ! 2954: ; None ! 2955: ; Error Returns: ! 2956: ; No error return. ! 2957: ; Registers Preserved: ! 2958: ; EBP ! 2959: ; Registers Destroyed: ! 2960: ; EAX,EBX,ECX,EDX,ESI,EDI,EFLAGS ! 2961: ; Calls: ! 2962: ; None ! 2963: ; ! 2964: ;-----------------------------------------------------------------------; ! 2965: ! 2966: align 4 ! 2967: cps_do_a_pass: ! 2968: ! 2969: ;-----------------------------------------------------------------------; ! 2970: ; Compute the offset within the save area. Note that this is relative ! 2971: ; to screen_buf. ! 2972: ; AH = ptbSave.ptb_y, AL = ptbSave.ptb_x ! 2973: ;-----------------------------------------------------------------------; ! 2974: ! 2975: shl ah,3 ! 2976: add al,ah ;y * 8 + x ! 2977: xor ah,ah ! 2978: cwde ! 2979: mov ulOffsetSave,eax ! 2980: ! 2981: .ERRNZ SAVE_BUFFER_WIDTH-8 ! 2982: .ERRNZ SAVE_BUFFER_HEIGHT-32 ! 2983: ! 2984: mov esi,pWorkingSave ;point to the save area ! 2985: add esi,eax ;ESI --> start address in save area ! 2986: ! 2987: ! 2988: ;-----------------------------------------------------------------------; ! 2989: ; Compute the offset within the AND/XOR masks. ! 2990: ; DH = ptbWork.ptb_y, DL = ptbWork.ptb_x ! 2991: ;-----------------------------------------------------------------------; ! 2992: ! 2993: xor ebx,ebx ! 2994: xchg dh,bl ! 2995: add edx,ebx ;y * 1 + x ! 2996: add ebx,ebx ;y * 2 ! 2997: add ebx,ebx ;y * 4 ! 2998: add ebx,edx ;y * 5 + x ! 2999: mov ulOffsetMask,ebx ! 3000: add ebx,pAndXor ;EBX --> start address of AND mask ! 3001: sub ebx,edi ;make EBX relative to EDI ! 3002: ! 3003: ;-----------------------------------------------------------------------; ! 3004: ; Compute the delta to the start of the next scanline of destination ! 3005: ; screen area ! 3006: ;-----------------------------------------------------------------------; ! 3007: ! 3008: mov al, cl ! 3009: movsx eax, al ! 3010: mov edx,lNextScan ! 3011: sub edx,eax ! 3012: mov ulDeltaScreen,edx ;delta to next scan of screen area ! 3013: ! 3014: ;-----------------------------------------------------------------------; ! 3015: ; Calculate EDX = jump table address ! 3016: ;-----------------------------------------------------------------------; ! 3017: ! 3018: mov edx,color_to_screen_entry_table[eax*4] ! 3019: ! 3020: .ERRNZ WORK_WIDTH-5 ! 3021: ! 3022: ;-----------------------------------------------------------------------; ! 3023: ; Compute the offset within the COLOR mask. ! 3024: ;-----------------------------------------------------------------------; ! 3025: ! 3026: push ebp ;need an extra register ! 3027: mov al,byte ptr iPlaneMask ;AL --> iPlaneMask ! 3028: mov ebp,ulOffsetMask ;EBP --> usoffset_mask ! 3029: add ebp,pColor ;EBP --> start address of COLOR mask ! 3030: shr al,1 ! 3031: jz @F ! 3032: add ebp,MASK_LENGTH ! 3033: shr al,1 ! 3034: jz @F ! 3035: add ebp,MASK_LENGTH ! 3036: shr al,1 ! 3037: jz @F ! 3038: add ebp,MASK_LENGTH ! 3039: @@: ! 3040: sub ebp,edi ;make BP relative ! 3041: ! 3042: jmp edx ! 3043: ! 3044: ;-----------------------------------------------------------------------; ! 3045: ; Register usage for the loop will be: ! 3046: ; ! 3047: ; EBX = offset off EDI to the AND mask ! 3048: ; CH = height ! 3049: ; EDX = loop starting address ! 3050: ; ESI --> Source (save area) ! 3051: ; EDI --> Destination (screen area) ! 3052: ; EBP = offset off EDI to the COLOR mask ! 3053: ;-----------------------------------------------------------------------; ! 3054: ! 3055: align 4 ! 3056: color_to_screen_width_5: ! 3057: lodsb ! 3058: and al,[ebx][edi] ! 3059: xor al,[ebp][edi] ! 3060: stosb ! 3061: color_to_screen_width_4: ! 3062: lodsb ! 3063: and al,[ebx][edi] ! 3064: xor al,[ebp][edi] ! 3065: stosb ! 3066: color_to_screen_width_3: ! 3067: lodsb ! 3068: and al,[ebx][edi] ! 3069: xor al,[ebp][edi] ! 3070: stosb ! 3071: color_to_screen_width_2: ! 3072: lodsb ! 3073: and al,[ebx][edi] ! 3074: xor al,[ebp][edi] ! 3075: stosb ! 3076: color_to_screen_width_1: ! 3077: lodsb ! 3078: and al,[ebx][edi] ! 3079: xor al,[ebp][edi] ! 3080: stosb ! 3081: color_to_screen_width_0: ! 3082: ! 3083: mov eax,ebp ;EAX --> next scan's COLOR mask ! 3084: pop ebp ! 3085: sub eax,ulScanMinusWorkWidth ! 3086: ! 3087: ; WE HAVE NO SPARE REGISTERS HERE ! 3088: ! 3089: xchg eax,ulOffsetSave ! 3090: add al,SAVE_BUFFER_WIDTH ;Take into account wrap around ! 3091: mov esi,pWorkingSave ;point to the save area ! 3092: add esi,eax ;ESI --> next scan's save area ! 3093: xchg ulOffsetSave,eax ! 3094: ! 3095: add edi,ulDeltaScreen ;EDI --> next scan's screen area ! 3096: sub ebx,ulScanMinusWorkWidth ! 3097: ;EBX --> next scan's AND mask ! 3098: dec ch ! 3099: jz cps_exit ! 3100: ! 3101: push ebp ! 3102: mov ebp,eax ;EBP --> next scan's COLOR mask ! 3103: jmp edx ;do the next scan line ! 3104: ! 3105: cps_exit: ! 3106: PLAIN_RET ! 3107: ! 3108: page ! 3109: ! 3110: ;--------------------------Private-Routine------------------------------; ! 3111: ; and_into_work ! 3112: ; ! 3113: ; All rectangles which are to be ANDed into the work area are ! 3114: ; dispatched to the routine which will do the actual ANDing. ! 3115: ; ! 3116: ; Entry: ! 3117: ; AL = fbAndRead ! 3118: ; Returns: ! 3119: ; None ! 3120: ; Error Returns: ! 3121: ; No error return. ! 3122: ; Registers Preserved: ! 3123: ; BP ! 3124: ; Registers Destroyed: ! 3125: ; AX,BX,CX,DX,SI,DI,FLAGS ! 3126: ; Calls: ! 3127: ; and_from_screen ! 3128: ; and_from_save ! 3129: ; ! 3130: ;-----------------------------------------------------------------------; ! 3131: ! 3132: align 4 ! 3133: and_into_work: ! 3134: ! 3135: push ebp ! 3136: ! 3137: ;-----------------------------------------------------------------------; ! 3138: ; Program the EGA for AND mode. This will be done using M_PROC_WRITE, ! 3139: ; M_DATA_READ, DR_AND, and setting GRAF_BIT_MASK to FF. All but setting ! 3140: ; DR_AND was set by save_hw_regs. All planes were also enabled for ! 3141: ; writing by save_hw_regs. ! 3142: ;-----------------------------------------------------------------------; ! 3143: ! 3144: mov ecx, eax ! 3145: mov dx, EGA_BASE + GRAF_ADDR ! 3146: mov ax, DR_AND SHL 8 + GRAF_DATA_ROT ! 3147: out dx, ax ! 3148: mov eax, ecx ! 3149: ! 3150: ;-----------------------------------------------------------------------; ! 3151: ; If FB_NEW_PTR or FB_WORK_AREA is set, then we only have a single ! 3152: ; rectangle to deal with, located on the screen. ! 3153: ;-----------------------------------------------------------------------; ! 3154: ! 3155: mov esi, ppdNew ! 3156: test al, FB_NEW_PTR ! 3157: jnz aiw_source_is_screen ! 3158: mov esi, offset FLAT:rdWork ! 3159: test al, FB_WORK_RECT ! 3160: jnz aiw_source_is_screen ! 3161: ! 3162: ; Some combination of FB_READ_X, FB_READ_Y, FB_OVERLAP exists ! 3163: ! 3164: test al, FB_READ_Y ! 3165: jz @F ! 3166: mov esi, offset FLAT:rdReadY ! 3167: call and_from_screen ! 3168: mov al, fbAndRead ! 3169: @@: ! 3170: ! 3171: test al, FB_READ_X ! 3172: jz @F ! 3173: mov esi, offset FLAT:rdReadX ! 3174: aiw_source_is_screen: ! 3175: call and_from_screen ! 3176: mov al, fbAndRead ! 3177: @@: ! 3178: ! 3179: test al, FB_OVERLAP ! 3180: jz @F ! 3181: mov esi, offset FLAT:rdOverlap ! 3182: call and_from_save ! 3183: @@: ! 3184: ! 3185: pop ebp ! 3186: ! 3187: PLAIN_RET ! 3188: ! 3189: page ! 3190: ! 3191: ;--------------------------Private-Routine------------------------------; ! 3192: ; and_from_screen ! 3193: ; ! 3194: ; The screen is ANDed with the AND mask and placed into the work area ! 3195: ; ! 3196: ; Entry: ! 3197: ; ESI --> RECT_DATA structure to use ! 3198: ; EGA programmed for AND mode ! 3199: ; Returns: ! 3200: ; None ! 3201: ; Error Returns: ! 3202: ; No error return. ! 3203: ; Registers Preserved: ! 3204: ; BP ! 3205: ; Registers Destroyed: ! 3206: ; AX,BX,CX,DX,SI,DI,FLAGS ! 3207: ; Calls: ! 3208: ; None ! 3209: ; ! 3210: ;-----------------------------------------------------------------------; ! 3211: ! 3212: align 4 ! 3213: and_from_screen: ! 3214: ! 3215: .ERRNZ pd_rd ;Must be at offset 0 ! 3216: ! 3217: mov eax,lNextScan ! 3218: sub eax,WORK_WIDTH ! 3219: mov ulNextSrcScan,eax ;set the source advance offset ! 3220: ! 3221: ;-----------------------------------------------------------------------; ! 3222: ; Map in the source and destination banks. ! 3223: ;-----------------------------------------------------------------------; ! 3224: ! 3225: ; Map the proper bank into the source window for the top source scan line. ! 3226: ! 3227: mov edi,pdsurf ! 3228: mov edx,[esi].rd_ptlScreen.ptl_y ! 3229: mov ulCurrentTopScan,edx ;remember where the top source scan is ! 3230: cmp edx,[edi].dsurf_rcl2WindowClipS.yTop ;is AND top less than ! 3231: ; current source bank? ! 3232: jl short afscr_map_init_bank ;yes, map in proper bank ! 3233: cmp edx,[edi].dsurf_rcl2WindowClipS.yBottom ;AND top greater than ! 3234: ; current source bank? ! 3235: jl short afscr_init_bank_mapped ;no, proper bank already mapped ! 3236: afscr_map_init_bank: ! 3237: ! 3238: ; Map bank containing the top destination (screen) scan line into dest window. ! 3239: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 3240: ! 3241: ptrCall <dword ptr [edi].dsurf_pfnBankControl2Window>, \ ! 3242: <edi,edx,JustifyTop,MapSourceBank> ! 3243: ! 3244: afscr_init_bank_mapped: ! 3245: ! 3246: ! 3247: ; Map the cursor bank into the destination window. ! 3248: ! 3249: mov edx,ulPtrBankScan ;scan line at end of cursor work bank ! 3250: cmp edx,[edi].dsurf_rcl2WindowClipD.yTop ;is cursor scan less than ! 3251: ; current dest bank? ! 3252: jl short afscr_map_ptr_bank ;yes, map in proper bank ! 3253: cmp edx,[edi].dsurf_rcl2WindowClipD.yBottom ;cursor scan greater ! 3254: ; than current dest ! 3255: ; bank? ! 3256: jl short afscr_ptr_bank_mapped ;no, proper bank already mapped ! 3257: afscr_map_ptr_bank: ! 3258: ! 3259: ; Map cursor work bank into source window. ! 3260: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 3261: ! 3262: ptrCall <dword ptr [edi].dsurf_pfnBankControl2Window>, \ ! 3263: <edi,edx,JustifyBottom,MapDestBank> ! 3264: ! 3265: afscr_ptr_bank_mapped: ! 3266: ! 3267: ! 3268: ;-----------------------------------------------------------------------; ! 3269: ; Compute the screen address of this rectangle and get its size ! 3270: ;-----------------------------------------------------------------------; ! 3271: ! 3272: mov ebx,lNextScan ! 3273: imul ebx,[esi].rd_ptlScreen.ptl_y ! 3274: add ebx,[esi].rd_ptlScreen.ptl_x ;start source offset in bitmap ! 3275: movzx ecx,WORD PTR [esi].rd_sizb ;CH = scans to copy ! 3276: ; CL = bytes across to copy ! 3277: ! 3278: .ERRNZ sizb_cy-sizb_cx-1 ! 3279: ! 3280: ;-----------------------------------------------------------------------; ! 3281: ; Compute the offset from the start of the work area and the AND mask ! 3282: ; (it's the same value). ! 3283: ;-----------------------------------------------------------------------; ! 3284: ! 3285: xor eax,eax ! 3286: movzx edx,WORD PTR [esi].rd_ptbWork ;Get origin in work area ! 3287: xchg al,dh ;AX = ptbWork.ptb_y, DX = ptbWork.ptb_x ! 3288: add edx,eax ;*1 + X component ! 3289: add eax,eax ;*2 ! 3290: add eax,eax ;*4 ! 3291: add eax,edx ;*5 + X = start from work/mask ! 3292: mov edi,eax ! 3293: ! 3294: .ERRNZ WORK_WIDTH-5 ! 3295: ! 3296: ;-----------------------------------------------------------------------; ! 3297: ; To save incrementing the source pointer (BX), subtract the AND ! 3298: ; mask pointer off of it. Then use [BX][SI] for addressing into the ! 3299: ; source. As SI is incremented, BX will effectively be incremented. ! 3300: ; ! 3301: ; The source pointer will have to be adjusted by lNextScan-sizb_cx. ! 3302: ;-----------------------------------------------------------------------; ! 3303: ! 3304: mov esi,pAndXor ;Set address of AND mask ! 3305: add esi,edi ! 3306: add edi,pPtrWork ;start dest offset in bitmap ! 3307: mov eax,pdsurf ! 3308: add edi,[eax].dsurf_pvBitmapStart2WindowD ;start dest virtual addr ! 3309: add ebx,[eax].dsurf_pvBitmapStart2WindowS ;start src virtual addr ! 3310: sub ebx,esi ;fudge back so we get away with one ! 3311: ; increment ! 3312: ! 3313: ; Calculate the number of scans we'll do in this bank. ! 3314: ! 3315: mov edx,[eax].dsurf_rcl2WindowClipS.yBottom ! 3316: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 3317: ; the initial bank ! 3318: sub eax,eax ! 3319: mov al,ch ;total # of scans to copy ! 3320: cmp eax,edx ;can we handle all remaining scans in ! 3321: ; this bank? ! 3322: jb short @F ;yes ! 3323: mov eax,edx ;no, so we'll do the whole bank's worth ! 3324: @@: ! 3325: add ulCurrentTopScan,eax ;set top scan for next bank ! 3326: sub ch,al ;count this bank's scans off total ! 3327: mov byte ptr cjTotalScans,ch ;remember # of scans after this bank ! 3328: mov ch,al ;# of scans to do in this bank ! 3329: ! 3330: ; Compute the delta to the start of the next scanline of the AND mask ! 3331: ; and the work area, and the next scan of the screen ! 3332: ! 3333: sub eax,eax ! 3334: mov al,cl ! 3335: mov edx,WORK_WIDTH ! 3336: sub edx,eax ! 3337: ! 3338: ; Look up the loop entry point, and start ANDing. ! 3339: ! 3340: mov eax,and_from_screen_entry_table[eax*4] ;look up the loop entry ! 3341: push ebp ;preserve stack frame pointer ! 3342: mov ebp,ulNextSrcScan ;source offset to next scan ! 3343: jmp eax ;enter the ANDing loop ! 3344: ! 3345: .ERRNZ WORK_WIDTH-5 ! 3346: ;-----------------------------------------------------------------------; ! 3347: ; Register usage for the loop will be: ! 3348: ; ! 3349: ; EAX = loop entry address ! 3350: ; EBX = offset off of SI to the screen source ! 3351: ; CH = height ! 3352: ; EDX = offset to next scan of AND mask & work area ! 3353: ; ESI --> AND mask ! 3354: ; EDI --> Destination in work area ! 3355: ;-----------------------------------------------------------------------; ! 3356: ! 3357: align 4 ! 3358: and_from_screen_width_5: ! 3359: cmp al, [ebx][esi] ;Load latches from work area ! 3360: movsb ;AND from screen into work area ! 3361: and_from_screen_width_4: ! 3362: cmp al, [ebx][esi] ! 3363: movsb ! 3364: and_from_screen_width_3: ! 3365: cmp al, [ebx][esi] ! 3366: movsb ! 3367: and_from_screen_width_2: ! 3368: cmp al, [ebx][esi] ! 3369: movsb ! 3370: and_from_screen_width_1: ! 3371: cmp al, [ebx][esi] ! 3372: movsb ! 3373: and_from_screen_width_0: ! 3374: ! 3375: add esi,edx ;--> next AND mask ! 3376: add edi,edx ;--> next destination ! 3377: add ebx,ebp ;--> next source ! 3378: ! 3379: dec ch ;count down scans in this bank ! 3380: jz short @F ;bank is finished ! 3381: jmp eax ;do next scan in this bank ! 3382: ! 3383: align 4 ! 3384: @@: ! 3385: pop ebp ;restore stack frame pointer ! 3386: cmp byte ptr cjTotalScans,0 ;more lines (in next dest bank)? ! 3387: jz short afscr_done ;no, we're done ! 3388: ;advance to next dest bank and continue ! 3389: ; ANDing ! 3390: push eax ;preserve entry vector ! 3391: push edx ;preserve dest next scan ! 3392: mov eax,pdsurf ! 3393: sub ebx,[eax].dsurf_pvBitmapStart2WindowS ! 3394: ;calculate the source offset within the ! 3395: ; bitmap, because the start address is ! 3396: ; about to move ! 3397: mov edx,ulCurrentTopScan ! 3398: ! 3399: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 3400: ! 3401: ptrCall <dword ptr [eax].dsurf_pfnBankControl2Window>, \ ! 3402: <eax,edx,JustifyTop,MapSourceBank> ;map in the next source bank ! 3403: ! 3404: mov eax,pdsurf ! 3405: add ebx,[eax].dsurf_pvBitmapStart2WindowS ! 3406: ;add back in the bitmap start address ! 3407: ; to yield the virtual source address ! 3408: mov edx,[eax].dsurf_rcl2WindowClipS.yBottom ! 3409: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 3410: ; the new bank ! 3411: sub eax,eax ! 3412: mov al,byte ptr cjTotalScans ;remaining scan count ! 3413: cmp eax,edx ;can we handle all remaining scans in ! 3414: ; this bank? ! 3415: jb short @F ;yes ! 3416: mov eax,edx ;no, so we'll do the whole bank's worth ! 3417: @@: ! 3418: add ulCurrentTopScan,eax ;set top scan for next bank ! 3419: sub byte ptr cjTotalScans,al ;count this bank's scans off total ! 3420: mov ch,al ;# of scans to do in this bank ! 3421: ! 3422: pop edx ;restore dest next scan ! 3423: pop eax ;restore entry vector ! 3424: ! 3425: push ebp ;preserve stack frame pointer ! 3426: mov ebp,ulNextSrcScan ;source offset to next scan ! 3427: jmp eax ;do the next block of scans ! 3428: ! 3429: afscr_done: ! 3430: PLAIN_RET ! 3431: ! 3432: page ! 3433: ! 3434: ;--------------------------Private-Routine------------------------------; ! 3435: ; and_from_save ! 3436: ; ! 3437: ; The given area of the save buffer is ANDed into the work buffer ! 3438: ; ! 3439: ; Entry: ! 3440: ; ESI --> RECT_DATA structure to use ! 3441: ; EGA programmed for AND mode ! 3442: ; Returns: ! 3443: ; None ! 3444: ; Error Returns: ! 3445: ; No error return. ! 3446: ; Registers Preserved: ! 3447: ; EBP ! 3448: ; Registers Destroyed: ! 3449: ; EAX,EBX,ECX,EDX,ESI,EDI,EFLAGS ! 3450: ; Calls: ! 3451: ; None ! 3452: ; ! 3453: ;-----------------------------------------------------------------------; ! 3454: ! 3455: ;-----------------------------------------------------------------------; ! 3456: ; This is the key to wrapping in the buffer. It is a power of two, and ! 3457: ; in this case the entire size is 256 bytes. If it wasn't 256 bytes, an ! 3458: ; and mask could be used for wrapping. ! 3459: ;-----------------------------------------------------------------------; ! 3460: ! 3461: .ERRNZ SAVE_BUFFER_WIDTH-8 ! 3462: .ERRNZ SAVE_BUFFER_HEIGHT-32 ! 3463: .ERRNZ SAVE_BUFFER_WIDTH*SAVE_BUFFER_HEIGHT-256 ! 3464: ! 3465: align 4 ! 3466: and_from_save: ! 3467: ! 3468: .ERRNZ pd_rd ! 3469: ! 3470: ; See if we'll wrap in X. If so, split the operation into two parts ! 3471: ! 3472: movzx eax, WORD PTR [esi].rd_ptbWork ! 3473: movzx ecx, WORD PTR [esi].rd_ptbSave ! 3474: ! 3475: .ERRNZ ptb_y-ptb_x-1 ! 3476: ! 3477: movzx edx, WORD PTR [esi].rd_sizb ! 3478: ! 3479: .ERRNZ sizb_cy-sizb_cx-1 ! 3480: ! 3481: mov bl, cl ! 3482: add bl, dl ! 3483: sub bl, SAVE_BUFFER_WIDTH ;BL = is overhang ! 3484: jle and_from_save_do_last_pass ;No overhang ! 3485: ! 3486: sub dl, bl ;Set X extent for pass 1 ! 3487: mov bh, dl ;Need it for pass 2 ! 3488: push esi ;Must keep rectangle pointer around ! 3489: push ebx ! 3490: call and_from_save_do_a_pass ;Process first half ! 3491: pop ebx ! 3492: pop esi ! 3493: movzx eax, WORD PTR [esi].rd_ptbWork ! 3494: movzx ecx, WORD PTR [esi].rd_ptbSave ! 3495: ! 3496: .ERRNZ ptb_y-ptb_x-1 ! 3497: ! 3498: movzx edx, WORD PTR [esi].rd_sizb ! 3499: ! 3500: .ERRNZ sizb_cy-sizb_cx-1 ! 3501: ! 3502: add al, bh ;Move right in work area ! 3503: mov dl, bl ;Set new extent ! 3504: xor cl, cl ;X origin in save area is 0 ! 3505: ! 3506: and_from_save_do_last_pass: ! 3507: ! 3508: call and_from_save_do_a_pass ! 3509: ! 3510: PLAIN_RET ! 3511: ! 3512: ! 3513: ;--------------------------Private-Routine------------------------------; ! 3514: ; and_from_save ! 3515: ; ! 3516: ; Inner loop subroutine for and_from_save. ! 3517: ; ! 3518: ; Entry: ! 3519: ; AL = X dest start offset in work area (in bytes) ! 3520: ; AH = Y dest start offset in work area (in scans) ! 3521: ; CL = X source start offset in save area (in bytes) ! 3522: ; CH = Y source start offset in save area (in scans) ! 3523: ; Upper word of ECX *must* be 0! ! 3524: ; DL = width to AND (in bytes) ! 3525: ; DH = height to AND (in scans) ! 3526: ; EGA programmed for AND mode ! 3527: ; Returns: ! 3528: ; None ! 3529: ; Error Returns: ! 3530: ; No error return. ! 3531: ; Registers Preserved: ! 3532: ; EBP ! 3533: ; Registers Destroyed: ! 3534: ; EAX,EBX,ECX,EDX,ESI,EDI,EFLAGS ! 3535: ; Calls: ! 3536: ; None ! 3537: ; ! 3538: ;------------------------------------------------------------------------; ! 3539: ! 3540: align 4 ! 3541: and_from_save_do_a_pass: ! 3542: ! 3543: push ebp ;save stack frame pointer ! 3544: ! 3545: push eax ! 3546: push ecx ! 3547: push edx ! 3548: ! 3549: ; Map the cursor bank in as both the read window and the write window, because ! 3550: ; both the save and work areas are in the cursor bank. Note that we always know ! 3551: ; that the operation fits in a single bank, which simplifies things ! 3552: ; considerably. ! 3553: ! 3554: mov esi,pdsurf ! 3555: mov edx,ulPtrBankScan ;scan line at end of cursor work bank ! 3556: cmp edx,[esi].dsurf_rcl1WindowClip.yTop ;is cursor scan less than ! 3557: ; current bank? ! 3558: jl short afsav_map_ptr_bank ;yes, map in proper bank ! 3559: cmp edx,[esi].dsurf_rcl1WindowClip.yBottom ;cursor scan greater ! 3560: ; than current bank? ! 3561: jl short afsav_ptr_bank_mapped ;no, proper bank already mapped ! 3562: afsav_map_ptr_bank: ! 3563: ! 3564: ; Map cursor work bank into source window. ! 3565: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 3566: ! 3567: ptrCall <dword ptr [esi].dsurf_pfnBankControl>,<esi,edx,JustifyBottom> ! 3568: ! 3569: afsav_ptr_bank_mapped: ! 3570: ! 3571: pop edx ! 3572: pop ecx ! 3573: pop eax ! 3574: ! 3575: ; Compute the offset within the work area, which is also the offset from ! 3576: ; the start of the AND mask. ! 3577: ! 3578: xor ebx,ebx ! 3579: xchg bl,ah ! 3580: add eax,ebx ;*1 + X ! 3581: add ebx,ebx ;*2 ! 3582: add ebx,ebx ;*4 ! 3583: add ebx,eax ;*5 + X ! 3584: mov edi,pPtrWork ! 3585: add edi,ebx ;--> destination in work area relative ! 3586: ; to start of bitmap ! 3587: mov esi,[esi].dsurf_pvBitmapStart ;bitmap start virtual address ! 3588: push esi ;remember bitmap start for calculating ! 3589: ; save area pointer ! 3590: add edi,esi ;virtual addresss of work area ! 3591: ; destination start ! 3592: mov esi,pAndXor ! 3593: add esi,ebx ;--> AND mask ! 3594: ; Compute the offset within the save ! 3595: ; area. Note that this is relative to ! 3596: ; screen_buf ! 3597: xor ebx,ebx ! 3598: xchg bl,ch ;EBX = ptbSave.ptb_y, ! 3599: ; ECX = ptbSave.ptb_x ! 3600: lea ebx,[ebx*8+ecx] ;EBX = offset in save area ! 3601: ! 3602: .ERRNZ SAVE_BUFFER_WIDTH-8 ! 3603: ! 3604: ; Compute the adjustment to each scanline. ! 3605: ! 3606: mov cl,dl ;width in bytes to AND ! 3607: mov eax,WORK_WIDTH ! 3608: sub eax,ecx ;width in bytes to skip from end of one ! 3609: ; mask/work buffer scan to start of ! 3610: ; next ! 3611: ! 3612: ; Look up the address at which to enter the AND loop. ! 3613: ! 3614: mov ecx,and_from_save_entry_table[ecx*4] ! 3615: ! 3616: ; Now get things into the correct registers and enter the loop ! 3617: ! 3618: pop ebp ;get back bitmap start virtual address ! 3619: add ebp,pPtrSave ;point to the save area ! 3620: push ebp ;remember save area virtual address ! 3621: add ebp,ebx ;set correct save buffer address ! 3622: sub ebp,esi ;want to use [SI][BP] ! 3623: jmp ecx ;enter following code ! 3624: ! 3625: ;-----------------------------------------------------------------------; ! 3626: ; Register usage for the loop will be: ! 3627: ; ! 3628: ; EAX = delta to next scan of AND mask and work area ! 3629: ; EBX = offset in save area of scan start ! 3630: ; ECX = loop address ! 3631: ; DH = height in scans ! 3632: ; ESI --> AND mask ! 3633: ; EDI --> Destination in work area ! 3634: ; EBP = delta from SI to next byte of save buffer ! 3635: ;-----------------------------------------------------------------------; ! 3636: ! 3637: align 4 ! 3638: and_from_save_width_5: ! 3639: cmp al, [ebp][esi] ;Load latches from screen ! 3640: movsb ;AND to the work area ! 3641: and_from_save_width_4: ! 3642: cmp al, [ebp][esi] ! 3643: movsb ! 3644: and_from_save_width_3: ! 3645: cmp al, [ebp][esi] ! 3646: movsb ! 3647: and_from_save_width_2: ! 3648: cmp al, [ebp][esi] ! 3649: movsb ! 3650: and_from_save_width_1: ! 3651: cmp al, [ebp][esi] ! 3652: movsb ! 3653: and_from_save_width_0: ! 3654: ! 3655: .ERRNZ and_from_save_width_0-and_from_save_width_1-5 ! 3656: .ERRNZ and_from_save_width_1-and_from_save_width_2-5 ! 3657: .ERRNZ and_from_save_width_2-and_from_save_width_3-5 ! 3658: .ERRNZ and_from_save_width_3-and_from_save_width_4-5 ! 3659: .ERRNZ and_from_save_width_4-and_from_save_width_5-5 ! 3660: ! 3661: dec dh ! 3662: jz and_from_save_done ! 3663: add esi,eax ;--> next AND mask ! 3664: add edi,eax ;--> next work buffer scan ! 3665: add bl,SAVE_BUFFER_WIDTH ;--> compute address of next ! 3666: ; scan in the work area ! 3667: pop ebp ;restore save area pointer ! 3668: push ebp ;push it again, for next time ! 3669: add ebp,ebx ! 3670: sub ebp,esi ;Want to use SI for incrementing ! 3671: ! 3672: jmp ecx ! 3673: ! 3674: and_from_save_done: ! 3675: pop ebp ;clear pushed save area pointer ! 3676: ! 3677: pop ebp ;restore stack frame pointer ! 3678: ! 3679: PLAIN_RET ! 3680: ! 3681: page ! 3682: ! 3683: ;--------------------------Private-Routine------------------------------; ! 3684: ; copy_things_around ! 3685: ; ! 3686: ; Rectangles to be copied from the save area to the screen are ! 3687: ; processed, followed by the rectangles to be copied from the ! 3688: ; screen to the save area. ! 3689: ; ! 3690: ; Entry: ! 3691: ; AL = fbFlush ! 3692: ; Returns: ! 3693: ; None ! 3694: ; Error Returns: ! 3695: ; No error return. ! 3696: ; Registers Preserved: ! 3697: ; BP ! 3698: ; Registers Destroyed: ! 3699: ; AX,BX,CX,DX,SI,DI,BP,FLAGS ! 3700: ; Calls: ! 3701: ; copy_save_to_screen ! 3702: ; copy_screen_to_save ! 3703: ; ! 3704: ;-----------------------------------------------------------------------; ! 3705: ! 3706: align 4 ! 3707: copy_things_around: ! 3708: ! 3709: ;-----------------------------------------------------------------------; ! 3710: ; Program the EGA for COPY mode. This will be done using M_PROC_WRITE, ! 3711: ; M_DATA_READ, DR_???, and setting GRAF_BIT_MASK to 00. All but setting ! 3712: ; GRAF_BIT_MASK was done by save_hw_regs. All planes were also enabled ! 3713: ; for writing by save_hw_regs. ! 3714: ;-----------------------------------------------------------------------; ! 3715: ! 3716: mov ecx, eax ! 3717: mov dx, EGA_BASE + GRAF_ADDR ! 3718: mov ax, GRAF_BIT_MASK ! 3719: out dx, ax ;Disable all bits ! 3720: mov eax, ecx ! 3721: ! 3722: ;-----------------------------------------------------------------------; ! 3723: ; Process any copying from the save area to the screen. If FB_OLD_PTR ! 3724: ; is set, then there cannot be a FB_FLUSH_X or FB_FLUSH_Y. ! 3725: ;-----------------------------------------------------------------------; ! 3726: ! 3727: mov esi, ppdOld ! 3728: test al, FB_OLD_PTR ! 3729: jnz cta_copy_from_save ;The old rectangle goes ! 3730: test al, FB_FLUSH_X ! 3731: jz @F ! 3732: mov esi, offset FLAT:rdFlushX ! 3733: call copy_save_to_screen ! 3734: mov al, fbFlush ! 3735: @@: ! 3736: test al, FB_FLUSH_Y ! 3737: jz @F ! 3738: mov esi, offset FLAT:rdFlushY ! 3739: cta_copy_from_save: ! 3740: call copy_save_to_screen ! 3741: @@: ! 3742: ! 3743: ;-----------------------------------------------------------------------; ! 3744: ; Process any copying from the screen to the save area. If FB_NEW_PTR ! 3745: ; or FB_WORK_RECT is set, then there can't be a FB_FLUSH_X or FB_FLUSH_Y ! 3746: ;-----------------------------------------------------------------------; ! 3747: ! 3748: mov al, fbAndRead ! 3749: mov esi, ppdNew ! 3750: test al, FB_NEW_PTR ! 3751: jnz cta_copy_to_save ! 3752: mov esi, offset FLAT:rdWork ! 3753: test al, FB_WORK_RECT ! 3754: jnz cta_copy_to_save ! 3755: ! 3756: ; Some combination of FB_READ_X, FB_READ_Y ! 3757: ! 3758: test al, FB_READ_X ! 3759: jz @F ! 3760: mov esi, offset FLAT:rdReadX ! 3761: call copy_screen_to_save ! 3762: mov al, fbAndRead ! 3763: @@: ! 3764: test al, FB_READ_Y ! 3765: jz @F ! 3766: mov esi, offset FLAT:rdReadY ! 3767: cta_copy_to_save: ! 3768: call copy_screen_to_save ! 3769: @@: ! 3770: PLAIN_RET ! 3771: ! 3772: page ! 3773: ! 3774: ;--------------------------Private-Routine------------------------------; ! 3775: ; copy_save_to_screen ! 3776: ; ! 3777: ; The given rectangle is copied from the save area to the screen ! 3778: ; ! 3779: ; Entry: ! 3780: ; ESI --> RECT_DATA structure to use ! 3781: ; EGA programmed for COPY mode ! 3782: ; Returns: ! 3783: ; None ! 3784: ; Error Returns: ! 3785: ; No error return. ! 3786: ; Registers Preserved: ! 3787: ; EBP ! 3788: ; Registers Destroyed: ! 3789: ; EAX,EBX,ECX,EDX,ESI,EDI,EFLAGS ! 3790: ; Calls: ! 3791: ; None ! 3792: ; ! 3793: ;-----------------------------------------------------------------------; ! 3794: ! 3795: ;-----------------------------------------------------------------------; ! 3796: ; This is the key to wrapping in the buffer. It is a power of two, and ! 3797: ; in this case the entire size is 256 bytes. If it wasn't 256 bytes, an ! 3798: ; and mask could be used for wrapping. ! 3799: ;-----------------------------------------------------------------------; ! 3800: ! 3801: .ERRNZ SAVE_BUFFER_WIDTH-8 ! 3802: .ERRNZ SAVE_BUFFER_HEIGHT-32 ! 3803: .ERRNZ SAVE_BUFFER_WIDTH*SAVE_BUFFER_HEIGHT-256 ! 3804: ! 3805: align 4 ! 3806: copy_save_to_screen: ! 3807: ! 3808: .ERRNZ pd_rd ! 3809: ! 3810: ; Map the proper bank into the destination window for the top destination ! 3811: ; scan line. ! 3812: ! 3813: mov ebx,pdsurf ! 3814: mov edx,[esi].rd_ptlScreen.ptl_y ! 3815: mov ulCurrentTopScan,edx ;remember where the top dest scan is ! 3816: cmp edx,[ebx].dsurf_rcl2WindowClipD.yTop ;is copy top less than ! 3817: ; current dest bank? ! 3818: jl short sts_map_init_bank ;yes, map in proper bank ! 3819: cmp edx,[ebx].dsurf_rcl2WindowClipD.yBottom ;copy top greater than ! 3820: ; current dest bank? ! 3821: jl short sts_init_bank_mapped ;no, proper bank already mapped ! 3822: sts_map_init_bank: ! 3823: ! 3824: ; Map bank containing the top destination (screen) scan line into dest window. ! 3825: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 3826: ! 3827: ptrCall <dword ptr [ebx].dsurf_pfnBankControl2Window>, \ ! 3828: <ebx,edx,JustifyTop,MapDestBank> ! 3829: ! 3830: sts_init_bank_mapped: ! 3831: ! 3832: ! 3833: ; Map the cursor bank into the source window. ! 3834: ! 3835: mov edx,ulPtrBankScan ;scan line at end of cursor work bank ! 3836: cmp edx,[ebx].dsurf_rcl2WindowClipS.yTop ;is cursor scan less than ! 3837: ; current source bank? ! 3838: jl short sts_map_ptr_bank ;yes, map in proper bank ! 3839: cmp edx,[ebx].dsurf_rcl2WindowClipS.yBottom ;cursor scan greater ! 3840: ; than current source ! 3841: ; bank? ! 3842: jl short sts_ptr_bank_mapped ;no, proper bank already mapped ! 3843: sts_map_ptr_bank: ! 3844: ! 3845: ; Map cursor work bank into source window. ! 3846: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 3847: ! 3848: ptrCall <dword ptr [ebx].dsurf_pfnBankControl2Window>, \ ! 3849: <ebx,edx,JustifyBottom,MapSourceBank> ! 3850: ! 3851: sts_ptr_bank_mapped: ! 3852: ! 3853: ! 3854: ; Compute the virtual address of the save area. ! 3855: ! 3856: mov eax,pPtrSave ! 3857: add eax,[ebx].dsurf_pvBitmapStart2WindowS ;save area virtual addr ! 3858: mov pSaveAddr,eax ! 3859: ! 3860: ; Compute the screen address and delta to next scan of the screen. ! 3861: ! 3862: mov edi,lNextScan ! 3863: imul edi,[esi].rd_ptlScreen.ptl_y ! 3864: add edi,[esi].rd_ptlScreen.ptl_x ;start dest offset in bitmap ! 3865: add edi,[ebx].dsurf_pvBitmapStart2WindowD ;start dest virtual addr ! 3866: movzx edx,WORD PTR [esi].rd_sizb ! 3867: ! 3868: .ERRNZ sizb_cy-sizb_cx-1 ! 3869: ! 3870: ; Calculate the number of scans we'll do in this bank. ! 3871: ! 3872: mov ecx,[ebx].dsurf_rcl2WindowClipD.yBottom ! 3873: sub ecx,ulCurrentTopScan ;max # of scans that can be handled in ! 3874: ; the initial bank ! 3875: sub eax,eax ! 3876: mov al,dh ;total # of scans to copy ! 3877: cmp eax,ecx ;can we handle all remaining scans in ! 3878: ; this bank? ! 3879: jb short @F ;yes ! 3880: mov eax,ecx ;no, so we'll do the whole bank's worth ! 3881: @@: ! 3882: add ulCurrentTopScan,eax ;set top scan for next bank ! 3883: sub dh,al ;count this bank's scans off total ! 3884: mov byte ptr cjTotalScans,dh ;remember # of scans after this bank ! 3885: mov dh,al ;# of scans to do in this bank ! 3886: ! 3887: ; Calculate the offset from the end of one dest scan line to the next. ! 3888: ! 3889: mov al,dl ;width to copy in bytes ! 3890: neg eax ! 3891: add eax,lNextScan ;offset from end of one dest scan to start of ! 3892: ; next ! 3893: ! 3894: ; Compute the save area offset. ! 3895: ! 3896: movzx ecx,WORD PTR [esi].rd_ptbSave ! 3897: ! 3898: .ERRNZ ptb_y-ptb_x-1 ! 3899: ! 3900: xor ebx,ebx ! 3901: xchg bl,ch ! 3902: lea ebx,[ebx*8+ecx] ! 3903: ! 3904: .ERRNZ SAVE_BUFFER_WIDTH-8 ! 3905: ! 3906: ; Determine if any wrap will occur, and handle it if so. ! 3907: ! 3908: add cl,dl ;add extent (DL) to start X (CL) ! 3909: sub cl,SAVE_BUFFER_WIDTH ! 3910: jg short save_to_screen_wraps ;CL = amount of wrap ! 3911: ! 3912: ;-----------------------------------------------------------------------; ! 3913: ; The copy will not wrap, so we can get into some tighter code for it. ! 3914: ; ! 3915: ; Currently: ! 3916: ; EAX = delta to next destination scan ! 3917: ; EBX = offset into the save buffer ! 3918: ; DL = width of copy ! 3919: ; DH = height of copy ! 3920: ; EDI --> destination ! 3921: ;-----------------------------------------------------------------------; ! 3922: ! 3923: copy_save_next_scan: ! 3924: sub ecx,ecx ;prepare for loading CL in loop ! 3925: push ebp ;preserve stack frame pointer ! 3926: mov ebp,pSaveAddr ! 3927: copy_save_next_scan_loop: ! 3928: lea esi,[ebp+ebx] ! 3929: mov cl,dl ! 3930: rep movsb ! 3931: add bl,SAVE_BUFFER_WIDTH ! 3932: add edi,eax ! 3933: dec dh ! 3934: jnz copy_save_next_scan_loop ! 3935: ! 3936: pop ebp ;restore stack frame pointer ! 3937: cmp byte ptr cjTotalScans,0 ;more lines (in next dest bank)? ! 3938: jz short sts_done ;no, we're done ! 3939: ;advance to next dest bank and continue ! 3940: ; copying ! 3941: push eax ;preserve dest next scan ! 3942: push edx ;preserve width of copy ! 3943: mov esi,pdsurf ! 3944: sub edi,[esi].dsurf_pvBitmapStart2WindowD ! 3945: ;calculate the destination offset ! 3946: ; within the bitmap, because the start ! 3947: ; address is about to move ! 3948: mov edx,ulCurrentTopScan ! 3949: ! 3950: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 3951: ! 3952: ptrCall <dword ptr [esi].dsurf_pfnBankControl2Window>, \ ! 3953: <esi,edx,JustifyTop,MapDestBank> ;map in the next dest bank ! 3954: ! 3955: add edi,[esi].dsurf_pvBitmapStart2WindowD ! 3956: ;add back in the bitmap start address ! 3957: ; to yield the virtual dest address ! 3958: mov edx,[esi].dsurf_rcl2WindowClipD.yBottom ! 3959: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 3960: ; the new bank ! 3961: sub eax,eax ! 3962: mov al,byte ptr cjTotalScans ;remaining scan count ! 3963: cmp eax,edx ;can we handle all remaining scans in ! 3964: ; this bank? ! 3965: jb short @F ;yes ! 3966: mov eax,edx ;no, so we'll do the whole bank's worth ! 3967: @@: ! 3968: add ulCurrentTopScan,eax ;set top scan for next bank ! 3969: sub byte ptr cjTotalScans,al ;count this bank's scans off total ! 3970: pop edx ;restore copy width in DL ! 3971: mov dh,al ;# of scans to do in this bank ! 3972: pop eax ;restore dest next scan ! 3973: jmp copy_save_next_scan ;do the next block of scans ! 3974: ! 3975: sts_done: ! 3976: PLAIN_RET ! 3977: ! 3978: ;-----------------------------------------------------------------------; ! 3979: ; The copy will wrap, so we have to handle it as two copies ! 3980: ; ! 3981: ; Currently: ! 3982: ; EDI --> destination ! 3983: ; EAX = delta to next destination scan ! 3984: ; DL = width of copy ! 3985: ; DH = height of copy ! 3986: ; EBX = offset into the save buffer ! 3987: ; CL = amount of overflow ! 3988: ;-----------------------------------------------------------------------; ! 3989: ! 3990: align 4 ! 3991: save_to_screen_wraps: ! 3992: sub dl,cl ;set extent of first copy ! 3993: mov byte ptr jPostWrapWidth,cl ;set extent of second copy ! 3994: sub ecx,ecx ;prepare for loading CL in loop ! 3995: ! 3996: copy_save_next_scan_wrap_loop: ! 3997: mov esi,pSaveAddr ! 3998: add esi,ebx ! 3999: mov cl,dl ! 4000: rep movsb ! 4001: sub esi,SAVE_BUFFER_WIDTH ! 4002: mov cl,byte ptr jPostWrapWidth ! 4003: rep movsb ! 4004: add bl,SAVE_BUFFER_WIDTH ! 4005: add edi,eax ! 4006: dec dh ! 4007: jnz copy_save_next_scan_wrap_loop ! 4008: ! 4009: cmp byte ptr cjTotalScans,0 ;more lines (in next dest bank)? ! 4010: jz short sts_done ;no, we're done ! 4011: ;advance to next dest bank and continue ! 4012: ; copying ! 4013: push eax ;preserve dest next scan ! 4014: push edx ;preserve width of copy ! 4015: mov esi,pdsurf ! 4016: sub edi,[esi].dsurf_pvBitmapStart2WindowD ! 4017: ;calculate the destination offset ! 4018: ; within the bitmap, because the start ! 4019: ; address is about to move ! 4020: mov edx,ulCurrentTopScan ! 4021: ! 4022: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 4023: ! 4024: ptrCall <dword ptr [esi].dsurf_pfnBankControl2Window>, \ ! 4025: <esi,edx,JustifyTop,MapDestBank> ;map in the next dest bank ! 4026: ! 4027: add edi,[esi].dsurf_pvBitmapStart2WindowD ! 4028: ;add back in the bitmap start address ! 4029: ; to yield the virtual dest address ! 4030: mov edx,[esi].dsurf_rcl2WindowClipD.yBottom ! 4031: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 4032: ; the new bank ! 4033: sub eax,eax ! 4034: mov al,byte ptr cjTotalScans ;remaining scan count ! 4035: cmp eax,edx ;can we handle all remaining scans in ! 4036: ; this bank? ! 4037: jb short @F ;yes ! 4038: mov eax,edx ;no, so we'll do the whole bank's worth ! 4039: @@: ! 4040: add ulCurrentTopScan,eax ;set top scan for next bank ! 4041: sub byte ptr cjTotalScans,al ;count this bank's scans off total ! 4042: pop edx ;restore copy width in DL ! 4043: mov dh,al ;# of scans to do in this bank ! 4044: pop eax ;restore dest next scan ! 4045: sub ecx,ecx ;prepare for loading CL in loop ! 4046: jmp copy_save_next_scan_wrap_loop ;do the next block of scans ! 4047: ! 4048: page ! 4049: ! 4050: ;--------------------------Private-Routine------------------------------; ! 4051: ; copy_screen_to_save ! 4052: ; ! 4053: ; The given rectangle is copied from the screen to the save area ! 4054: ; ! 4055: ; Entry: ! 4056: ; ESI --> RECT_DATA structure to use ! 4057: ; EGA programmed for COPY mode ! 4058: ; Returns: ! 4059: ; None ! 4060: ; Error Returns: ! 4061: ; No error return. ! 4062: ; Registers Preserved: ! 4063: ; EBP ! 4064: ; Registers Destroyed: ! 4065: ; EAX,EBX,ECX,EDX,ESI,EDI,EFLAGS ! 4066: ; Calls: ! 4067: ; None ! 4068: ; ! 4069: ;-----------------------------------------------------------------------; ! 4070: ! 4071: ! 4072: ;-----------------------------------------------------------------------; ! 4073: ; This is the key to wrapping in the buffer. It is a power of two, and ! 4074: ; in this case the entire size is 256 bytes. If it wasn't 256 bytes, an ! 4075: ; and mask could be used for wrapping. ! 4076: ;-----------------------------------------------------------------------; ! 4077: ! 4078: .ERRNZ SAVE_BUFFER_WIDTH-8 ! 4079: .ERRNZ SAVE_BUFFER_HEIGHT-32 ! 4080: .ERRNZ SAVE_BUFFER_WIDTH*SAVE_BUFFER_HEIGHT-256 ! 4081: ! 4082: align 4 ! 4083: copy_screen_to_save: ! 4084: ! 4085: .ERRNZ pd_rd ! 4086: ! 4087: ; Map the proper bank into the source window for the top source scan line. ! 4088: ! 4089: mov ebx,pdsurf ! 4090: mov edx,[esi].rd_ptlScreen.ptl_y ! 4091: mov ulCurrentTopScan,edx ;remember where the top source scan is ! 4092: cmp edx,[ebx].dsurf_rcl2WindowClipS.yTop ;is copy top less than ! 4093: ; current source bank? ! 4094: jl short scrts_map_init_bank ;yes, map in proper bank ! 4095: cmp edx,[ebx].dsurf_rcl2WindowClipS.yBottom ;copy top greater than ! 4096: ; current source bank? ! 4097: jl short scrts_init_bank_mapped ;no, proper bank already mapped ! 4098: scrts_map_init_bank: ! 4099: ! 4100: ; Map bank containing the top source (screen) scan line into source window. ! 4101: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 4102: ! 4103: ptrCall <dword ptr [ebx].dsurf_pfnBankControl2Window>, \ ! 4104: <ebx,edx,JustifyTop,MapSourceBank> ! 4105: ! 4106: scrts_init_bank_mapped: ! 4107: ! 4108: ! 4109: ; Map the cursor bank into the dest window. ! 4110: ! 4111: mov edx,ulPtrBankScan ;scan line at end of cursor work bank ! 4112: cmp edx,[ebx].dsurf_rcl2WindowClipD.yTop ;is cursor scan less than ! 4113: ; current dest bank? ! 4114: jl short scrts_map_ptr_bank ;yes, map in proper bank ! 4115: cmp edx,[ebx].dsurf_rcl2WindowClipD.yBottom ;cursor scan greater ! 4116: ; than current dest ! 4117: ; bank? ! 4118: jl short scrts_ptr_bank_mapped ;no, proper bank already mapped ! 4119: scrts_map_ptr_bank: ! 4120: ! 4121: ; Map cursor work bank into dest window. ! 4122: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 4123: ! 4124: ptrCall <dword ptr [ebx].dsurf_pfnBankControl2Window>, \ ! 4125: <ebx,edx,JustifyBottom,MapDestBank> ! 4126: ! 4127: scrts_ptr_bank_mapped: ! 4128: ! 4129: ! 4130: ; Compute the virtual address of the save area. ! 4131: ! 4132: mov eax,pPtrSave ! 4133: add eax,[ebx].dsurf_pvBitmapStart2WindowD ;save area virtual addr ! 4134: mov pSaveAddr,eax ! 4135: ! 4136: ; Compute the source screen address and delta to next scan of the screen. ! 4137: ! 4138: mov edi,lNextScan ! 4139: imul edi,[esi].rd_ptlScreen.ptl_y ! 4140: add edi,[esi].rd_ptlScreen.ptl_x ;start source offset in bitmap ! 4141: add edi,[ebx].dsurf_pvBitmapStart2WindowS ;start source virtual ! 4142: ; address ! 4143: movzx edx,WORD PTR [esi].rd_sizb ! 4144: ! 4145: .ERRNZ sizb_cy-sizb_cx-1 ! 4146: ! 4147: ; Calculate the number of scans we'll do in this bank. ! 4148: ! 4149: mov ecx,[ebx].dsurf_rcl2WindowClipS.yBottom ! 4150: sub ecx,ulCurrentTopScan ;max # of scans that can be handled in ! 4151: ; the initial bank ! 4152: sub eax,eax ! 4153: mov al,dh ;total # of scans to copy ! 4154: cmp eax,ecx ;can we handle all remaining scans in ! 4155: ; this bank? ! 4156: jb short @F ;yes ! 4157: mov eax,ecx ;no, so we'll do the whole bank's worth ! 4158: @@: ! 4159: add ulCurrentTopScan,eax ;set top scan for next bank ! 4160: sub dh,al ;count this bank's scans off total ! 4161: mov byte ptr cjTotalScans,dh ;remember # of scans after this bank ! 4162: mov dh,al ;# of scans to do in this bank ! 4163: ! 4164: ; Calculate the offset from the end of one source scan line to the next. ! 4165: ! 4166: mov al,dl ;width to copy in bytes ! 4167: neg eax ! 4168: add eax,lNextScan ;offset from end of one source scan to start of ! 4169: ; next ! 4170: ! 4171: ; Compute the save area offset. ! 4172: ! 4173: movzx ecx,WORD PTR [esi].rd_ptbSave ! 4174: ! 4175: .ERRNZ ptb_y-ptb_x-1 ! 4176: ! 4177: xor ebx,ebx ! 4178: xchg bl,ch ! 4179: lea ebx,[ebx*8+ecx] ! 4180: ! 4181: .ERRNZ SAVE_BUFFER_WIDTH-8 ! 4182: ! 4183: mov esi,edi ;ESI -> initial source byte ! 4184: ! 4185: ; Determine if any wrap will occur, and handle it if so. ! 4186: ! 4187: add cl,dl ;add extent (DL) to start X (CL) ! 4188: sub cl,SAVE_BUFFER_WIDTH ! 4189: jg short screen_to_save_wraps ;CL = amount of wrap ! 4190: ! 4191: ;-----------------------------------------------------------------------; ! 4192: ; The copy will not wrap, so we can get into some tighter code for it. ! 4193: ; ! 4194: ; Currently: ! 4195: ; EAX = delta to next source scan ! 4196: ; EBX = offset into the save buffer ! 4197: ; DL = width of copy ! 4198: ; DH = height of copy ! 4199: ; ESI --> source ! 4200: ;-----------------------------------------------------------------------; ! 4201: ! 4202: copy_screen_next_scan: ! 4203: sub ecx,ecx ;prepare for loading CL in loop ! 4204: push ebp ;preserve stack frame pointer ! 4205: mov ebp,pSaveAddr ! 4206: copy_screen_next_scan_loop: ! 4207: lea edi,[ebp+ebx] ! 4208: mov cl,dl ! 4209: rep movsb ! 4210: add bl,SAVE_BUFFER_WIDTH ! 4211: add esi,eax ! 4212: dec dh ! 4213: jnz copy_screen_next_scan_loop ! 4214: ! 4215: pop ebp ;restore stack frame pointer ! 4216: cmp byte ptr cjTotalScans,0 ;more lines (in next source bank)? ! 4217: jz short scrts_done ;no, we're done ! 4218: ;advance to next source bank and ! 4219: ; continue copying ! 4220: push eax ;preserve source next scan ! 4221: push edx ;preserve width of copy ! 4222: mov edi,pdsurf ! 4223: sub esi,[edi].dsurf_pvBitmapStart2WindowS ! 4224: ;calculate the source offset ! 4225: ; within the bitmap, because the start ! 4226: ; address is about to move ! 4227: mov edx,ulCurrentTopScan ! 4228: ! 4229: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 4230: ! 4231: ptrCall <dword ptr [edi].dsurf_pfnBankControl2Window>, \ ! 4232: <edi,edx,JustifyTop,MapSourceBank> ;map in the next source bank ! 4233: ! 4234: add esi,[edi].dsurf_pvBitmapStart2WindowS ! 4235: ;add back in the bitmap start address ! 4236: ; to yield the virtual source address ! 4237: mov edx,[edi].dsurf_rcl2WindowClipS.yBottom ! 4238: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 4239: ; the new bank ! 4240: sub eax,eax ! 4241: mov al,byte ptr cjTotalScans ;remaining scan count ! 4242: cmp eax,edx ;can we handle all remaining scans in ! 4243: ; this bank? ! 4244: jb short @F ;yes ! 4245: mov eax,edx ;no, so we'll do the whole bank's worth ! 4246: @@: ! 4247: add ulCurrentTopScan,eax ;set top scan for next bank ! 4248: sub byte ptr cjTotalScans,al ;count this bank's scans off total ! 4249: pop edx ;restore copy width in DL ! 4250: mov dh,al ;# of scans to do in this bank ! 4251: pop eax ;restore source next scan ! 4252: jmp copy_screen_next_scan ;do the next block of scans ! 4253: ! 4254: scrts_done: ! 4255: PLAIN_RET ! 4256: ! 4257: ;-----------------------------------------------------------------------; ! 4258: ; The copy will wrap, so we have to handle it as two copies ! 4259: ; ! 4260: ; Currently: ! 4261: ; EAX = delta to next source scan ! 4262: ; EBX = offset into the save buffer ! 4263: ; CL = amount of overflow ! 4264: ; DL = width of copy ! 4265: ; DH = height of copy ! 4266: ; ESI --> source ! 4267: ;-----------------------------------------------------------------------; ! 4268: ! 4269: align 4 ! 4270: screen_to_save_wraps: ! 4271: sub dl,cl ;set extent of first copy ! 4272: mov byte ptr jPostWrapWidth,cl ;set extent of second copy ! 4273: sub ecx,ecx ;prepare for loading CL in loop ! 4274: ! 4275: copy_screen_next_scan_wrap_loop: ! 4276: mov edi,pSaveAddr ! 4277: add edi,ebx ! 4278: mov cl,dl ! 4279: rep movsb ! 4280: sub edi,SAVE_BUFFER_WIDTH ! 4281: mov cl,byte ptr jPostWrapWidth ! 4282: rep movsb ! 4283: add bl,SAVE_BUFFER_WIDTH ! 4284: add esi,eax ! 4285: dec dh ! 4286: jnz copy_screen_next_scan_wrap_loop ! 4287: ! 4288: cmp byte ptr cjTotalScans,0 ;more lines (in next source bank)? ! 4289: jz short scrts_done ;no, we're done ! 4290: ;advance to next source bank and ! 4291: ; continue copying ! 4292: push eax ;preserve source next scan ! 4293: push edx ;preserve width of copy ! 4294: mov edi,pdsurf ! 4295: sub esi,[edi].dsurf_pvBitmapStart2WindowS ! 4296: ;calculate the source offset ! 4297: ; within the bitmap, because the start ! 4298: ; address is about to move ! 4299: mov edx,ulCurrentTopScan ! 4300: ! 4301: ; Note: EBX, ESI, and EDI preserved, according to C calling conventions. ! 4302: ! 4303: ptrCall <dword ptr [edi].dsurf_pfnBankControl2Window>, \ ! 4304: <edi,edx,JustifyTop,MapSourceBank> ;map in the next source bank ! 4305: ! 4306: add esi,[edi].dsurf_pvBitmapStart2WindowS ! 4307: ;add back in the bitmap start address ! 4308: ; to yield the virtual source address ! 4309: mov edx,[edi].dsurf_rcl2WindowClipS.yBottom ! 4310: sub edx,ulCurrentTopScan ;max # of scans that can be handled in ! 4311: ; the new bank ! 4312: sub eax,eax ! 4313: mov al,byte ptr cjTotalScans ;remaining scan count ! 4314: cmp eax,edx ;can we handle all remaining scans in ! 4315: ; this bank? ! 4316: jb short @F ;yes ! 4317: mov eax,edx ;no, so we'll do the whole bank's worth ! 4318: @@: ! 4319: add ulCurrentTopScan,eax ;set top scan for next bank ! 4320: sub byte ptr cjTotalScans,al ;count this bank's scans off total ! 4321: pop edx ;restore copy width in DL ! 4322: mov dh,al ;# of scans to do in this bank ! 4323: pop eax ;restore source next scan ! 4324: sub ecx,ecx ;prepare for loading CL in loop ! 4325: jmp copy_screen_next_scan_wrap_loop ;do the next block of scans ! 4326: ! 4327: endProc vDrawPointer ! 4328: ! 4329: ;-----------------------------------------------------------------------; ! 4330: ; vDIB4Convert* ! 4331: ; ! 4332: ; Converts the specified number of source 4 bpp bits into the ! 4333: ; buffer. These are support routines for vDIB4Planer, where a ! 4334: ; source byte converts into two aligned bits ! 4335: ; ! 4336: ; Entry: ! 4337: ; EAX 31:8 = 0 ! 4338: ; EBP --> Bit conversion table ! 4339: ; ESI --> Source bitmap ! 4340: ; EDI --> Planer destination ! 4341: ; ECX = Loop count ! 4342: ; Exit: ! 4343: ; EBP --> Bit conversion table ! 4344: ; ESI --> Next source byte ! 4345: ; EDI --> Next planer destination ! 4346: ; EDX = Last planer byte accumulated ! 4347: ; Registers Destroyed: ! 4348: ; EAX,ECX,EDX ! 4349: ; Registers Preserved: ! 4350: ;-----------------------------------------------------------------------; ! 4351: extrn aulDefBitMapping:dword ! 4352: ! 4353: align 4 ! 4354: vDIB4Convert8 proc ! 4355: lodsb ! 4356: mov ebx,eax ! 4357: shr eax,4 ! 4358: and ebx,00001111b ! 4359: mov edx,[ebp][eax*4] ! 4360: shl edx,1 ! 4361: or edx,[ebp][ebx*4] ! 4362: vDIB4Convert6: ! 4363: lodsb ! 4364: shl edx,1 ! 4365: mov ebx,eax ! 4366: shr eax,4 ! 4367: and ebx,00001111b ! 4368: or edx,[ebp][eax*4] ! 4369: shl edx,1 ! 4370: or edx,[ebp][ebx*4] ! 4371: vDIB4Convert4: ! 4372: lodsb ! 4373: shl edx,1 ! 4374: mov ebx,eax ! 4375: shr eax,4 ! 4376: and ebx,00001111b ! 4377: or edx,[ebp][eax*4] ! 4378: shl edx,1 ! 4379: or edx,[ebp][ebx*4] ! 4380: vDIB4Convert2: ! 4381: lodsb ! 4382: shl edx,1 ! 4383: mov ebx,eax ! 4384: shr eax,4 ! 4385: and ebx,00001111b ! 4386: or edx,[ebp][eax*4] ! 4387: shl edx,1 ! 4388: or edx,[ebp][ebx*4] ! 4389: mov [edi][4*0],dl ! 4390: mov [edi][4*1],dh ! 4391: ror edx,16 ! 4392: mov [edi][4*2],dl ! 4393: mov [edi][4*3],dh ! 4394: inc edi ! 4395: dec ecx ! 4396: jnz vDIB4Convert8 ! 4397: ret ! 4398: ! 4399: vDIB4Convert8 endp ! 4400: ! 4401: page ! 4402: ;-----------------------------------------------------------------------; ! 4403: ; vConvertDIBPointer ! 4404: ; ! 4405: ; Converts the passed DIB into a planer format, then synthesizes the ! 4406: ; XOR mask. ! 4407: ; ! 4408: ; Entry: ! 4409: ; ESI --> Color Bits, 4bpp format ! 4410: ; EDI --> Planer destination ! 4411: ; ECX = Bitmap height ! 4412: ; EBP = pulXlate for color mapping ! 4413: ; DX = wFlags ! 4414: ; Exit: ! 4415: ; None ! 4416: ; Registers Destroyed: ! 4417: ; EAX,EBX,ECX,EDX,ESI,EDI,Flags ! 4418: ; Registers Preserved: ! 4419: ;-----------------------------------------------------------------------; ! 4420: ! 4421: align 4 ! 4422: vConvertDIBPointer proc ! 4423: ! 4424: ; Convert the scans as necessary into planer format. We'll assume a fixed ! 4425: ; size of 32 bits wide ! 4426: ! 4427: push edx ;Save ! 4428: push edi ! 4429: @@: ! 4430: push ecx ;Save loop count ! 4431: push edi ;Save destination pointer ! 4432: push esi ;Save source pointer ! 4433: mov ecx,PTR_WIDTH ! 4434: xor eax,eax ;Needs to be zero initialized ! 4435: call vDIB4Convert8 ;Convert one scan ! 4436: pop esi ! 4437: pop edi ! 4438: pop ecx ! 4439: add edi,16 ;--> next destination scan ! 4440: add esi,16 ;--> next source scan ! 4441: dec ecx ! 4442: jnz @B ! 4443: ! 4444: ; The bitmap has been converted into planer format. If it needs flipping, ! 4445: ; then flip it ! 4446: ! 4447: pop esi ;Start of plane 0 ! 4448: pop edx ! 4449: or dl,dl ! 4450: js skipping_first_invert ;Color bitmap is TOPDOWN ! 4451: mov ecx,PTR_HEIGHT / 2 ;* scans to flip ! 4452: lea edi,[esi][PTR_HEIGHT*4*4] ;--> last scan ! 4453: ! 4454: flip_next_scan: ! 4455: sub edi,16 ;decrement target pointer ! 4456: ! 4457: mov eax,[esi][00h] ;Load ! 4458: xchg [edi][00h],eax ;Swap ! 4459: mov [esi][00h],eax ;Save ! 4460: ! 4461: mov eax,[esi][04h] ;Load ! 4462: xchg [edi][04h],eax ;Swap ! 4463: mov [esi][04h],eax ;Save ! 4464: ! 4465: mov eax,[esi][08h] ;Load ! 4466: xchg [edi][08h],eax ;Swap ! 4467: mov [esi][08h],eax ;Save ! 4468: ! 4469: mov eax,[esi][0Ch] ;Load ! 4470: xchg [edi][0Ch],eax ;Swap ! 4471: mov [esi][0Ch],eax ;Save ! 4472: ! 4473: add esi,16 ;increment source pointer ! 4474: loop flip_next_scan ! 4475: ! 4476: skipping_first_invert: ! 4477: ret ! 4478: ! 4479: vConvertDIBPointer endp ! 4480: ! 4481: _TEXT$01 ends ! 4482: ! 4483: end ! 4484:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.