You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2972 lines
124 KiB
2972 lines
124 KiB
;---------------------------Module-Header------------------------------;
|
|
; Module Name: fasttext.asm
|
|
;
|
|
; Copyright (c) 1992 Microsoft Corporation
|
|
;-----------------------------------------------------------------------;
|
|
;-----------------------------------------------------------------------;
|
|
; BOOL vFastText(PDEV * ppdev, GLYPHPOS * pGlyphPos, ULONG ulGlyphCount,
|
|
; PBYTE pTempBuffer, ULONG ulBufDelta, ULONG ulCharInc,
|
|
; RECTL * prclText, RECTL * prclOpaque, INT iFgColor,
|
|
; INT iBgColor, ULONG fDrawFlags);
|
|
; ppdev -
|
|
; pGlyphPos -
|
|
; ulGlyphCount - # of glyphs to draw. Must never be 0.
|
|
; pTempBuffer -
|
|
; ulBufDelta - logical width of temp buffer in bytes. This value *must* be the
|
|
; same number of bytes spanned by prclText; it is assumed that
|
|
; scans in the temp buffer are contiguous
|
|
; ulCharInc -
|
|
; prclText -
|
|
; prclOpaque -
|
|
; iFgColor -
|
|
; iBgColor -
|
|
; fDrawFlags -
|
|
;
|
|
; Performs accelerated proportional text drawing.
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; Note: The general opaque text back-end currently assumes that it will
|
|
; never receive a text string with a bounding box that does not span at
|
|
; least one quadpixel (the four pixels at a VGA screen address).
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; Note: The term "quadpixel" means a four-pixel set stored across all
|
|
; four planes of VGA memory in planar high-color mode. Quadpixels map to
|
|
; nibbles in the temp buffer in which text is assembled, where nibbles
|
|
; are always bits 4-7 or 0-3.
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; Note: The direction flag is *not* explicitly set or cleared.
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; Note: Assumes the text rectangle has a positive height and width. Will
|
|
; not work properly if this is not the case.
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
comment $
|
|
|
|
The overall approach of this module is to draw the text into a system
|
|
memory buffer, then copy the buffer to the screen a word at a time
|
|
using write mode 2 and clever use of the VGA hardware so that no OUTs
|
|
and a minimum of display memory reads are required. The clever use is
|
|
setting the ALUs to XOR, the latches to the background color, and the
|
|
write mode to 2, so each nibble in bits 0-3 written by the CPU turns
|
|
into 0 or 0ffh for that plane. Then the Bit Mask is set to fg ^ bg,
|
|
so that common bits between the fg and bg are preserved, while non-
|
|
common bits are either preserved (=bg color) by a 0->000h bit for
|
|
that plane, or flipped (=fg color) by a 1->0ffh bit for that plane. The
|
|
Map Mask is used to clip edges; no read before write is required. Note
|
|
that bits 0-3 must be reversed to match the order of pixels in planes
|
|
0-3. Note also that we write a whole word, containing two nibbles in
|
|
bits 0-3 of each byte, at once, to draw 8 pixels per write.
|
|
|
|
commend $
|
|
|
|
.386
|
|
|
|
ifndef DOS_PLATFORM
|
|
.model small,c
|
|
else
|
|
ifdef STD_CALL
|
|
.model small,c
|
|
else
|
|
.model small,pascal
|
|
endif; STD_CALL
|
|
endif; DOS_PLATFORM
|
|
|
|
assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
|
|
assume fs:nothing,gs:nothing
|
|
|
|
.xlist
|
|
include stdcall.inc ;calling convention cmacros
|
|
include i386\strucs.inc
|
|
include i386\driver.inc
|
|
include i386\egavga.inc
|
|
|
|
.list
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.data
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Tables used to branch into glyph-drawing optimizations.
|
|
;
|
|
; Handles narrow (1-4 bytes wide) glyph drawing, for case where initial byte
|
|
; should be MOVed even if it's not aligned (intended for use in drawing the
|
|
; first glyph in a string). Table format is:
|
|
; Bits 3-2: dest width
|
|
; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
|
|
; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
|
|
align 4
|
|
MovInitialTableNarrow label dword
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd mov_first_1_wide_rotated_need_last ;nonalign, 1 wide, need last
|
|
dd mov_first_1_wide_unrotated ;aligned, 1 wide
|
|
dd mov_first_1_wide_rotated_no_last ;nonalign, 1 wide, no last
|
|
dd mov_first_1_wide_unrotated ;aligned, 1 wide
|
|
dd mov_first_2_wide_rotated_need_last ;nonalign, 2 wide, need last
|
|
dd mov_first_2_wide_unrotated ;aligned, 2 wide
|
|
dd mov_first_2_wide_rotated_no_last ;nonalign, 2 wide, no last
|
|
dd mov_first_2_wide_unrotated ;aligned, 2 wide
|
|
dd mov_first_3_wide_rotated_need_last ;nonalign, 3 wide, need last
|
|
dd mov_first_3_wide_unrotated ;aligned, 3 wide
|
|
dd mov_first_3_wide_rotated_no_last ;nonalign, 3 wide, no last
|
|
dd mov_first_3_wide_unrotated ;aligned, 3 wide
|
|
dd mov_first_4_wide_rotated_need_last ;nonalign, 4 wide, need last
|
|
dd mov_first_4_wide_unrotated ;aligned, 4 wide
|
|
dd mov_first_4_wide_rotated_no_last ;nonalign, 4 wide, no last
|
|
dd mov_first_4_wide_unrotated ;aligned, 4 wide
|
|
|
|
; Handles narrow (1-4 bytes wide) glyph drawing, for case where initial byte
|
|
; ORed if it's not aligned (intended for use in drawing all but the first glyph
|
|
; in a string). Table format is:
|
|
; Bits 3-2: dest width
|
|
; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
|
|
; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
|
|
align 4
|
|
OrInitialTableNarrow label dword
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd or_first_1_wide_rotated_need_last ;nonalign, 1 wide, need last
|
|
dd mov_first_1_wide_unrotated ;aligned, 1 wide
|
|
dd or_first_1_wide_rotated_no_last ;nonalign, 1 wide, no last
|
|
dd mov_first_1_wide_unrotated ;aligned, 1 wide
|
|
dd or_first_2_wide_rotated_need_last ;nonalign, 2 wide, need last
|
|
dd mov_first_2_wide_unrotated ;aligned, 2 wide
|
|
dd or_first_2_wide_rotated_no_last ;nonalign, 2 wide, no last
|
|
dd mov_first_2_wide_unrotated ;aligned, 2 wide
|
|
dd or_first_3_wide_rotated_need_last ;nonalign, 3 wide, need last
|
|
dd mov_first_3_wide_unrotated ;aligned, 3 wide
|
|
dd or_first_3_wide_rotated_no_last ;nonalign, 3 wide, no last
|
|
dd mov_first_3_wide_unrotated ;aligned, 3 wide
|
|
dd or_first_4_wide_rotated_need_last ;nonalign, 4 wide, need last
|
|
dd mov_first_4_wide_unrotated ;aligned, 4 wide
|
|
dd or_first_4_wide_rotated_no_last ;nonalign, 4 wide, no last
|
|
dd mov_first_4_wide_unrotated ;aligned, 4 wide
|
|
|
|
; Handles narrow (1-4 bytes wide) glyph drawing, for case where all bytes
|
|
; should be ORed (intended for use in drawing potentially overlapping glyphs).
|
|
; Table format is:
|
|
; Bits 3-2: dest width
|
|
; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
|
|
; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
|
|
align 4
|
|
OrAllTableNarrow label dword
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd draw_prop_done ;0 wide
|
|
dd or_all_1_wide_rotated_need_last ;nonalign, 1 wide, need last
|
|
dd or_all_1_wide_unrotated ;aligned, 1 wide
|
|
dd or_all_1_wide_rotated_no_last ;nonalign, 1 wide, no last
|
|
dd or_all_1_wide_unrotated ;aligned, 1 wide
|
|
dd or_all_2_wide_rotated_need_last ;nonalign, 2 wide, need last
|
|
dd or_all_2_wide_unrotated ;aligned, 2 wide
|
|
dd or_all_2_wide_rotated_no_last ;nonalign, 2 wide, no last
|
|
dd or_all_2_wide_unrotated ;aligned, 2 wide
|
|
dd or_all_3_wide_rotated_need_last ;nonalign, 3 wide, need last
|
|
dd or_all_3_wide_unrotated ;aligned, 3 wide
|
|
dd or_all_3_wide_rotated_no_last ;nonalign, 3 wide, no last
|
|
dd or_all_3_wide_unrotated ;aligned, 3 wide
|
|
dd or_all_4_wide_rotated_need_last ;nonalign, 4 wide, need last
|
|
dd or_all_4_wide_unrotated ;aligned, 4 wide
|
|
dd or_all_4_wide_rotated_no_last ;nonalign, 4 wide, no last
|
|
dd or_all_4_wide_unrotated ;aligned, 4 wide
|
|
|
|
; Handles arbitrarily wide glyph drawing, for case where initial byte should be
|
|
; MOVed even if it's not aligned (intended for use in drawing the first glyph
|
|
; in a string). Table format is:
|
|
; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
|
|
; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
|
|
align 4
|
|
MovInitialTableWide label dword
|
|
dd mov_first_N_wide_rotated_need_last ;nonalign, need last
|
|
dd mov_first_N_wide_unrotated ;aligned
|
|
dd mov_first_N_wide_rotated_no_last ;nonalign, no last
|
|
dd mov_first_N_wide_unrotated ;aligned
|
|
|
|
; Handles arbitrarily wide glyph drawing, for case where initial byte should be
|
|
; ORed if it's not aligned (intended for use in drawing all but the first glyph
|
|
; in a string). Table format is:
|
|
; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
|
|
; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
|
|
align 4
|
|
OrInitialTableWide label dword
|
|
dd or_first_N_wide_rotated_need_last ;nonalign, need last
|
|
dd mov_first_N_wide_unrotated ;aligned
|
|
dd or_first_N_wide_rotated_no_last ;nonalign, no last
|
|
dd mov_first_N_wide_unrotated ;aligned
|
|
|
|
; Handles arbitrarily wide glyph drawing, for case where all bytes should
|
|
; be ORed (intended for use in drawing potentially overlapping glyphs).
|
|
; Table format is:
|
|
; Bit 1 : 1 if don't need last source byte, 0 if do need last source byte
|
|
; Bit 0 : 1 if no rotation (aligned), 0 if rotation (non-aligned)
|
|
align 4
|
|
OrAllTableWide label dword
|
|
dd or_all_N_wide_rotated_need_last ;nonalign, need last
|
|
dd or_all_N_wide_unrotated ;aligned
|
|
dd or_all_N_wide_rotated_no_last ;nonalign, no last
|
|
dd or_all_N_wide_unrotated ;aligned
|
|
|
|
; Vectors to entry points for drawing various types of text. '*' means works as
|
|
; is but could be acclerated with a custom scanning loop.
|
|
align 4
|
|
MasterTextTypeTable label dword ;tops aligned overlap fixed pitch
|
|
dd draw_nf_ntb_o_to_temp_start ; N N N *
|
|
dd draw_f_ntb_o_to_temp_start ; N N Y *
|
|
dd draw_nf_ntb_o_to_temp_start ; N Y N
|
|
dd draw_f_ntb_o_to_temp_start ; N Y Y
|
|
dd draw_nf_tb_no_to_temp_start ; Y N N
|
|
dd draw_f_tb_no_to_temp_start ; Y N Y
|
|
dd draw_nf_ntb_o_to_temp_start ; Y Y N *
|
|
dd draw_f_ntb_o_to_temp_start ; Y Y Y *
|
|
|
|
;-----------------------------------------------------------------------
|
|
; Tables of pointers to optimizations for drawing up to four pixels
|
|
; of transparent text based on the upper or lower nibble of a byte.
|
|
align 4
|
|
xpar_high_nibble_table label dword
|
|
dd xpar_high_nibble_0
|
|
dd xpar_high_nibble_1
|
|
dd xpar_high_nibble_2
|
|
dd xpar_high_nibble_3
|
|
dd xpar_high_nibble_4
|
|
dd xpar_high_nibble_5
|
|
dd xpar_high_nibble_6
|
|
dd xpar_high_nibble_7
|
|
dd xpar_high_nibble_8
|
|
dd xpar_high_nibble_9
|
|
dd xpar_high_nibble_A
|
|
dd xpar_high_nibble_B
|
|
dd xpar_high_nibble_C
|
|
dd xpar_high_nibble_D
|
|
dd xpar_high_nibble_E
|
|
dd xpar_high_nibble_F
|
|
|
|
align 4
|
|
xpar_low_nibble_table label dword
|
|
dd xpar_low_nibble_0
|
|
dd xpar_low_nibble_1
|
|
dd xpar_low_nibble_2
|
|
dd xpar_low_nibble_3
|
|
dd xpar_low_nibble_4
|
|
dd xpar_low_nibble_5
|
|
dd xpar_low_nibble_6
|
|
dd xpar_low_nibble_7
|
|
dd xpar_low_nibble_8
|
|
dd xpar_low_nibble_9
|
|
dd xpar_low_nibble_A
|
|
dd xpar_low_nibble_B
|
|
dd xpar_low_nibble_C
|
|
dd xpar_low_nibble_D
|
|
dd xpar_low_nibble_E
|
|
dd xpar_low_nibble_F
|
|
|
|
; Masks for clipping for the four possible left and right edge alignments
|
|
jOpaqueLeftMasks label byte
|
|
db 0ffh,00eh,00ch,008h
|
|
|
|
jOpaqueRightMasks label byte
|
|
db 0ffh,001h,003h,007h
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.code
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc vFastText,44,<\
|
|
uses esi edi ebx,\
|
|
ppdev:ptr,\
|
|
pGlyphPos:ptr,\
|
|
ulGlyphCount:dword,\
|
|
pTempBuffer:ptr,\
|
|
ulBufDelta:dword,\
|
|
ulCharInc:dword,\
|
|
prclText:ptr,\
|
|
prclOpaque:ptr,\
|
|
iFgColor:dword,\
|
|
iBgColor:dword,\
|
|
fDrawFlags:dword>
|
|
|
|
local ulGlyDelta:dword ;width per scan of source glyph, in bytes
|
|
local ulWidthInBytes:dword ;width of glyph, in bytes
|
|
local ulTmpWidthInBytes:dword ;working byte-width count
|
|
local ulGlyphX:dword ;for fixed-pitch text, maintains the current
|
|
; glyph's left-edge X coordinate
|
|
local pGlyphLoop:dword ;pointer to glyph-processing loop
|
|
local ulTempLeft:dword ;X coordinate on screen of left edge of temp
|
|
; buffer
|
|
local ulXparBytes:dword ;general loop count storage
|
|
local ulTmpSrcDelta:dword ;distance from end of one buffer text scan to
|
|
; start of next
|
|
local ulTmpDstDelta:dword ;distance from end of one screen text scan to
|
|
; start of next
|
|
local ulTopScan:dword ;top scan of dest text rect in current bank
|
|
local ulBottomScan:dword ;bottom scan of dest text rect
|
|
local ulNumScans:dword ;# of scans to draw
|
|
local ulScreenDelta:dword ;scan-to-scan offset in screen
|
|
local ulScreenDeltaLinear:dword ;scan-to-scan offset in screen when in
|
|
; nice, neat linear packed-pixel mode
|
|
local ulTextWidthInBytesMinus1:dword ;# of bytes across spanned by
|
|
; text, minus 1
|
|
local pScreen:dword ;pointer to first screen byte to which to draw
|
|
local pfnEdgeVector:dword ;pointer to routine to draw any needed edges
|
|
local pfnFirstOpaqVector:dword ;pointer to initial drawing routine
|
|
; called for opaque (either whole
|
|
; bytes, or edge(s) if no whole bytes)
|
|
local ulWholeWidthInQuadpixelPairs:dword ;# of quadpixel pairs to copy
|
|
local ulWholeWidthInQuadpixelPairsMinus1:dword ;# of whole bytes to
|
|
; copy - 1
|
|
local ulOddQuadpixel:dword ;1 if odd quadpixel in quadpixel-pair
|
|
; copy
|
|
local ulTextLeft:dword ;left edge of leftmost glyph
|
|
local ulLeftMask:dword ;for opaque text, left edge mask for string
|
|
local ulRightMask:dword ;for opaque text, right edge mask for string
|
|
local ulScans:dword ;# of scans in glyph
|
|
local ulYOrigin:dword ;Y origin of text in string (all glyphs are at
|
|
; the same Y origin)
|
|
local pGlyphFlipTable:dword ;pointer to look-up table used to reverse
|
|
; the order of bits 0-3 and 4-7
|
|
local ulLeftEdgeShift:dword ;amount by which to right-shift left-edge
|
|
; nibbles during opaque expansion to
|
|
; right-justify them (0 or 4)
|
|
local ulRightEdgeShift:dword ;amount by which to right-shift right-edge
|
|
; nibbles during opaque expansion to
|
|
; right-justify them (0 or 4)
|
|
local ulVGAWidthInBytesMinus1:dword ;# of VGA addresses from left edge
|
|
; to right edge of destination
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set the pointer to the table used to flip glyph bits 0-3 and 4-7. This
|
|
; table is guaranteed to be on a 256-byte boundary, so look-up can be
|
|
; performed simply by loading the low byte of a pointer register.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov esi,ppdev
|
|
mov ebx,prclText ;point to bounding text rect during 486
|
|
; interlock slot
|
|
mov eax,[esi].pdev_pjGlyphFlipTable
|
|
mov pGlyphFlipTable,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; If 8 wide, byte aligned, and opaque, handle with very fast special-case
|
|
; code.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp ulCharInc,8 ;8 wide?
|
|
jnz short @F ;no
|
|
cmp fDrawFlags,5 ;fixed pitch?
|
|
jnz short @F ;no
|
|
cmp prclOpaque,0 ;opaque?
|
|
jz short @F ;no
|
|
test [ebx].xLeft,111b ;byte aligned?
|
|
jz special_8_wide_aligned_opaque ;yes, special-case
|
|
@@:
|
|
|
|
general_handler::
|
|
|
|
mov esi,ppdev
|
|
mov eax,[ebx].yTop
|
|
mov ulTopScan,eax ;Y screen coordinate of top edge of temp buf
|
|
mov eax,[ebx].xLeft
|
|
and eax,not 7
|
|
mov ulTempLeft,eax ;X screen coordinate of left edge of temp buf
|
|
|
|
mov eax,fDrawFlags
|
|
|
|
mov edx,[ebx].yBottom
|
|
mov ulBottomScan,edx ;bottom scan of text area
|
|
|
|
jmp MasterTextTypeTable[eax*4]
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Entry point for fixed-pitch | tops and bottoms aligned | no overlap.
|
|
; Sets up to draw first glyph.
|
|
;-----------------------------------------------------------------------;
|
|
draw_f_tb_no_to_temp_start::
|
|
mov ebx,pGlyphPos ;point to the first glyph to draw
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
|
|
mov edi,[ebx].gp_x ;dest X coordinate
|
|
sub edi,ulTempLeft ;adjust relative to the left of the
|
|
; temp buffer (we assume the text is
|
|
; right at the top of the text rect
|
|
; and hence the buffer)
|
|
mov ulGlyphX,edi ;remember where this glyph started
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
mov pGlyphLoop,offset draw_f_tb_no_to_temp_loop
|
|
;draw additional characters with this
|
|
; loop
|
|
jmp short draw_to_temp_start_entry
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Entry point for non-fixed-pitch | tops and bottoms aligned | no overlap.
|
|
; Sets up to draw first glyph.
|
|
;-----------------------------------------------------------------------;
|
|
draw_nf_tb_no_to_temp_start::
|
|
mov ebx,pGlyphPos ;point to the first glyph to draw
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
|
|
mov edi,[ebx].gp_x ;dest X coordinate
|
|
sub edi,ulTempLeft ;adjust relative to the left of the
|
|
; temp buffer
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
mov pGlyphLoop,offset draw_nf_tb_no_to_temp_loop
|
|
;draw additional characters with this
|
|
; loop
|
|
draw_to_temp_start_entry::
|
|
add edi,[esi].gb_x ;adjust to position of upper left glyph
|
|
; corner in dest
|
|
mov ecx,edi
|
|
shr edi,3 ;byte offset of first column of glyph
|
|
; offset of upper left of glyph in temp
|
|
; buffer
|
|
add edi,pTempBuffer ;initial dest byte in temp buffer
|
|
|
|
and ecx,111b ;bit alignment of upper left in temp
|
|
|
|
;calculate scan-to-scan glyph width
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
|
|
lea eax,[ebx+ecx+7]
|
|
shr eax,3 ;# of dest bytes per scan
|
|
|
|
add ebx,7
|
|
shr ebx,3 ;# of source bytes per scan
|
|
|
|
mov edx,ulBufDelta ;width of destination buffer in bytes
|
|
|
|
cmp eax,4 ;do we have special case code for this
|
|
; dest width?
|
|
ja short @F ;no, handle as general case
|
|
;yes, handle as special case
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp MovInitialTableNarrow[eax*4]
|
|
;branch to draw the first glyph; never
|
|
; need to OR first glyph, because
|
|
; there's nothing there yet
|
|
|
|
@@: ;too wide to special case
|
|
mov ulWidthInBytes,eax ;# of bytes across dest
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
mov eax,0
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
add ebx,7
|
|
shr ebx,3 ;glyph width in bytes
|
|
mov ulGlyDelta,ebx
|
|
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp MovInitialTableWide[eax*4]
|
|
;branch to draw the first glyph; never
|
|
; need to OR first glyph, because
|
|
; there's nothing there yet
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Entry point for fixed-pitch | tops and bottoms not aligned | overlap.
|
|
; Sets up to draw first glyph.
|
|
;-----------------------------------------------------------------------;
|
|
draw_f_ntb_o_to_temp_start::
|
|
mov ebx,pGlyphPos ;point to the first glyph to draw
|
|
mov pGlyphLoop,offset draw_f_ntb_o_to_temp_loop
|
|
;draw additional characters with this
|
|
; loop
|
|
mov edi,[ebx].gp_x ;dest X coordinate
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
sub edi,ulTempLeft ;adjust relative to the left of the
|
|
; temp buffer
|
|
mov ulGlyphX,edi ;remember where this glyph started
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
add edi,[esi].gb_x ;adjust to position of upper left glyph
|
|
; corner in dest
|
|
mov ecx,edi
|
|
shr edi,3 ;byte offset of first column of glyph
|
|
; offset of upper left of glyph in temp
|
|
; buffer
|
|
jmp short draw_to_temp_start_entry2
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Entry point for non-fixed-pitch | tops and bottoms not aligned | overlap.
|
|
; Sets up to draw first glyph.
|
|
;-----------------------------------------------------------------------;
|
|
draw_nf_ntb_o_to_temp_start::
|
|
mov ebx,pGlyphPos ;point to the first glyph to draw
|
|
mov pGlyphLoop,offset draw_nf_ntb_o_to_temp_loop
|
|
;draw additional characters with this
|
|
; loop
|
|
mov edi,[ebx].gp_x ;dest X coordinate
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
sub edi,ulTempLeft ;adjust relative to the left of the
|
|
; temp buffer
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
add edi,[esi].gb_x ;adjust to position of upper left glyph
|
|
; corner in dest
|
|
mov ecx,edi
|
|
shr edi,3 ;byte offset of first column of glyph
|
|
; offset of upper left of glyph in temp
|
|
; buffer
|
|
draw_to_temp_start_entry2::
|
|
mov eax,[ebx].gp_y ;dest origin Y coordinate
|
|
sub eax,ulTopScan ;coord of glyph origin in temp buffer
|
|
mov ulYOrigin,eax ;remember the Y origin of all glyphs
|
|
; (necessary because glyph positions
|
|
; after first aren't set for fixed-
|
|
; pitch strings)
|
|
add eax,[esi].gb_y ;adjust to position of upper left glyph
|
|
; corner in dest
|
|
mul ulBufDelta ;offset in buffer of top glyph scan
|
|
add eax,pTempBuffer ;initial dest byte
|
|
add edi,eax
|
|
|
|
and ecx,111b ;bit alignment of upper left in temp
|
|
|
|
;calculate scan-to-scan glyph width
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
|
|
lea eax,[ebx+ecx+7]
|
|
shr eax,3 ;# of dest bytes per scan
|
|
|
|
add ebx,7
|
|
shr ebx,3 ;# of source bytes per scan
|
|
|
|
mov edx,ulBufDelta ;width of destination buffer in bytes
|
|
|
|
cmp eax,4 ;do we have special case code for this
|
|
; dest width?
|
|
ja short @F ;no, handle as general case
|
|
;yes, handle as special case
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp OrAllTableNarrow[eax*4] ;branch to draw the first glyph; OR all
|
|
; glyphs, because text may overlap
|
|
|
|
@@: ;too wide to special case
|
|
mov ulWidthInBytes,eax ;# of bytes across dest
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
mov eax,0
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
add ebx,7
|
|
shr ebx,3 ;glyph width in bytes
|
|
mov ulGlyDelta,ebx
|
|
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp OrAllTableWide[eax*4] ;branch to draw the first glyph; OR all ; glyphs, because text may overlap never
|
|
; glyphs, because text may overlap
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to draw all fixed-pitch | tops and bottoms aligned | no overlap
|
|
; glyphs after first.
|
|
;-----------------------------------------------------------------------;
|
|
draw_f_tb_no_to_temp_loop::
|
|
dec ulGlyphCount ;any more glyphs to draw?
|
|
jz draw_to_screen ;no, done
|
|
mov ebx,pGlyphPos
|
|
add ebx,size GLYPHPOS ;point to the next glyph (the one
|
|
mov pGlyphPos,ebx ; we're going to draw this time)
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
|
|
mov edi,ulGlyphX ;last glyph's dest X start in temp buf
|
|
add edi,ulCharInc ;this glyph's dest X start in temp buf
|
|
mov ulGlyphX,edi ;remember for next glyph
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
jmp short draw_to_temp_loop_entry
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to draw all non-fixed-pitch | tops and bottoms aligned | no overlap
|
|
; glyphs after first.
|
|
;-----------------------------------------------------------------------;
|
|
draw_nf_tb_no_to_temp_loop::
|
|
dec ulGlyphCount ;any more glyphs to draw?
|
|
jz draw_to_screen ;no, done
|
|
mov ebx,pGlyphPos
|
|
add ebx,size GLYPHPOS ;point to the next glyph (the one we're
|
|
mov pGlyphPos,ebx ; going to draw this time)
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
mov edi,[ebx].gp_x ;dest X coordinate
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
sub edi,ulTempLeft ;adjust relative to the left edge of
|
|
; the temp buffer
|
|
|
|
draw_to_temp_loop_entry::
|
|
add edi,[esi].gb_x ;adjust to position of upper left glyph
|
|
; corner in dest
|
|
mov ecx,edi ;pixel X coordinate in temp buffer
|
|
shr edi,3 ;byte offset of first column = dest
|
|
; offset of upper left of glyph in temp
|
|
; buffer
|
|
add edi,pTempBuffer ;initial dest byte
|
|
|
|
and ecx,111b ;bit alignment of upper left in temp
|
|
|
|
;calculate scan-to-scan glyph width
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
|
|
lea eax,[ebx+ecx+7]
|
|
shr eax,3 ;# of dest bytes to copy to per scan
|
|
|
|
add ebx,7
|
|
shr ebx,3 ;# of source bytes to copy from per
|
|
; scan
|
|
mov edx,ulBufDelta ;width of destination buffer in bytes
|
|
|
|
cmp eax,4 ;do we have special case code for this
|
|
; dest width?
|
|
ja short @F ;no, handle as general case
|
|
;yes, handle as special case
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp OrInitialTableNarrow[eax*4] ;branch to draw the first glyph;
|
|
; need to OR the 1st byte if
|
|
; non-aligned to avoid overwriting
|
|
; what's already there
|
|
@@: ;too wide to special case
|
|
mov ulWidthInBytes,eax ;# of bytes across dest
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
mov eax,0
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
add ebx,7
|
|
shr ebx,3 ;glyph width in bytes
|
|
mov ulGlyDelta,ebx
|
|
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp OrInitialTableWide[eax*4] ;branch to draw the next glyph;
|
|
; need to OR the 1st byte if
|
|
; non-aligned to avoid overwriting
|
|
; what's already there
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to draw all fixed-pitch | tops and bottoms not aligned | overlap
|
|
; glyphs after first.
|
|
;-----------------------------------------------------------------------;
|
|
draw_f_ntb_o_to_temp_loop::
|
|
dec ulGlyphCount ;any more glyphs to draw?
|
|
jz draw_to_screen ;no, done
|
|
mov ebx,pGlyphPos
|
|
add ebx,size GLYPHPOS ;point to the next glyph (the one we're
|
|
mov pGlyphPos,ebx ; going to draw this time)
|
|
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
mov edi,ulGlyphX ;last glyph's dest X start in temp buf
|
|
add edi,ulCharInc ;this glyph's dest X start in temp buf
|
|
mov ulGlyphX,edi ;remember for next glyph
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
|
|
jmp short draw_to_temp_loop_entry2
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to draw all non-fixed-pitch | tops and bottoms not aligned | overlap
|
|
; glyphs after first.
|
|
;-----------------------------------------------------------------------;
|
|
draw_nf_ntb_o_to_temp_loop::
|
|
dec ulGlyphCount ;any more glyphs to draw?
|
|
jz draw_to_screen ;no, done
|
|
mov ebx,pGlyphPos
|
|
add ebx,size GLYPHPOS ;point to the next glyph (the one we're
|
|
mov pGlyphPos,ebx ; going to draw this time)
|
|
|
|
mov esi,[ebx].gp_pgdf ;point to glyph def
|
|
mov edi,[ebx].gp_x ;dest X coordinate
|
|
mov esi,[esi].gdf_pgb ;point to glyph bits
|
|
sub edi,ulTempLeft ;adjust relative to the left edge of
|
|
; the temp buffer
|
|
draw_to_temp_loop_entry2::
|
|
add edi,[esi].gb_x ;adjust to position of upper left glyph
|
|
; corner in dest
|
|
mov ecx,edi ;pixel X coordinate in temp buffer
|
|
shr edi,3 ;byte offset of first column = dest
|
|
; offset of upper left of glyph in temp
|
|
; buffer
|
|
mov eax,ulYOrigin ;dest Y coordinate
|
|
|
|
add eax,[esi].gb_y ;adjust to position of upper left glyph
|
|
; corner in dest
|
|
mul ulBufDelta ;offset in buffer of top glyph scan
|
|
add eax,pTempBuffer ;initial dest byte
|
|
add edi,eax
|
|
|
|
and ecx,111b ;bit alignment of upper left in temp
|
|
|
|
;calculate scan-to-scan glyph width
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
|
|
lea eax,[ebx+ecx+7]
|
|
shr eax,3 ;# of dest bytes to copy to per scan
|
|
|
|
add ebx,7
|
|
shr ebx,3 ;# of source bytes to copy from per
|
|
; scan
|
|
mov edx,ulBufDelta ;width of destination buffer in bytes
|
|
|
|
cmp eax,4 ;do we have special case code for this
|
|
; dest width?
|
|
ja short @F ;no, handle as general case
|
|
;yes, handle as special case
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp OrAllTableNarrow[eax*4] ;branch to draw the next glyph
|
|
|
|
@@: ;too wide to special case
|
|
mov ulWidthInBytes,eax ;# of bytes across dest
|
|
cmp ebx,eax ;carry if more dest than source bytes
|
|
; (last source byte not needed)
|
|
mov eax,0
|
|
rcl eax,1 ;factor last source byte status in
|
|
cmp cl,1 ;carry if aligned
|
|
rcl eax,1 ;factor in alignment (aligned or not)
|
|
|
|
mov ebx,[esi].gb_cx ;glyph width in pixels
|
|
add ebx,7
|
|
shr ebx,3 ;glyph width in bytes
|
|
mov ulGlyDelta,ebx
|
|
|
|
mov ebx,[esi].gb_cy ;# of scans in glyph
|
|
add esi,gb_aj ;point to the first glyph byte
|
|
|
|
jmp OrAllTableWide[eax*4] ;branch to draw the next glyph
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Routines to draw all scans of a single glyph into the temp buffer,
|
|
; optimized for the following cases:
|
|
;
|
|
; 1 to 4 byte-wide destination rectangles for each of:
|
|
; No rotation needed
|
|
; Rotation needed, same # of source as dest bytes needed
|
|
; Rotation needed, one less source than dest bytes needed
|
|
;
|
|
; Additionally, the three cases are handled for 5 and wider cases by a
|
|
; general routine for each case.
|
|
;
|
|
; If rotation is needed, there are three sorts of routines:
|
|
;
|
|
; 1) The leftmost byte is MOVed, to initialize the byte. Succeeding bytes are
|
|
; MOVed. This is generally used for the leftmost glyph of a string.
|
|
; 2) The leftmost byte is ORed into the existing byte. Succeeding bytes are
|
|
; MOVed. This is generally used after the leftmost glyph, because this may
|
|
; not be the first data written to that byte.
|
|
; 3) All bytes are ORed. This is for drawing when characters might overlap.
|
|
;
|
|
; If rotation is not needed, there are two sorts of routines:
|
|
;
|
|
; 1) The leftmost byte is MOVed, to initialize the byte. Succeeding bytes are
|
|
; MOVed. This is generally used for the leftmost glyph of a string.
|
|
; 2) All bytes are ORed. This is for drawing when characters might overlap.
|
|
;
|
|
; On entry:
|
|
; EBX = # of scans to copy
|
|
; CL = right rotation
|
|
; EDX = ulBufDelta = width per scan of destination buffer, in bytes
|
|
; ESI = pointer to first glyph byte
|
|
; EDI = pointer to first dest buffer byte
|
|
; DF = cleared
|
|
; ulGlyDelta = width per scan of source glyph, in bytes (wide case only)
|
|
; ulWidthInBytes = width of glyph, in bytes (required only for 5 and
|
|
; wider cases)
|
|
;
|
|
; On exit:
|
|
; Any or all of EAX, EBX, ECX, EDX, ESI, and EDI may be trashed.
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 1 byte wide dest, rotated.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_1_wide_rotated_need_last::
|
|
or_all_1_wide_rotated_no_last::
|
|
or_first_1_wide_rotated_need_last::
|
|
or_first_1_wide_rotated_no_last::
|
|
or_first_1_wide_rotated_loop::
|
|
mov ch,[esi]
|
|
inc esi
|
|
shr ch,cl
|
|
or [edi],ch
|
|
add edi,edx
|
|
dec ebx
|
|
jnz or_first_1_wide_rotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 1 byte wide dest, rotated.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_1_wide_rotated_need_last::
|
|
mov_first_1_wide_rotated_no_last::
|
|
mov_first_1_wide_rotated_loop::
|
|
mov ch,[esi]
|
|
inc esi
|
|
shr ch,cl
|
|
mov [edi],ch
|
|
add edi,edx
|
|
dec ebx
|
|
jnz mov_first_1_wide_rotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 1 byte wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_1_wide_unrotated::
|
|
mov_first_1_wide_unrotated_loop::
|
|
mov al,[esi]
|
|
inc esi
|
|
mov [edi],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz mov_first_1_wide_unrotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 1 byte wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_1_wide_unrotated::
|
|
or_all_1_wide_unrotated_loop::
|
|
mov al,[esi]
|
|
inc esi
|
|
or [edi],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz or_all_1_wide_unrotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 2 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_2_wide_rotated_need_last::
|
|
or_first_2_wide_rotated_need_loop::
|
|
mov ax,[esi]
|
|
add esi,2
|
|
ror ax,cl
|
|
or [edi],al
|
|
mov [edi+1],ah
|
|
add edi,edx
|
|
dec ebx
|
|
jnz or_first_2_wide_rotated_need_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 2 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_2_wide_rotated_need_last::
|
|
or_all_2_wide_rotated_need_loop::
|
|
mov ax,[esi]
|
|
add esi,2
|
|
ror ax,cl
|
|
or [edi],ax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz or_all_2_wide_rotated_need_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 2 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_2_wide_rotated_need_last::
|
|
mov_first_2_wide_rotated_need_loop::
|
|
mov ax,[esi]
|
|
add esi,2
|
|
ror ax,cl
|
|
mov [edi],ax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz mov_first_2_wide_rotated_need_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 2 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_2_wide_rotated_no_last::
|
|
or_first_2_wide_rotated_loop::
|
|
sub eax,eax
|
|
mov ah,[esi]
|
|
inc esi
|
|
shr eax,cl
|
|
or [edi],ah
|
|
mov [edi+1],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz or_first_2_wide_rotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 2 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_2_wide_rotated_no_last::
|
|
or_all_2_wide_rotated_loop::
|
|
sub eax,eax
|
|
mov al,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
or [edi],ax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz or_all_2_wide_rotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 2 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_2_wide_rotated_no_last::
|
|
mov_first_2_wide_rotated_loop::
|
|
sub eax,eax
|
|
mov al,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
mov [edi],ax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz mov_first_2_wide_rotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 2 bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_2_wide_unrotated::
|
|
mov_first_2_wide_unrotated_loop::
|
|
mov ax,[esi]
|
|
add esi,2
|
|
mov [edi],ax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz mov_first_2_wide_unrotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 2 bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_2_wide_unrotated::
|
|
or_all_2_wide_unrotated_loop::
|
|
mov ax,[esi]
|
|
add esi,2
|
|
or [edi],ax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz or_all_2_wide_unrotated_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 3 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_3_wide_rotated_need_last::
|
|
@@:
|
|
mov al,[esi]
|
|
shr al,cl
|
|
or [edi],al
|
|
mov ax,[esi]
|
|
ror ax,cl
|
|
mov [edi+1],ah
|
|
mov ax,[esi+1]
|
|
add esi,3
|
|
ror ax,cl
|
|
mov [edi+2],ah
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 3 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_3_wide_rotated_need_last::
|
|
@@:
|
|
mov al,[esi]
|
|
shr al,cl
|
|
or [edi],al
|
|
mov ax,[esi]
|
|
ror ax,cl
|
|
or [edi+1],ah
|
|
mov ax,[esi+1]
|
|
add esi,3
|
|
ror ax,cl
|
|
or [edi+2],ah
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 3 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_3_wide_rotated_need_last::
|
|
@@:
|
|
mov al,[esi]
|
|
shr al,cl
|
|
mov [edi],al
|
|
mov ax,[esi]
|
|
ror ax,cl
|
|
mov [edi+1],ah
|
|
mov ax,[esi+1]
|
|
add esi,3
|
|
ror ax,cl
|
|
mov [edi+2],ah
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 3 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_3_wide_rotated_no_last::
|
|
neg cl
|
|
and cl,111b ;convert from right shift to left shift
|
|
@@:
|
|
sub eax,eax
|
|
mov ax,[esi]
|
|
add esi,2
|
|
xchg ah,al
|
|
shl eax,cl
|
|
mov [edi+1],ah
|
|
mov [edi+2],al
|
|
shr eax,16
|
|
or [edi],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 3 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_3_wide_rotated_no_last::
|
|
neg cl
|
|
and cl,111b ;convert from right shift to left shift
|
|
@@:
|
|
sub eax,eax
|
|
mov ax,[esi]
|
|
add esi,2
|
|
xchg ah,al
|
|
shl eax,cl
|
|
xchg ah,al
|
|
or [edi+1],ax
|
|
shr eax,16
|
|
or [edi],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 3 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_3_wide_rotated_no_last::
|
|
neg cl
|
|
and cl,111b ;convert from right shift to left shift
|
|
@@:
|
|
sub eax,eax
|
|
mov ax,[esi]
|
|
add esi,2
|
|
xchg ah,al
|
|
shl eax,cl
|
|
mov [edi+1],ah
|
|
mov [edi+2],al
|
|
shr eax,16
|
|
mov [edi],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 3 bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_3_wide_unrotated::
|
|
@@:
|
|
mov ax,[esi]
|
|
mov [edi],ax
|
|
mov al,[esi+2]
|
|
add esi,3
|
|
mov [edi+2],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 3 bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_3_wide_unrotated::
|
|
@@:
|
|
mov ax,[esi]
|
|
or [edi],ax
|
|
mov al,[esi+2]
|
|
add esi,3
|
|
or [edi+2],al
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 4 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_4_wide_rotated_need_last::
|
|
@@:
|
|
mov eax,[esi]
|
|
add esi,4
|
|
xchg ah,al
|
|
ror eax,16
|
|
xchg ah,al
|
|
shr eax,cl
|
|
xchg ah,al
|
|
mov [edi+2],ax
|
|
shr eax,16
|
|
mov [edi+1],al
|
|
or [edi],ah
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 4 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_4_wide_rotated_need_last::
|
|
@@:
|
|
mov eax,[esi]
|
|
add esi,4
|
|
xchg ah,al
|
|
ror eax,16
|
|
xchg ah,al
|
|
shr eax,cl
|
|
xchg ah,al
|
|
ror eax,16
|
|
xchg al,ah
|
|
or [edi],eax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 4 bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_4_wide_rotated_need_last::
|
|
@@:
|
|
mov eax,[esi]
|
|
add esi,4
|
|
xchg ah,al
|
|
ror eax,16
|
|
xchg ah,al
|
|
shr eax,cl
|
|
xchg ah,al
|
|
ror eax,16
|
|
xchg ah,al
|
|
mov [edi],eax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, 4 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_4_wide_rotated_no_last::
|
|
@@:
|
|
mov ax,[esi]
|
|
xchg ah,al
|
|
shl eax,16
|
|
mov ah,[esi+2]
|
|
add esi,3
|
|
shr eax,cl
|
|
xchg ah,al
|
|
mov [edi+2],ax
|
|
shr eax,16
|
|
mov [edi+1],al
|
|
or [edi],ah
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 4 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_4_wide_rotated_no_last::
|
|
@@:
|
|
mov ax,[esi]
|
|
xchg ah,al
|
|
shl eax,16
|
|
mov ah,[esi+2]
|
|
add esi,3
|
|
shr eax,cl
|
|
xchg ah,al
|
|
ror eax,16
|
|
xchg ah,al
|
|
or [edi],eax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 4 bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_4_wide_rotated_no_last::
|
|
@@:
|
|
mov ax,[esi]
|
|
xchg ah,al
|
|
shl eax,16
|
|
mov ah,[esi+2]
|
|
add esi,3
|
|
shr eax,cl
|
|
xchg ah,al
|
|
ror eax,16
|
|
xchg ah,al
|
|
mov [edi],eax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, 4 bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_4_wide_unrotated::
|
|
@@:
|
|
mov eax,[esi]
|
|
add esi,4
|
|
mov [edi],eax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, 4 bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_4_wide_unrotated::
|
|
@@:
|
|
mov eax,[esi]
|
|
add esi,4
|
|
or [edi],eax
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, n bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_N_wide_rotated_need_last::
|
|
mov eax,ulWidthInBytes
|
|
mov edx,ulBufDelta
|
|
sub edx,eax
|
|
mov ulTmpDstDelta,edx
|
|
dec eax ;source doesn't advance after first byte, and
|
|
; we do the first byte outside the loop
|
|
mov edx,ulGlyDelta
|
|
sub edx,eax
|
|
mov ulTmpSrcDelta,edx
|
|
mov ulTmpWidthInBytes,eax
|
|
ofNwrnl_scan_loop:
|
|
mov al,[esi] ;do the initial, ORed byte separately
|
|
shr al,cl
|
|
or [edi],al
|
|
inc edi
|
|
mov edx,ulTmpWidthInBytes
|
|
@@:
|
|
mov ax,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
mov [edi],ah
|
|
inc edi
|
|
dec edx
|
|
jnz @B
|
|
add esi,ulTmpSrcDelta
|
|
add edi,ulTmpDstDelta
|
|
dec ebx
|
|
jnz ofNwrnl_scan_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, n bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_N_wide_rotated_need_last::
|
|
mov eax,ulWidthInBytes
|
|
mov edx,ulBufDelta
|
|
sub edx,eax
|
|
mov ulTmpDstDelta,edx
|
|
dec eax ;source doesn't advance after first byte, and
|
|
; we do the first byte outside the loop
|
|
mov edx,ulGlyDelta
|
|
sub edx,eax
|
|
mov ulTmpSrcDelta,edx
|
|
mov ulTmpWidthInBytes,eax
|
|
oaNwrnl_scan_loop:
|
|
mov al,[esi] ;do the initial, ORed byte separately
|
|
shr al,cl
|
|
or [edi],al
|
|
inc edi
|
|
mov edx,ulTmpWidthInBytes
|
|
@@:
|
|
mov ax,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
or [edi],ah
|
|
inc edi
|
|
dec edx
|
|
jnz @B
|
|
add esi,ulTmpSrcDelta
|
|
add edi,ulTmpDstDelta
|
|
dec ebx
|
|
jnz oaNwrnl_scan_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, n bytes wide dest, rotated, need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_N_wide_rotated_need_last::
|
|
mov eax,ulWidthInBytes
|
|
mov edx,ulBufDelta
|
|
sub edx,eax
|
|
mov ulTmpDstDelta,edx
|
|
mov eax,ulWidthInBytes
|
|
dec eax ;source doesn't advance after first byte, and
|
|
; we do the first byte outside the loop
|
|
mov edx,ulGlyDelta
|
|
sub edx,eax
|
|
mov ulTmpSrcDelta,edx
|
|
mov ulTmpWidthInBytes,eax
|
|
mfNwrnl_scan_loop:
|
|
mov al,[esi] ;do the initial byte separately
|
|
shr al,cl
|
|
mov [edi],al
|
|
inc edi
|
|
mov edx,ulTmpWidthInBytes
|
|
@@:
|
|
mov ax,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
mov [edi],ah
|
|
inc edi
|
|
dec edx
|
|
jnz @B
|
|
add esi,ulTmpSrcDelta
|
|
add edi,ulTmpDstDelta
|
|
dec ebx
|
|
jnz mfNwrnl_scan_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR first byte, N bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_first_N_wide_rotated_no_last::
|
|
mov eax,ulWidthInBytes
|
|
dec eax ;one less because we don't advance after the
|
|
; last byte
|
|
mov edx,ulBufDelta
|
|
sub edx,eax
|
|
mov ulTmpDstDelta,edx
|
|
dec eax ;source doesn't advance after first byte, and
|
|
; we do the first & last bytes outside the
|
|
; loop; already subtracted 1 above
|
|
mov edx,ulGlyDelta
|
|
sub edx,eax
|
|
mov ulTmpSrcDelta,edx
|
|
mov ulTmpWidthInBytes,eax
|
|
ofNwr_scan_loop:
|
|
mov al,[esi] ;do the initial, ORed byte separately
|
|
shr al,cl
|
|
or [edi],al
|
|
inc edi
|
|
mov edx,ulTmpWidthInBytes
|
|
@@:
|
|
mov ax,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
mov [edi],ah
|
|
inc edi
|
|
dec edx
|
|
jnz @B
|
|
|
|
mov ah,[esi] ;do the final byte separately
|
|
sub al,al
|
|
shr eax,cl
|
|
mov [edi],al
|
|
|
|
add esi,ulTmpSrcDelta
|
|
add edi,ulTmpDstDelta
|
|
dec ebx
|
|
jnz ofNwr_scan_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, N bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_N_wide_rotated_no_last::
|
|
mov eax,ulWidthInBytes
|
|
dec eax ;one less because we don't advance after the
|
|
; last byte
|
|
mov edx,ulBufDelta
|
|
sub edx,eax
|
|
mov ulTmpDstDelta,edx
|
|
dec eax ;source doesn't advance after first byte, and
|
|
; we do the first & last bytes outside the
|
|
; loop; already subtracted 1 above
|
|
mov edx,ulGlyDelta
|
|
sub edx,eax
|
|
mov ulTmpSrcDelta,edx
|
|
mov ulTmpWidthInBytes,eax
|
|
oaNwr_scan_loop:
|
|
mov al,[esi] ;do the initial, ORed byte separately
|
|
shr al,cl
|
|
or [edi],al
|
|
inc edi
|
|
mov edx,ulTmpWidthInBytes
|
|
@@:
|
|
mov ax,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
or [edi],ah
|
|
inc edi
|
|
dec edx
|
|
jnz @B
|
|
|
|
mov ah,[esi] ;do the final byte separately
|
|
sub al,al
|
|
shr eax,cl
|
|
or [edi],al
|
|
|
|
add esi,ulTmpSrcDelta
|
|
add edi,ulTmpDstDelta
|
|
dec ebx
|
|
jnz oaNwr_scan_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, N bytes wide dest, rotated, don't need final source byte.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_N_wide_rotated_no_last::
|
|
mov eax,ulWidthInBytes
|
|
dec eax ;one less because we don't advance after the
|
|
; last byte
|
|
mov edx,ulBufDelta
|
|
sub edx,eax
|
|
mov ulTmpDstDelta,edx
|
|
dec eax ;source doesn't advance after first byte, and
|
|
; we do the first & last bytes outside the
|
|
; loop; already subtracted 1 above
|
|
mov edx,ulGlyDelta
|
|
sub edx,eax
|
|
mov ulTmpSrcDelta,edx
|
|
mov ulTmpWidthInBytes,eax
|
|
mfNwr_scan_loop:
|
|
mov al,[esi] ;do the initial byte separately
|
|
shr al,cl
|
|
mov [edi],al
|
|
inc edi
|
|
mov edx,ulTmpWidthInBytes
|
|
@@:
|
|
mov ax,[esi]
|
|
inc esi
|
|
ror ax,cl
|
|
mov [edi],ah
|
|
inc edi
|
|
dec edx
|
|
jnz @B
|
|
|
|
mov ah,[esi] ;do the final byte separately
|
|
sub al,al
|
|
shr eax,cl
|
|
mov [edi],al
|
|
|
|
add esi,ulTmpSrcDelta
|
|
add edi,ulTmpDstDelta
|
|
dec ebx
|
|
jnz mfNwr_scan_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; MOV first byte, N bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
mov_first_N_wide_unrotated::
|
|
mov edx,ulBufDelta
|
|
mov eax,ulWidthInBytes
|
|
sub edx,eax
|
|
shr eax,1 ;width in words
|
|
jc short odd_width ;there's at least one odd byte
|
|
shr eax,1 ;width in dwords
|
|
jc short two_odd_bytes ;there's an odd word
|
|
;copy width is a dword multiple
|
|
@@:
|
|
mov ecx,eax
|
|
rep movsd ;copy as many dwords as possible
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
odd_width::
|
|
shr eax,1 ;width in dwords
|
|
jc short three_odd_bytes ;there's an odd word and an odd byte
|
|
;there's just an odd byte
|
|
inc edx ;because we won't advance after last byte
|
|
@@:
|
|
mov ecx,eax
|
|
rep movsd ;copy as many dwords as possible
|
|
mov cl,[esi]
|
|
inc esi
|
|
mov [edi],cl
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
two_odd_bytes::
|
|
add edx,2 ;because we won't advance after last word
|
|
@@:
|
|
mov ecx,eax
|
|
rep movsd ;copy as many dwords as possible
|
|
mov cx,[esi]
|
|
add esi,2
|
|
mov [edi],cx
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
three_odd_bytes::
|
|
add edx,3 ;because we won't advance after last word/byte
|
|
@@:
|
|
mov ecx,eax
|
|
rep movsd ;copy as many dwords as possible
|
|
mov cx,[esi]
|
|
mov [edi],cx
|
|
mov cl,[esi+2]
|
|
add esi,3
|
|
mov [edi+2],cl
|
|
add edi,edx
|
|
dec ebx
|
|
jnz @B
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; OR all bytes, N bytes wide dest, unrotated.
|
|
;-----------------------------------------------------------------------;
|
|
or_all_N_wide_unrotated::
|
|
mov edx,ulBufDelta
|
|
mov eax,ulWidthInBytes
|
|
sub edx,eax
|
|
shr eax,1 ;width in words
|
|
jc short or_odd_width ;there's at least one odd byte
|
|
shr eax,1 ;width in dwords
|
|
jc short or_two_odd_bytes ;there's an odd word
|
|
;copy width is a dword multiple
|
|
or_no_odd_bytes_loop::
|
|
push ebx ;preserve scan count
|
|
mov ebx,eax
|
|
@@:
|
|
mov ecx,[esi]
|
|
add esi,4
|
|
or [edi],ecx
|
|
add edi,4 ;copy as many dwords as possible
|
|
dec ebx
|
|
jnz @B
|
|
add edi,edx
|
|
pop ebx ;restore scan count
|
|
dec ebx
|
|
jnz or_no_odd_bytes_loop
|
|
jmp pGlyphLoop
|
|
|
|
or_odd_width::
|
|
shr eax,1 ;width in dwords
|
|
jc short or_three_odd_bytes ;there's an odd word and an odd byte
|
|
;there's just an odd byte
|
|
inc edx ;skip over last byte too
|
|
or_one_odd_bytes_loop::
|
|
push ebx ;preserve scan count
|
|
mov ebx,eax
|
|
@@:
|
|
mov ecx,[esi]
|
|
add esi,4
|
|
or [edi],ecx
|
|
add edi,4 ;copy as many dwords as possible
|
|
dec ebx
|
|
jnz @B
|
|
mov cl,[esi]
|
|
or [edi],cl
|
|
inc esi
|
|
add edi,edx
|
|
pop ebx ;restore scan count
|
|
dec ebx
|
|
jnz or_one_odd_bytes_loop
|
|
jmp pGlyphLoop
|
|
|
|
or_two_odd_bytes::
|
|
add edx,2 ;skip over last 2 bytes too
|
|
or_two_odd_bytes_loop::
|
|
push ebx ;preserve scan count
|
|
mov ebx,eax
|
|
@@:
|
|
mov ecx,[esi]
|
|
add esi,4
|
|
or [edi],ecx
|
|
add edi,4 ;copy as many dwords as possible
|
|
dec ebx
|
|
jnz @B
|
|
mov cx,[esi]
|
|
or [edi],cx
|
|
add esi,2
|
|
add edi,edx
|
|
pop ebx ;restore scan count
|
|
dec ebx
|
|
jnz or_two_odd_bytes_loop
|
|
jmp pGlyphLoop
|
|
|
|
or_three_odd_bytes::
|
|
add edx,3 ;skip over last 3 bytes too
|
|
or_three_odd_bytes_loop::
|
|
push ebx ;preserve scan count
|
|
mov ebx,eax
|
|
@@:
|
|
mov ecx,[esi]
|
|
add esi,4
|
|
or [edi],ecx
|
|
add edi,4 ;copy as many dwords as possible
|
|
dec ebx
|
|
jnz @B
|
|
mov cx,[esi]
|
|
or [edi],cx
|
|
mov cl,[esi+2]
|
|
or [edi+2],cl
|
|
add esi,3
|
|
add edi,edx
|
|
pop ebx ;restore scan count
|
|
dec ebx
|
|
jnz or_three_odd_bytes_loop
|
|
jmp pGlyphLoop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; At this point, the text is drawn to the temp buffer.
|
|
; Now, color-expand the temp buffer to the screen.
|
|
;
|
|
; Input:
|
|
; ppdev = pointer to target surface's PDEV (screen)
|
|
; prclText = pointer to text bounding rectangle
|
|
; prclOpaque = pointer to opaquing rectangle, if there is one
|
|
; iFgColor = text color
|
|
; iBgColor = opaquing rectangle color, if there is one
|
|
; ulTempLeft = X coordinate on dest of left edge of temp buffer pointed
|
|
; to by pTempBuffer
|
|
; pTempBuffer = pointer to first byte (upper left corner) of
|
|
; temp buffer into which we're drawing. This should be
|
|
; word-aligned with the destination
|
|
; ulBufDelta = destination scan-to-scan offset
|
|
; Text drawn to temp buffer
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
draw_to_screen::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Is this transparent or opaque text?
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp prclOpaque,0
|
|
jnz opaque_text
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Transparent text.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Calculate drawing parameters.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov esi,prclText
|
|
mov ebx,ppdev
|
|
mov eax,[esi].xRight
|
|
mov edx,[esi].xLeft
|
|
and edx,not 7
|
|
add eax,7
|
|
sub eax,edx
|
|
shr eax,3 ;width of text in temp buffer in bytes, rounded
|
|
mov ulXparBytes,eax ; up. Also number of quadpixels to draw
|
|
|
|
mov ecx,[ebx].pdev_lNextScan
|
|
mov ulScreenDelta,ecx
|
|
shl eax,3 ;each temp buffer byte maps to eight VGA
|
|
; addresses (two quadpixels in linear mode)
|
|
sub ecx,eax ;offset to next scan in screen
|
|
mov ulTmpDstDelta,ecx
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Calculate the offset of the initial destination quadpixel.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,[esi].yTop
|
|
mul ulScreenDelta
|
|
mov edi,ulTempLeft
|
|
add edi,eax ;offset in bitmap of first quadpixel's byte
|
|
; (remember, this is linear mode)
|
|
;-----------------------------------------------------------------------;
|
|
; Map in the bank containing the top scan of the text, if it's not
|
|
; mapped in already.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,[esi].yTop ;top scan line of text
|
|
mov ulTopScan,eax
|
|
mov esi,pTempBuffer ;initial source address
|
|
cmp eax,[ebx].pdev_rcl1WindowClip.yTop ;is text top less than
|
|
; current bank?
|
|
jl short xpar_map_init_bank ;yes, map in proper bank
|
|
cmp eax,[ebx].pdev_rcl1WindowClip.yBottom ;text top greater than
|
|
; current bank?
|
|
jl short xpar_init_bank_mapped ;no, proper bank already mapped
|
|
xpar_map_init_bank::
|
|
|
|
; Map in the bank containing the top scan line of the fill.
|
|
; Preserves EBX, ESI, and EDI.
|
|
|
|
ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>
|
|
|
|
xpar_init_bank_mapped::
|
|
|
|
add edi,[ebx].pdev_pvBitmapStart ;initial destination address
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Main loop for processing fill in each bank.
|
|
;
|
|
; At start of loop, EBX->pdsurf
|
|
;-----------------------------------------------------------------------;
|
|
|
|
xpar_bank_loop::
|
|
mov edx,ulBottomScan ;bottom of destination rectangle
|
|
cmp edx,[ebx].pdev_rcl1WindowClip.yBottom
|
|
;which comes first, the bottom of the
|
|
; text rect or the bottom of the
|
|
; current bank?
|
|
jl short @F ;text bottom comes first, so draw to
|
|
; that; this is the last bank in text
|
|
mov edx,[ebx].pdev_rcl1WindowClip.yBottom
|
|
;bank bottom comes first; draw to
|
|
; bottom of bank
|
|
@@:
|
|
sub edx,ulTopScan ;# of scans to draw in bank
|
|
|
|
mov al,byte ptr iFgColor
|
|
mov ah,al
|
|
mov ebx,eax
|
|
shl eax,16
|
|
mov ax,bx ;put drawing color in all bytes of EAX
|
|
|
|
sub ebx,ebx ;prepare for look-up in loop
|
|
xpar_scan_loop::
|
|
|
|
mov ecx,ulXparBytes ;number of quadpixel pairs to draw
|
|
|
|
mov bl,[esi] ;get next glyph byte
|
|
and bl,bl ;are all 8 pixels transparent?
|
|
jz xpar_low_nibble_0 ;yes, just skip everything in this byte
|
|
shr bl,4 ;shift the high nibble into the low
|
|
; nibble
|
|
jmp xpar_high_nibble_table[ebx*4] ;branch to draw up to four
|
|
; pixels, followed by a branch to
|
|
; draw the the other nibble (up
|
|
; to four more pixels)
|
|
xpar_scan_done::
|
|
|
|
add edi,ulTmpDstDelta ;point to next screen scan
|
|
|
|
dec edx ;count down scans
|
|
jnz xpar_scan_loop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; See if there are more banks to draw.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,ppdev
|
|
mov eax,[ebx].pdev_rcl1WindowClip.yBottom ;is the text bottom in
|
|
cmp ulBottomScan,eax ; the current bank?
|
|
jnle short do_next_xpar_bank ;no, map in the next bank and draw
|
|
|
|
cRet vFastText ;yes, so we're done
|
|
|
|
do_next_xpar_bank::
|
|
mov ulTopScan,eax
|
|
sub edi,[ebx].pdev_pvBitmapStart ;convert from address to offset
|
|
; within bitmap
|
|
ptrCall <dword ptr [ebx].pdev_pfnBankControl>,<ebx,eax,JustifyTop>
|
|
;map in the bank (call preserves
|
|
; EBX, ESI, and EDI)
|
|
add edi,[ebx].pdev_pvBitmapStart ;convert from offset within bitmap
|
|
; to address (bitmap start just
|
|
; moved)
|
|
jmp xpar_bank_loop ;we're ready to draw to the new
|
|
; bank
|
|
|
|
;-----------------------------------------------------------------------
|
|
; Routines to draw 0-4 pixels with the color in each byte of EAX, depending
|
|
; on the value of the nibble describing the four pixels to draw. "high_nibble"
|
|
; routines draw based on the upper nibble of the byte pointed to by ESI;
|
|
; "low_nibble" routines draw based on the lower nibble of that byte.
|
|
;
|
|
; EAX = color with which to draw, repeated four times
|
|
; EBX = zero (0)
|
|
; ECX = the number of nibble pairs (source bytes = pixels*8) to draw
|
|
; EDX = not used (preserved)
|
|
; ESI = pointer to first nibble pair to draw
|
|
; EDI = pointer to first destination byte to which to draw
|
|
;
|
|
; Must always be entered on the high nibble and extended for an even number of
|
|
; nibbles.
|
|
|
|
;-----------------------------------------------------------------------
|
|
; Macro to draw the four pixels represented by the high nibble of the byte at
|
|
; [ESI].
|
|
|
|
DO_HIGH_NIBBLE macro
|
|
inc esi ;point to the next glyph byte
|
|
add edi,8 ;point to the next destination 8-pixel set
|
|
dec ecx ;count down nibble pairs (8-pixel sets)
|
|
jz xpar_scan_done ;done with this scan
|
|
mov bl,[esi] ;not done; get next glyph byte
|
|
and bl,bl ;are all 8 pixels transparent?
|
|
jz xpar_low_nibble_0 ;yes, just skip everything in this byte
|
|
shr bl,4 ;shift the high nibble into the low nibble
|
|
jmp xpar_high_nibble_table[ebx*4] ;branch to draw up to four pixels
|
|
endm
|
|
|
|
;-----------------------------------------------------------------------
|
|
; Macro to draw the four pixels represented by the low nibble of the byte at
|
|
; [ESI].
|
|
|
|
DO_LOW_NIBBLE macro
|
|
mov bl,[esi] ;get glyph byte again, for the low nibble this
|
|
; time
|
|
and ebx,0fh ;isolate the low nibble
|
|
jmp xpar_low_nibble_table[ebx*4] ;branch to draw up to four pixels
|
|
endm
|
|
|
|
;-----------------------------------------------------------------------
|
|
|
|
xpar_high_nibble_F::
|
|
mov [edi],eax
|
|
xpar_high_nibble_0::
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_E::
|
|
mov [edi],ax
|
|
mov [edi+2],al
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_D::
|
|
mov [edi],ax
|
|
mov [edi+3],al
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_C::
|
|
mov [edi],ax
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_B::
|
|
mov [edi],al
|
|
mov [edi+2],ax
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_8::
|
|
mov [edi],al
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_6::
|
|
mov [edi+1],ax
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_5::
|
|
mov [edi+1],al
|
|
mov [edi+3],al
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_4::
|
|
mov [edi+1],al
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_7::
|
|
mov [edi+1],al
|
|
xpar_high_nibble_3::
|
|
mov [edi+2],ax
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_A::
|
|
mov [edi],al
|
|
xpar_high_nibble_2::
|
|
mov [edi+2],al
|
|
DO_LOW_NIBBLE
|
|
|
|
xpar_high_nibble_9::
|
|
mov [edi],al
|
|
xpar_high_nibble_1::
|
|
mov [edi+3],al
|
|
DO_LOW_NIBBLE
|
|
|
|
|
|
xpar_low_nibble_0::
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_F::
|
|
mov [edi+4],eax
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_E::
|
|
mov [edi+4],ax
|
|
mov [edi+6],al
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_D::
|
|
mov [edi+4],ax
|
|
mov [edi+7],al
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_C::
|
|
mov [edi+4],ax
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_B::
|
|
mov [edi+4],al
|
|
mov [edi+6],ax
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_8::
|
|
mov [edi+4],al
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_6::
|
|
mov [edi+5],ax
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_5::
|
|
mov [edi+5],al
|
|
mov [edi+7],al
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_4::
|
|
mov [edi+5],al
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_7::
|
|
mov [edi+5],al
|
|
xpar_low_nibble_3::
|
|
mov [edi+6],ax
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_A::
|
|
mov [edi+4],al
|
|
xpar_low_nibble_2::
|
|
mov [edi+6],al
|
|
DO_HIGH_NIBBLE
|
|
|
|
xpar_low_nibble_9::
|
|
mov [edi+4],al
|
|
xpar_low_nibble_1::
|
|
mov [edi+7],al
|
|
DO_HIGH_NIBBLE
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Opaque text.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
opaque_text::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Calculate drawing parameters.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,ppdev
|
|
mov esi,prclText ;point to bounding rectangle for text
|
|
|
|
mov eax,[ebx].pdev_lPlanarNextScan ;set the screen width in
|
|
mov ulScreenDelta,eax ; quadpixels
|
|
|
|
sub eax,eax ;assume clipped edge bytes won't need
|
|
mov ulLeftEdgeShift,eax ; to be shifted into position
|
|
mov ulRightEdgeShift,eax
|
|
|
|
mov eax,[esi].xRight
|
|
mov ebx,eax
|
|
and ebx,11b ;dest right edge % 4
|
|
mov edx,[esi].xLeft
|
|
mov ulTextLeft,edx ;remember dest left edge
|
|
mov cl,jOpaqueRightMasks[ebx] ;set right edge clip mask
|
|
mov ebx,edx
|
|
and ebx,11b ;dest left edge % 4
|
|
mov ulRightMask,ecx
|
|
mov cl,jOpaqueLeftMasks[ebx] ;set left edge clip mask
|
|
mov ulLeftMask,ecx
|
|
|
|
and edx,not 7 ;left edge, rounded down to nearest byte
|
|
dec eax ;right edge - 1
|
|
sub eax,edx
|
|
shr eax,3 ;width of the text in the temp buffer in bytes,
|
|
; rounded up, minus 1. This is used to point to
|
|
; the partial right edge, if there is one
|
|
mov ulTextWidthInBytesMinus1,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Figure out what edges we need to handle, and calculate some info for
|
|
; doing whole bytes.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,[esi].xLeft
|
|
mov eax,[esi].xRight
|
|
and edx,not 3
|
|
add eax,3
|
|
sub eax,edx
|
|
shr eax,2 ;width of the text in the temp buffer in
|
|
; quadpixels, rounded up (counting all whole
|
|
; and partial quadpixels)
|
|
cmp eax,1 ;only one quadpixels total?
|
|
jnz short @F ;no
|
|
;yes, special case a single quadpixel
|
|
mov ecx,offset opaq_check_more_banks ;assume it's a solid
|
|
; quadpixel
|
|
mov ebx,ulLeftMask
|
|
and ebx,ulRightMask
|
|
cmp bl,0ffh ;solid quadpixel?
|
|
jz short opaq_set_deltas_and_edge_vector ;yes, all set
|
|
mov ulLeftMask,ebx ;no, draw as a left edge
|
|
dec eax ;there are no whole quadpixels
|
|
mov ecx,offset opaq_draw_left_edge_only
|
|
test [esi].xLeft,100b ;is partial quadpixel in bits 0-3?
|
|
jnz opaq_set_edge_vector ;yes, no shift required, already set
|
|
mov ulLeftEdgeShift,4 ;no, must shift right 4 to get into
|
|
; bits 0-3
|
|
jmp short opaq_set_edge_vector ;yes, all set
|
|
|
|
@@:
|
|
lea edx,[eax-1]
|
|
mov ulVGAWidthInBytesMinus1,edx ;offset from leftmost VGA dest byte
|
|
; to rightmost
|
|
|
|
test [esi].xLeft,11b ;is left edge a solid quadpixel?
|
|
jz short opaq_left_edge_solid ;yes
|
|
dec eax ;one less whole quadpixel
|
|
mov ecx,offset opaq_draw_left_edge_only ;assume right edge is solid
|
|
test [esi].xLeft,100b ;is partial quadpixel in bits 0-3?
|
|
jnz short @F ;yes, no shift required, already set
|
|
mov ulLeftEdgeShift,4 ;no, must shift right 4 to get into
|
|
; bits 0-3
|
|
@@:
|
|
test [esi].xRight,11b ;is right edge a solid quadpixel?
|
|
jz short opaq_set_deltas_and_edge_vector ;yes, all set
|
|
dec eax ;one less whole quadpixel
|
|
mov ecx,offset opaq_draw_both_edges ;both edges are non-solid
|
|
jmp short opaq_set_right_edge_shift
|
|
|
|
opaq_left_edge_solid::
|
|
mov ecx,offset opaq_check_more_banks ;assume right edge is solid
|
|
test [esi].xRight,11b ;is right edge a solid quadpixel?
|
|
jz short opaq_set_deltas_and_edge_vector ;yes, all set
|
|
dec eax ;one less whole quadpixel
|
|
mov ecx,offset opaq_draw_right_edge_only ;no, do non-solid right
|
|
; edge
|
|
opaq_set_right_edge_shift:
|
|
test [esi].xRight,100b ;is partial quadpixel in bits 0-3?
|
|
jnz short opaq_set_deltas_and_edge_vector
|
|
;yes, no shift required, already set
|
|
mov ulRightEdgeShift,4 ;no, must shift right 4 to get into
|
|
; bits 0-3
|
|
|
|
; At this point, EAX = # of whole quadpixels across source = # of whole bytes
|
|
; (addresses) across destination
|
|
|
|
opaq_set_deltas_and_edge_vector:
|
|
mov edi,ulScreenDelta
|
|
sub edi,eax ;whole bytes offset to next scan in screen
|
|
; (there are four pixels--one quadpixel--
|
|
; at each VGA address)
|
|
mov ulTmpDstDelta,edi
|
|
|
|
mov edx,[esi].xLeft
|
|
mov edi,[esi].xRight
|
|
add edx,3
|
|
and edx,not 7
|
|
add edi,4
|
|
sub edi,edx
|
|
shr edi,3 ;width of the text in the temp buffer in bytes,
|
|
; counting bytes containing whole quadpixels
|
|
; but not bytes containing only partial
|
|
; quadpixels. (Remember, text bytes map to
|
|
; quadpixel pairs; text nibbles map to
|
|
; quadpixels)
|
|
sub edi,ulBufDelta
|
|
neg edi
|
|
mov ulTmpSrcDelta,edi ;offset to next scan in source buffer when
|
|
; doing whole quadpixels
|
|
opaq_set_edge_vector::
|
|
mov pfnEdgeVector,ecx ;save address of partial-quadpixel-
|
|
; drawing code, or end of loop if no
|
|
; partial edge
|
|
mov edx,eax ;# of whole quadpixels
|
|
mov pfnFirstOpaqVector,offset opaq_whole_quadpixels
|
|
;assume there are whole quadpixels
|
|
; to copy, in which case we'll draw
|
|
; them first, then the partial edge
|
|
; quadpixels
|
|
sub edi,edi
|
|
shr edx,1 ;# of quadpixels / 2
|
|
mov ulWholeWidthInQuadpixelPairs,edx ;# of quadpixel pairs to copy
|
|
adc edi,edi ;odd quadpixel status
|
|
mov ulOddQuadpixel,edi ;1 if there is an odd quadpixel, 0 else
|
|
dec edx
|
|
mov ulWholeWidthInQuadpixelPairsMinus1,edx
|
|
;# of whole quadpixel pairs to copy,
|
|
; minus 1 (for case with both leading
|
|
; and trailing quadpixels)
|
|
cmp eax,0 ;are there any whole quadpixels at all?
|
|
jg short @F ;yes, we're all set
|
|
;no, set up for edge(s) only
|
|
mov pfnFirstOpaqVector,ecx ;the edges are first and only, because
|
|
; there are no whole quadpixels
|
|
@@:
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Determine the screen offset of the first destination byte.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,ppdev
|
|
mov eax,ulTopScan
|
|
mov ecx,eax
|
|
mul ulScreenDelta
|
|
mov edi,[esi].xLeft
|
|
shr edi,2 ;left edge screen offset in quadpixels
|
|
add edi,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Map in the bank containing the top scan of the text, if it's not
|
|
; mapped in already.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp ecx,[ebx].pdev_rcl1PlanarClip.yTop ;is text top less than
|
|
; current bank?
|
|
jl short opaq_map_init_bank ;yes, map in proper bank
|
|
cmp ecx,[ebx].pdev_rcl1PlanarClip.yBottom ;text top greater than
|
|
; current bank?
|
|
jl short opaq_init_bank_mapped ;no, proper bank already mapped
|
|
opaq_map_init_bank::
|
|
|
|
; Map in the bank containing the top scan line of the fill.
|
|
; Preserves EBX, ESI, and EDI.
|
|
|
|
ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>,<ebx,ecx,JustifyTop>
|
|
|
|
opaq_init_bank_mapped::
|
|
|
|
add edi,[ebx].pdev_pvBitmapStart ;initial destination address
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Load the latches with the background color.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
sub eax,eax
|
|
mov edx,[esi].xLeft
|
|
and edx,011b
|
|
cmp eax,edx ;is the first quadpixel a full
|
|
; quadpixel?
|
|
adc eax,eax ;if so, EAX = 1, else EAX = 0
|
|
mov edx,iBgColor
|
|
mov [edi+eax],dl ;write the bg color to the first full
|
|
; quadpixel, in each of the four planes
|
|
mov dl,[edi+eax] ;read back the quadpixel to load the
|
|
; latches with the bg color
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up the VGA's hardware for read mode 0 and write mode 2, the ALUs
|
|
; for XOR, and the Bit Mask to 1 for bits that differ between the fg and
|
|
; bg, 0 for bits that are the same.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,VGA_BASE + GRAF_ADDR
|
|
mov ah,byte ptr [ebx].pdev_ulrm0_wmX[2]
|
|
;write mode 2 setting for Graphics Mode
|
|
mov al,GRAF_MODE
|
|
out dx,ax ;write mode 2 to expand glyph bits to
|
|
; 0 or 0ffh per plane
|
|
mov eax,GRAF_DATA_ROT + (DR_XOR SHL 8)
|
|
out dx,ax ;XOR to flip latched data to make ~bg
|
|
|
|
mov ah,byte ptr iBgColor
|
|
xor ah,byte ptr iFgColor
|
|
mov al,GRAF_BIT_MASK
|
|
out dx,ax ;pass through common fg & bg bits
|
|
; unchanged from bg color in latches;
|
|
; non-common bits come from XOR in the
|
|
; ALUs, flipped from the bg to the fg
|
|
; state if the glyph bit for the pixel
|
|
; in that plane is 1, still in bg state
|
|
; if the glyph bit for that plane is 0
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Main loop for processing fill in each bank.
|
|
;
|
|
; At start of loop and on each loop, EBX->ppdev and EDI->first destination
|
|
; byte.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
opaq_bank_loop::
|
|
mov pScreen,edi ;remember initial copy destination
|
|
|
|
mov edx,ulBottomScan ;bottom of destination rectangle
|
|
cmp edx,[ebx].pdev_rcl1PlanarClip.yBottom
|
|
;which comes first, the bottom of the
|
|
; text rect or the bottom of the
|
|
; current bank?
|
|
jl short @F ;text bottom comes first, so draw to
|
|
; that; this is the last bank in text
|
|
mov edx,[ebx].pdev_rcl1PlanarClip.yBottom
|
|
;bank bottom comes first; draw to
|
|
; bottom of bank
|
|
@@:
|
|
sub edx,ulTopScan ;# of scans to draw in bank
|
|
mov ulNumScans,edx
|
|
jmp pfnFirstOpaqVector ;do first sort of drawing (whole
|
|
; bytes, or edge(s) if no whole
|
|
; bytes)
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Draw the whole quadpixels, handling as many as possible paired into
|
|
; bytes so we can draw 8 pixels at a time.
|
|
;
|
|
; On entry:
|
|
; EDI = first destination byte
|
|
;-----------------------------------------------------------------------;
|
|
opaq_whole_quadpixels::
|
|
mov esi,pTempBuffer ;point to first source byte
|
|
mov eax,ulTextLeft ;left edge
|
|
test eax,011b ;is there a partial (masked) edge?
|
|
jz short @f ;no, start addresses are correct
|
|
inc edi ;yes, skip over one dest byte for the
|
|
; four pixels in the partial edge
|
|
test eax,100b ;do we have a partial left edge in the
|
|
; second quadpixel?
|
|
jz short @f ;no, source start address is correct
|
|
inc esi ;yes, skip over a source byte because
|
|
; the partial edge is all that's in
|
|
; this byte
|
|
@@:
|
|
mov ebx,pGlyphFlipTable ;point to the look-up table we'll use
|
|
; to flip the glyph bits into the form
|
|
; required by planar mode
|
|
mov edx,ulNumScans ;# of scans to draw
|
|
|
|
;decide which copy loop to use, based
|
|
; on the word-alignment of the dest
|
|
; rectangle with the screen
|
|
;the following tests rely on VGA even
|
|
; addresses being aligned to the start
|
|
; of corresponding source buffer bytes
|
|
; (4-pixel sets at even VGA addresses
|
|
; match up to the upper quadpixels of
|
|
; source buffer bytes)
|
|
test edi,1 ;is dest word-aligned?
|
|
jnz short opaq_need_leading ;no, need leading quadpixel
|
|
;yes, no leading quadpixel
|
|
cmp ulOddQuadpixel,1 ;odd width in quadpixels?
|
|
jnz short opaq_scan_loop ;no, no trailing quadpixel
|
|
jmp opaq_scan_loop_t ;yes, trailing quadpixel
|
|
|
|
opaq_need_leading: ;there's a leading quadpixel
|
|
cmp ulOddQuadpixel,1 ;odd width in quadpixels?
|
|
jnz opaq_scan_loop_lt ;no, trailing quadpixel
|
|
jmp opaq_scan_loop_l ;yes, no trailing quadpixel
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loops for copying whole quadpixels to the screen, as much as possible a
|
|
; quadpixel pair at a time.
|
|
; On entry:
|
|
; EBX = pointer to flip table
|
|
; EDX = # of scans to draw
|
|
; ESI = pointer to first buffer byte from which to copy
|
|
; EDI = pointer to first screen byte to which to copy
|
|
; ulTmpSrcDelta = offset to next buffer scan
|
|
; ulTmpDstDelta = offset to next destination (VGA) scan
|
|
; ulWholeWidthInQuadpixelPairs = # of whole bytes to copy
|
|
; ulWholeWidthInQuadpixelPairsMinus1 = # of whole bytes to copy, minus 1
|
|
; LATER could break out and optimize short runs, such as 1, 2, 3, 4 wide.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop for doing whole opaque words: no leading quadpixel, no trailing
|
|
; quadpixel.
|
|
;-----------------------------------------------------------------------;
|
|
opaq_scan_loop::
|
|
opaq_sl_row_loop:
|
|
mov ecx,ulWholeWidthInQuadpixelPairs
|
|
opaq_sl_byte_loop:
|
|
mov bl,[esi] ;get the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 0-3 and 4-7
|
|
inc esi ;point to the next temp buffer byte
|
|
mov ah,al
|
|
shr al,4 ;first quadpixel to draw in AL, next in AH
|
|
mov [edi],ax ;draw the glyph
|
|
add edi,2 ;point to the next destination address
|
|
|
|
dec ecx
|
|
jnz opaq_sl_byte_loop
|
|
opaq_sl_whole_done:
|
|
add esi,ulTmpSrcDelta ;point to next buffer scan
|
|
add edi,ulTmpDstDelta ;point to next screen scan
|
|
dec edx ;count down scans
|
|
jnz opaq_sl_row_loop
|
|
jmp pfnEdgeVector ;do the edge(s)
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop for doing whole opaque words: leading quadpixel, no trailing
|
|
; quadpixel.
|
|
;-----------------------------------------------------------------------;
|
|
opaq_scan_loop_l::
|
|
opaq_sll_row_loop:
|
|
mov bl,[esi] ;get the first temp buffer byte
|
|
inc esi ;point to the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 0-3
|
|
mov [edi],al ;draw the first 4 pixels (the leading quadpixel)
|
|
inc edi ;point to the next destination address
|
|
|
|
mov ecx,ulWholeWidthInQuadpixelPairs
|
|
test ecx,ecx ;see if there's anything else to draw
|
|
jz short opaq_sll_whole_done
|
|
opaq_sll_byte_loop:
|
|
mov bl,[esi] ;get the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 0-3 and 4-7
|
|
inc esi ;point to the next temp buffer byte
|
|
mov ah,al
|
|
shr al,4 ;first quadpixel to draw in AL, next in AH
|
|
mov [edi],ax ;draw the glyph
|
|
add edi,2 ;point to the next destination address
|
|
|
|
dec ecx
|
|
jnz opaq_sll_byte_loop
|
|
opaq_sll_whole_done:
|
|
add esi,ulTmpSrcDelta ;point to next buffer scan
|
|
add edi,ulTmpDstDelta ;point to next screen scan
|
|
dec edx ;count down scans
|
|
jnz opaq_sll_row_loop
|
|
jmp pfnEdgeVector ;do the edge(s)
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop for doing whole opaque words: leading byte, trailing byte.
|
|
;-----------------------------------------------------------------------;
|
|
opaq_scan_loop_lt::
|
|
opaq_sllt_row_loop:
|
|
mov bl,[esi] ;get the first temp buffer byte
|
|
inc esi ;point to the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 0-3
|
|
mov [edi],al ;draw the first 4 pixels (the leading quadpixel)
|
|
inc edi ;point to the next destination address
|
|
|
|
mov ecx,ulWholeWidthInQuadpixelPairsMinus1
|
|
test ecx,ecx ;see if there's anything else to draw
|
|
jz short opaq_sllt_whole_done
|
|
opaq_sllt_byte_loop:
|
|
mov bl,[esi] ;get the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 0-3 and 4-7
|
|
inc esi ;point to the next temp buffer byte
|
|
mov ah,al
|
|
shr al,4 ;first quadpixel to draw in AL, next in AH
|
|
mov [edi],ax ;draw the glyph
|
|
add edi,2 ;point to the next destination address
|
|
|
|
dec ecx
|
|
jnz opaq_sllt_byte_loop
|
|
opaq_sllt_whole_done:
|
|
mov bl,[esi] ;get the last temp buffer byte
|
|
inc esi ;point to the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 4-7
|
|
shr eax,4 ;put the quadpixel in bits 0-3
|
|
mov [edi],al ;draw the last 4 pixels (the trailing quadpixel)
|
|
inc edi ;point to the next destination address
|
|
|
|
add esi,ulTmpSrcDelta ;point to next buffer scan
|
|
add edi,ulTmpDstDelta ;point to next screen scan
|
|
dec edx ;count down scans
|
|
jnz opaq_sllt_row_loop
|
|
jmp pfnEdgeVector ;do the edge(s)
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop for doing whole opaque words: no leading byte, trailing byte.
|
|
;-----------------------------------------------------------------------;
|
|
opaq_scan_loop_t::
|
|
opaq_slt_row_loop:
|
|
mov ecx,ulWholeWidthInQuadpixelPairs
|
|
test ecx,ecx ;see if there's anything else to draw
|
|
jz short opaq_slt_whole_done
|
|
opaq_slt_byte_loop:
|
|
mov bl,[esi] ;get the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 0-3 and 4-7
|
|
inc esi ;point to the next temp buffer byte
|
|
mov ah,al
|
|
shr al,4 ;first quadpixel to draw in AL, next in AH
|
|
mov [edi],ax ;draw the glyph
|
|
add edi,2 ;point to the next destination address
|
|
|
|
dec ecx
|
|
jnz opaq_slt_byte_loop
|
|
opaq_slt_whole_done:
|
|
mov bl,[esi] ;get the last temp buffer byte
|
|
inc esi ;point to the next temp buffer byte
|
|
mov al,[ebx] ;reverse the order of bits 4-7
|
|
shr eax,4 ;put the quadpixel in bits 0-3
|
|
mov [edi],al ;draw the last 4 pixels (the trailing quadpixel)
|
|
inc edi ;point to the next destination address
|
|
|
|
add esi,ulTmpSrcDelta ;point to next buffer scan
|
|
add edi,ulTmpDstDelta ;point to next screen scan
|
|
dec edx ;count down scans
|
|
jnz opaq_slt_row_loop
|
|
jmp pfnEdgeVector ;do the edge(s)
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Draw a partial left edge.
|
|
;-----------------------------------------------------------------------;
|
|
opaq_draw_left_edge_only::
|
|
|
|
push offset opaq_edges_done ;return here when done with edge
|
|
|
|
opaq_draw_left_edge_only_entry::
|
|
mov esi,pTempBuffer ;source start
|
|
mov edi,pScreen ;destination (VGA) start
|
|
mov ecx,ulLeftEdgeShift ;CL=amount by which to shift byte to
|
|
; right-justify desired quadpixel (0 or
|
|
; 4)
|
|
mov eax,ulLeftMask ;clip mask for edge
|
|
|
|
; Enter here to copy a partial edge, with the Map Mask set to clip, ESI
|
|
; pointing to the first source byte to copy, EDI pointing to the first dest
|
|
; byte to copy to, CL the amount by which to right-shift to get the quadpixel
|
|
; of interest into bits 0-3, and AL the Map Mask setting to clip the edge
|
|
|
|
opaq_draw_edge_entry:
|
|
push ebp ;preserve stack frame pointer
|
|
|
|
mov edx,VGA_BASE + SEQ_DATA ;SEQ_INDEX already points to Map Mask
|
|
out dx,al ;set Map Mask for left edge
|
|
|
|
mov edx,ulScreenDelta ;width of a screen scan in addresses
|
|
mov eax,ulNumScans ;height of text
|
|
mov ebx,pGlyphFlipTable ;point to the look-up table we'll use
|
|
; to flip the glyph bits into the form
|
|
; required by planar mode
|
|
mov ebp,ulBufDelta ;width of a source scan in bytes
|
|
;***stack frame unavailable***
|
|
opaq_edge_loop::
|
|
mov bl,[esi] ;get the next text buffer byte
|
|
shr bl,cl ;move the desired quadpixel into bits 0-3
|
|
add esi,ebp ;point to the next destination byte
|
|
mov bl,[ebx] ;reverse the order of bits 0-3
|
|
mov [edi],bl ;draw up to four pixels, with the Map Mask
|
|
; clipping, if necessary
|
|
add edi,edx ;point to the next destination byte
|
|
|
|
dec eax
|
|
jnz opaq_edge_loop
|
|
|
|
pop ebp ;restore stack frame pointer
|
|
;***stack frame available***
|
|
retn
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Draw a partial right edge only. Once we've set up the pointers, this
|
|
; is done with exactly the same code as the left edge.
|
|
;-----------------------------------------------------------------------;
|
|
opaq_draw_right_edge_only::
|
|
push offset opaq_edges_done ;return here when done with edge
|
|
|
|
opaq_draw_right_edge_only_entry::
|
|
mov esi,ulTextWidthInBytesMinus1
|
|
add esi,pTempBuffer ;point to right edge start in buffer
|
|
mov edi,ulVGAWidthInBytesMinus1
|
|
add edi,pScreen ;point to right edge start in screen
|
|
mov ecx,ulRightEdgeShift ;CL=amount by which to shift byte to
|
|
; right-justify desired quadpixel (0 or
|
|
; 4)
|
|
mov eax,ulRightMask ;clip mask for edge
|
|
|
|
jmp opaq_draw_edge_entry
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Draw both left and right partial edges. We do this by calling first
|
|
; the left and then the right edge drawing code.
|
|
;-----------------------------------------------------------------------;
|
|
opaq_draw_both_edges::
|
|
call opaq_draw_left_edge_only_entry
|
|
call opaq_draw_right_edge_only_entry
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Restore Map Mask to enable all planes, now that we're done drawing
|
|
; partial edges.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
opaq_edges_done:
|
|
mov al,MM_ALL
|
|
mov edx,VGA_BASE + SEQ_DATA ;SEQ_INDEX already points to Map Mask
|
|
out dx,al ;set Map Mask for left edge
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; See if there are more banks to draw.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
opaq_check_more_banks::
|
|
mov ebx,ppdev
|
|
mov eax,[ebx].pdev_rcl1PlanarClip.yBottom ;is the text bottom in
|
|
cmp ulBottomScan,eax ; the current bank?
|
|
jnle short opaq_do_next_bank ;no, do the next bank
|
|
;yes, so we're done
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Restore the VGA's hardware to the default state.
|
|
; The Graphics Controller Index still points to the Bit Mask at this
|
|
; point.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,VGA_BASE + GRAF_DATA
|
|
mov al,0ffh
|
|
out dx,al ;enable all bits through the Bit Mask
|
|
|
|
mov esi,ppdev
|
|
dec edx ;point back to the Graphics Index reg
|
|
mov ah,byte ptr [esi].pdev_ulrm0_wmX[0]
|
|
;write mode 0 setting for Graphics Mode
|
|
mov al,GRAF_MODE
|
|
out dx,ax ;write mode 0, read mode 0
|
|
|
|
mov eax,GRAF_DATA_ROT + (DR_SET SHL 8)
|
|
out dx,ax ;replace mode, no rotate
|
|
|
|
cRet vFastText
|
|
|
|
|
|
opaq_do_next_bank::
|
|
mov esi,prclText
|
|
mov ulTopScan,eax ;this will be the top of the next bank
|
|
mov ecx,eax
|
|
mul ulScreenDelta
|
|
mov edi,[esi].xLeft
|
|
shr edi,2 ;convert from pixels to quadpixels
|
|
add edi,eax ;next screen byte to which to copy
|
|
|
|
ptrCall <dword ptr [ebx].pdev_pfnPlanarControl>,<ebx,ecx,JustifyTop>
|
|
;map in the bank (call preserves EBX,
|
|
; ESI, and EDI)
|
|
|
|
add edi,[ebx].pdev_pvBitmapStart ;initial destination address
|
|
|
|
mov eax,ulBufDelta
|
|
mul ulNumScans
|
|
add pTempBuffer,eax ;advance to next temp buffer scan to
|
|
; copy
|
|
|
|
jmp opaq_bank_loop ;we're ready to draw in the new bank
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Special 8-wide aligned opaque drawing code. Loads the latches with the
|
|
; background color, sets the Bit Mask to 1 for bits that differ between
|
|
; the foreground and background, sets the ALUs to XOR, then uses write
|
|
; mode 3 to draw the glyphs. Joyously, there are no partial bytes to
|
|
; worry about, so we can really crank up the code.
|
|
;
|
|
; On entry:
|
|
; EBX = prclText
|
|
;-----------------------------------------------------------------------;
|
|
special_8_wide_aligned_opaque::
|
|
|
|
mov esi,ppdev
|
|
mov edi,[ebx].yBottom
|
|
mov eax,[ebx].yTop
|
|
sub edi,eax ;height of glyphs
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Map in the bank containing the top scan of the text, if it's not
|
|
; mapped in already.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp eax,[esi].pdev_rcl1PlanarClip.yTop ;is text top less than
|
|
; current bank?
|
|
jl short s8wao_map_init_bank ;yes, map in proper bank
|
|
cmp eax,[esi].pdev_rcl1PlanarClip.yBottom ;text top greater than
|
|
; current bank?
|
|
jl short s8wa0_init_bank_mapped ;no, proper bank already mapped
|
|
s8wao_map_init_bank::
|
|
|
|
; Map in the bank containing the top scan line of the text, making sure we're
|
|
; in planar mode at the same time.
|
|
; Preserves EBX, ESI, and EDI.
|
|
|
|
ptrCall <dword ptr [esi].pdev_pfnPlanarControl>,<esi,eax,JustifyTop>
|
|
|
|
s8wa0_init_bank_mapped::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; We handle only cases where the text lies entirely in one bank.
|
|
; LATER handle broken rasters and/or bank-spanning cases?
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,[esi].pdev_rcl1PlanarClip.yBottom
|
|
sub eax,[ebx].yTop ;maximum run in bank
|
|
cmp edi,eax ;does all the text fit in the bank?
|
|
jg general_handler ;no, let general code handle it
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up variables.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ulScans,edi ;# of scans
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Point to the first screen byte at which to draw.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,[ebx].yTop
|
|
mul [esi].pdev_lPlanarNextScan
|
|
mov edi,[ebx].xLeft
|
|
shr edi,2
|
|
add edi,eax ;next screen byte to which to copy
|
|
add edi,[esi].pdev_pvBitmapStart ;initial destination address
|
|
mov pScreen,edi
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Load the latches with the background color.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,iBgColor
|
|
mov byte ptr [edi],al ;write the bg color to the first byte
|
|
mov al,[edi] ;read back the byte to load the
|
|
; latches with the bg color
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up the VGA's hardware for read mode 0 and write mode 2, the ALUs
|
|
; for XOR, and the Bit Mask to 1 for bits that differ between the fg and
|
|
; bg, 0 for bits that are the same.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,VGA_BASE + GRAF_ADDR
|
|
mov ah,byte ptr [esi].pdev_ulrm0_wmX[2]
|
|
;write mode 2 setting for Graphics Mode
|
|
mov al,GRAF_MODE
|
|
out dx,ax ;write mode 2 to expand glyph bits to
|
|
; 0 or 0ffh per plane
|
|
mov eax,GRAF_DATA_ROT + (DR_XOR SHL 8)
|
|
out dx,ax ;XOR to flip latched data to make ~bg
|
|
|
|
mov ah,byte ptr iBgColor
|
|
xor ah,byte ptr iFgColor
|
|
mov al,GRAF_BIT_MASK
|
|
out dx,ax ;pass through common fg & bg bits
|
|
; unchanged from bg color in latches;
|
|
; non-common bits come from XOR in the
|
|
; ALUs, flipped from the bg to the fg
|
|
; state if the glyph bit for the pixel
|
|
; in that plane is 1, still in bg state
|
|
; if the glyph bit for that plane is 0
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up the screen scan offset in EDX.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,[esi].pdev_lPlanarNextScan ;offset from one scan to next
|
|
|
|
mov ecx,ulGlyphCount
|
|
|
|
s8wao_glyph_loop:
|
|
mov ebx,pGlyphPos ;point to the current glyph to draw
|
|
add pGlyphPos,(size GLYPHPOS) ;point to the next glyph
|
|
mov edi,pScreen ;point to current glyph's screen
|
|
; location
|
|
mov esi,[ebx].gp_pgdf ;point to current glyph def
|
|
add pScreen,2 ;point to the next glyph's screen
|
|
; location
|
|
mov ecx,ulScans ;# of scans
|
|
mov esi,[esi].gdf_pgb ;point to current glyph
|
|
mov ebx,pGlyphFlipTable ;point to the look-up table we'll use
|
|
; to flip the glyph bits into the form
|
|
; required by planar mode
|
|
add esi,gb_aj ;point to the current glyph's bits
|
|
|
|
s8wao_byte_loop::
|
|
mov bl,[esi] ;get the next glyph byte
|
|
inc esi ;point to the next glyph byte
|
|
mov al,[ebx] ;reverse the order of bits 0-3 and 4-7
|
|
mov ah,al
|
|
shr al,4 ;first quadpixel to draw in AL, next in AH
|
|
mov [edi],ax ;draw the glyph
|
|
add edi,edx ;point to the next destination byte
|
|
|
|
dec ecx ;count down glyph scans
|
|
jnz s8wao_byte_loop
|
|
|
|
dec ulGlyphCount ;count down glyphs
|
|
jnz s8wao_glyph_loop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Restore the VGA's hardware to the default state.
|
|
; The Graphics Controller Index still points to the Bit Mask at this
|
|
; point.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,VGA_BASE + GRAF_DATA
|
|
mov al,0ffh
|
|
out dx,al ;enable all bits through the Bit Mask
|
|
|
|
mov esi,ppdev
|
|
dec edx ;point back to the Graphics Index reg
|
|
mov ah,byte ptr [esi].pdev_ulrm0_wmX[0]
|
|
;write mode 0 setting for Graphics Mode
|
|
mov al,GRAF_MODE
|
|
out dx,ax ;write mode 0, read mode 0
|
|
|
|
mov eax,GRAF_DATA_ROT + (DR_SET SHL 8)
|
|
out dx,ax ;replace mode, no rotate
|
|
|
|
draw_prop_done::
|
|
cRet vFastText
|
|
|
|
endProc vFastText
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; VOID vSetWriteModes(ULONG * pulWriteModes);
|
|
;
|
|
; Sets the four bytes at *pulWriteModes to the values to be written to
|
|
; the Graphics Mode register to select read mode 0 and:
|
|
; write mode 0, write mode 1, write mode 2, and write mode 3,
|
|
; respectively.
|
|
;
|
|
; Must already be in graphics mode when this is called.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc vSetWriteModes,4,< \
|
|
pulWriteModes:ptr >
|
|
|
|
mov edx,VGA_BASE + GRAF_ADDR
|
|
mov al,GRAF_MODE
|
|
out dx,al ;point the GC Index to the Graphics Mode reg
|
|
inc edx ;point to the GC Data reg
|
|
in al,dx ;get the current setting of the Graphics Mode
|
|
and eax,0fch ;mask off the write mode fields
|
|
mov ah,al
|
|
mov edx,eax
|
|
shl edx,16
|
|
or eax,edx ;put the Graphics Mode setting in all 4 bytes
|
|
mov edx,pulWriteModes ;the mode values go here
|
|
or eax,03020100h ;insert the write mode fields
|
|
mov [edx],eax ;store the Graphics Mode settings
|
|
|
|
cRet vSetWriteModes
|
|
|
|
endProc vSetWriteModes
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; VOID vClearMemDword(PULONG * pulBuffer, ULONG ulDwordCount);
|
|
;
|
|
; Clears ulCount dwords starting at pjBuffer.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
pulBuffer equ [esp+8]
|
|
ulDwordCount equ [esp+12]
|
|
|
|
cProc vClearMemDword,8,<>
|
|
|
|
push edi
|
|
mov edi,pulBuffer
|
|
mov ecx,ulDwordCount
|
|
sub eax,eax
|
|
rep stosd
|
|
pop edi
|
|
|
|
cRet vClearMemDword
|
|
|
|
endProc vClearMemDword
|
|
|
|
public general_handler
|
|
public draw_f_tb_no_to_temp_start
|
|
public draw_nf_tb_no_to_temp_start
|
|
public draw_to_temp_start_entry
|
|
public draw_f_ntb_o_to_temp_start
|
|
public draw_nf_ntb_o_to_temp_start
|
|
public draw_to_temp_start_entry2
|
|
public draw_f_tb_no_to_temp_loop
|
|
public draw_nf_tb_no_to_temp_loop
|
|
public draw_to_temp_loop_entry
|
|
public draw_f_ntb_o_to_temp_loop
|
|
public draw_nf_ntb_o_to_temp_loop
|
|
public draw_to_temp_loop_entry2
|
|
public or_all_1_wide_rotated_need_last
|
|
public or_all_1_wide_rotated_no_last
|
|
public or_first_1_wide_rotated_need_last
|
|
public or_first_1_wide_rotated_no_last
|
|
public or_first_1_wide_rotated_loop
|
|
public mov_first_1_wide_rotated_need_last
|
|
public mov_first_1_wide_rotated_no_last
|
|
public mov_first_1_wide_rotated_loop
|
|
public mov_first_1_wide_unrotated
|
|
public mov_first_1_wide_unrotated_loop
|
|
public or_all_1_wide_unrotated
|
|
public or_all_1_wide_unrotated_loop
|
|
public or_first_2_wide_rotated_need_last
|
|
public or_first_2_wide_rotated_need_loop
|
|
public or_all_2_wide_rotated_need_last
|
|
public or_all_2_wide_rotated_need_loop
|
|
public mov_first_2_wide_rotated_need_last
|
|
public mov_first_2_wide_rotated_need_loop
|
|
public or_first_2_wide_rotated_no_last
|
|
public or_first_2_wide_rotated_loop
|
|
public or_all_2_wide_rotated_no_last
|
|
public or_all_2_wide_rotated_loop
|
|
public mov_first_2_wide_rotated_no_last
|
|
public mov_first_2_wide_rotated_loop
|
|
public mov_first_2_wide_unrotated
|
|
public mov_first_2_wide_unrotated_loop
|
|
public or_all_2_wide_unrotated
|
|
public or_all_2_wide_unrotated_loop
|
|
public or_first_3_wide_rotated_need_last
|
|
public or_all_3_wide_rotated_need_last
|
|
public mov_first_3_wide_rotated_need_last
|
|
public or_first_3_wide_rotated_no_last
|
|
public or_all_3_wide_rotated_no_last
|
|
public mov_first_3_wide_rotated_no_last
|
|
public mov_first_3_wide_unrotated
|
|
public or_all_3_wide_unrotated
|
|
public or_first_4_wide_rotated_need_last
|
|
public or_all_4_wide_rotated_need_last
|
|
public mov_first_4_wide_rotated_need_last
|
|
public or_first_4_wide_rotated_no_last
|
|
public or_all_4_wide_rotated_no_last
|
|
public mov_first_4_wide_rotated_no_last
|
|
public mov_first_4_wide_unrotated
|
|
public or_all_4_wide_unrotated
|
|
public or_first_N_wide_rotated_need_last
|
|
public or_all_N_wide_rotated_need_last
|
|
public mov_first_N_wide_rotated_need_last
|
|
public or_first_N_wide_rotated_no_last
|
|
public or_all_N_wide_rotated_no_last
|
|
public mov_first_N_wide_rotated_no_last
|
|
public mov_first_N_wide_unrotated
|
|
public odd_width
|
|
public two_odd_bytes
|
|
public three_odd_bytes
|
|
public or_all_N_wide_unrotated
|
|
public or_no_odd_bytes_loop
|
|
public or_odd_width
|
|
public or_one_odd_bytes_loop
|
|
public or_two_odd_bytes
|
|
public or_two_odd_bytes_loop
|
|
public or_three_odd_bytes
|
|
public or_three_odd_bytes_loop
|
|
public draw_to_screen
|
|
public opaque_text
|
|
public opaq_left_edge_solid
|
|
public opaq_set_edge_vector
|
|
public opaq_map_init_bank
|
|
public opaq_init_bank_mapped
|
|
public opaq_bank_loop
|
|
public opaq_whole_quadpixels
|
|
public opaq_scan_loop
|
|
public opaq_scan_loop_l
|
|
public opaq_scan_loop_lt
|
|
public opaq_scan_loop_t
|
|
public opaq_draw_left_edge_only
|
|
public opaq_draw_left_edge_only_entry
|
|
public opaq_edge_loop
|
|
public opaq_draw_right_edge_only
|
|
public opaq_draw_right_edge_only_entry
|
|
public opaq_draw_both_edges
|
|
public opaq_check_more_banks
|
|
public opaq_do_next_bank
|
|
public special_8_wide_aligned_opaque
|
|
public s8wa0_init_bank_mapped
|
|
public s8wao_byte_loop
|
|
public s8wao_map_init_bank
|
|
public xpar_map_init_bank
|
|
public xpar_init_bank_mapped
|
|
public xpar_bank_loop
|
|
public xpar_scan_loop
|
|
public xpar_scan_done
|
|
public do_next_xpar_bank
|
|
public xpar_high_nibble_F
|
|
public xpar_high_nibble_E
|
|
public xpar_high_nibble_D
|
|
public xpar_high_nibble_C
|
|
public xpar_high_nibble_B
|
|
public xpar_high_nibble_8
|
|
public xpar_high_nibble_6
|
|
public xpar_high_nibble_5
|
|
public xpar_high_nibble_4
|
|
public xpar_high_nibble_7
|
|
public xpar_high_nibble_3
|
|
public xpar_high_nibble_A
|
|
public xpar_high_nibble_2
|
|
public xpar_high_nibble_9
|
|
public xpar_high_nibble_1
|
|
public xpar_high_nibble_0
|
|
public xpar_low_nibble_F
|
|
public xpar_low_nibble_E
|
|
public xpar_low_nibble_D
|
|
public xpar_low_nibble_C
|
|
public xpar_low_nibble_B
|
|
public xpar_low_nibble_8
|
|
public xpar_low_nibble_6
|
|
public xpar_low_nibble_5
|
|
public xpar_low_nibble_4
|
|
public xpar_low_nibble_7
|
|
public xpar_low_nibble_3
|
|
public xpar_low_nibble_A
|
|
public xpar_low_nibble_2
|
|
public xpar_low_nibble_9
|
|
public xpar_low_nibble_1
|
|
public xpar_low_nibble_0
|
|
|
|
|
|
end
|