|
|
1.1 ! root 1: ;---------------------------Module-Header------------------------------; ! 2: ; Module Name: fasttext.asm ! 3: ; ! 4: ; Copyright (c) 1992 Microsoft Corporation ! 5: ;-----------------------------------------------------------------------; ! 6: ;-----------------------------------------------------------------------; ! 7: ; VOID vFastText(GLYPHPOS * pGlyphPos, ULONG ulGlyphCount, PBYTE pTempBuffer, ! 8: ; ULONG ulBufDelta, ULONG ulCharInc, DEVSURF * pdsurf, ! 9: ; RECTL * prclText, RECTL * prclOpaque, INT iFgColor, ! 10: ; INT iBgColor, ULONG fDrawFlags, RECTL * prclClip); ! 11: ; pGlyphPos - ! 12: ; ulGlyphCount - # of glyphs to draw. Must never be 0. ! 13: ; pTempBuffer - ! 14: ; ulBufDelta - ! 15: ; ulCharInc - ! 16: ; pdsurf - ! 17: ; prclText - ! 18: ; prclOpaque - ! 19: ; iFgColor - ! 20: ; iBgColor - ! 21: ; fDrawFlags - ! 22: ; prclClip - ! 23: ; ! 24: ; Performs accelerated proportional text drawing. ! 25: ; ! 26: ;-----------------------------------------------------------------------; ! 27: ; ! 28: ; Note: Assumes the text rectangle has a positive height and width. Will ! 29: ; not work properly if this is not the case. ! 30: ; ! 31: ; Note: The opaquing rectangle is assumed to match the text bounding ! 32: ; rectangle exactly; prclOpaque is used only to determine whether or ! 33: ; not opaquing is required. ! 34: ; ! 35: ; Note: Handles clipping only for opaque text. ! 36: ; ! 37: ; Note: For opaque text, handles only unclipped and rectangle-clipped ! 38: ; cases, not complex-clipped. ! 39: ; ! 40: ; Note: For maximum performance, we should not bother to draw fully- ! 41: ; clipped characters to the temp buffer. ! 42: ; ! 43: ; Note: We do not yet support extra rectangles (underlines). We should. ! 44: ; ! 45: ; Note: We do not handle clipping or bank spanning in the very fast ! 46: ; byte-wide-aligned-fixed-pitch console text. This would be an ! 47: ; opportunity for somewhat faster console text performance. ! 48: ; ! 49: ;-----------------------------------------------------------------------; ! 50: ; ! 51: ; Set LOOP_UNROLL_SHIFT to the log2 of the number of times you want to unroll ! 52: ; loops in this module that are implemented with the unrolling macros. For ! 53: ; example, LOOP_UNROLL_SHIFT of 3 yields 2**3 = 8 times unrolling. This is ! 54: ; the only thing you need to change to control unrolling. ! 55: ! 56: LOOP_UNROLL_SHIFT equ 2 ! 57: ! 58: ;-----------------------------------------------------------------------; ! 59: ! 60: comment $ ! 61: ! 62: The overall approach of this module is to draw the text into a system ! 63: memory buffer, then copy the buffer to the screen a word at a time ! 64: using write mode 3 so that no OUTs and a minimum of display memory reads ! 65: are required. ! 66: ! 67: commend $ ! 68: ! 69: .386 ! 70: ! 71: ifndef DOS_PLATFORM ! 72: .model small,c ! 73: else ! 74: ifdef STD_CALL ! 75: .model small,c ! 76: else ! 77: .model small,pascal ! 78: endif; STD_CALL ! 79: endif; DOS_PLATFORM ! 80: ! 81: assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT ! 82: assume fs:nothing,gs:nothing ! 83: ! 84: .xlist ! 85: include stdcall.inc ;calling convention cmacros ! 86: include i386\egavga.inc ! 87: include i386\strucs.inc ! 88: include i386\unroll.inc ! 89: ! 90: .list ! 91: ! 92: ;-----------------------------------------------------------------------; ! 93: ! 94: .data ! 95: ! 96: ;-----------------------------------------------------------------------; ! 97: ; Tables used to branch into glyph-drawing optimizations. ! 98: ; ! 99: ; Handles narrow (1-4 bytes wide) glyph drawing, for case where initial byte ! 100: ; should be MOVed even if it's not aligned (intended for use in drawing the ! 101: ; first glyph in a string). Table format is: ! 102: ; Bits 3-2: dest width ! 103: ; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte ! 104: ; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned) ! 105: align 4 ! 106: MovInitialTableNarrow label dword ! 107: dd draw_prop_done ;0 wide ! 108: dd draw_prop_done ;0 wide ! 109: dd draw_prop_done ;0 wide ! 110: dd draw_prop_done ;0 wide ! 111: dd mov_first_1_wide_rotated_need_last ;nonalign, 1 wide, need last ! 112: dd mov_first_1_wide_unrotated ;aligned, 1 wide ! 113: dd mov_first_1_wide_rotated_no_last ;nonalign, 1 wide, no last ! 114: dd mov_first_1_wide_unrotated ;aligned, 1 wide ! 115: dd mov_first_2_wide_rotated_need_last ;nonalign, 2 wide, need last ! 116: dd mov_first_2_wide_unrotated ;aligned, 2 wide ! 117: dd mov_first_2_wide_rotated_no_last ;nonalign, 2 wide, no last ! 118: dd mov_first_2_wide_unrotated ;aligned, 2 wide ! 119: dd mov_first_3_wide_rotated_need_last ;nonalign, 3 wide, need last ! 120: dd mov_first_3_wide_unrotated ;aligned, 3 wide ! 121: dd mov_first_3_wide_rotated_no_last ;nonalign, 3 wide, no last ! 122: dd mov_first_3_wide_unrotated ;aligned, 3 wide ! 123: dd mov_first_4_wide_rotated_need_last ;nonalign, 4 wide, need last ! 124: dd mov_first_4_wide_unrotated ;aligned, 4 wide ! 125: dd mov_first_4_wide_rotated_no_last ;nonalign, 4 wide, no last ! 126: dd mov_first_4_wide_unrotated ;aligned, 4 wide ! 127: ! 128: ; Handles narrow (1-4 bytes wide) glyph drawing, for case where initial byte ! 129: ; ORed if it's not aligned (intended for use in drawing all but the first glyph ! 130: ; in a string). Table format is: ! 131: ; Bits 3-2: dest width ! 132: ; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte ! 133: ; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned) ! 134: align 4 ! 135: OrInitialTableNarrow label dword ! 136: dd draw_prop_done ;0 wide ! 137: dd draw_prop_done ;0 wide ! 138: dd draw_prop_done ;0 wide ! 139: dd draw_prop_done ;0 wide ! 140: dd or_first_1_wide_rotated_need_last ;nonalign, 1 wide, need last ! 141: dd mov_first_1_wide_unrotated ;aligned, 1 wide ! 142: dd or_first_1_wide_rotated_no_last ;nonalign, 1 wide, no last ! 143: dd mov_first_1_wide_unrotated ;aligned, 1 wide ! 144: dd or_first_2_wide_rotated_need_last ;nonalign, 2 wide, need last ! 145: dd mov_first_2_wide_unrotated ;aligned, 2 wide ! 146: dd or_first_2_wide_rotated_no_last ;nonalign, 2 wide, no last ! 147: dd mov_first_2_wide_unrotated ;aligned, 2 wide ! 148: dd or_first_3_wide_rotated_need_last ;nonalign, 3 wide, need last ! 149: dd mov_first_3_wide_unrotated ;aligned, 3 wide ! 150: dd or_first_3_wide_rotated_no_last ;nonalign, 3 wide, no last ! 151: dd mov_first_3_wide_unrotated ;aligned, 3 wide ! 152: dd or_first_4_wide_rotated_need_last ;nonalign, 4 wide, need last ! 153: dd mov_first_4_wide_unrotated ;aligned, 4 wide ! 154: dd or_first_4_wide_rotated_no_last ;nonalign, 4 wide, no last ! 155: dd mov_first_4_wide_unrotated ;aligned, 4 wide ! 156: ! 157: ; Handles narrow (1-4 bytes wide) glyph drawing, for case where all bytes ! 158: ; should be ORed (intended for use in drawing potentially overlapping glyphs). ! 159: ; Table format is: ! 160: ; Bits 3-2: dest width ! 161: ; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte ! 162: ; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned) ! 163: align 4 ! 164: OrAllTableNarrow label dword ! 165: dd draw_prop_done ;0 wide ! 166: dd draw_prop_done ;0 wide ! 167: dd draw_prop_done ;0 wide ! 168: dd draw_prop_done ;0 wide ! 169: dd or_all_1_wide_rotated_need_last ;nonalign, 1 wide, need last ! 170: dd or_all_1_wide_unrotated ;aligned, 1 wide ! 171: dd or_all_1_wide_rotated_no_last ;nonalign, 1 wide, no last ! 172: dd or_all_1_wide_unrotated ;aligned, 1 wide ! 173: dd or_all_2_wide_rotated_need_last ;nonalign, 2 wide, need last ! 174: dd or_all_2_wide_unrotated ;aligned, 2 wide ! 175: dd or_all_2_wide_rotated_no_last ;nonalign, 2 wide, no last ! 176: dd or_all_2_wide_unrotated ;aligned, 2 wide ! 177: dd or_all_3_wide_rotated_need_last ;nonalign, 3 wide, need last ! 178: dd or_all_3_wide_unrotated ;aligned, 3 wide ! 179: dd or_all_3_wide_rotated_no_last ;nonalign, 3 wide, no last ! 180: dd or_all_3_wide_unrotated ;aligned, 3 wide ! 181: dd or_all_4_wide_rotated_need_last ;nonalign, 4 wide, need last ! 182: dd or_all_4_wide_unrotated ;aligned, 4 wide ! 183: dd or_all_4_wide_rotated_no_last ;nonalign, 4 wide, no last ! 184: dd or_all_4_wide_unrotated ;aligned, 4 wide ! 185: ! 186: ; Handles arbitrarily wide glyph drawing, for case where initial byte should be ! 187: ; MOVed even if it's not aligned (intended for use in drawing the first glyph ! 188: ; in a string). Table format is: ! 189: ; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte ! 190: ; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned) ! 191: align 4 ! 192: MovInitialTableWide label dword ! 193: dd mov_first_N_wide_rotated_need_last ;nonalign, need last ! 194: dd mov_first_N_wide_unrotated ;aligned ! 195: dd mov_first_N_wide_rotated_no_last ;nonalign, no last ! 196: dd mov_first_N_wide_unrotated ;aligned ! 197: ! 198: ; Handles arbitrarily wide glyph drawing, for case where initial byte should be ! 199: ; ORed if it's not aligned (intended for use in drawing all but the first glyph ! 200: ; in a string). Table format is: ! 201: ; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte ! 202: ; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned) ! 203: align 4 ! 204: OrInitialTableWide label dword ! 205: dd or_first_N_wide_rotated_need_last ;nonalign, need last ! 206: dd mov_first_N_wide_unrotated ;aligned ! 207: dd or_first_N_wide_rotated_no_last ;nonalign, no last ! 208: dd mov_first_N_wide_unrotated ;aligned ! 209: ! 210: ; Handles arbitrarily wide glyph drawing, for case where all bytes should ! 211: ; be ORed (intended for use in drawing potentially overlapping glyphs). ! 212: ; Table format is: ! 213: ; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte ! 214: ; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned) ! 215: align 4 ! 216: OrAllTableWide label dword ! 217: dd or_all_N_wide_rotated_need_last ;nonalign, need last ! 218: dd or_all_N_wide_unrotated ;aligned ! 219: dd or_all_N_wide_rotated_no_last ;nonalign, no last ! 220: dd or_all_N_wide_unrotated ;aligned ! 221: ! 222: ; Vectors to entry points for drawing various types of text. '*' means works as ! 223: ; is but could be acclerated with a custom scanning loop. ! 224: align 4 ! 225: MasterTextTypeTable label dword ;tops aligned overlap fixed pitch ! 226: dd draw_nf_ntb_o_to_temp_start ; N N N * ! 227: dd draw_f_ntb_o_to_temp_start ; N N Y * ! 228: dd draw_nf_ntb_o_to_temp_start ; N Y N ! 229: dd draw_f_ntb_o_to_temp_start ; N Y Y ! 230: dd draw_nf_tb_no_to_temp_start ; Y N N ! 231: dd draw_f_tb_no_to_temp_start ; Y N Y ! 232: dd draw_nf_ntb_o_to_temp_start ; Y Y N * ! 233: dd draw_f_ntb_o_to_temp_start ; Y Y Y * ! 234: ! 235: ; Masks for clipping for the eight possible left and right edge alignments ! 236: jOpaqueLeftMasks label byte ! 237: db 0ffh,07fh,03fh,01fh,00fh,007h,003h,001h ! 238: ! 239: jOpaqueRightMasks label byte ! 240: db 0ffh,080h,0c0h,0e0h,0f0h,0f8h,0fch,0feh ! 241: ! 242: ;-----------------------------------------------------------------------; ! 243: ! 244: .code ! 245: ! 246: _TEXT$01 SEGMENT DWORD USE32 PUBLIC 'CODE' ! 247: ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING ! 248: ! 249: ;-----------------------------------------------------------------------; ! 250: ! 251: cProc vFastText,48,<\ ! 252: uses esi edi ebx,\ ! 253: pGlyphPos:ptr,\ ! 254: ulGlyphCount:dword,\ ! 255: pTempBuffer:ptr,\ ! 256: ulBufDelta:dword,\ ! 257: ulCharInc:dword,\ ! 258: pdsurf:ptr,\ ! 259: prclText:ptr,\ ! 260: prclOpaque:ptr,\ ! 261: iFgColor:dword,\ ! 262: iBgColor:dword,\ ! 263: fDrawFlags:dword,\ ! 264: prclClip:dword> ! 265: ! 266: local ulGlyDelta:dword ;width per scan of source glyph, in bytes ! 267: local ulWidthInBytes:dword ;width of glyph, in bytes ! 268: local ulTmpWidthInBytes:dword ;working byte-width count ! 269: local ulGlyphX:dword ;for fixed-pitch text, maintains the current ! 270: ; glyph's left-edge X coordinate ! 271: local pGlyphLoop:dword ;pointer to glyph-processing loop ! 272: local ulTempLeft:dword ;X coordinate on screen of left edge of temp ! 273: ; buffer ! 274: local ulTempTop:dword ;Y coordinate on screen of top edge of temp ! 275: ; buffer ! 276: local pfnEntry:dword ;pointer to unrolled loop entry point ! 277: local ulLoopCount:dword ;general loop count storage ! 278: local ulTmpSrcDelta:dword ;distance from end of one buffer text scan to ! 279: ; start of next ! 280: local ulTmpDstDelta:dword ;distance from end of one screen text scan to ! 281: ; start of next ! 282: local ulTopScan:dword ;top scan of dest text rect in current bank ! 283: local ulBottomScan:dword ;bottom scan of dest text rect ! 284: local ulNumScans:dword ;# of scans to draw ! 285: local ulScreenDelta:dword ;scan-to-scan offset in screen ! 286: local ulTextWidthInBytes:dword ;# of bytes across spanned by text ! 287: local pScreen:dword ;pointer to first screen byte to which to draw ! 288: local pfnEdgeVector:dword ;pointer to routine to draw any needed edges ! 289: local pfnFirstOpaqVector:dword ;pointer to initial drawing routine ! 290: ; called for opaque (either whole ! 291: ; bytes, or edge(s) if no whole bytes) ! 292: local ulWholeWidthInWords:dword ;# of whole words to copy ! 293: local ulWholeWidthInWordsMinus1:dword ;# of whole words to copy, -1 ! 294: local ulOddByte:dword ;1 if odd byte in whole word copy ! 295: local ulTextLeft:dword ;left edge of leftmost glyph ! 296: local ulLeftMask:dword ;for opaque text, left edge mask for string ! 297: local ulRightMask:dword ;for opaque text, right edge mask for string ! 298: local ulUnrolledCount:dword ;# of unrolled loop reps ! 299: local ulUnrolledOddCount:dword ;# of unrolled loop odd reps ! 300: local ulYOrigin:dword ;Y origin of text in string (all glyphs are at ! 301: ; the same Y origin) ! 302: local rclClippedBounds[16]:byte ;clipped destination rectangle; ! 303: ; defined as "byte" due to assembler ! 304: ; limitations ! 305: ! 306: ;-----------------------------------------------------------------------; ! 307: ! 308: cld ! 309: ! 310: ;-----------------------------------------------------------------------; ! 311: ; Draws either a fixed or a non-fixed-pitch string to the temporary ! 312: ; buffer. Assumes this is a horizontal string, so the origins of all glyphs ! 313: ; are at the same Y coordinate. Draws leftmost glyph entirely with MOVs, ! 314: ; even if it's not aligned, in order to ensure that the leftmost byte ! 315: ; gets cleared when we're working with butted characters. For other ! 316: ; non-aligned glyphs, leftmost byte is ORed, other bytes are MOVed. ! 317: ; ! 318: ; Input: ! 319: ; pGlyphPos = pointer to array of GLYPHPOS structures to draw ! 320: ; ulGlyphCount = # of glyphs to draw ! 321: ; ulTempLeft = X coordinate on dest of left edge of temp buffer pointed ! 322: ; to by pTempBuffer ! 323: ; pTempBuffer = pointer to first byte (upper left corner) of ! 324: ; temp buffer into which we're drawing. This should be ! 325: ; word-aligned with the destination ! 326: ; ulBufDelta = destination scan-to-scan offset ! 327: ; ulCharInc = offset from one glyph to next (fixed-pitch only) ! 328: ; fDrawFlags = indicate the type of text to be drawn ! 329: ; Temp buffer zeroed if text doesn't cover every single pixel ! 330: ; ! 331: ; Fixed-pitch means equal spacing between glyph positions, not that all ! 332: ; glyphs butt together or equal spacing between upper left corners. ! 333: ;-----------------------------------------------------------------------; ! 334: ! 335: ;-----------------------------------------------------------------------; ! 336: ; If 8 wide, byte aligned, and opaque, handle with very fast special-case ! 337: ; code. ! 338: ;-----------------------------------------------------------------------; ! 339: ! 340: mov ebx,prclText ! 341: cmp ulCharInc,8 ;8 wide? ! 342: jnz short @F ;no ! 343: cmp fDrawFlags,5 ;fixed pitch? ! 344: jnz short @F ;no ! 345: cmp prclOpaque,0 ;opaque? ! 346: jz short @F ;no ! 347: cmp prclClip,0 ;is there clipping? ! 348: jnz short @F ;yes ! 349: test [ebx].xLeft,111b ;byte aligned? ! 350: jz special_8_wide_aligned_opaque ;yes, special-case ! 351: @@: ! 352: ! 353: ;-----------------------------------------------------------------------; ! 354: ; Handle all cases other than 8-wide byte-aligned. ! 355: ;-----------------------------------------------------------------------; ! 356: ! 357: general_handler: ! 358: mov esi,pdsurf ! 359: mov eax,[ebx].yTop ! 360: mov ulTempTop,eax ;Y screen coordinate of top edge of temp buf ! 361: mov eax,[ebx].xLeft ! 362: and eax,not 7 ! 363: mov ulTempLeft,eax ;X screen coordinate of left edge of temp buf ! 364: mov eax,[esi].dsurf_lNextScan ! 365: mov ulScreenDelta,eax ! 366: ! 367: mov eax,fDrawFlags ! 368: ! 369: jmp MasterTextTypeTable[eax*4] ! 370: ! 371: ;-----------------------------------------------------------------------; ! 372: ; Entry point for fixed-pitch | tops and bottoms aligned | no overlap. ! 373: ; Sets up to draw first glyph. ! 374: ;-----------------------------------------------------------------------; ! 375: draw_f_tb_no_to_temp_start: ! 376: mov ebx,pGlyphPos ;point to the first glyph to draw ! 377: mov esi,[ebx].gp_pgdf ;point to glyph def ! 378: ! 379: mov edi,[ebx].gp_x ;dest X coordinate ! 380: sub edi,ulTempLeft ;adjust relative to the left of the ! 381: ; temp buffer (we assume the text is ! 382: ; right at the top of the text rect ! 383: ; and hence the buffer) ! 384: mov ulGlyphX,edi ;remember where this glyph started ! 385: mov esi,[esi].gdf_pgb ;point to glyph bits ! 386: mov pGlyphLoop,offset draw_f_tb_no_to_temp_loop ! 387: ;draw additional characters with this ! 388: ; loop ! 389: jmp short draw_to_temp_start_entry ! 390: ! 391: ;-----------------------------------------------------------------------; ! 392: ; Entry point for non-fixed-pitch | tops and bottoms aligned | no overlap. ! 393: ; Sets up to draw first glyph. ! 394: ;-----------------------------------------------------------------------; ! 395: draw_nf_tb_no_to_temp_start: ! 396: mov ebx,pGlyphPos ;point to the first glyph to draw ! 397: mov esi,[ebx].gp_pgdf ;point to glyph def ! 398: ! 399: mov edi,[ebx].gp_x ;dest X coordinate ! 400: sub edi,ulTempLeft ;adjust relative to the left of the ! 401: ; temp buffer ! 402: mov esi,[esi].gdf_pgb ;point to glyph bits ! 403: mov pGlyphLoop,offset draw_nf_tb_no_to_temp_loop ! 404: ;draw additional characters with this ! 405: ; loop ! 406: draw_to_temp_start_entry: ! 407: add edi,[esi].gb_x ;adjust to position of upper left glyph ! 408: ; corner in dest ! 409: ;BUGBUG add or sub? ! 410: mov ecx,edi ! 411: shr edi,3 ;byte offset of first column of glyph ! 412: ; offset of upper left of glyph in temp ! 413: ; buffer ! 414: add edi,pTempBuffer ;initial dest byte in temp buffer ! 415: ! 416: and ecx,111b ;bit alignment of upper left in temp ! 417: ! 418: ;calculate scan-to-scan glyph width ! 419: mov ebx,[esi].gb_cx ;glyph width in pixels ! 420: ! 421: lea eax,[ebx+ecx+7] ! 422: shr eax,3 ;# of dest bytes per scan ! 423: ! 424: add ebx,7 ! 425: shr ebx,3 ;# of source bytes per scan ! 426: ! 427: mov edx,ulBufDelta ;width of destination buffer in bytes ! 428: ! 429: cmp eax,4 ;do we have special case code for this ! 430: ; dest width? ! 431: ja short @F ;no, handle as general case ! 432: ;yes, handle as special case ! 433: cmp ebx,eax ;carry if more dest than source bytes ! 434: ; (last source byte not needed) ! 435: rcl eax,1 ;factor last source byte status in ! 436: cmp cl,1 ;carry if aligned ! 437: rcl eax,1 ;factor in alignment (aligned or not) ! 438: mov ebx,[esi].gb_cy ;# of scans in glyph ! 439: add esi,gb_aj ;point to the first glyph byte ! 440: ! 441: jmp MovInitialTableNarrow[eax*4] ! 442: ;branch to draw the first glyph; never ! 443: ; need to OR first glyph, because ! 444: ; there's nothing there yet ! 445: ! 446: @@: ;too wide to special case ! 447: mov ulWidthInBytes,eax ;# of bytes across dest ! 448: cmp ebx,eax ;carry if more dest than source bytes ! 449: ; (last source byte not needed) ! 450: mov eax,0 ! 451: rcl eax,1 ;factor last source byte status in ! 452: cmp cl,1 ;carry if aligned ! 453: rcl eax,1 ;factor in alignment (aligned or not) ! 454: ! 455: mov ebx,[esi].gb_cx ;glyph width in pixels ! 456: add ebx,7 ! 457: shr ebx,3 ;glyph width in bytes ! 458: mov ulGlyDelta,ebx ! 459: ! 460: mov ebx,[esi].gb_cy ;# of scans in glyph ! 461: add esi,gb_aj ;point to the first glyph byte ! 462: ! 463: jmp MovInitialTableWide[eax*4] ! 464: ;branch to draw the first glyph; never ! 465: ; need to OR first glyph, because ! 466: ; there's nothing there yet ! 467: ! 468: ;-----------------------------------------------------------------------; ! 469: ; Entry point for fixed-pitch | tops and bottoms not aligned | overlap. ! 470: ; Sets up to draw first glyph. ! 471: ;-----------------------------------------------------------------------; ! 472: draw_f_ntb_o_to_temp_start: ! 473: mov ebx,pGlyphPos ;point to the first glyph to draw ! 474: mov pGlyphLoop,offset draw_f_ntb_o_to_temp_loop ! 475: ;draw additional characters with this ! 476: ; loop ! 477: mov edi,[ebx].gp_x ;dest X coordinate ! 478: mov esi,[ebx].gp_pgdf ;point to glyph def ! 479: sub edi,ulTempLeft ;adjust relative to the left of the ! 480: ; temp buffer ! 481: mov ulGlyphX,edi ;remember where this glyph started ! 482: mov esi,[esi].gdf_pgb ;point to glyph bits ! 483: add edi,[esi].gb_x ;adjust to position of upper left glyph ! 484: ; corner in dest ! 485: mov ecx,edi ! 486: shr edi,3 ;byte offset of first column of glyph ! 487: ; offset of upper left of glyph in temp ! 488: ; buffer ! 489: jmp short draw_to_temp_start_entry2 ! 490: ! 491: ;-----------------------------------------------------------------------; ! 492: ; Entry point for non-fixed-pitch | tops and bottoms not aligned | overlap. ! 493: ; Sets up to draw first glyph. ! 494: ;-----------------------------------------------------------------------; ! 495: draw_nf_ntb_o_to_temp_start: ! 496: mov ebx,pGlyphPos ;point to the first glyph to draw ! 497: mov pGlyphLoop,offset draw_nf_ntb_o_to_temp_loop ! 498: ;draw additional characters with this ! 499: ; loop ! 500: mov edi,[ebx].gp_x ;dest X coordinate ! 501: mov esi,[ebx].gp_pgdf ;point to glyph def ! 502: sub edi,ulTempLeft ;adjust relative to the left of the ! 503: ; temp buffer ! 504: mov esi,[esi].gdf_pgb ;point to glyph bits ! 505: add edi,[esi].gb_x ;adjust to position of upper left glyph ! 506: ; corner in dest ! 507: ;BUGBUG add or sub? ! 508: mov ecx,edi ! 509: shr edi,3 ;byte offset of first column of glyph ! 510: ; offset of upper left of glyph in temp ! 511: ; buffer ! 512: draw_to_temp_start_entry2: ! 513: mov eax,[ebx].gp_y ;dest origin Y coordinate ! 514: sub eax,ulTempTop ;coord of glyph origin in temp buffer ! 515: mov ulYOrigin,eax ;remember the Y origin of all glyphs ! 516: ; (necessary because glyph positions ! 517: ; after first aren't set for fixed- ! 518: ; pitch strings) ! 519: add eax,[esi].gb_y ;adjust to position of upper left glyph ! 520: ; corner in dest ! 521: mul ulBufDelta ;offset in buffer of top glyph scan ! 522: add eax,pTempBuffer ;initial dest byte ! 523: add edi,eax ! 524: ! 525: and ecx,111b ;bit alignment of upper left in temp ! 526: ! 527: ;calculate scan-to-scan glyph width ! 528: mov ebx,[esi].gb_cx ;glyph width in pixels ! 529: ! 530: lea eax,[ebx+ecx+7] ! 531: shr eax,3 ;# of dest bytes per scan ! 532: ! 533: add ebx,7 ! 534: shr ebx,3 ;# of source bytes per scan ! 535: ! 536: mov edx,ulBufDelta ;width of destination buffer in bytes ! 537: ! 538: cmp eax,4 ;do we have special case code for this ! 539: ; dest width? ! 540: ja short @F ;no, handle as general case ! 541: ;yes, handle as special case ! 542: cmp ebx,eax ;carry if more dest than source bytes ! 543: ; (last source byte not needed) ! 544: rcl eax,1 ;factor last source byte status in ! 545: cmp cl,1 ;carry if aligned ! 546: rcl eax,1 ;factor in alignment (aligned or not) ! 547: mov ebx,[esi].gb_cy ;# of scans in glyph ! 548: add esi,gb_aj ;point to the first glyph byte ! 549: ! 550: jmp OrAllTableNarrow[eax*4] ;branch to draw the first glyph; OR all ! 551: ; glyphs, because text may overlap ! 552: ! 553: @@: ;too wide to special case ! 554: mov ulWidthInBytes,eax ;# of bytes across dest ! 555: cmp ebx,eax ;carry if more dest than source bytes ! 556: ; (last source byte not needed) ! 557: mov eax,0 ! 558: rcl eax,1 ;factor last source byte status in ! 559: cmp cl,1 ;carry if aligned ! 560: rcl eax,1 ;factor in alignment (aligned or not) ! 561: ! 562: mov ebx,[esi].gb_cx ;glyph width in pixels ! 563: add ebx,7 ! 564: shr ebx,3 ;glyph width in bytes ! 565: mov ulGlyDelta,ebx ! 566: ! 567: mov ebx,[esi].gb_cy ;# of scans in glyph ! 568: add esi,gb_aj ;point to the first glyph byte ! 569: ! 570: jmp OrAllTableWide[eax*4] ;branch to draw the first glyph; OR all ; glyphs, because text may overlap never ! 571: ; glyphs, because text may overlap ! 572: ! 573: ;-----------------------------------------------------------------------; ! 574: ; Loop to draw all fixed-pitch | tops and bottoms aligned | no overlap ! 575: ; glyphs after first. ! 576: ;-----------------------------------------------------------------------; ! 577: draw_f_tb_no_to_temp_loop: ! 578: dec ulGlyphCount ;any more glyphs to draw? ! 579: jz draw_to_screen ;no, done ! 580: mov ebx,pGlyphPos ! 581: add ebx,size GLYPHPOS ;point to the next glyph (the one ! 582: mov pGlyphPos,ebx ; we're going to draw this time) ! 583: mov esi,[ebx].gp_pgdf ;point to glyph def ! 584: ! 585: mov edi,ulGlyphX ;last glyph's dest X start in temp buf ! 586: add edi,ulCharInc ;this glyph's dest X start in temp buf ! 587: mov ulGlyphX,edi ;remember for next glyph ! 588: mov esi,[esi].gdf_pgb ;point to glyph bits ! 589: jmp short draw_to_temp_loop_entry ! 590: ! 591: ;-----------------------------------------------------------------------; ! 592: ; Loop to draw all non-fixed-pitch | tops and bottoms aligned | no overlap ! 593: ; glyphs after first. ! 594: ;-----------------------------------------------------------------------; ! 595: draw_nf_tb_no_to_temp_loop: ! 596: dec ulGlyphCount ;any more glyphs to draw? ! 597: jz draw_to_screen ;no, done ! 598: mov ebx,pGlyphPos ! 599: add ebx,size GLYPHPOS ;point to the next glyph (the one we're ! 600: mov pGlyphPos,ebx ; going to draw this time) ! 601: mov esi,[ebx].gp_pgdf ;point to glyph def ! 602: mov edi,[ebx].gp_x ;dest X coordinate ! 603: mov esi,[esi].gdf_pgb ;point to glyph bits ! 604: sub edi,ulTempLeft ;adjust relative to the left edge of ! 605: ; the temp buffer ! 606: ! 607: draw_to_temp_loop_entry: ! 608: add edi,[esi].gb_x ;adjust to position of upper left glyph ! 609: ; corner in dest ! 610: mov ecx,edi ;pixel X coordinate in temp buffer ! 611: shr edi,3 ;byte offset of first column = dest ! 612: ; offset of upper left of glyph in temp ! 613: ; buffer ! 614: add edi,pTempBuffer ;initial dest byte ! 615: ! 616: and ecx,111b ;bit alignment of upper left in temp ! 617: ! 618: ;calculate scan-to-scan glyph width ! 619: mov ebx,[esi].gb_cx ;glyph width in pixels ! 620: ! 621: lea eax,[ebx+ecx+7] ! 622: shr eax,3 ;# of dest bytes to copy to per scan ! 623: ! 624: add ebx,7 ! 625: shr ebx,3 ;# of source bytes to copy from per ! 626: ; scan ! 627: mov edx,ulBufDelta ;width of destination buffer in bytes ! 628: ! 629: cmp eax,4 ;do we have special case code for this ! 630: ; dest width? ! 631: ja short @F ;no, handle as general case ! 632: ;yes, handle as special case ! 633: cmp ebx,eax ;carry if more dest than source bytes ! 634: ; (last source byte not needed) ! 635: rcl eax,1 ;factor last source byte status in ! 636: cmp cl,1 ;carry if aligned ! 637: rcl eax,1 ;factor in alignment (aligned or not) ! 638: mov ebx,[esi].gb_cy ;# of scans in glyph ! 639: add esi,gb_aj ;point to the first glyph byte ! 640: ! 641: jmp OrInitialTableNarrow[eax*4] ;branch to draw the first glyph; ! 642: ; need to OR the 1st byte if ! 643: ; non-aligned to avoid overwriting ! 644: ; what's already there ! 645: @@: ;too wide to special case ! 646: mov ulWidthInBytes,eax ;# of bytes across dest ! 647: cmp ebx,eax ;carry if more dest than source bytes ! 648: ; (last source byte not needed) ! 649: mov eax,0 ! 650: rcl eax,1 ;factor last source byte status in ! 651: cmp cl,1 ;carry if aligned ! 652: rcl eax,1 ;factor in alignment (aligned or not) ! 653: ! 654: mov ebx,[esi].gb_cx ;glyph width in pixels ! 655: add ebx,7 ! 656: shr ebx,3 ;glyph width in bytes ! 657: mov ulGlyDelta,ebx ! 658: ! 659: mov ebx,[esi].gb_cy ;# of scans in glyph ! 660: add esi,gb_aj ;point to the first glyph byte ! 661: ! 662: jmp OrInitialTableWide[eax*4] ;branch to draw the next glyph; ! 663: ; need to OR the 1st byte if ! 664: ; non-aligned to avoid overwriting ! 665: ; what's already there ! 666: ! 667: ;-----------------------------------------------------------------------; ! 668: ; Loop to draw all fixed-pitch | tops and bottoms not aligned | overlap ! 669: ; glyphs after first. ! 670: ;-----------------------------------------------------------------------; ! 671: draw_f_ntb_o_to_temp_loop: ! 672: dec ulGlyphCount ;any more glyphs to draw? ! 673: jz draw_to_screen ;no, done ! 674: mov ebx,pGlyphPos ! 675: add ebx,size GLYPHPOS ;point to the next glyph (the one we're ! 676: mov pGlyphPos,ebx ; going to draw this time) ! 677: ! 678: mov esi,[ebx].gp_pgdf ;point to glyph def ! 679: mov edi,ulGlyphX ;last glyph's dest X start in temp buf ! 680: add edi,ulCharInc ;this glyph's dest X start in temp buf ! 681: mov ulGlyphX,edi ;remember for next glyph ! 682: mov esi,[esi].gdf_pgb ;point to glyph bits ! 683: ! 684: jmp short draw_to_temp_loop_entry2 ! 685: ! 686: ;-----------------------------------------------------------------------; ! 687: ; Loop to draw all non-fixed-pitch | tops and bottoms not aligned | overlap ! 688: ; glyphs after first. ! 689: ;-----------------------------------------------------------------------; ! 690: draw_nf_ntb_o_to_temp_loop: ! 691: dec ulGlyphCount ;any more glyphs to draw? ! 692: jz draw_to_screen ;no, done ! 693: mov ebx,pGlyphPos ! 694: add ebx,size GLYPHPOS ;point to the next glyph (the one we're ! 695: mov pGlyphPos,ebx ; going to draw this time) ! 696: ! 697: mov esi,[ebx].gp_pgdf ;point to glyph def ! 698: mov edi,[ebx].gp_x ;dest X coordinate ! 699: mov esi,[esi].gdf_pgb ;point to glyph bits ! 700: sub edi,ulTempLeft ;adjust relative to the left edge of ! 701: ; the temp buffer ! 702: draw_to_temp_loop_entry2: ! 703: add edi,[esi].gb_x ;adjust to position of upper left glyph ! 704: ; corner in dest ! 705: mov ecx,edi ;pixel X coordinate in temp buffer ! 706: shr edi,3 ;byte offset of first column = dest ! 707: ; offset of upper left of glyph in temp ! 708: ; buffer ! 709: mov eax,ulYOrigin ;dest Y coordinate ! 710: ! 711: add eax,[esi].gb_y ;adjust to position of upper left glyph ! 712: ; corner in dest ! 713: mul ulBufDelta ;offset in buffer of top glyph scan ! 714: add eax,pTempBuffer ;initial dest byte ! 715: add edi,eax ! 716: ! 717: and ecx,111b ;bit alignment of upper left in temp ! 718: ! 719: ;calculate scan-to-scan glyph width ! 720: mov ebx,[esi].gb_cx ;glyph width in pixels ! 721: ! 722: lea eax,[ebx+ecx+7] ! 723: shr eax,3 ;# of dest bytes to copy to per scan ! 724: ! 725: add ebx,7 ! 726: shr ebx,3 ;# of source bytes to copy from per ! 727: ; scan ! 728: mov edx,ulBufDelta ;width of destination buffer in bytes ! 729: ! 730: cmp eax,4 ;do we have special case code for this ! 731: ; dest width? ! 732: ja short @F ;no, handle as general case ! 733: ;yes, handle as special case ! 734: cmp ebx,eax ;carry if more dest than source bytes ! 735: ; (last source byte not needed) ! 736: rcl eax,1 ;factor last source byte status in ! 737: cmp cl,1 ;carry if aligned ! 738: rcl eax,1 ;factor in alignment (aligned or not) ! 739: mov ebx,[esi].gb_cy ;# of scans in glyph ! 740: add esi,gb_aj ;point to the first glyph byte ! 741: ! 742: jmp OrAllTableNarrow[eax*4] ;branch to draw the next glyph ! 743: ! 744: @@: ;too wide to special case ! 745: mov ulWidthInBytes,eax ;# of bytes across dest ! 746: cmp ebx,eax ;carry if more dest than source bytes ! 747: ; (last source byte not needed) ! 748: mov eax,0 ! 749: rcl eax,1 ;factor last source byte status in ! 750: cmp cl,1 ;carry if aligned ! 751: rcl eax,1 ;factor in alignment (aligned or not) ! 752: ! 753: mov ebx,[esi].gb_cx ;glyph width in pixels ! 754: add ebx,7 ! 755: shr ebx,3 ;glyph width in bytes ! 756: mov ulGlyDelta,ebx ! 757: ! 758: mov ebx,[esi].gb_cy ;# of scans in glyph ! 759: add esi,gb_aj ;point to the first glyph byte ! 760: ! 761: jmp OrAllTableWide[eax*4] ;branch to draw the next glyph ! 762: ! 763: ;-----------------------------------------------------------------------; ! 764: ; Routines to draw all scans of a single glyph into the temp buffer, ! 765: ; optimized for the following cases: ! 766: ; ! 767: ; 1 to 4 byte-wide destination rectangles for each of: ! 768: ; No rotation needed ! 769: ; Rotation needed, same # of source as dest bytes needed ! 770: ; Rotation needed, one less source than dest bytes needed ! 771: ; ! 772: ; Additionally, the three cases are handled for 5 and wider cases by a ! 773: ; general routine for each case. ! 774: ; ! 775: ; If rotation is needed, there are three sorts of routines: ! 776: ; ! 777: ; 1) The leftmost byte is MOVed, to initialize the byte. Succeeding bytes are ! 778: ; MOVed. This is generally used for the leftmost glyph of a string. ! 779: ; 2) The leftmost byte is ORed into the existing byte. Succeeding bytes are ! 780: ; MOVed. This is generally used after the leftmost glyph, because this may ! 781: ; not be the first data written to that byte. ! 782: ; 3) All bytes are ORed. This is for drawing when characters might overlap. ! 783: ; ! 784: ; If rotation is not needed, there are two sorts of routines: ! 785: ; ! 786: ; 1) The leftmost byte is MOVed, to initialize the byte. Succeeding bytes are ! 787: ; MOVed. This is generally used for the leftmost glyph of a string. ! 788: ; 2) All bytes are ORed. This is for drawing when characters might overlap. ! 789: ; ! 790: ; On entry: ! 791: ; EBX = # of scans to copy ! 792: ; CL = right rotation ! 793: ; EDX = ulBufDelta = width per scan of destination buffer, in bytes ! 794: ; ESI = pointer to first glyph byte ! 795: ; EDI = pointer to first dest buffer byte ! 796: ; DF = cleared ! 797: ; ulGlyDelta = width per scan of source glyph, in bytes (wide case only) ! 798: ; ulWidthInBytes = width of glyph, in bytes (required only for 5 and ! 799: ; wider cases) ! 800: ; ! 801: ; On exit: ! 802: ; Any or all of EAX, EBX, ECX, EDX, ESI, and EDI may be trashed. ! 803: ! 804: ;-----------------------------------------------------------------------; ! 805: ; OR first byte, 1 byte wide dest, rotated. ! 806: ;-----------------------------------------------------------------------; ! 807: or_all_1_wide_rotated_need_last: ! 808: or_all_1_wide_rotated_no_last: ! 809: or_first_1_wide_rotated_need_last: ! 810: or_first_1_wide_rotated_no_last: ! 811: SET_UP_UNROLL_AND_BRANCH ebx,eax,or_first_1_wide_rotated_table, \ ! 812: LOOP_UNROLL_SHIFT ! 813: ! 814: UNROLL_LOOP_ENTRY_TABLE or_first_1_wide_rotated_table,OF1WR, \ ! 815: LOOP_UNROLL_COUNT ! 816: ! 817: MOR_FIRST_1_WIDE_ROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 818: &ENTRY_LABEL&ENTRY_INDEX&: ! 819: mov ch,[esi] ! 820: inc esi ! 821: shr ch,cl ! 822: or [edi],ch ! 823: add edi,edx ! 824: endm ;-----------------------------------; ! 825: ! 826: or_first_1_wide_rotated_loop: ! 827: UNROLL_LOOP MOR_FIRST_1_WIDE_ROTATED,OF1WR,LOOP_UNROLL_COUNT ! 828: dec ebx ! 829: jnz or_first_1_wide_rotated_loop ! 830: jmp pGlyphLoop ! 831: ! 832: ;-----------------------------------------------------------------------; ! 833: ; MOV first byte, 1 byte wide dest, rotated. ! 834: ;-----------------------------------------------------------------------; ! 835: mov_first_1_wide_rotated_need_last: ! 836: mov_first_1_wide_rotated_no_last: ! 837: SET_UP_UNROLL_AND_BRANCH ebx,eax,mov_first_1_wide_rotated_table, \ ! 838: LOOP_UNROLL_SHIFT ! 839: ! 840: UNROLL_LOOP_ENTRY_TABLE mov_first_1_wide_rotated_table,MF1WR, \ ! 841: LOOP_UNROLL_COUNT ! 842: ! 843: MMOV_FIRST_1_WIDE_ROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 844: &ENTRY_LABEL&ENTRY_INDEX&: ! 845: mov ch,[esi] ! 846: inc esi ! 847: shr ch,cl ! 848: mov [edi],ch ! 849: add edi,edx ! 850: endm ;-----------------------------------; ! 851: ! 852: mov_first_1_wide_rotated_loop: ! 853: UNROLL_LOOP MMOV_FIRST_1_WIDE_ROTATED,MF1WR,LOOP_UNROLL_COUNT ! 854: dec ebx ! 855: jnz mov_first_1_wide_rotated_loop ! 856: jmp pGlyphLoop ! 857: ! 858: ;-----------------------------------------------------------------------; ! 859: ; MOV first byte, 1 byte wide dest, unrotated. ! 860: ;-----------------------------------------------------------------------; ! 861: mov_first_1_wide_unrotated: ! 862: ! 863: SET_UP_UNROLL_AND_BRANCH ebx,eax,mov_first_1_wide_unrotated_table, \ ! 864: LOOP_UNROLL_SHIFT ! 865: ! 866: UNROLL_LOOP_ENTRY_TABLE mov_first_1_wide_unrotated_table,MF1WU, \ ! 867: LOOP_UNROLL_COUNT ! 868: ! 869: MMOV_FIRST_1_WIDE_UNROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 870: &ENTRY_LABEL&ENTRY_INDEX&: ! 871: mov al,[esi] ! 872: inc esi ! 873: mov [edi],al ! 874: add edi,edx ! 875: endm ;-----------------------------------; ! 876: ! 877: mov_first_1_wide_unrotated_loop: ! 878: UNROLL_LOOP MMOV_FIRST_1_WIDE_UNROTATED,MF1WU,LOOP_UNROLL_COUNT ! 879: dec ebx ! 880: jnz mov_first_1_wide_unrotated_loop ! 881: jmp pGlyphLoop ! 882: ! 883: ;-----------------------------------------------------------------------; ! 884: ; OR all bytes, 1 byte wide dest, unrotated. ! 885: ;-----------------------------------------------------------------------; ! 886: or_all_1_wide_unrotated: ! 887: SET_UP_UNROLL_AND_BRANCH ebx,eax,or_all_1_wide_unrotated_table, \ ! 888: LOOP_UNROLL_SHIFT ! 889: ! 890: UNROLL_LOOP_ENTRY_TABLE or_all_1_wide_unrotated_table,OA1WU, \ ! 891: LOOP_UNROLL_COUNT ! 892: ! 893: MOR_ALL_1_WIDE_UNROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 894: &ENTRY_LABEL&ENTRY_INDEX&: ! 895: mov al,[esi] ! 896: inc esi ! 897: or [edi],al ! 898: add edi,edx ! 899: endm ;-----------------------------------; ! 900: ! 901: or_all_1_wide_unrotated_loop: ! 902: UNROLL_LOOP MOR_ALL_1_WIDE_UNROTATED,OA1WU,LOOP_UNROLL_COUNT ! 903: dec ebx ! 904: jnz or_all_1_wide_unrotated_loop ! 905: jmp pGlyphLoop ! 906: ! 907: ;-----------------------------------------------------------------------; ! 908: ; OR first byte, 2 bytes wide dest, rotated, need final source byte. ! 909: ;-----------------------------------------------------------------------; ! 910: or_first_2_wide_rotated_need_last: ! 911: SET_UP_UNROLL_AND_BRANCH ebx,eax,or_first_2_wide_rotated_need_table, \ ! 912: LOOP_UNROLL_SHIFT ! 913: ! 914: UNROLL_LOOP_ENTRY_TABLE or_first_2_wide_rotated_need_table,OF2WRN, \ ! 915: LOOP_UNROLL_COUNT ! 916: ! 917: MOR_FIRST_2_WIDE_ROTATED_NEED macro ENTRY_LABEL,ENTRY_INDEX ! 918: &ENTRY_LABEL&ENTRY_INDEX&: ! 919: mov ax,[esi] ! 920: add esi,2 ! 921: ror ax,cl ! 922: or [edi],al ! 923: mov [edi+1],ah ! 924: add edi,edx ! 925: endm ;-----------------------------------; ! 926: ! 927: or_first_2_wide_rotated_need_loop: ! 928: UNROLL_LOOP MOR_FIRST_2_WIDE_ROTATED_NEED,OF2WRN,LOOP_UNROLL_COUNT ! 929: dec ebx ! 930: jnz or_first_2_wide_rotated_need_loop ! 931: jmp pGlyphLoop ! 932: ! 933: ;-----------------------------------------------------------------------; ! 934: ; OR all bytes, 2 bytes wide dest, rotated, need final source byte. ! 935: ;-----------------------------------------------------------------------; ! 936: or_all_2_wide_rotated_need_last: ! 937: SET_UP_UNROLL_AND_BRANCH ebx,eax,or_all_2_wide_rotated_need_table, \ ! 938: LOOP_UNROLL_SHIFT ! 939: ! 940: UNROLL_LOOP_ENTRY_TABLE or_all_2_wide_rotated_need_table,OA2WRN, \ ! 941: LOOP_UNROLL_COUNT ! 942: ! 943: MOR_ALL_2_WIDE_ROTATED_NEED macro ENTRY_LABEL,ENTRY_INDEX ! 944: &ENTRY_LABEL&ENTRY_INDEX&: ! 945: mov ax,[esi] ! 946: add esi,2 ! 947: ror ax,cl ! 948: or [edi],ax ! 949: add edi,edx ! 950: endm ;-----------------------------------; ! 951: ! 952: or_all_2_wide_rotated_need_loop: ! 953: UNROLL_LOOP MOR_ALL_2_WIDE_ROTATED_NEED,OA2WRN,LOOP_UNROLL_COUNT ! 954: dec ebx ! 955: jnz or_all_2_wide_rotated_need_loop ! 956: jmp pGlyphLoop ! 957: ! 958: ;-----------------------------------------------------------------------; ! 959: ; MOV first byte, 2 bytes wide dest, rotated, need final source byte. ! 960: ;-----------------------------------------------------------------------; ! 961: mov_first_2_wide_rotated_need_last: ! 962: SET_UP_UNROLL_AND_BRANCH ebx,eax,mov_first_2_wide_rotated_need_table, \ ! 963: LOOP_UNROLL_SHIFT ! 964: ! 965: UNROLL_LOOP_ENTRY_TABLE mov_first_2_wide_rotated_need_table,MF2WRN, \ ! 966: LOOP_UNROLL_COUNT ! 967: ! 968: MMOV_FIRST_2_WIDE_ROTATED_NEED macro ENTRY_LABEL,ENTRY_INDEX ! 969: &ENTRY_LABEL&ENTRY_INDEX&: ! 970: mov ax,[esi] ! 971: add esi,2 ! 972: ror ax,cl ! 973: mov [edi],ax ! 974: add edi,edx ! 975: endm ;-----------------------------------; ! 976: ! 977: mov_first_2_wide_rotated_need_loop: ! 978: UNROLL_LOOP MMOV_FIRST_2_WIDE_ROTATED_NEED,MF2WRN,LOOP_UNROLL_COUNT ! 979: dec ebx ! 980: jnz mov_first_2_wide_rotated_need_loop ! 981: jmp pGlyphLoop ! 982: ! 983: ;-----------------------------------------------------------------------; ! 984: ; OR first byte, 2 bytes wide dest, rotated, don't need final source byte. ! 985: ;-----------------------------------------------------------------------; ! 986: or_first_2_wide_rotated_no_last: ! 987: SET_UP_UNROLL_AND_BRANCH ebx,eax,or_first_2_wide_rotated_table, \ ! 988: LOOP_UNROLL_SHIFT ! 989: ! 990: UNROLL_LOOP_ENTRY_TABLE or_first_2_wide_rotated_table,OF2WR, \ ! 991: LOOP_UNROLL_COUNT ! 992: ! 993: MOR_FIRST_2_WIDE_ROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 994: &ENTRY_LABEL&ENTRY_INDEX&: ! 995: sub eax,eax ! 996: mov ah,[esi] ! 997: inc esi ! 998: shr eax,cl ! 999: or [edi],ah ! 1000: mov [edi+1],al ! 1001: add edi,edx ! 1002: endm ;-----------------------------------; ! 1003: ! 1004: or_first_2_wide_rotated_loop: ! 1005: UNROLL_LOOP MOR_FIRST_2_WIDE_ROTATED,OF2WR,LOOP_UNROLL_COUNT ! 1006: dec ebx ! 1007: jnz or_first_2_wide_rotated_loop ! 1008: jmp pGlyphLoop ! 1009: ! 1010: ;-----------------------------------------------------------------------; ! 1011: ; OR all bytes, 2 bytes wide dest, rotated, don't need final source byte. ! 1012: ;-----------------------------------------------------------------------; ! 1013: or_all_2_wide_rotated_no_last: ! 1014: SET_UP_UNROLL_AND_BRANCH ebx,eax,or_all_2_wide_rotated_table, \ ! 1015: LOOP_UNROLL_SHIFT ! 1016: ! 1017: UNROLL_LOOP_ENTRY_TABLE or_all_2_wide_rotated_table,OA2WR, \ ! 1018: LOOP_UNROLL_COUNT ! 1019: ! 1020: MOR_ALL_2_WIDE_ROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 1021: &ENTRY_LABEL&ENTRY_INDEX&: ! 1022: sub eax,eax ! 1023: mov al,[esi] ! 1024: inc esi ! 1025: ror ax,cl ! 1026: or [edi],ax ! 1027: add edi,edx ! 1028: endm ;-----------------------------------; ! 1029: ! 1030: or_all_2_wide_rotated_loop: ! 1031: UNROLL_LOOP MOR_ALL_2_WIDE_ROTATED,OA2WR,LOOP_UNROLL_COUNT ! 1032: dec ebx ! 1033: jnz or_all_2_wide_rotated_loop ! 1034: jmp pGlyphLoop ! 1035: ! 1036: ;-----------------------------------------------------------------------; ! 1037: ; MOV first byte, 2 bytes wide dest, rotated, don't need final source byte. ! 1038: ;-----------------------------------------------------------------------; ! 1039: mov_first_2_wide_rotated_no_last: ! 1040: SET_UP_UNROLL_AND_BRANCH ebx,eax,mov_first_2_wide_rotated_table, \ ! 1041: LOOP_UNROLL_SHIFT ! 1042: ! 1043: UNROLL_LOOP_ENTRY_TABLE mov_first_2_wide_rotated_table,MF2WR, \ ! 1044: LOOP_UNROLL_COUNT ! 1045: ! 1046: MMOV_FIRST_2_WIDE_ROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 1047: &ENTRY_LABEL&ENTRY_INDEX&: ! 1048: sub eax,eax ! 1049: mov al,[esi] ! 1050: inc esi ! 1051: ror ax,cl ! 1052: mov [edi],ax ! 1053: add edi,edx ! 1054: endm ;-----------------------------------; ! 1055: ! 1056: mov_first_2_wide_rotated_loop: ! 1057: UNROLL_LOOP MMOV_FIRST_2_WIDE_ROTATED,MF2WR,LOOP_UNROLL_COUNT ! 1058: dec ebx ! 1059: jnz mov_first_2_wide_rotated_loop ! 1060: jmp pGlyphLoop ! 1061: ! 1062: ;-----------------------------------------------------------------------; ! 1063: ; MOV first byte, 2 bytes wide dest, unrotated. ! 1064: ;-----------------------------------------------------------------------; ! 1065: mov_first_2_wide_unrotated: ! 1066: SET_UP_UNROLL_AND_BRANCH ebx,eax,mov_first_2_wide_unrotated_table, \ ! 1067: LOOP_UNROLL_SHIFT ! 1068: ! 1069: UNROLL_LOOP_ENTRY_TABLE mov_first_2_wide_unrotated_table,MF2WU, \ ! 1070: LOOP_UNROLL_COUNT ! 1071: ! 1072: MMOV_FIRST_2_WIDE_UNROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 1073: &ENTRY_LABEL&ENTRY_INDEX&: ! 1074: mov ax,[esi] ! 1075: add esi,2 ! 1076: mov [edi],ax ! 1077: add edi,edx ! 1078: endm ;-----------------------------------; ! 1079: ! 1080: mov_first_2_wide_unrotated_loop: ! 1081: UNROLL_LOOP MMOV_FIRST_2_WIDE_UNROTATED,MF2WU,LOOP_UNROLL_COUNT ! 1082: dec ebx ! 1083: jnz mov_first_2_wide_unrotated_loop ! 1084: jmp pGlyphLoop ! 1085: ! 1086: ;-----------------------------------------------------------------------; ! 1087: ; OR all bytes, 2 bytes wide dest, unrotated. ! 1088: ;-----------------------------------------------------------------------; ! 1089: or_all_2_wide_unrotated: ! 1090: SET_UP_UNROLL_AND_BRANCH ebx,eax,or_all_2_wide_unrotated_table, \ ! 1091: LOOP_UNROLL_SHIFT ! 1092: ! 1093: UNROLL_LOOP_ENTRY_TABLE or_all_2_wide_unrotated_table,OA2WU, \ ! 1094: LOOP_UNROLL_COUNT ! 1095: ! 1096: MOR_ALL_2_WIDE_UNROTATED macro ENTRY_LABEL,ENTRY_INDEX ! 1097: &ENTRY_LABEL&ENTRY_INDEX&: ! 1098: mov ax,[esi] ! 1099: add esi,2 ! 1100: or [edi],ax ! 1101: add edi,edx ! 1102: endm ;-----------------------------------; ! 1103: ! 1104: or_all_2_wide_unrotated_loop: ! 1105: UNROLL_LOOP MOR_ALL_2_WIDE_UNROTATED,OA2WU,LOOP_UNROLL_COUNT ! 1106: dec ebx ! 1107: jnz or_all_2_wide_unrotated_loop ! 1108: jmp pGlyphLoop ! 1109: ! 1110: ;-----------------------------------------------------------------------; ! 1111: ; OR first byte, 3 bytes wide dest, rotated, need final source byte. ! 1112: ;-----------------------------------------------------------------------; ! 1113: or_first_3_wide_rotated_need_last: ! 1114: @@: ! 1115: mov al,[esi] ! 1116: shr al,cl ! 1117: or [edi],al ! 1118: mov ax,[esi] ! 1119: ror ax,cl ! 1120: mov [edi+1],ah ! 1121: mov ax,[esi+1] ! 1122: add esi,3 ! 1123: ror ax,cl ! 1124: mov [edi+2],ah ! 1125: add edi,edx ! 1126: dec ebx ! 1127: jnz @B ! 1128: jmp pGlyphLoop ! 1129: ! 1130: ;-----------------------------------------------------------------------; ! 1131: ; OR first byte, 3 bytes wide dest, rotated, need final source byte. ! 1132: ;-----------------------------------------------------------------------; ! 1133: or_all_3_wide_rotated_need_last: ! 1134: @@: ! 1135: mov al,[esi] ! 1136: shr al,cl ! 1137: or [edi],al ! 1138: mov ax,[esi] ! 1139: ror ax,cl ! 1140: or [edi+1],ah ! 1141: mov ax,[esi+1] ! 1142: add esi,3 ! 1143: ror ax,cl ! 1144: or [edi+2],ah ! 1145: add edi,edx ! 1146: dec ebx ! 1147: jnz @B ! 1148: jmp pGlyphLoop ! 1149: ! 1150: ;-----------------------------------------------------------------------; ! 1151: ; MOV first byte, 3 bytes wide dest, rotated, need final source byte. ! 1152: ;-----------------------------------------------------------------------; ! 1153: mov_first_3_wide_rotated_need_last: ! 1154: @@: ! 1155: mov al,[esi] ! 1156: shr al,cl ! 1157: mov [edi],al ! 1158: mov ax,[esi] ! 1159: ror ax,cl ! 1160: mov [edi+1],ah ! 1161: mov ax,[esi+1] ! 1162: add esi,3 ! 1163: ror ax,cl ! 1164: mov [edi+2],ah ! 1165: add edi,edx ! 1166: dec ebx ! 1167: jnz @B ! 1168: jmp pGlyphLoop ! 1169: ! 1170: ;-----------------------------------------------------------------------; ! 1171: ; OR first byte, 3 bytes wide dest, rotated, don't need final source byte. ! 1172: ;-----------------------------------------------------------------------; ! 1173: or_first_3_wide_rotated_no_last: ! 1174: neg cl ! 1175: and cl,111b ;convert from right shift to left shift ! 1176: @@: ! 1177: sub eax,eax ! 1178: mov ax,[esi] ! 1179: add esi,2 ! 1180: xchg ah,al ! 1181: shl eax,cl ! 1182: mov [edi+1],ah ! 1183: mov [edi+2],al ! 1184: shr eax,16 ! 1185: or [edi],al ! 1186: add edi,edx ! 1187: dec ebx ! 1188: jnz @B ! 1189: jmp pGlyphLoop ! 1190: ! 1191: ;-----------------------------------------------------------------------; ! 1192: ; OR all bytes, 3 bytes wide dest, rotated, don't need final source byte. ! 1193: ;-----------------------------------------------------------------------; ! 1194: or_all_3_wide_rotated_no_last: ! 1195: neg cl ! 1196: and cl,111b ;convert from right shift to left shift ! 1197: @@: ! 1198: sub eax,eax ! 1199: mov ax,[esi] ! 1200: add esi,2 ! 1201: xchg ah,al ! 1202: shl eax,cl ! 1203: xchg ah,al ! 1204: or [edi+1],ax ! 1205: shr eax,16 ! 1206: or [edi],al ! 1207: add edi,edx ! 1208: dec ebx ! 1209: jnz @B ! 1210: jmp pGlyphLoop ! 1211: ! 1212: ;-----------------------------------------------------------------------; ! 1213: ; MOV first byte, 3 bytes wide dest, rotated, don't need final source byte. ! 1214: ;-----------------------------------------------------------------------; ! 1215: mov_first_3_wide_rotated_no_last: ! 1216: neg cl ! 1217: and cl,111b ;convert from right shift to left shift ! 1218: @@: ! 1219: sub eax,eax ! 1220: mov ax,[esi] ! 1221: add esi,2 ! 1222: xchg ah,al ! 1223: shl eax,cl ! 1224: mov [edi+1],ah ! 1225: mov [edi+2],al ! 1226: shr eax,16 ! 1227: mov [edi],al ! 1228: add edi,edx ! 1229: dec ebx ! 1230: jnz @B ! 1231: jmp pGlyphLoop ! 1232: ! 1233: ;-----------------------------------------------------------------------; ! 1234: ; MOV first byte, 3 bytes wide dest, unrotated. ! 1235: ;-----------------------------------------------------------------------; ! 1236: mov_first_3_wide_unrotated: ! 1237: @@: ! 1238: mov ax,[esi] ! 1239: mov [edi],ax ! 1240: mov al,[esi+2] ! 1241: add esi,3 ! 1242: mov [edi+2],al ! 1243: add edi,edx ! 1244: dec ebx ! 1245: jnz @B ! 1246: jmp pGlyphLoop ! 1247: ! 1248: ;-----------------------------------------------------------------------; ! 1249: ; OR all bytes, 3 bytes wide dest, unrotated. ! 1250: ;-----------------------------------------------------------------------; ! 1251: or_all_3_wide_unrotated: ! 1252: @@: ! 1253: mov ax,[esi] ! 1254: or [edi],ax ! 1255: mov al,[esi+2] ! 1256: add esi,3 ! 1257: or [edi+2],al ! 1258: add edi,edx ! 1259: dec ebx ! 1260: jnz @B ! 1261: jmp pGlyphLoop ! 1262: ! 1263: ;-----------------------------------------------------------------------; ! 1264: ; OR first byte, 4 bytes wide dest, rotated, need final source byte. ! 1265: ;-----------------------------------------------------------------------; ! 1266: or_first_4_wide_rotated_need_last: ! 1267: @@: ! 1268: mov eax,[esi] ! 1269: add esi,4 ! 1270: xchg ah,al ! 1271: ror eax,16 ! 1272: xchg ah,al ! 1273: shr eax,cl ! 1274: xchg ah,al ! 1275: mov [edi+2],ax ! 1276: shr eax,16 ! 1277: mov [edi+1],al ! 1278: or [edi],ah ! 1279: add edi,edx ! 1280: dec ebx ! 1281: jnz @B ! 1282: jmp pGlyphLoop ! 1283: ! 1284: ;-----------------------------------------------------------------------; ! 1285: ; OR all bytes, 4 bytes wide dest, rotated, need final source byte. ! 1286: ;-----------------------------------------------------------------------; ! 1287: or_all_4_wide_rotated_need_last: ! 1288: @@: ! 1289: mov eax,[esi] ! 1290: add esi,4 ! 1291: xchg ah,al ! 1292: ror eax,16 ! 1293: xchg ah,al ! 1294: shr eax,cl ! 1295: xchg ah,al ! 1296: ror eax,16 ! 1297: xchg al,ah ! 1298: or [edi],eax ! 1299: add edi,edx ! 1300: dec ebx ! 1301: jnz @B ! 1302: jmp pGlyphLoop ! 1303: ! 1304: ;-----------------------------------------------------------------------; ! 1305: ; MOV first byte, 4 bytes wide dest, rotated, need final source byte. ! 1306: ;-----------------------------------------------------------------------; ! 1307: mov_first_4_wide_rotated_need_last: ! 1308: @@: ! 1309: mov eax,[esi] ! 1310: add esi,4 ! 1311: xchg ah,al ! 1312: ror eax,16 ! 1313: xchg ah,al ! 1314: shr eax,cl ! 1315: xchg ah,al ! 1316: ror eax,16 ! 1317: xchg ah,al ! 1318: mov [edi],eax ! 1319: add edi,edx ! 1320: dec ebx ! 1321: jnz @B ! 1322: jmp pGlyphLoop ! 1323: ! 1324: ;-----------------------------------------------------------------------; ! 1325: ; OR first byte, 4 bytes wide dest, rotated, don't need final source byte. ! 1326: ;-----------------------------------------------------------------------; ! 1327: or_first_4_wide_rotated_no_last: ! 1328: @@: ! 1329: mov ax,[esi] ! 1330: xchg ah,al ! 1331: shl eax,16 ! 1332: mov ah,[esi+2] ! 1333: add esi,3 ! 1334: shr eax,cl ! 1335: xchg ah,al ! 1336: mov [edi+2],ax ! 1337: shr eax,16 ! 1338: mov [edi+1],al ! 1339: or [edi],ah ! 1340: add edi,edx ! 1341: dec ebx ! 1342: jnz @B ! 1343: jmp pGlyphLoop ! 1344: ! 1345: ;-----------------------------------------------------------------------; ! 1346: ; OR all bytes, 4 bytes wide dest, rotated, don't need final source byte. ! 1347: ;-----------------------------------------------------------------------; ! 1348: or_all_4_wide_rotated_no_last: ! 1349: @@: ! 1350: mov ax,[esi] ! 1351: xchg ah,al ! 1352: shl eax,16 ! 1353: mov ah,[esi+2] ! 1354: add esi,3 ! 1355: shr eax,cl ! 1356: xchg ah,al ! 1357: ror eax,16 ! 1358: xchg ah,al ! 1359: or [edi],eax ! 1360: add edi,edx ! 1361: dec ebx ! 1362: jnz @B ! 1363: jmp pGlyphLoop ! 1364: ! 1365: ;-----------------------------------------------------------------------; ! 1366: ; MOV first byte, 4 bytes wide dest, rotated, don't need final source byte. ! 1367: ;-----------------------------------------------------------------------; ! 1368: mov_first_4_wide_rotated_no_last: ! 1369: @@: ! 1370: mov ax,[esi] ! 1371: xchg ah,al ! 1372: shl eax,16 ! 1373: mov ah,[esi+2] ! 1374: add esi,3 ! 1375: shr eax,cl ! 1376: xchg ah,al ! 1377: ror eax,16 ! 1378: xchg ah,al ! 1379: mov [edi],eax ! 1380: add edi,edx ! 1381: dec ebx ! 1382: jnz @B ! 1383: jmp pGlyphLoop ! 1384: ! 1385: ;-----------------------------------------------------------------------; ! 1386: ; MOV first byte, 4 bytes wide dest, unrotated. ! 1387: ;-----------------------------------------------------------------------; ! 1388: mov_first_4_wide_unrotated: ! 1389: @@: ! 1390: mov eax,[esi] ! 1391: add esi,4 ! 1392: mov [edi],eax ! 1393: add edi,edx ! 1394: dec ebx ! 1395: jnz @B ! 1396: jmp pGlyphLoop ! 1397: ! 1398: ;-----------------------------------------------------------------------; ! 1399: ; OR all bytes, 4 bytes wide dest, unrotated. ! 1400: ;-----------------------------------------------------------------------; ! 1401: or_all_4_wide_unrotated: ! 1402: @@: ! 1403: mov eax,[esi] ! 1404: add esi,4 ! 1405: or [edi],eax ! 1406: add edi,edx ! 1407: dec ebx ! 1408: jnz @B ! 1409: jmp pGlyphLoop ! 1410: ! 1411: ;-----------------------------------------------------------------------; ! 1412: ; OR first byte, n bytes wide dest, rotated, need final source byte. ! 1413: ;-----------------------------------------------------------------------; ! 1414: or_first_N_wide_rotated_need_last: ! 1415: mov eax,ulWidthInBytes ! 1416: mov edx,ulBufDelta ! 1417: sub edx,eax ! 1418: mov ulTmpDstDelta,edx ! 1419: dec eax ;source doesn't advance after first byte, and ! 1420: ; we do the first byte outside the loop ! 1421: mov edx,ulGlyDelta ! 1422: sub edx,eax ! 1423: mov ulTmpSrcDelta,edx ! 1424: mov ulTmpWidthInBytes,eax ! 1425: ofNwrnl_scan_loop: ! 1426: mov al,[esi] ;do the initial, ORed byte separately ! 1427: shr al,cl ! 1428: or [edi],al ! 1429: inc edi ! 1430: mov edx,ulTmpWidthInBytes ! 1431: @@: ! 1432: mov ax,[esi] ! 1433: inc esi ! 1434: ror ax,cl ! 1435: mov [edi],ah ! 1436: inc edi ! 1437: dec edx ! 1438: jnz @B ! 1439: add esi,ulTmpSrcDelta ! 1440: add edi,ulTmpDstDelta ! 1441: dec ebx ! 1442: jnz ofNwrnl_scan_loop ! 1443: jmp pGlyphLoop ! 1444: ! 1445: ;-----------------------------------------------------------------------; ! 1446: ; OR all bytes, n bytes wide dest, rotated, need final source byte. ! 1447: ;-----------------------------------------------------------------------; ! 1448: or_all_N_wide_rotated_need_last: ! 1449: mov eax,ulWidthInBytes ! 1450: mov edx,ulBufDelta ! 1451: sub edx,eax ! 1452: mov ulTmpDstDelta,edx ! 1453: dec eax ;source doesn't advance after first byte, and ! 1454: ; we do the first byte outside the loop ! 1455: mov edx,ulGlyDelta ! 1456: sub edx,eax ! 1457: mov ulTmpSrcDelta,edx ! 1458: mov ulTmpWidthInBytes,eax ! 1459: oaNwrnl_scan_loop: ! 1460: mov al,[esi] ;do the initial, ORed byte separately ! 1461: shr al,cl ! 1462: or [edi],al ! 1463: inc edi ! 1464: mov edx,ulTmpWidthInBytes ! 1465: @@: ! 1466: mov ax,[esi] ! 1467: inc esi ! 1468: ror ax,cl ! 1469: or [edi],ah ! 1470: inc edi ! 1471: dec edx ! 1472: jnz @B ! 1473: add esi,ulTmpSrcDelta ! 1474: add edi,ulTmpDstDelta ! 1475: dec ebx ! 1476: jnz oaNwrnl_scan_loop ! 1477: jmp pGlyphLoop ! 1478: ! 1479: ;-----------------------------------------------------------------------; ! 1480: ; MOV first byte, n bytes wide dest, rotated, need final source byte. ! 1481: ;-----------------------------------------------------------------------; ! 1482: mov_first_N_wide_rotated_need_last: ! 1483: mov eax,ulWidthInBytes ! 1484: mov edx,ulBufDelta ! 1485: sub edx,eax ! 1486: mov ulTmpDstDelta,edx ! 1487: mov eax,ulWidthInBytes ! 1488: dec eax ;source doesn't advance after first byte, and ! 1489: ; we do the first byte outside the loop ! 1490: mov edx,ulGlyDelta ! 1491: sub edx,eax ! 1492: mov ulTmpSrcDelta,edx ! 1493: mov ulTmpWidthInBytes,eax ! 1494: mfNwrnl_scan_loop: ! 1495: mov al,[esi] ;do the initial byte separately ! 1496: shr al,cl ! 1497: mov [edi],al ! 1498: inc edi ! 1499: mov edx,ulTmpWidthInBytes ! 1500: @@: ! 1501: mov ax,[esi] ! 1502: inc esi ! 1503: ror ax,cl ! 1504: mov [edi],ah ! 1505: inc edi ! 1506: dec edx ! 1507: jnz @B ! 1508: add esi,ulTmpSrcDelta ! 1509: add edi,ulTmpDstDelta ! 1510: dec ebx ! 1511: jnz mfNwrnl_scan_loop ! 1512: jmp pGlyphLoop ! 1513: ! 1514: ;-----------------------------------------------------------------------; ! 1515: ; OR first byte, N bytes wide dest, rotated, don't need final source byte. ! 1516: ;-----------------------------------------------------------------------; ! 1517: or_first_N_wide_rotated_no_last: ! 1518: mov eax,ulWidthInBytes ! 1519: dec eax ;one less because we don't advance after the ! 1520: ; last byte ! 1521: mov edx,ulBufDelta ! 1522: sub edx,eax ! 1523: mov ulTmpDstDelta,edx ! 1524: dec eax ;source doesn't advance after first byte, and ! 1525: ; we do the first & last bytes outside the ! 1526: ; loop; already subtracted 1 above ! 1527: mov edx,ulGlyDelta ! 1528: sub edx,eax ! 1529: mov ulTmpSrcDelta,edx ! 1530: mov ulTmpWidthInBytes,eax ! 1531: ofNwr_scan_loop: ! 1532: mov al,[esi] ;do the initial, ORed byte separately ! 1533: shr al,cl ! 1534: or [edi],al ! 1535: inc edi ! 1536: mov edx,ulTmpWidthInBytes ! 1537: @@: ! 1538: mov ax,[esi] ! 1539: inc esi ! 1540: ror ax,cl ! 1541: mov [edi],ah ! 1542: inc edi ! 1543: dec edx ! 1544: jnz @B ! 1545: ! 1546: mov ah,[esi] ;do the final byte separately ! 1547: sub al,al ! 1548: shr eax,cl ! 1549: mov [edi],al ! 1550: ! 1551: add esi,ulTmpSrcDelta ! 1552: add edi,ulTmpDstDelta ! 1553: dec ebx ! 1554: jnz ofNwr_scan_loop ! 1555: jmp pGlyphLoop ! 1556: ! 1557: ;-----------------------------------------------------------------------; ! 1558: ; OR all bytes, N bytes wide dest, rotated, don't need final source byte. ! 1559: ;-----------------------------------------------------------------------; ! 1560: or_all_N_wide_rotated_no_last: ! 1561: mov eax,ulWidthInBytes ! 1562: dec eax ;one less because we don't advance after the ! 1563: ; last byte ! 1564: mov edx,ulBufDelta ! 1565: sub edx,eax ! 1566: mov ulTmpDstDelta,edx ! 1567: dec eax ;source doesn't advance after first byte, and ! 1568: ; we do the first & last bytes outside the ! 1569: ; loop; already subtracted 1 above ! 1570: mov edx,ulGlyDelta ! 1571: sub edx,eax ! 1572: mov ulTmpSrcDelta,edx ! 1573: mov ulTmpWidthInBytes,eax ! 1574: oaNwr_scan_loop: ! 1575: mov al,[esi] ;do the initial, ORed byte separately ! 1576: shr al,cl ! 1577: or [edi],al ! 1578: inc edi ! 1579: mov edx,ulTmpWidthInBytes ! 1580: @@: ! 1581: mov ax,[esi] ! 1582: inc esi ! 1583: ror ax,cl ! 1584: or [edi],ah ! 1585: inc edi ! 1586: dec edx ! 1587: jnz @B ! 1588: ! 1589: mov ah,[esi] ;do the final byte separately ! 1590: sub al,al ! 1591: shr eax,cl ! 1592: or [edi],al ! 1593: ! 1594: add esi,ulTmpSrcDelta ! 1595: add edi,ulTmpDstDelta ! 1596: dec ebx ! 1597: jnz oaNwr_scan_loop ! 1598: jmp pGlyphLoop ! 1599: ! 1600: ;-----------------------------------------------------------------------; ! 1601: ; MOV first byte, N bytes wide dest, rotated, don't need final source byte. ! 1602: ;-----------------------------------------------------------------------; ! 1603: mov_first_N_wide_rotated_no_last: ! 1604: mov eax,ulWidthInBytes ! 1605: dec eax ;one less because we don't advance after the ! 1606: ; last byte ! 1607: mov edx,ulBufDelta ! 1608: sub edx,eax ! 1609: mov ulTmpDstDelta,edx ! 1610: dec eax ;source doesn't advance after first byte, and ! 1611: ; we do the first & last bytes outside the ! 1612: ; loop; already subtracted 1 above ! 1613: mov edx,ulGlyDelta ! 1614: sub edx,eax ! 1615: mov ulTmpSrcDelta,edx ! 1616: mov ulTmpWidthInBytes,eax ! 1617: mfNwr_scan_loop: ! 1618: mov al,[esi] ;do the initial byte separately ! 1619: shr al,cl ! 1620: mov [edi],al ! 1621: inc edi ! 1622: mov edx,ulTmpWidthInBytes ! 1623: @@: ! 1624: mov ax,[esi] ! 1625: inc esi ! 1626: ror ax,cl ! 1627: mov [edi],ah ! 1628: inc edi ! 1629: dec edx ! 1630: jnz @B ! 1631: ! 1632: mov ah,[esi] ;do the final byte separately ! 1633: sub al,al ! 1634: shr eax,cl ! 1635: mov [edi],al ! 1636: ! 1637: add esi,ulTmpSrcDelta ! 1638: add edi,ulTmpDstDelta ! 1639: dec ebx ! 1640: jnz mfNwr_scan_loop ! 1641: jmp pGlyphLoop ! 1642: ! 1643: ;-----------------------------------------------------------------------; ! 1644: ; MOV first byte, N bytes wide dest, unrotated. ! 1645: ;-----------------------------------------------------------------------; ! 1646: mov_first_N_wide_unrotated: ! 1647: mov edx,ulBufDelta ! 1648: mov eax,ulWidthInBytes ! 1649: sub edx,eax ! 1650: shr eax,1 ;width in words ! 1651: jc short odd_width ;there's at least one odd byte ! 1652: shr eax,1 ;width in dwords ! 1653: jc short two_odd_bytes ;there's an odd word ! 1654: ;copy width is a dword multiple ! 1655: @@: ! 1656: mov ecx,eax ! 1657: rep movsd ;copy as many dwords as possible ! 1658: add edi,edx ! 1659: dec ebx ! 1660: jnz @B ! 1661: jmp pGlyphLoop ! 1662: ! 1663: odd_width: ! 1664: shr eax,1 ;width in dwords ! 1665: jc short three_odd_bytes ;there's an odd word and an odd byte ! 1666: ;there's just an odd byte ! 1667: inc edx ;because we won't advance after last byte ! 1668: @@: ! 1669: mov ecx,eax ! 1670: rep movsd ;copy as many dwords as possible ! 1671: mov cl,[esi] ! 1672: inc esi ! 1673: mov [edi],cl ! 1674: add edi,edx ! 1675: dec ebx ! 1676: jnz @B ! 1677: jmp pGlyphLoop ! 1678: ! 1679: two_odd_bytes: ! 1680: add edx,2 ;because we won't advance after last word ! 1681: @@: ! 1682: mov ecx,eax ! 1683: rep movsd ;copy as many dwords as possible ! 1684: mov cx,[esi] ! 1685: add esi,2 ! 1686: mov [edi],cx ! 1687: add edi,edx ! 1688: dec ebx ! 1689: jnz @B ! 1690: jmp pGlyphLoop ! 1691: ! 1692: three_odd_bytes: ! 1693: add edx,3 ;because we won't advance after last word/byte ! 1694: @@: ! 1695: mov ecx,eax ! 1696: rep movsd ;copy as many dwords as possible ! 1697: mov cx,[esi] ! 1698: mov [edi],cx ! 1699: mov cl,[esi+2] ! 1700: add esi,3 ! 1701: mov [edi+2],cl ! 1702: add edi,edx ! 1703: dec ebx ! 1704: jnz @B ! 1705: jmp pGlyphLoop ! 1706: ! 1707: ;-----------------------------------------------------------------------; ! 1708: ; OR all bytes, N bytes wide dest, unrotated. ! 1709: ;-----------------------------------------------------------------------; ! 1710: or_all_N_wide_unrotated: ! 1711: mov edx,ulBufDelta ! 1712: mov eax,ulWidthInBytes ! 1713: sub edx,eax ! 1714: shr eax,1 ;width in words ! 1715: jc short or_odd_width ;there's at least one odd byte ! 1716: shr eax,1 ;width in dwords ! 1717: jc short or_two_odd_bytes ;there's an odd word ! 1718: ;copy width is a dword multiple ! 1719: or_no_odd_bytes_loop: ! 1720: push ebx ;preserve scan count ! 1721: mov ebx,eax ! 1722: @@: ! 1723: mov ecx,[esi] ! 1724: add esi,4 ! 1725: or [edi],ecx ! 1726: add edi,4 ;copy as many dwords as possible ! 1727: dec ebx ! 1728: jnz @B ! 1729: add edi,edx ! 1730: pop ebx ;restore scan count ! 1731: dec ebx ! 1732: jnz or_no_odd_bytes_loop ! 1733: jmp pGlyphLoop ! 1734: ! 1735: or_odd_width: ! 1736: shr eax,1 ;width in dwords ! 1737: jc short three_odd_bytes ;there's an odd word and an odd byte ! 1738: ;there's just an odd byte ! 1739: inc edx ;skip over last byte too ! 1740: or_one_odd_bytes_loop: ! 1741: push ebx ;preserve scan count ! 1742: mov ebx,eax ! 1743: @@: ! 1744: mov ecx,[esi] ! 1745: add esi,4 ! 1746: or [edi],ecx ! 1747: add edi,4 ;copy as many dwords as possible ! 1748: dec ebx ! 1749: jnz @B ! 1750: mov cl,[esi] ! 1751: or [edi],cl ! 1752: inc esi ! 1753: add edi,edx ! 1754: pop ebx ;restore scan count ! 1755: dec ebx ! 1756: jnz or_one_odd_bytes_loop ! 1757: jmp pGlyphLoop ! 1758: ! 1759: or_two_odd_bytes: ! 1760: add edx,2 ;skip over last 2 bytes too ! 1761: or_two_odd_bytes_loop: ! 1762: push ebx ;preserve scan count ! 1763: mov ebx,eax ! 1764: @@: ! 1765: mov ecx,[esi] ! 1766: add esi,4 ! 1767: or [edi],ecx ! 1768: add edi,4 ;copy as many dwords as possible ! 1769: dec ebx ! 1770: jnz @B ! 1771: mov cx,[esi] ! 1772: or [edi],cx ! 1773: add esi,2 ! 1774: add edi,edx ! 1775: pop ebx ;restore scan count ! 1776: dec ebx ! 1777: jnz or_two_odd_bytes_loop ! 1778: jmp pGlyphLoop ! 1779: ! 1780: or_three_odd_bytes: ! 1781: add edx,3 ;skip over last 3 bytes too ! 1782: or_three_odd_bytes_loop: ! 1783: push ebx ;preserve scan count ! 1784: mov ebx,eax ! 1785: @@: ! 1786: mov ecx,[esi] ! 1787: add esi,4 ! 1788: or [edi],ecx ! 1789: add edi,4 ;copy as many dwords as possible ! 1790: dec ebx ! 1791: jnz @B ! 1792: mov cx,[esi] ! 1793: or [edi],cx ! 1794: mov cl,[esi+2] ! 1795: or [edi+2],cl ! 1796: add esi,3 ! 1797: add edi,edx ! 1798: pop ebx ;restore scan count ! 1799: dec ebx ! 1800: jnz or_three_odd_bytes_loop ! 1801: jmp pGlyphLoop ! 1802: ! 1803: ;-----------------------------------------------------------------------; ! 1804: ; At this point, the text is drawn to the temp buffer. ! 1805: ; Now, draw the temp buffer to the screen. ! 1806: ; ! 1807: ; Input: ! 1808: ; pdsurf = pointer to target surface (screen) ! 1809: ; prclText = pointer to text bounding rectangle ! 1810: ; prclOpaque = pointer to opaquing rectangle, if there is one ! 1811: ; iFgColor = text color ! 1812: ; iBgColor = opaquing rectangle color, if there is one ! 1813: ; ulTempLeft = X coordinate on dest of left edge of temp buffer pointed ! 1814: ; to by pTempBuffer ! 1815: ; pTempBuffer = pointer to first byte (upper left corner) of ! 1816: ; temp buffer into which we're drawing. This should be ! 1817: ; word-aligned with the destination ! 1818: ; ulBufDelta = destination scan-to-scan offset ! 1819: ; Text drawn to temp buffer ! 1820: ; ! 1821: ;-----------------------------------------------------------------------; ! 1822: draw_to_screen: ! 1823: ! 1824: ;-----------------------------------------------------------------------; ! 1825: ; Is this transparent or opaque text? ! 1826: ;-----------------------------------------------------------------------; ! 1827: ! 1828: mov esi,prclText ! 1829: cmp prclOpaque,0 ! 1830: jnz opaque_text ! 1831: ! 1832: ;-----------------------------------------------------------------------; ! 1833: ; Transparent text. ! 1834: ; ESI = prclText ! 1835: ;-----------------------------------------------------------------------; ! 1836: ! 1837: ;-----------------------------------------------------------------------; ! 1838: ; Set up the VGA's hardware for read mode 1 and write mode 3. ! 1839: ;-----------------------------------------------------------------------; ! 1840: ! 1841: mov edx,VGA_BASE + GRAF_ADDR ! 1842: mov eax,GRAF_MODE + ((M_AND_WRITE + M_COLOR_READ) SHL 8) ! 1843: out dx,ax ;write mode 3 so we can do masking ! 1844: ; without OUTs, read mode 1 so we can ! 1845: ; read 0xFF from memory always, for ! 1846: ; ANDing (because Color Don't Care is ! 1847: ; all zeros) ! 1848: ! 1849: mov al,GRAF_SET_RESET ! 1850: mov ah,byte ptr iFgColor ! 1851: out dx,ax ;set the drawing color ! 1852: ! 1853: ;-----------------------------------------------------------------------; ! 1854: ; Calculate drawing parameters. ! 1855: ;-----------------------------------------------------------------------; ! 1856: ! 1857: mov eax,[esi].yBottom ! 1858: mov ulBottomScan,eax ;bottom scan of text area ! 1859: mov eax,[esi].xRight ! 1860: mov edx,[esi].xLeft ! 1861: and edx,not 7 ! 1862: add eax,7 ! 1863: sub eax,edx ! 1864: shr eax,3 ;width of text in bytes, rounded up ! 1865: ! 1866: mov edx,eax ;width in bytes ! 1867: mov ecx,eax ! 1868: and edx,7 ;# of odd (non-qword) bytes ! 1869: mov edi,XparEntryTable[edx*4] ! 1870: mov pfnEntry,edi ;entry point into unrolled loop for odd bytes ! 1871: add ecx,7 ! 1872: shr ecx,3 ;width in qwords (unrolled loop count) ! 1873: mov ulLoopCount,ecx ! 1874: ! 1875: neg edx ;amount by which we have to compensate back ! 1876: and edx,07h ; before starting, because of the hard-wired ! 1877: ; displacements used in the unrolled loop ! 1878: ! 1879: add eax,edx ;adjust effective width for compensation ! 1880: ! 1881: mov ecx,ulBufDelta ! 1882: sub ecx,eax ;offset to next scan in temp buffer ! 1883: mov ulTmpSrcDelta,ecx ! 1884: ! 1885: mov ebx,pdsurf ! 1886: mov ecx,ulScreenDelta ! 1887: sub ecx,eax ;offset to next scan in screen ! 1888: mov ulTmpDstDelta,ecx ! 1889: ! 1890: mov eax,[esi].yTop ! 1891: imul eax,ulScreenDelta ;this form of IMUL so we can avoid wiping ! 1892: ; out EDX ! 1893: mov edi,[esi].xLeft ! 1894: shr edi,3 ! 1895: add edi,eax ! 1896: sub edi,edx ;compensate back for displacement of initial ! 1897: ; entry point into unrolled loop, below ! 1898: ! 1899: ;-----------------------------------------------------------------------; ! 1900: ; Map in the bank containing the top scan of the text, if it's not ! 1901: ; mapped in already. ! 1902: ;-----------------------------------------------------------------------; ! 1903: ! 1904: mov eax,[esi].yTop ;top scan line of text ! 1905: mov ulTopScan,eax ! 1906: mov esi,pTempBuffer ;initial source address ! 1907: sub esi,edx ;compensate back for displacement of initial ! 1908: ; entry point into unrolled loop, below ! 1909: cmp eax,[ebx].dsurf_rcl1WindowClip.yTop ;is text top less than ! 1910: ; current bank? ! 1911: jl short xpar_map_init_bank ;yes, map in proper bank ! 1912: cmp eax,[ebx].dsurf_rcl1WindowClip.yBottom ;text top greater than ! 1913: ; current bank? ! 1914: jl short xpar_init_bank_mapped ;no, proper bank already mapped ! 1915: xpar_map_init_bank: ! 1916: ! 1917: ; Map in the bank containing the top scan line of the fill. ! 1918: ; Preserves EBX, ESI, and EDI. ! 1919: ! 1920: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyTop> ! 1921: ! 1922: xpar_init_bank_mapped: ! 1923: ! 1924: add edi,[ebx].dsurf_pvBitmapStart ;initial destination address ! 1925: ! 1926: ;-----------------------------------------------------------------------; ! 1927: ; Main loop for processing fill in each bank. ! 1928: ; ! 1929: ; At start of loop, EBX->pdsurf ! 1930: ;-----------------------------------------------------------------------; ! 1931: ! 1932: xpar_bank_loop: ! 1933: mov edx,ulBottomScan ;bottom of destination rectangle ! 1934: cmp edx,[ebx].dsurf_rcl1WindowClip.yBottom ! 1935: ;which comes first, the bottom of the ! 1936: ; text rect or the bottom of the ! 1937: ; current bank? ! 1938: jl short @F ;text bottom comes first, so draw to ! 1939: ; that; this is the last bank in text ! 1940: mov edx,[ebx].dsurf_rcl1WindowClip.yBottom ! 1941: ;bank bottom comes first; draw to ! 1942: ; bottom of bank ! 1943: @@: ! 1944: sub edx,ulTopScan ;# of scans to draw in bank ! 1945: mov ebx,ulTmpSrcDelta ! 1946: ! 1947: xpar_scan_loop: ! 1948: mov ecx,ulLoopCount ;unrolled loop count ! 1949: jmp pfnEntry ;jump into the unrolled loop ! 1950: ! 1951: ;----------------------------------------------------------------------- ! 1952: ; Entry points into unrolled xpar loop for various odd byte counts. ! 1953: align 4 ! 1954: XparEntryTable label dword ! 1955: dd xpar_enter_8 ! 1956: dd xpar_enter_1 ! 1957: dd xpar_enter_2 ! 1958: dd xpar_enter_3 ! 1959: dd xpar_enter_4 ! 1960: dd xpar_enter_5 ! 1961: dd xpar_enter_6 ! 1962: dd xpar_enter_7 ! 1963: ! 1964: ;----------------------------------------------------------------------- ! 1965: ; Unrolled xpar loop. ! 1966: xpar_byte_loop: ! 1967: xpar_enter_8: ! 1968: mov al,[esi] ;get next temp buffer byte ! 1969: and al,al ;is it zero? ! 1970: jz short @F ;yes, skip it ! 1971: and [edi],al ;draw the byte with transparency ! 1972: @@: ! 1973: xpar_enter_7: ! 1974: mov al,[esi+1] ;get next temp buffer byte ! 1975: and al,al ;is it zero? ! 1976: jz short @F ;yes, skip it ! 1977: and [edi+1],al ;draw the byte with transparency ! 1978: @@: ! 1979: xpar_enter_6: ! 1980: mov al,[esi+2] ;get next temp buffer byte ! 1981: and al,al ;is it zero? ! 1982: jz short @F ;yes, skip it ! 1983: and [edi+2],al ;draw the byte with transparency ! 1984: @@: ! 1985: xpar_enter_5: ! 1986: mov al,[esi+3] ;get next temp buffer byte ! 1987: and al,al ;is it zero? ! 1988: jz short @F ;yes, skip it ! 1989: and [edi+3],al ;draw the byte with transparency ! 1990: @@: ! 1991: xpar_enter_4: ! 1992: mov al,[esi+4] ;get next temp buffer byte ! 1993: and al,al ;is it zero? ! 1994: jz short @F ;yes, skip it ! 1995: and [edi+4],al ;draw the byte with transparency ! 1996: @@: ! 1997: xpar_enter_3: ! 1998: mov al,[esi+5] ;get next temp buffer byte ! 1999: and al,al ;is it zero? ! 2000: jz short @F ;yes, skip it ! 2001: and [edi+5],al ;draw the byte with transparency ! 2002: @@: ! 2003: xpar_enter_2: ! 2004: mov al,[esi+6] ;get next temp buffer byte ! 2005: and al,al ;is it zero? ! 2006: jz short @F ;yes, skip it ! 2007: and [edi+6],al ;draw the byte with transparency ! 2008: @@: ! 2009: xpar_enter_1: ! 2010: mov al,[esi+7] ;get next temp buffer byte ! 2011: and al,al ;is it zero? ! 2012: jz short @F ;yes, skip it ! 2013: and [edi+7],al ;draw the byte with transparency ! 2014: @@: ! 2015: add esi,8 ! 2016: add edi,8 ! 2017: dec ecx ! 2018: jnz xpar_byte_loop ! 2019: ! 2020: add esi,ebx ;point to next buffer scan ! 2021: add edi,ulTmpDstDelta ;point to next screen scan ! 2022: ! 2023: dec edx ;count down scans ! 2024: jnz xpar_scan_loop ! 2025: ! 2026: ;-----------------------------------------------------------------------; ! 2027: ; See if there are more banks to draw. ! 2028: ;-----------------------------------------------------------------------; ! 2029: ! 2030: mov ebx,pdsurf ! 2031: mov eax,[ebx].dsurf_rcl1WindowClip.yBottom ;is the text bottom in ! 2032: cmp ulBottomScan,eax ; the current bank? ! 2033: jnle short do_next_xpar_bank ;no, map in the next bank and draw ! 2034: ;yes, so we're done ! 2035: ! 2036: ;-----------------------------------------------------------------------; ! 2037: ; Restore the VGA's hardware state and we're done. ! 2038: ;-----------------------------------------------------------------------; ! 2039: ! 2040: mov edx,VGA_BASE + GRAF_ADDR ! 2041: mov eax,GRAF_MODE + ((M_PROC_WRITE + M_DATA_READ) SHL 8) ! 2042: out dx,ax ;restore read mode 0 and write mode 0 ! 2043: ! 2044: draw_prop_done: ! 2045: cRet vFastText ! 2046: ! 2047: do_next_xpar_bank: ! 2048: mov ulTopScan,eax ! 2049: sub edi,[ebx].dsurf_pvBitmapStart ;convert from address to offset ! 2050: ; within bitmap ! 2051: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,eax,JustifyTop> ! 2052: ;map in the bank (call preserves EBX, ! 2053: ; ESI, and EDI) ! 2054: add edi,[ebx].dsurf_pvBitmapStart ;convert from offset within ! 2055: ; bitmap to address (bitmap start ! 2056: ; just moved) ! 2057: jmp xpar_bank_loop ;we're ready to draw in the new bank ! 2058: ! 2059: ;-----------------------------------------------------------------------; ! 2060: ; Handle opaque clipping. ! 2061: ;-----------------------------------------------------------------------; ! 2062: ! 2063: do_opaque_clip: ! 2064: mov ebx,[esi].yBottom ! 2065: cmp [edi].yBottom,ebx ;is the bottom edge of the text box clipped? ! 2066: jg short @F ;no ! 2067: mov ebx,[edi].yBottom ;yes ! 2068: @@: ! 2069: mov dword ptr rclClippedBounds.yBottom,ebx ;set the (possibly ! 2070: ; clipped) bottom edge ! 2071: mov eax,[esi].yTop ! 2072: cmp [edi].yTop,eax ;is the top edge of the text box clipped? ! 2073: jle short @F ;no ! 2074: ;yes ! 2075: sub eax,[edi].yTop ! 2076: neg eax ;# of scans we just clipped off ! 2077: mul ulBufDelta ;# of bytes by which to advance through source ! 2078: add pTempBuffer,eax ;advance in source to account for Y clipping ! 2079: mov eax,[edi].yTop ;new top edge ! 2080: @@: ! 2081: mov dword ptr rclClippedBounds.yTop,eax ;set the (possibly clipped) ! 2082: ; top edge ! 2083: cmp eax,ebx ;is there a gap between clipped top & bottom? ! 2084: jnl short opaq_fully_clipped ;no, fully clipped ! 2085: ! 2086: mov edx,[esi].xRight ! 2087: cmp [edi].xRight,edx ;is the right edge of the text box clipped? ! 2088: jg short @F ;no ! 2089: mov edx,[edi].xRight ;yes ! 2090: @@: ! 2091: mov dword ptr rclClippedBounds.xRight,edx ;set the (possibly ! 2092: ; clipped) right edge ! 2093: mov eax,[esi].xLeft ! 2094: cmp [edi].xLeft,eax ;is the left edge of the text box clipped? ! 2095: jle short @F ;no ! 2096: ;yes ! 2097: mov ebx,[edi].xLeft ;EBX = new left edge ! 2098: and eax,not 0111b ;floor the old left edge in its byte ! 2099: sub ebx,eax ! 2100: shr ebx,3 ;# of bytes to advance in source ! 2101: add pTempBuffer,ebx ;advance in source to account for X clipping ! 2102: mov eax,[edi].xLeft ;new left edge ! 2103: @@: ! 2104: mov dword ptr rclClippedBounds.xLeft,eax ;set the (possibly ! 2105: ; clipped) left edge ! 2106: cmp eax,edx ;is there a gap between clipped left & right? ! 2107: jnl short opaq_fully_clipped ;no, fully clipped ! 2108: ! 2109: lea esi,rclClippedBounds ;this is now the destination rect ! 2110: jmp short clip_set ! 2111: ! 2112: opaq_fully_clipped: ! 2113: jmp done ! 2114: ! 2115: ;-----------------------------------------------------------------------; ! 2116: ; Opaque text. ! 2117: ; ESI = prclText ! 2118: ;-----------------------------------------------------------------------; ! 2119: ! 2120: opaque_text: ! 2121: ! 2122: ;-----------------------------------------------------------------------; ! 2123: ; Clip to the clip rectangle, if necessary. ! 2124: ;-----------------------------------------------------------------------; ! 2125: ! 2126: mov edi,prclClip ! 2127: and edi,edi ;is there clipping? ! 2128: jnz short do_opaque_clip ;yes ! 2129: ! 2130: ; ESI->destination text rectangle at this point ! 2131: clip_set: ! 2132: ! 2133: ;-----------------------------------------------------------------------; ! 2134: ; Set up the VGA's hardware for read mode 1 and write mode 3. ! 2135: ;-----------------------------------------------------------------------; ! 2136: ! 2137: mov edx,VGA_BASE + GRAF_ADDR ! 2138: mov eax,GRAF_MODE + ((M_AND_WRITE + M_COLOR_READ) SHL 8) ! 2139: out dx,ax ;write mode 3 so we can do masking ! 2140: ; without OUTs, read mode 1 so we can ! 2141: ; read 0xFF from memory always, for ! 2142: ; ANDing (because Color Don't Care is ! 2143: ; all zeros) ! 2144: ! 2145: ;-----------------------------------------------------------------------; ! 2146: ; Calculate the drawing parameters. ! 2147: ;-----------------------------------------------------------------------; ! 2148: ! 2149: mov eax,[esi].yBottom ! 2150: mov ulBottomScan,eax ;bottom scan of text area ! 2151: mov eax,[esi].xRight ! 2152: mov ebx,eax ! 2153: and ebx,111b ! 2154: mov edx,[esi].xLeft ! 2155: mov ch,jOpaqueRightMasks[ebx] ;set right edge clip mask ! 2156: mov ebx,edx ! 2157: and ebx,111b ! 2158: mov ulRightMask,ecx ;mask is expected to be in CH ! 2159: mov ch,jOpaqueLeftMasks[ebx] ;set left edge clip mask ! 2160: mov ulLeftMask,ecx ;mask is expected to be in CH ! 2161: ! 2162: mov ulTextLeft,edx ! 2163: and edx,not 7 ! 2164: add eax,7 ! 2165: sub eax,edx ! 2166: shr eax,3 ;width of text in bytes, rounded up ! 2167: mov ulTextWidthInBytes,eax ! 2168: ! 2169: ;-----------------------------------------------------------------------; ! 2170: ; Figure out what edges we need to handle, and calculate some info for ! 2171: ; doing whole bytes. ! 2172: ;-----------------------------------------------------------------------; ! 2173: ! 2174: cmp eax,1 ;only one byte total? ! 2175: jnz short @F ;no ! 2176: ;yes, special case ! 2177: mov ecx,offset opaq_check_more_banks ;assume it's a solid byte ! 2178: mov ebx,ulLeftMask ! 2179: and ebx,ulRightMask ! 2180: cmp bh,0ffh ;solid byte? ! 2181: jz short opaq_set_edge_vector ;yes, all set ! 2182: mov ulLeftMask,ebx ;no, draw as a left edge ! 2183: dec eax ;there are no whole bytes ! 2184: mov ecx,offset opaq_draw_left_edge_only ! 2185: jmp short opaq_set_edge_vector ;yes, all set ! 2186: ! 2187: @@: ! 2188: test [esi].xLeft,111b ;is left edge a solid byte? ! 2189: jz short opaq_left_edge_solid ;yes ! 2190: dec eax ;no, count off from whole bytes ! 2191: mov ecx,offset opaq_draw_left_edge_only ;assume right edge is solid ! 2192: test [esi].xRight,111b ;is right edge a solid byte? ! 2193: jz short opaq_set_edge_vector ;yes, all set ! 2194: dec eax ;no, count off from whole bytes ! 2195: mov ecx,offset opaq_draw_both_edges ;both edges are non-solid ! 2196: jmp short opaq_set_edge_vector ! 2197: ! 2198: opaq_left_edge_solid: ! 2199: mov ecx,offset opaq_check_more_banks ;assume right edge is solid ! 2200: test [esi].xRight,111b ;is right edge a solid byte? ! 2201: jz short opaq_set_edge_vector ;yes, all set ! 2202: dec eax ;no, count off from whole bytes ! 2203: mov ecx,offset opaq_draw_right_edge_only ;no, do non-solid right ! 2204: ; edge ! 2205: opaq_set_edge_vector: ! 2206: mov edi,ulBufDelta ! 2207: sub edi,eax ;whole bytes offset to next scan in temp buffer ! 2208: mov ulTmpSrcDelta,edi ! 2209: ! 2210: mov edi,ulScreenDelta ! 2211: sub edi,eax ;whole bytes offset to next scan in screen ! 2212: mov ulTmpDstDelta,edi ! 2213: ! 2214: mov pfnEdgeVector,ecx ! 2215: mov edx,eax ! 2216: mov pfnFirstOpaqVector,offset opaq_whole_bytes ! 2217: ;assume there are whole bytes, in which ! 2218: ; case we'll draw them first, then the ! 2219: ; edge bytes ! 2220: sub edi,edi ! 2221: shr edx,1 ;whole words ! 2222: mov ulWholeWidthInWords,edx ! 2223: adc edi,edi ;odd byte status ! 2224: mov ulOddByte,edi ! 2225: dec edx ;whole words - 1 ! 2226: mov ulWholeWidthInWordsMinus1,edx ! 2227: cmp eax,0 ;are there any whole bytes at all? ! 2228: jg short opaq_edges_set ;yes, we're all set ! 2229: ;no, set up for edge(s) only ! 2230: mov pfnFirstOpaqVector,ecx ;the edges are first, because there are ! 2231: ; no whole bytes ! 2232: ! 2233: opaq_edges_set: ! 2234: ! 2235: ;-----------------------------------------------------------------------; ! 2236: ; Determine the screen offset of the first destination byte. ! 2237: ;-----------------------------------------------------------------------; ! 2238: ! 2239: mov eax,[esi].yTop ! 2240: mov ulTopScan,eax ! 2241: mov ecx,eax ! 2242: mul ulScreenDelta ! 2243: mov edi,[esi].xLeft ! 2244: shr edi,3 ! 2245: mov ulTempLeft,edi ;remember the offset to the first dest byte ! 2246: add edi,eax ! 2247: ! 2248: ;-----------------------------------------------------------------------; ! 2249: ; Map in the bank containing the top scan of the text, if it's not ! 2250: ; mapped in already. ! 2251: ;-----------------------------------------------------------------------; ! 2252: ! 2253: mov ebx,pdsurf ! 2254: cmp ecx,[ebx].dsurf_rcl1WindowClip.yTop ;is text top less than ! 2255: ; current bank? ! 2256: jl short opaq_map_init_bank ;yes, map in proper bank ! 2257: cmp ecx,[ebx].dsurf_rcl1WindowClip.yBottom ;text top greater than ! 2258: ; current bank? ! 2259: jl short opaq_init_bank_mapped ;no, proper bank already mapped ! 2260: opaq_map_init_bank: ! 2261: ! 2262: ; Map in the bank containing the top scan line of the fill. ! 2263: ; Preserves EBX, ESI, and EDI. ! 2264: ! 2265: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,ecx,JustifyTop> ! 2266: ! 2267: opaq_init_bank_mapped: ! 2268: ! 2269: add edi,[ebx].dsurf_pvBitmapStart ;initial destination address ! 2270: mov pScreen,edi ! 2271: ! 2272: mov edx,VGA_BASE + GRAF_ADDR ! 2273: mov al,GRAF_SET_RESET ! 2274: out dx,al ;leave the GC Index pointing to ! 2275: ; set/reset ! 2276: ! 2277: ;-----------------------------------------------------------------------; ! 2278: ; Main loop for processing fill in each bank. ! 2279: ; ! 2280: ; At start of loop and on each loop, EBX->pdsurf and EDI->first destination ! 2281: ; byte. ! 2282: ;-----------------------------------------------------------------------; ! 2283: ! 2284: opaq_bank_loop: ! 2285: mov edx,ulBottomScan ;bottom of destination rectangle ! 2286: cmp edx,[ebx].dsurf_rcl1WindowClip.yBottom ! 2287: ;which comes first, the bottom of the ! 2288: ; text rect or the bottom of the ! 2289: ; current bank? ! 2290: jl short @F ;text bottom comes first, so draw to ! 2291: ; that; this is the last bank in text ! 2292: mov edx,[ebx].dsurf_rcl1WindowClip.yBottom ! 2293: ;bank bottom comes first; draw to ! 2294: ; bottom of bank ! 2295: @@: ! 2296: sub edx,ulTopScan ;# of scans to draw in bank ! 2297: mov ulNumScans,edx ! 2298: jmp pfnFirstOpaqVector ;do first sort of drawing (whole ! 2299: ; bytes, or edge(s) if no whole ! 2300: ; bytes) ! 2301: ! 2302: ;-----------------------------------------------------------------------; ! 2303: ; Draws whole bytes, which can be handled by simply loading the latches ! 2304: ; with the background color and using write mode 3 to punch the ! 2305: ; foreground color through. ! 2306: ; ! 2307: ; On entry: ! 2308: ; EDI = first destination byte ! 2309: ;-----------------------------------------------------------------------; ! 2310: opaq_whole_bytes: ! 2311: mov esi,pTempBuffer ! 2312: test ulTextLeft,111b ;is left edge solid? ! 2313: jz short @F ;yes ! 2314: inc esi ;no, point to leftmost source and dest ! 2315: inc edi ; bytes (skip over partial left edge) ! 2316: @@: ! 2317: ! 2318: ;-----------------------------------------------------------------------; ! 2319: ; Load the latches with the background color. ! 2320: ;-----------------------------------------------------------------------; ! 2321: ! 2322: mov edx,VGA_BASE + GRAF_DATA ! 2323: mov eax,iBgColor ! 2324: out dx,al ;set/reset color = background ! 2325: ! 2326: mov byte ptr [edi],0ffh ;we're in write mode 3, so write the ! 2327: ; set/reset = background color ! 2328: mov al,byte ptr [edi] ;latch the background color ! 2329: ! 2330: mov eax,iFgColor ! 2331: out dx,al ;set/reset color = foreground now ! 2332: ! 2333: mov eax,ulTmpSrcDelta ! 2334: mov ebx,ulTmpDstDelta ! 2335: mov edx,ulNumScans ! 2336: ;decide which copy loop to use ! 2337: test edi,1 ;is dest word-aligned? ! 2338: jnz short @F ;no, need leading byte ! 2339: ;yes, no leading byte ! 2340: cmp ulOddByte,1 ;odd width? ! 2341: jnz short opaq_scan_loop ;no, no trailing byte ! 2342: jmp short opaq_scan_loop_t ;yes, trailing byte ! 2343: ! 2344: @@: ! 2345: cmp ulOddByte,1 ;odd width? ! 2346: jz short opaq_scan_loop_l ;yes, no trailing byte ! 2347: jmp short opaq_scan_loop_lt ;no, trailing byte ! 2348: ! 2349: ;-----------------------------------------------------------------------; ! 2350: ; Loops for copying whole bytes to the screen, as much as possible a word ! 2351: ; at a time. ! 2352: ; On entry: ! 2353: ; EAX = offset to next buffer scan ! 2354: ; EBX = offset to next screen scan ! 2355: ; EDX = # of scans to draw ! 2356: ; ESI = pointer to first buffer byte from which to copy ! 2357: ; EDI = pointer to first screen byte to which to copy ! 2358: ; DF = cleared ! 2359: ; LATER could break out and optimize short runs, such as 1, 2, 3, 4 wide. ! 2360: ;-----------------------------------------------------------------------; ! 2361: ! 2362: ; Loop for doing whole opaque words: no leading byte, no trailing byte. ! 2363: opaq_scan_loop: ! 2364: @@: ! 2365: mov ecx,ulWholeWidthInWords ! 2366: rep movsw ! 2367: add esi,eax ;point to next buffer scan ! 2368: add edi,ebx ;point to next screen scan ! 2369: dec edx ;count down scans ! 2370: jnz @B ! 2371: jmp pfnEdgeVector ;do the edge(s) ! 2372: ! 2373: ; Loop for doing whole opaque words: leading byte, no trailing byte. ! 2374: opaq_scan_loop_l: ! 2375: @@: ! 2376: movsb ! 2377: mov ecx,ulWholeWidthInWords ! 2378: rep movsw ! 2379: add esi,eax ;point to next buffer scan ! 2380: add edi,ebx ;point to next screen scan ! 2381: dec edx ;count down scans ! 2382: jnz @B ! 2383: jmp pfnEdgeVector ;do the edge(s) ! 2384: ! 2385: ; Loop for doing whole opaque words: leading byte, trailing byte. ! 2386: opaq_scan_loop_lt: ! 2387: @@: ! 2388: movsb ! 2389: mov ecx,ulWholeWidthInWordsMinus1 ;one word gets done as 2 bytes ! 2390: rep movsw ! 2391: movsb ! 2392: add esi,eax ;point to next buffer scan ! 2393: add edi,ebx ;point to next screen scan ! 2394: dec edx ;count down scans ! 2395: jnz @B ! 2396: jmp pfnEdgeVector ;do the edge(s) ! 2397: ! 2398: ; Loop for doing whole opaque words: no leading byte, trailing byte. ! 2399: opaq_scan_loop_t: ! 2400: @@: ! 2401: mov ecx,ulWholeWidthInWords ! 2402: rep movsw ! 2403: movsb ! 2404: add esi,eax ;point to next buffer scan ! 2405: add edi,ebx ;point to next screen scan ! 2406: dec edx ;count down scans ! 2407: jnz @B ! 2408: jmp pfnEdgeVector ;do the edge(s) ! 2409: ! 2410: ;-----------------------------------------------------------------------; ! 2411: ; Draw the left edge only. ! 2412: ;-----------------------------------------------------------------------; ! 2413: opaq_draw_left_edge_only: ! 2414: ! 2415: ;-----------------------------------------------------------------------; ! 2416: ; First, draw the foreground pixels. ! 2417: ;-----------------------------------------------------------------------; ! 2418: ! 2419: push offset opaq_check_more_banks ;return here when done with edge ! 2420: ! 2421: opaq_draw_left_edge_only_entry: ! 2422: mov edx,VGA_BASE + GRAF_DATA ! 2423: mov eax,iFgColor ! 2424: out dx,al ;set/reset color = foreground ! 2425: ! 2426: mov ebx,ulBufDelta ! 2427: mov edx,ulScreenDelta ! 2428: mov esi,pTempBuffer ! 2429: mov edi,pScreen ! 2430: push esi ;remember starting buffer and screen offsets ! 2431: push edi ; for when we do the background pass ! 2432: mov eax,ulLeftMask ;AH = clip mask ! 2433: push eax ;preserve clip mask for background pass ! 2434: push ebp ;preserve stack frame pointer ! 2435: mov ecx,ulNumScans ! 2436: mov ebp,ecx ! 2437: add ecx,3 ! 2438: shr ecx,2 ;# of quadscans ! 2439: and ebp,11b ! 2440: jmp dword ptr OpaqFgEdgeTable[ebp*4] ! 2441: ! 2442: align 4 ! 2443: OpaqFgEdgeTable label dword ! 2444: dd opaq_fg_edge_entry_4 ! 2445: dd opaq_fg_edge_entry_1 ! 2446: dd opaq_fg_edge_entry_2 ! 2447: dd opaq_fg_edge_entry_3 ! 2448: ! 2449: opaq_fg_edge_loop: ! 2450: opaq_fg_edge_entry_4: ! 2451: mov al,[esi] ! 2452: add esi,ebx ! 2453: and al,ah ! 2454: and [edi],al ! 2455: add edi,edx ! 2456: opaq_fg_edge_entry_3: ! 2457: mov al,[esi] ! 2458: add esi,ebx ! 2459: and al,ah ! 2460: and [edi],al ! 2461: add edi,edx ! 2462: opaq_fg_edge_entry_2: ! 2463: mov al,[esi] ! 2464: add esi,ebx ! 2465: and al,ah ! 2466: and [edi],al ! 2467: add edi,edx ! 2468: opaq_fg_edge_entry_1: ! 2469: mov al,[esi] ! 2470: add esi,ebx ! 2471: and al,ah ! 2472: and [edi],al ! 2473: add edi,edx ! 2474: ! 2475: dec ecx ! 2476: jnz opaq_fg_edge_loop ! 2477: ! 2478: pop ebp ;restore stack frame pointer ! 2479: ! 2480: ;-----------------------------------------------------------------------; ! 2481: ; Now draw the background pixels with inverted buffer contents. ! 2482: ;-----------------------------------------------------------------------; ! 2483: ! 2484: mov edx,VGA_BASE + GRAF_DATA ! 2485: mov eax,iBgColor ! 2486: out dx,al ;set/reset color = background ! 2487: ! 2488: pop eax ;retrieve clip mask ! 2489: pop edi ;retrieve the initial screen and ! 2490: pop esi ; buffer offsets ! 2491: ! 2492: mov edx,ulScreenDelta ! 2493: ! 2494: push ebp ;preserve stack frame pointer ! 2495: mov ecx,ulNumScans ! 2496: mov ebp,ecx ! 2497: and ebp,11b ! 2498: add ecx,3 ! 2499: shr ecx,2 ;# of quadscans ! 2500: jmp dword ptr OpaqBgEdgeTable[ebp*4] ! 2501: ! 2502: align 4 ! 2503: OpaqBgEdgeTable label dword ! 2504: dd opaq_bg_edge_entry_4 ! 2505: dd opaq_bg_edge_entry_1 ! 2506: dd opaq_bg_edge_entry_2 ! 2507: dd opaq_bg_edge_entry_3 ! 2508: ! 2509: opaq_bg_edge_loop: ! 2510: opaq_bg_edge_entry_4: ! 2511: mov al,[esi] ! 2512: add esi,ebx ! 2513: not al ! 2514: and al,ah ! 2515: and [edi],al ! 2516: add edi,edx ! 2517: opaq_bg_edge_entry_3: ! 2518: mov al,[esi] ! 2519: add esi,ebx ! 2520: not al ! 2521: and al,ah ! 2522: and [edi],al ! 2523: add edi,edx ! 2524: opaq_bg_edge_entry_2: ! 2525: mov al,[esi] ! 2526: add esi,ebx ! 2527: not al ! 2528: and al,ah ! 2529: and [edi],al ! 2530: add edi,edx ! 2531: opaq_bg_edge_entry_1: ! 2532: mov al,[esi] ! 2533: add esi,ebx ! 2534: not al ! 2535: and al,ah ! 2536: and [edi],al ! 2537: add edi,edx ! 2538: ! 2539: dec ecx ! 2540: jnz opaq_bg_edge_loop ! 2541: ! 2542: pop ebp ;restore stack frame pointer ! 2543: ! 2544: retn ! 2545: ! 2546: ;-----------------------------------------------------------------------; ! 2547: ; Draw the right edge only. Once we've set up the pointers, this is done ! 2548: ; with exactly the same code as the left edge. ! 2549: ;-----------------------------------------------------------------------; ! 2550: opaq_draw_right_edge_only: ! 2551: push offset opaq_check_more_banks ;return here when done with edge ! 2552: ! 2553: opaq_draw_right_edge_only_entry: ! 2554: mov edx,VGA_BASE + GRAF_DATA ! 2555: mov eax,iFgColor ! 2556: out dx,al ;set/reset color = foreground ! 2557: ! 2558: mov ebx,ulBufDelta ! 2559: mov edx,ulScreenDelta ! 2560: mov edi,ulTextWidthInBytes ! 2561: dec edi ! 2562: mov esi,pTempBuffer ! 2563: add esi,edi ;point to right edge start in buffer ! 2564: add edi,pScreen ;point to right edge start in screen ! 2565: push esi ;remember starting buffer and screen offsets ! 2566: push edi ; for when we do the background pass ! 2567: mov eax,ulRightMask ;AH = clip mask ! 2568: push eax ;preserve clip mask for background pass ! 2569: push ebp ;preserve stack frame pointer ! 2570: mov ecx,ulNumScans ! 2571: mov ebp,ecx ! 2572: add ecx,3 ! 2573: shr ecx,2 ;# of quadscans ! 2574: and ebp,11b ! 2575: jmp OpaqFgEdgeTable[ebp*4] ! 2576: ! 2577: ;-----------------------------------------------------------------------; ! 2578: ; Draw both the left and right edges. We do this by calling first the ! 2579: ; left and then the right edge drawing code. ! 2580: ;-----------------------------------------------------------------------; ! 2581: opaq_draw_both_edges: ! 2582: call opaq_draw_left_edge_only_entry ! 2583: call opaq_draw_right_edge_only_entry ! 2584: ! 2585: ;-----------------------------------------------------------------------; ! 2586: ; See if there are more banks to draw. ! 2587: ;-----------------------------------------------------------------------; ! 2588: ! 2589: opaq_check_more_banks: ! 2590: mov ebx,pdsurf ! 2591: mov eax,[ebx].dsurf_rcl1WindowClip.yBottom ;is the text bottom in ! 2592: cmp ulBottomScan,eax ; the current bank? ! 2593: jnle short do_next_opaq_bank ;no, map in the next bank and draw ! 2594: ;yes, so we're done ! 2595: ! 2596: ;-----------------------------------------------------------------------; ! 2597: ; Restore the VGA's hardware state and we're done. ! 2598: ;-----------------------------------------------------------------------; ! 2599: ! 2600: opaq_done: ! 2601: mov edx,VGA_BASE + GRAF_ADDR ! 2602: mov eax,GRAF_MODE + ((M_PROC_WRITE + M_DATA_READ) SHL 8) ! 2603: out dx,ax ;restore read mode 0 and write mode 0 ! 2604: done: ! 2605: cRet vFastText ! 2606: ! 2607: do_next_opaq_bank: ! 2608: mov ulTopScan,eax ;this will be the top of the next bank ! 2609: mov ecx,eax ;set aside scan # for bank manager call ! 2610: mul ulScreenDelta ! 2611: mov edi,ulTempLeft ! 2612: add edi,eax ;next screen byte to which to copy ! 2613: ! 2614: ptrCall <dword ptr [ebx].dsurf_pfnBankControl>,<ebx,ecx,JustifyTop> ! 2615: ;map in the bank (call preserves EBX, ! 2616: ; ESI, and EDI) ! 2617: ! 2618: add edi,[ebx].dsurf_pvBitmapStart ;initial destination address ! 2619: mov pScreen,edi ! 2620: ! 2621: mov eax,ulBufDelta ! 2622: mul ulNumScans ! 2623: add pTempBuffer,eax ;advance to next temp buffer scan to ! 2624: ; copy ! 2625: jmp opaq_bank_loop ;we're ready to draw in the new bank ! 2626: ! 2627: ;-----------------------------------------------------------------------; ! 2628: ; Special 8-wide aligned opaque drawing code. Loads the latches with the ! 2629: ; background color, sets the Set/Reset color to the foreground color, ! 2630: ; then uses write mode 3 to draw the glyphs. Joyously, there are no ! 2631: ; partial bytes to worry about, so we can really crank up the code. ! 2632: ; ! 2633: ; On entry: ! 2634: ; EBX = prclText ! 2635: ;-----------------------------------------------------------------------; ! 2636: special_8_wide_aligned_opaque: ! 2637: ! 2638: mov esi,pdsurf ! 2639: mov edi,[ebx].yBottom ! 2640: mov eax,[ebx].yTop ! 2641: sub edi,eax ;height of glyphs ! 2642: ! 2643: ;-----------------------------------------------------------------------; ! 2644: ; Map in the bank containing the top scan of the text, if it's not ! 2645: ; mapped in already. ! 2646: ;-----------------------------------------------------------------------; ! 2647: ! 2648: cmp eax,[esi].dsurf_rcl1WindowClip.yTop ;is text top less than ! 2649: ; current bank? ! 2650: jl short s8wao_map_init_bank ;yes, map in proper bank ! 2651: cmp eax,[esi].dsurf_rcl1WindowClip.yBottom ;text top greater than ! 2652: ; current bank? ! 2653: jl short s8wa0_init_bank_mapped ;no, proper bank already mapped ! 2654: s8wao_map_init_bank: ! 2655: ! 2656: ; Map in the bank containing the top scan line of the text. ! 2657: ; Preserves EBX, ESI, and EDI. ! 2658: ! 2659: ptrCall <dword ptr [esi].dsurf_pfnBankControl>,<esi,eax,JustifyTop> ! 2660: ! 2661: s8wa0_init_bank_mapped: ! 2662: ! 2663: mov eax,[esi].dsurf_rcl1WindowClip.yBottom ! 2664: sub eax,[ebx].yTop ;maximum run in bank ! 2665: cmp edi,eax ;does all the text fit in the bank? ! 2666: jg general_handler ;no, let general code handle it ! 2667: ;LATER could handle here ! 2668: ! 2669: ;-----------------------------------------------------------------------; ! 2670: ; Set up variables. ! 2671: ;-----------------------------------------------------------------------; ! 2672: ! 2673: mov eax,edi ;# of scans in glyphs ! 2674: add eax,7 ! 2675: shr eax,3 ;# of unrolled loops needed to draw ! 2676: ; glyph scans ! 2677: mov ulUnrolledCount,eax ;# of unrolled loop reps ! 2678: and edi,111b ;# of odd scans in first unrolled ! 2679: ; loop ! 2680: mov ulUnrolledOddCount,edi ;# of odd unrolled loop reps ! 2681: ! 2682: ;-----------------------------------------------------------------------; ! 2683: ; Point to the first screen byte at which to draw. ! 2684: ;-----------------------------------------------------------------------; ! 2685: ! 2686: mov eax,[ebx].yTop ! 2687: mul [esi].dsurf_lNextScan ! 2688: mov edi,[ebx].xLeft ! 2689: shr edi,3 ! 2690: add edi,eax ;next screen byte to which to copy ! 2691: add edi,[esi].dsurf_pvBitmapStart ;initial destination address ! 2692: mov pScreen,edi ! 2693: ! 2694: ;-----------------------------------------------------------------------; ! 2695: ; Set up the VGA's hardware for read mode 0 and write mode 3. ! 2696: ;-----------------------------------------------------------------------; ! 2697: ! 2698: mov edx,VGA_BASE + GRAF_ADDR ! 2699: mov eax,GRAF_MODE + ((M_AND_WRITE + M_DATA_READ) SHL 8) ! 2700: out dx,ax ;write mode 3 so we can do masking ! 2701: ; without OUTs ! 2702: ! 2703: ;-----------------------------------------------------------------------; ! 2704: ; Load the latches with the background color. ! 2705: ;-----------------------------------------------------------------------; ! 2706: ! 2707: mov ah,byte ptr iBgColor ! 2708: mov al,GRAF_SET_RESET ! 2709: out dx,ax ;set/reset color = background ! 2710: ! 2711: mov byte ptr [edi],0ffh ;we're in write mode 3, so write the ! 2712: ; set/reset = background color ! 2713: mov al,byte ptr [edi] ;latch the background color ! 2714: ! 2715: inc edx ;point to GC Data register ! 2716: mov eax,iFgColor ! 2717: out dx,al ;set/reset color = foreground now ! 2718: ! 2719: ;-----------------------------------------------------------------------; ! 2720: ; Set up the screen scan offset in EDX, and decide whether we need to do ! 2721: ; a leading glyph or not. ! 2722: ;-----------------------------------------------------------------------; ! 2723: ! 2724: mov edx,[esi].dsurf_lNextScan ;offset from one scan to next ! 2725: ! 2726: test edi,1 ;is leading glyph address even or odd? ! 2727: jz short s8wa0_word ;even, so no leading glyph ! 2728: ! 2729: ;-----------------------------------------------------------------------; ! 2730: ; Do the leading glyph. ! 2731: ;-----------------------------------------------------------------------; ! 2732: ! 2733: mov ebx,pGlyphPos ;point to the first glyph to draw ! 2734: add pGlyphPos,size GLYPHPOS ;point to the next glyph ! 2735: inc pScreen ;point to the next glyph's screen ! 2736: ; location ! 2737: dec ulGlyphCount ;count off this character ! 2738: mov ecx,ulUnrolledCount ;# of unrolled loop reps ! 2739: mov esi,[ebx].gp_pgdf ;point to glyph def ! 2740: mov eax,ulUnrolledOddCount ;# of odd unrolled loop reps ! 2741: mov esi,[esi].gdf_pgb ;point to glyph bits ! 2742: add esi,gb_aj ;point to the first glyph byte ! 2743: push offset s8wa0_word ;return here to do glyph pairs ! 2744: jmp dword ptr s8wao_byte_table[eax*4] ;branch into unrolled loop ! 2745: ! 2746: s8wa0_word: ! 2747: mov ecx,ulGlyphCount ! 2748: shr ecx,1 ;# of words we can copy, now that ! 2749: ; we're word-aligned ! 2750: jz s8wa0_trailing ;no words to copy ! 2751: mov eax,ulUnrolledOddCount ;# of odd unrolled loop reps ! 2752: mov ulWholeWidthInWords,ecx ! 2753: mov eax,dword ptr s8wao_word_table[eax*4] ;entry point into ! 2754: mov pGlyphLoop,eax ; unrolled loop ! 2755: ! 2756: s8wa0_word_loop: ! 2757: mov ebx,pGlyphPos ;point to the next glyph pair to draw ! 2758: add pGlyphPos,((size GLYPHPOS)*2) ;point to the next glyph pair ! 2759: mov edi,pScreen ;point to current glyph pair's screen ! 2760: ; location ! 2761: add pScreen,2 ;point to the next glyph pair's ! 2762: ; screen location ! 2763: mov esi,[ebx].gp_pgdf ;point to first glyph def ! 2764: mov ebx,[ebx+(size GLYPHPOS)].gp_pgdf ;point to second glyph def ! 2765: mov esi,[esi].gdf_pgb ;point to first glyph ! 2766: mov ebx,[ebx].gdf_pgb ;point to second glyph ! 2767: add esi,gb_aj ;point to the first glyph's bits ! 2768: add ebx,gb_aj ;point to the second glyph's bits ! 2769: mov ecx,ulUnrolledCount ;# of unrolled loop reps ! 2770: jmp pGlyphLoop ;branch into unrolled loop ! 2771: ! 2772: align 4 ! 2773: s8wao_word_table label dword ! 2774: dd s8wao_word_8 ! 2775: dd s8wao_word_1 ! 2776: dd s8wao_word_2 ! 2777: dd s8wao_word_3 ! 2778: dd s8wao_word_4 ! 2779: dd s8wao_word_5 ! 2780: dd s8wao_word_6 ! 2781: dd s8wao_word_7 ! 2782: ! 2783: s8wao_word_loop: ! 2784: s8wao_word_8: ! 2785: mov al,[esi] ! 2786: inc esi ! 2787: mov ah,[ebx] ! 2788: inc ebx ! 2789: mov [edi],ax ! 2790: add edi,edx ! 2791: s8wao_word_7: ! 2792: mov al,[esi] ! 2793: inc esi ! 2794: mov ah,[ebx] ! 2795: inc ebx ! 2796: mov [edi],ax ! 2797: add edi,edx ! 2798: s8wao_word_6: ! 2799: mov al,[esi] ! 2800: inc esi ! 2801: mov ah,[ebx] ! 2802: inc ebx ! 2803: mov [edi],ax ! 2804: add edi,edx ! 2805: s8wao_word_5: ! 2806: mov al,[esi] ! 2807: inc esi ! 2808: mov ah,[ebx] ! 2809: inc ebx ! 2810: mov [edi],ax ! 2811: add edi,edx ! 2812: s8wao_word_4: ! 2813: mov al,[esi] ! 2814: inc esi ! 2815: mov ah,[ebx] ! 2816: inc ebx ! 2817: mov [edi],ax ! 2818: add edi,edx ! 2819: s8wao_word_3: ! 2820: mov al,[esi] ! 2821: inc esi ! 2822: mov ah,[ebx] ! 2823: inc ebx ! 2824: mov [edi],ax ! 2825: add edi,edx ! 2826: s8wao_word_2: ! 2827: mov al,[esi] ! 2828: inc esi ! 2829: mov ah,[ebx] ! 2830: inc ebx ! 2831: mov [edi],ax ! 2832: add edi,edx ! 2833: s8wao_word_1: ! 2834: mov al,[esi] ! 2835: inc esi ! 2836: mov ah,[ebx] ! 2837: inc ebx ! 2838: mov [edi],ax ! 2839: add edi,edx ! 2840: ! 2841: dec ecx ;count down glyph scans ! 2842: jnz s8wao_word_loop ! 2843: ! 2844: dec ulWholeWidthInWords ;count down glyph pairs ! 2845: jnz s8wa0_word_loop ! 2846: ! 2847: ;-----------------------------------------------------------------------; ! 2848: ; Do the trailing character, if there is one. ! 2849: ;-----------------------------------------------------------------------; ! 2850: ! 2851: s8wa0_trailing: ! 2852: test ulGlyphCount,1 ;trailing byte count ! 2853: ;is there a trailing character? ! 2854: jz opaq_done ;no, we're done ! 2855: ! 2856: mov ebx,pGlyphPos ;point to the last glyph to draw ! 2857: mov edi,pScreen ;point to the final glyph's screen ! 2858: ; location ! 2859: mov esi,[ebx].gp_pgdf ;point to glyph def ! 2860: mov ecx,ulUnrolledCount ;# of unrolled loop reps ! 2861: mov esi,[esi].gdf_pgb ;point to glyph bits ! 2862: mov eax,ulUnrolledOddCount ;# of odd unrolled loop reps ! 2863: add esi,gb_aj ;point to the first glyph byte ! 2864: push offset opaq_done ;return here to finish up ! 2865: jmp dword ptr s8wao_byte_table[eax*4] ;branch into unrolled loop ! 2866: ! 2867: align 4 ! 2868: s8wao_byte_table label dword ! 2869: dd s8wao_byte_8 ! 2870: dd s8wao_byte_1 ! 2871: dd s8wao_byte_2 ! 2872: dd s8wao_byte_3 ! 2873: dd s8wao_byte_4 ! 2874: dd s8wao_byte_5 ! 2875: dd s8wao_byte_6 ! 2876: dd s8wao_byte_7 ! 2877: ! 2878: s8wao_byte_loop: ! 2879: s8wao_byte_8: ! 2880: mov al,[esi] ! 2881: inc esi ! 2882: mov [edi],al ! 2883: add edi,edx ! 2884: s8wao_byte_7: ! 2885: mov al,[esi] ! 2886: inc esi ! 2887: mov [edi],al ! 2888: add edi,edx ! 2889: s8wao_byte_6: ! 2890: mov al,[esi] ! 2891: inc esi ! 2892: mov [edi],al ! 2893: add edi,edx ! 2894: s8wao_byte_5: ! 2895: mov al,[esi] ! 2896: inc esi ! 2897: mov [edi],al ! 2898: add edi,edx ! 2899: s8wao_byte_4: ! 2900: mov al,[esi] ! 2901: inc esi ! 2902: mov [edi],al ! 2903: add edi,edx ! 2904: s8wao_byte_3: ! 2905: mov al,[esi] ! 2906: inc esi ! 2907: mov [edi],al ! 2908: add edi,edx ! 2909: s8wao_byte_2: ! 2910: mov al,[esi] ! 2911: inc esi ! 2912: mov [edi],al ! 2913: add edi,edx ! 2914: s8wao_byte_1: ! 2915: mov al,[esi] ! 2916: inc esi ! 2917: mov [edi],al ! 2918: add edi,edx ! 2919: ! 2920: dec ecx ! 2921: jnz s8wao_byte_loop ! 2922: ! 2923: retn ! 2924: ! 2925: endProc vFastText ! 2926: ! 2927: ;-----------------------------------------------------------------------; ! 2928: ; VOID vClearMemDword(PULONG * pulBuffer, ULONG ulDwordCount); ! 2929: ; ! 2930: ; Clears ulCount dwords starting at pjBuffer. ! 2931: ;-----------------------------------------------------------------------; ! 2932: ! 2933: pulBuffer equ [esp+8] ! 2934: ulDwordCount equ [esp+12] ! 2935: ! 2936: cProc vClearMemDword,8,<> ! 2937: ! 2938: push edi ! 2939: mov edi,pulBuffer ! 2940: mov ecx,ulDwordCount ! 2941: sub eax,eax ! 2942: rep stosd ! 2943: pop edi ! 2944: ! 2945: cRet vClearMemDword ! 2946: ! 2947: endProc vClearMemDword ! 2948: ! 2949: public draw_f_tb_no_to_temp_start ! 2950: public draw_nf_tb_no_to_temp_start ! 2951: public draw_to_temp_start_entry ! 2952: public draw_f_ntb_o_to_temp_start ! 2953: public draw_nf_ntb_o_to_temp_start ! 2954: public draw_to_temp_start_entry2 ! 2955: public draw_f_tb_no_to_temp_loop ! 2956: public draw_nf_tb_no_to_temp_loop ! 2957: public draw_to_temp_loop_entry ! 2958: public draw_f_ntb_o_to_temp_loop ! 2959: public draw_nf_ntb_o_to_temp_loop ! 2960: public draw_to_temp_loop_entry2 ! 2961: public or_all_1_wide_rotated_need_last ! 2962: public or_all_1_wide_rotated_no_last ! 2963: public or_first_1_wide_rotated_need_last ! 2964: public or_first_1_wide_rotated_no_last ! 2965: public or_first_1_wide_rotated_loop ! 2966: public mov_first_1_wide_rotated_need_last ! 2967: public mov_first_1_wide_rotated_no_last ! 2968: public mov_first_1_wide_rotated_loop ! 2969: public mov_first_1_wide_unrotated ! 2970: public mov_first_1_wide_unrotated_loop ! 2971: public or_all_1_wide_unrotated ! 2972: public or_all_1_wide_unrotated_loop ! 2973: public or_first_2_wide_rotated_need_last ! 2974: public or_first_2_wide_rotated_need_loop ! 2975: public or_all_2_wide_rotated_need_last ! 2976: public or_all_2_wide_rotated_need_loop ! 2977: public mov_first_2_wide_rotated_need_last ! 2978: public mov_first_2_wide_rotated_need_loop ! 2979: public or_first_2_wide_rotated_no_last ! 2980: public or_first_2_wide_rotated_loop ! 2981: public or_all_2_wide_rotated_no_last ! 2982: public or_all_2_wide_rotated_loop ! 2983: public mov_first_2_wide_rotated_no_last ! 2984: public mov_first_2_wide_rotated_loop ! 2985: public mov_first_2_wide_unrotated ! 2986: public mov_first_2_wide_unrotated_loop ! 2987: public or_all_2_wide_unrotated ! 2988: public or_all_2_wide_unrotated_loop ! 2989: public or_first_3_wide_rotated_need_last ! 2990: public or_all_3_wide_rotated_need_last ! 2991: public mov_first_3_wide_rotated_need_last ! 2992: public or_first_3_wide_rotated_no_last ! 2993: public or_all_3_wide_rotated_no_last ! 2994: public mov_first_3_wide_rotated_no_last ! 2995: public mov_first_3_wide_unrotated ! 2996: public or_all_3_wide_unrotated ! 2997: public or_first_4_wide_rotated_need_last ! 2998: public or_all_4_wide_rotated_need_last ! 2999: public mov_first_4_wide_rotated_need_last ! 3000: public or_first_4_wide_rotated_no_last ! 3001: public or_all_4_wide_rotated_no_last ! 3002: public mov_first_4_wide_rotated_no_last ! 3003: public mov_first_4_wide_unrotated ! 3004: public or_all_4_wide_unrotated ! 3005: public or_first_N_wide_rotated_need_last ! 3006: public or_all_N_wide_rotated_need_last ! 3007: public mov_first_N_wide_rotated_need_last ! 3008: public or_first_N_wide_rotated_no_last ! 3009: public or_all_N_wide_rotated_no_last ! 3010: public mov_first_N_wide_rotated_no_last ! 3011: public mov_first_N_wide_unrotated ! 3012: public odd_width ! 3013: public two_odd_bytes ! 3014: public three_odd_bytes ! 3015: public or_all_N_wide_unrotated ! 3016: public or_no_odd_bytes_loop ! 3017: public or_odd_width ! 3018: public or_one_odd_bytes_loop ! 3019: public or_two_odd_bytes ! 3020: public or_two_odd_bytes_loop ! 3021: public or_three_odd_bytes ! 3022: public or_three_odd_bytes_loop ! 3023: public draw_to_screen ! 3024: public xpar_map_init_bank ! 3025: public xpar_init_bank_mapped ! 3026: public xpar_bank_loop ! 3027: public xpar_scan_loop ! 3028: public xpar_byte_loop ! 3029: public xpar_enter_8 ! 3030: public xpar_enter_7 ! 3031: public xpar_enter_6 ! 3032: public xpar_enter_5 ! 3033: public xpar_enter_4 ! 3034: public xpar_enter_3 ! 3035: public xpar_enter_2 ! 3036: public xpar_enter_1 ! 3037: public draw_prop_done ! 3038: public do_next_xpar_bank ! 3039: public opaque_text ! 3040: public opaq_left_edge_solid ! 3041: public opaq_set_edge_vector ! 3042: public opaq_edges_set ! 3043: public opaq_map_init_bank ! 3044: public opaq_init_bank_mapped ! 3045: public opaq_bank_loop ! 3046: public opaq_whole_bytes ! 3047: public opaq_scan_loop ! 3048: public opaq_scan_loop_l ! 3049: public opaq_scan_loop_lt ! 3050: public opaq_scan_loop_t ! 3051: public opaq_draw_left_edge_only ! 3052: public opaq_draw_left_edge_only_entry ! 3053: public opaq_fg_edge_loop ! 3054: public opaq_fg_edge_entry_4 ! 3055: public opaq_fg_edge_entry_3 ! 3056: public opaq_fg_edge_entry_2 ! 3057: public opaq_fg_edge_entry_1 ! 3058: public opaq_bg_edge_loop ! 3059: public opaq_bg_edge_entry_4 ! 3060: public opaq_bg_edge_entry_3 ! 3061: public opaq_bg_edge_entry_2 ! 3062: public opaq_bg_edge_entry_1 ! 3063: public opaq_draw_right_edge_only ! 3064: public opaq_draw_right_edge_only_entry ! 3065: public opaq_draw_both_edges ! 3066: public opaq_check_more_banks ! 3067: public do_next_opaq_bank ! 3068: public opaq_done ! 3069: public special_8_wide_aligned_opaque ! 3070: public s8wa0_init_bank_mapped ! 3071: public s8wa0_word ! 3072: public s8wao_word_loop ! 3073: public s8wao_word_8 ! 3074: public s8wao_word_7 ! 3075: public s8wao_word_6 ! 3076: public s8wao_word_5 ! 3077: public s8wao_word_4 ! 3078: public s8wao_word_3 ! 3079: public s8wao_word_2 ! 3080: public s8wao_word_1 ! 3081: public s8wa0_trailing ! 3082: public s8wao_byte_loop ! 3083: public s8wao_byte_8 ! 3084: public s8wao_byte_7 ! 3085: public s8wao_byte_6 ! 3086: public s8wao_byte_5 ! 3087: public s8wao_byte_4 ! 3088: public s8wao_byte_3 ! 3089: public s8wao_byte_2 ! 3090: public s8wao_byte_1 ! 3091: public s8wao_map_init_bank ! 3092: public do_opaque_clip ! 3093: public opaq_fully_clipped ! 3094: ! 3095: _TEXT$01 ends ! 3096: ! 3097: end ! 3098:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.