Annotation of ntddk/src/video/displays/vga256/i386/fasttext.asm, revision 1.1

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

unix.superglobalmegacorp.com

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