Annotation of ntddk/src/video/displays/vga/i386/fasttext.asm, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.