1129 lines
46 KiB
NASM
1129 lines
46 KiB
NASM
;
|
||
; Command & Conquer Red Alert(tm)
|
||
; Copyright 2025 Electronic Arts Inc.
|
||
;
|
||
; This program is free software: you can redistribute it and/or modify
|
||
; it under the terms of the GNU General Public License as published by
|
||
; the Free Software Foundation, either version 3 of the License, or
|
||
; (at your option) any later version.
|
||
;
|
||
; This program is distributed in the hope that it will be useful,
|
||
; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
; GNU General Public License for more details.
|
||
;
|
||
; You should have received a copy of the GNU General Public License
|
||
; along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
;
|
||
|
||
;***************************************************************************
|
||
;** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S **
|
||
;***************************************************************************
|
||
;* *
|
||
;* Project Name : WWLIB32 *
|
||
;* *
|
||
;* File Name : DRAWSHP.ASM *
|
||
;* *
|
||
;* Programmer : Phil W. Gorrow *
|
||
;* *
|
||
;* Start Date : April 13, 1992 *
|
||
;* *
|
||
;* Last Update : September 14, 1994 [IML] *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* Functions: *
|
||
;* Draw_Shape -- Draws a shape at given buffer coordinates and clips *
|
||
;* Not_Supported -- Replacement function for Draw_Shape routines not used*
|
||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||
;********************* Model & Processor Directives ************************
|
||
IDEAL
|
||
P386
|
||
MODEL USE32 FLAT
|
||
|
||
|
||
; this struct is here to remove the hardwire way of programing
|
||
; implemented in the funtion Draw_Shape in ian image of
|
||
|
||
STRUC VVPC_IMAGE
|
||
Off dd ?
|
||
Width dd ?
|
||
Height dd ?
|
||
Page dd ?
|
||
ENDS
|
||
|
||
|
||
|
||
STRUC GVPC_IMAGE
|
||
vvpc VVPC_IMAGE <>
|
||
Xpos dd ?
|
||
Ypos dd ?
|
||
GraphicBuff dd ?
|
||
ENDS
|
||
|
||
|
||
;******************************** Includes *********************************
|
||
INCLUDE "shape.inc"
|
||
|
||
|
||
;****************************** Declarations ********************************
|
||
GLOBAL Draw_Shape:NEAR
|
||
GLOBAL LCW_Uncompress:NEAR
|
||
GLOBAL _ShapeBuffer:DWORD
|
||
GLOBAL _ShapeBufferSize:DWORD
|
||
|
||
GLOBAL MaskPage : dword
|
||
GLOBAL BackGroundPage : dword
|
||
|
||
|
||
;********************************* Data ************************************
|
||
DATASEG
|
||
;---------------------------------------------------------------------------
|
||
; Shape buffer & its size, set by Set_Shape_Buffer()
|
||
;---------------------------------------------------------------------------
|
||
_ShapeBuffer DD 0
|
||
_ShapeBufferSize DD 0
|
||
|
||
;---------------------------------------------------------------------------
|
||
; Address of MaskPage & BackGroundPage, set by Init_Priority_System()
|
||
;---------------------------------------------------------------------------
|
||
MaskPage DD 0
|
||
BackGroundPage DD 0
|
||
|
||
;---------------------------------------------------------------------------
|
||
; Predator effect variables
|
||
;---------------------------------------------------------------------------
|
||
PredCount DD 0
|
||
PredTable DB 1, 3, 2, 5, 4, 3, 2, 1
|
||
PredValue DD 1
|
||
PartialPred DD 0 ; partially faded predator effect value
|
||
PartialCount DD 0
|
||
|
||
;---------------------------------------------------------------------------
|
||
; 32 bit versions of 16 bit stack variables
|
||
;---------------------------------------------------------------------------
|
||
Flags DD ? ; globally accessible copy of flags
|
||
|
||
viewport_ptr DD ? ; pointer to upper-left corner of viewport
|
||
viewport_width DD ? ; viewport width
|
||
viewport_height DD ? ; viewport height
|
||
viewport_yadd DD ? ; viewport y add
|
||
viewport_x DD ? ; viewport x-coord
|
||
viewport_y DD ? ; viewport y-coord
|
||
buff_ptr DD ? ; pointer to buffer containing viewport
|
||
|
||
;********************************* Code ************************************
|
||
CODESEG
|
||
|
||
|
||
;***************************************************************************
|
||
;* Draw_Shape -- Draws a shape at given buffer coordinates and clips *
|
||
;* *
|
||
;* INPUT: *
|
||
;* DWORD gvp_ptr ; pointer to graphic viewport info *
|
||
;* DWORD shape_ptr ; the shape pointer to draw *
|
||
;* DWORD draw_x ; x-coord of hotspot in viewport *
|
||
;* DWORD draw_y ; y-coord of hotspot in viewport *
|
||
;* DWORD flags ; the flags for drawing the shape *
|
||
;* *
|
||
;* Optional Arguments: If the following flags are used, the given args *
|
||
;* MUST be present. Note that, if more than one one set of args is used, *
|
||
;* they must appear in this order (alphabetical). *
|
||
;* SHAPE_COLOR: DWORD color_table (256 bytes) *
|
||
;* SHAPE_FADING: DWORD fade_table (256 bytes), DWORD fade_count *
|
||
;* SHAPE_GHOST: DWORD is_translucent tbl, DWORD translucent tbl *
|
||
;* SHAPE_PARTIAL: DWORD predator partial_value (0-255) *
|
||
;* SHAPE_PRIORITY: DWORD priority_level *
|
||
;* SHAPE_SCALING: DWORD x_scale, WORD y_scale *
|
||
;* SHAPE_SHADOW: DWORD shadowing_table (256 bytes) *
|
||
;* *
|
||
;* OUTPUT: *
|
||
;* none. *
|
||
;* *
|
||
;* WARNINGS: *
|
||
;* none. *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* *
|
||
;* File Organization: *
|
||
;* drawshp.asm : this file *
|
||
;* shape.inc : main shape header file; contains declarations for all *
|
||
;* globals, procedures and constants *
|
||
;* ds_table.asm: contains the procedure address tables for LSkipRout, *
|
||
;* RSkipRout, DrawRout, & PixelRout *
|
||
;* ds_l*.asm : left-skip routines *
|
||
;* ds_r*.asm : right-skip routines *
|
||
;* ds_d*.asm : drawing routines *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* *
|
||
;* Shape format: *
|
||
;* Header: *
|
||
;* UWORD SType (0=normal, 1=16-color, 2=uncompressed, 4=variable-color) *
|
||
;* UBYTE Height *
|
||
;* UWORD Width *
|
||
;* UBYTE unmodified height *
|
||
;* UWORD size of shape in memory, including this header *
|
||
;* UWORD uncompressed data size *
|
||
;* Normal Shape: *
|
||
;* UBYTE [compressed] Shape data *
|
||
;* 16-color shape: *
|
||
;* UBYTE 16-color table *
|
||
;* UBYTE [compressed] Shape data *
|
||
;* variable-color shape: *
|
||
;* UBYTE # colors *
|
||
;* UBYTE color table (variable-length) *
|
||
;* UBYTE [compressed] Shape data *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* *
|
||
;* Uncompressed shape data format: *
|
||
;* Data is stored as a bitmap, with 0's treated as a special case. Every *
|
||
;* 0 byte is followed by a repetition count byte. Every scan line is *
|
||
;* compressed separately. Thus, the following bitmap results in the *
|
||
;* following shape data: *
|
||
;* 0 0 0 5 6 7 0 0 0 0 *
|
||
;* 0 0 0 5 6 7 0 0 0 0 *
|
||
;* 0 0 0 5 6 7 0 0 0 0 *
|
||
;* *
|
||
;* 0 3 5 6 7 0 4 *
|
||
;* 0 3 5 6 7 0 4 *
|
||
;* 0 3 5 6 7 0 4 *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* *
|
||
;* How scaling is handled: *
|
||
;* Scaling is done by accumulating the x & y scale values. When the high *
|
||
;* byte of the accumulated value is set, the pixel (for x-scaling) or *
|
||
;* the line (for y-scaling) is drawn. The high byte is then cleared, *
|
||
;* and the low byte is left so roundoffs continue to accumulate. *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* *
|
||
;* Drawing Procedures: *
|
||
;* *
|
||
;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
|
||
;* *
|
||
;* RSkipRout: skips given # bytes of data on the right-hand side of a *
|
||
;* shape. Just has to handle changing the current byte offset in the *
|
||
;* shape data buffer, since the draw routine knows where the left-hand *
|
||
;* side of the drawable region is. The routine may skip more bytes than *
|
||
;* it was told if it encounters a run of 0's, but it's assumed that a *
|
||
;* run of 0's will never go past the right edge of a shape. *
|
||
;* Input: *
|
||
;* ECX - number of uncompressed bytes to skip *
|
||
;* ESI - shape buffer data address *
|
||
;* Output: *
|
||
;* ECX - negative # bytes overrun, or 0 *
|
||
;* ESI - updated to the current location in the shape data *
|
||
;* *
|
||
;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
|
||
;* *
|
||
;* LSkipRout: skips given # bytes of data on the left-hand side of a *
|
||
;* shape. This routine must update the shape data byte offset, and it *
|
||
;* must properly update the current drawing position due to scaling, so *
|
||
;* it's a little more involved than the RSkip routine. The routine may *
|
||
;* skip more bytes than it's told if it encounters a run of 0's. If this *
|
||
;* happens, the draw routine must take these extra bytes into *
|
||
;* consideration. *
|
||
;* Input: *
|
||
;* ECX = number of uncompressed bytes to skip *
|
||
;* ESI = shape (source) buffer data address *
|
||
;* EDI = viewport (destination) address *
|
||
;* [WidthCount] = shape's width in bytes *
|
||
;* Output: *
|
||
;* ECX - negative # pixels (not bytes) overrun, or 0 *
|
||
;* EDX - accumulated XTotal value at new pixel location *
|
||
;* ESI - updated to the current location in the shape data *
|
||
;* EDI - incr/decr by # pixels (not bytes) overrun *
|
||
;* [WidthCount] - decremented by # bytes skipped *
|
||
;* *
|
||
;*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*
|
||
;* *
|
||
;* DrawRout: draws one row of pixels, handles scaling, reversal and *
|
||
;* any per pixel effects like predator, shadow etc. *
|
||
;* EDX must be set up as follows: *
|
||
;* - No scaling: 0 *
|
||
;* - No left-clipping: 0 *
|
||
;* - Left clipping, but no overrun: set to computed initial value for *
|
||
;* that viewport coordinate *
|
||
;* - Left clipping, with overrun: set to XTotal value for that coordinate *
|
||
;* In any case, only the low byte of DL should contain data; the current *
|
||
;* byte in the shapebuffer should always be the first drawable pixel, *
|
||
;* even if it's partially clipped (in which case DL will contain data). *
|
||
;* Input: *
|
||
;* ECX = number of pixels (not bytes) to draw *
|
||
;* EDX = XTotal initializer value *
|
||
;* ESI = shape (source) buffer address *
|
||
;* EDI = viewport (destination) address *
|
||
;* [WidthCount] = remaining bytes on the line *
|
||
;* Output: *
|
||
;* ESI - updated to current location in the shape data *
|
||
;* EDI - incr/decr by # pixels (not bytes) drawn/skipped *
|
||
;* [WidthCount] - decremented by # bytes (not pixels) drawn *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* *
|
||
;* Algorithm: *
|
||
;* - Initialize globals *
|
||
;* - Pull optional arguments off the stack *
|
||
;* - Set up drawing procedure pointers based on drawing flags *
|
||
;* - Read the values from the shape header *
|
||
;* - Compute the shape's scaled width & height *
|
||
;* - Adjust the shape's drawing coordinates based on centering & *
|
||
;* viewport-relative flag settings *
|
||
;* - Compute the clipped areas of the shape *
|
||
;* - Compute the number of drawn pixels horizontally & vertically *
|
||
;* - Compute the starting drawing offset in the viewport *
|
||
;* - Draw the shape *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* *
|
||
;* HISTORY: *
|
||
;* 04/13/1992 PWG : Created. *
|
||
;* 08/19/1993 SKB : Split drawshp.asm into several modules. *
|
||
;* 05/26/1994 BR : Converted to 32-bit, restructured quite a bit. *
|
||
;* 08/09/1994 IML : Added C++ style interface. Various optimizations. *
|
||
;* 09/06/1994 IML : Ammendments for integration of p_* and ds_* routines.*
|
||
;* 09/14/1994 IML : Now handles LCW compression. *
|
||
;*=========================================================================*
|
||
PROC Draw_Shape C NEAR
|
||
USES eax,ebx,ecx,edx,edi,esi
|
||
|
||
;--------------------------------------------------------------------
|
||
; Arguments:
|
||
;--------------------------------------------------------------------
|
||
ARG gvp_ptr:DWORD ; pointer to graphic viewport info
|
||
ARG shape_ptr:DWORD ; the shape pointer to draw
|
||
ARG draw_x:DWORD ; the destination x pixel
|
||
ARG draw_y:DWORD ; the destination y pixel
|
||
ARG flags:DWORD ; the flags for drawing the shape
|
||
|
||
IF FALSE
|
||
;--------------------------------------------------------------------
|
||
; Define the local stack variables that Draw_Shape needs. These
|
||
; parameters are defined in shape.inc. They're included here
|
||
; just for reference.
|
||
;--------------------------------------------------------------------
|
||
;
|
||
;...................... proc addresses ..............................
|
||
;
|
||
LOCAL LSkipRout:DWORD ; pointer to the skip routine
|
||
LOCAL RSkipRout:DWORD ; pointer to the skip routine
|
||
LOCAL DrawRout:DWORD ; pointer to the draw routine
|
||
;
|
||
;.................... optional arguments ............................
|
||
;
|
||
LOCAL ColorTable:DWORD ; ptr to the shapes color table
|
||
LOCAL FadingTable:DWORD ; extracted fading table pointer
|
||
LOCAL FadingNum:DWORD ; get the number of times to fade
|
||
LOCAL IsTranslucent:DWORD ; ptr to "are we translucent?" tbl
|
||
LOCAL Translucent:DWORD ; ptr to "ok we are translucent!" tbl
|
||
LOCAL PriLevel:BYTE ; the priority level of the object
|
||
LOCAL ScaleX:DWORD ; the x increment to scale by
|
||
LOCAL ScaleY:DWORD ; the y increment to scale by
|
||
LOCAL ShadowingTable:DWORD ; ptr to the shadowing table
|
||
;
|
||
;.................... Shape header values ...........................
|
||
;
|
||
LOCAL ShapeType:DWORD ; shape type
|
||
LOCAL ShapeWidth:DWORD ; shape's unscaled width
|
||
LOCAL ShapeHeight:DWORD ; shape's unscaled height
|
||
LOCAL UncompDataLen:DWORD ; uncompressed data length
|
||
LOCAL ShapeData:DWORD ; pointer to [compressed] shape data
|
||
;
|
||
;.................. Scaled shape dimensions .........................
|
||
;
|
||
LOCAL ScaledWidth:DWORD ; shape's scaled width
|
||
LOCAL ScaledHeight:DWORD ; shape's scaled height
|
||
;
|
||
;.................. Pixel clipping variables ........................
|
||
;
|
||
LOCAL LeftClipPixels:DWORD ; # left-clipped pixels
|
||
LOCAL RightClipPixels:DWORD ; # right-clipped pixels
|
||
LOCAL TopClipPixels:DWORD ; # top-clipped pixels
|
||
LOCAL BotClipPixels:DWORD ; # bottom-clipped pixels
|
||
LOCAL PixelWidth:DWORD ; width of drawable area in pixels
|
||
LOCAL PixelHeight:DWORD ; height of drawable area in pixels
|
||
;
|
||
;..................... Drawing variables ............................
|
||
;
|
||
LOCAL NumColors:DWORD ; # colors for 16-color shapes
|
||
LOCAL StartDraw:DWORD ; ptr to starting draw position
|
||
LOCAL NextLine:DWORD ; offset of next drawing line
|
||
LOCAL LeftClipBytes:DWORD ; # left-clipped bytes
|
||
LOCAL XTotal:DWORD ; accumulated x-pixels for scaling
|
||
LOCAL XTotalInit:DWORD ; initial roundoff bits for XTotal
|
||
LOCAL YTotal:DWORD ; accumulated y-pixels for scaling
|
||
LOCAL HeightCount:DWORD ; height counter for drawing lines
|
||
LOCAL LineStart:DWORD ; address of start of line
|
||
LOCAL WidthCount:DWORD ; counts down # bytes skipped
|
||
LOCAL StashReg:DWORD ; temp variable for draw routines
|
||
LOCAL MaskAdjust:DWORD ; priority buffer offset
|
||
LOCAL BackAdjust:DWORD ; background buffer offset
|
||
LOCAL StashECX:DWORD ; temp variable for ECX register
|
||
LOCAL StashEDX:DWORD ; temp variable for EDX register
|
||
|
||
ENDIF
|
||
|
||
;====================================================================
|
||
; Initialization:
|
||
; - allocate space for globals
|
||
; - validate shape pointer
|
||
; - set SHAPE_COMPACT flag if needed
|
||
;====================================================================
|
||
;--------------------------------------------------------------------
|
||
; Allocate stack space for our local variables.
|
||
;--------------------------------------------------------------------
|
||
LOCAL Local_Stack:BYTE:Local_Size
|
||
|
||
;--------------------------------------------------------------------
|
||
; Make sure the shape pointer is not NULL
|
||
;--------------------------------------------------------------------
|
||
cmp [shape_ptr],0 ; compare shape ptr value to NULL
|
||
jnz ??valid_shp ; if non-zero, it's valid
|
||
jmp ??exit ; otherwise get the heck outta here
|
||
|
||
;--------------------------------------------------------------------
|
||
; Move gvp info into local variables
|
||
;--------------------------------------------------------------------
|
||
??valid_shp:
|
||
mov edi,[gvp_ptr] ; get pointer to graphic viewport info
|
||
mov esi, [(type GVPC_IMAGE ptr edi). vvpc . Off ] ; extract viewport pointer
|
||
mov [viewport_ptr],esi
|
||
mov ebx,[(type GVPC_IMAGE ptr edi) . vvpc . Width ] ; extract viewport width
|
||
mov [viewport_width],ebx
|
||
mov eax,[(type GVPC_IMAGE ptr edi) . vvpc . Height ] ; extract viewport height
|
||
mov [viewport_height],eax
|
||
mov ecx,[(type GVPC_IMAGE ptr edi) . vvpc . Page ] ; calculate y add value
|
||
add ecx,ebx
|
||
mov [viewport_yadd],ecx
|
||
mov eax,[(type GVPC_IMAGE ptr edi) . Xpos ] ; extract viewport x-coord
|
||
mov [viewport_x],eax
|
||
mov eax, [(type GVPC_IMAGE ptr edi) . Ypos ] ; extract viewport y-coord
|
||
mov [viewport_y],eax
|
||
mul ecx ; calculate buffer pointer
|
||
add eax,[viewport_x]
|
||
sub esi,eax
|
||
mov [buff_ptr],esi
|
||
|
||
|
||
;--------------------------------------------------------------------
|
||
; If this shape is a compact shape, set that bit in the flags arg
|
||
;--------------------------------------------------------------------
|
||
mov edi,[shape_ptr] ; check for compact shape flag
|
||
test [BYTE PTR edi],MAKESHAPE_COMPACT
|
||
|
||
jz ??do_args ; if not process flags as is
|
||
or [flags],SHAPE_COMPACT ; mark it as a compact shape
|
||
|
||
;====================================================================
|
||
; Pull off optional arguments:
|
||
; EDI is used as an offset from the 'flags' parameter, to point
|
||
; to the optional argument currently being processed.
|
||
;====================================================================
|
||
??do_args:
|
||
mov edi,4 ; optional params start past flags
|
||
|
||
;--------------------------------------------------------------------
|
||
; Initialize optional argument values:
|
||
;--------------------------------------------------------------------
|
||
mov [ColorTable],0 ; default = NULL
|
||
mov [FadingTable],0 ; default = NULL
|
||
mov [FadingNum],0 ; default = no fading
|
||
mov [IsTranslucent],0 ; default = NULL
|
||
mov [Translucent],0 ; default = NULL
|
||
mov [PriLevel],0 ; default = no priority
|
||
mov [ScaleX],100h ; default = unity X scaling
|
||
mov [ScaleY],100h ; default = unity Y scaling
|
||
mov [ShadowingTable],0 ; default = NULL
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_COLOR: DWORD color_table[256]
|
||
;--------------------------------------------------------------------
|
||
??color:
|
||
test [flags],SHAPE_COLOR ; does it have a color table
|
||
jz ??fading ; if not skip to fading
|
||
or [flags],SHAPE_COMPACT ; mark it as a compact shape
|
||
; (for remapping purposes only)
|
||
mov eax,[flags + edi]
|
||
mov [ColorTable],eax ; save address of color table
|
||
add edi,4 ; point to next optional argument
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_FADING: DWORD fade_table[256], DWORD fade_count
|
||
;--------------------------------------------------------------------
|
||
??fading:
|
||
test [flags],SHAPE_FADING ; are we fading this shape
|
||
jz ??ghost ; skip to ghosting check
|
||
mov eax,[flags + edi]
|
||
mov [FadingTable],eax ; save address of fading tbl
|
||
|
||
mov eax,[flags + edi + 4] ; get fade num
|
||
|
||
add edi,8 ; next argument
|
||
cmp eax,0 ; check if it's 0
|
||
jnz ??set_fading ; if not, store fade num
|
||
and [flags],NOT SHAPE_FADING ; otherwise, don't fade
|
||
|
||
??set_fading:
|
||
mov [FadingNum],eax
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_GHOST: DWORD is_translucent tbl, DWORD translucent tbl
|
||
;--------------------------------------------------------------------
|
||
??ghost:
|
||
test [flags],SHAPE_GHOST ; are we ghosting this shape
|
||
jz ??init_predator ; skip to predator check
|
||
mov eax,[flags + edi]
|
||
mov [IsTranslucent],eax ; save ptr to is_trans. tbl
|
||
mov eax,[flags + edi + 4]
|
||
mov [Translucent],eax ; save ptr to translucent tbl
|
||
add edi,8 ; next argument
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_PREDATOR: Initialize the predator effect variables
|
||
;--------------------------------------------------------------------
|
||
??init_predator:
|
||
test [flags],SHAPE_PREDATOR ; is predator effect on
|
||
jz ??partial ; if not skip to partial
|
||
inc [PredCount] ; the pred table is byte aligned
|
||
and [PredCount],PRED_MASK ; keep entries within bounds
|
||
mov eax,[PredCount]
|
||
mov al,[BYTE PTR PredTable + eax]
|
||
mov [PredValue],eax ; put the pred value cs
|
||
mov [PartialCount],0 ; clear the partial count
|
||
mov [PartialPred],100h ; init partial to off
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_PARTIAL: DWORD partial_pred_value (0-255)
|
||
;--------------------------------------------------------------------
|
||
??partial:
|
||
test [flags],SHAPE_PARTIAL ; is this a partial pred?
|
||
jz ??priority ; if not check priority
|
||
mov eax,[flags + edi] ; pull the partial value
|
||
mov [PartialPred],eax ; store it off
|
||
add edi,4 ; next argument
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_PRIORITY: DWORD priority_level
|
||
;--------------------------------------------------------------------
|
||
??priority:
|
||
test [flags],SHAPE_PRIORITY ; is this a priority draw
|
||
jz ??scale ; if not skip to scale
|
||
mov eax,[flags + edi]
|
||
mov [PriLevel],al ; store priority level
|
||
add edi,4 ; next argument
|
||
mov eax,[MaskPage] ; calculate priority buffer
|
||
sub eax,[buff_ptr] ; offset
|
||
mov [MaskAdjust],eax
|
||
mov eax,[BackGroundPage] ; calculate background buffer
|
||
sub eax,[buff_ptr] ; offset
|
||
mov [BackAdjust],eax
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_SCALING: DWORD x_scale, WORD y_scale
|
||
;--------------------------------------------------------------------
|
||
??scale:
|
||
test [flags],SHAPE_SCALING ; are we scaling this shape.
|
||
jz ??shadow ; if not then skip scale y value
|
||
mov eax,[flags + edi]
|
||
mov [ScaleX],eax
|
||
mov eax,[flags + edi + 4]
|
||
mov [ScaleY],eax
|
||
add edi,8 ; next argument
|
||
|
||
;--------------------------------------------------------------------
|
||
; SHAPE_SHADOW: DWORD shadow_table[256]
|
||
;--------------------------------------------------------------------
|
||
??shadow:
|
||
test [flags],SHAPE_SHADOW ; are we ghosting this shape
|
||
jz short ??get_header ; if not then skip
|
||
mov eax,[flags + edi]
|
||
mov [ShadowingTable],eax ; save address of shadow table
|
||
add edi,4 ; next argument
|
||
|
||
|
||
??get_header:
|
||
;====================================================================
|
||
; Get Shape header values
|
||
;====================================================================
|
||
mov esi,[shape_ptr] ; prepare to read header
|
||
movzx eax,[WORD PTR esi]
|
||
mov [ShapeType],eax ; extract shape type
|
||
movzx eax,[BYTE PTR esi + 2]
|
||
mov [ShapeHeight],eax
|
||
movzx eax,[WORD PTR esi + 3] ; extract shape height
|
||
mov [ShapeWidth],eax
|
||
movzx eax,[WORD PTR esi + 8] ; extract uncompressed data length
|
||
mov [UncompDataLen],eax
|
||
add esi,10 ; reposition index
|
||
|
||
;--------------------------------------------------------------------
|
||
; Now get NumColors, ColorTable address, & data pointer:
|
||
; <16-color shape:
|
||
; shape.Colortable[0] = # colors
|
||
; shape data is after that many colors
|
||
; 16-color shape:
|
||
; shape.Colortable[] contains colors
|
||
; shape data is after those colors
|
||
; default 256-color shape:
|
||
; shape data starts at shape.Colortable[0]
|
||
; Note: ColorTable is set only if flags & SHAPE_COLOR is 0; otherwise,
|
||
; the color table was passed in & we already have a pointer to it
|
||
;--------------------------------------------------------------------
|
||
;
|
||
;....................... <16-color shape: ...........................
|
||
;
|
||
test [ShapeType],MAKESHAPE_VARIABLE
|
||
jz ??check_16
|
||
movzx eax,[BYTE PTR esi] ; read # colors
|
||
mov [NumColors],eax ; save # colors
|
||
inc esi
|
||
test [flags],SHAPE_COLOR ; don't set ColorTable if
|
||
jnz ??norm_get_data_addr ; it was passed in
|
||
mov [ColorTable],esi ; save color table pointer
|
||
|
||
??norm_get_data_addr:
|
||
add esi,[NumColors] ; skip past color data
|
||
mov [ShapeData],esi ; set data address
|
||
jmp ??setup_procs
|
||
|
||
;....................... 16-color shape: ............................
|
||
??check_16:
|
||
test [ShapeType],MAKESHAPE_COMPACT
|
||
jz ??256_get_data_addr
|
||
mov [NumColors],16 ; save # colors
|
||
test [flags],SHAPE_COLOR ; don't set ColorTable if
|
||
jnz ??16_get_data_addr ; it was passed in
|
||
mov [ColorTable],esi ; save color table pointer
|
||
|
||
??16_get_data_addr:
|
||
add esi,[NumColors] ; skip past color data
|
||
mov [ShapeData],esi ; set data address
|
||
jmp ??setup_procs
|
||
;
|
||
;....................... 256-color shape: ...........................
|
||
;
|
||
??256_get_data_addr:
|
||
mov [ShapeData],esi ; set data address
|
||
|
||
;====================================================================
|
||
; Set up the drawing procedure addresses
|
||
;====================================================================
|
||
;--------------------------------------------------------------------
|
||
; This code uses HORZ_REV, VERT_REV, & SCALING flags as an
|
||
; offset into the LSkipTable, RSkipTable, and DrawTable. These
|
||
; flags combined have values from 00h-07h, so each table must have
|
||
; at least 8 entries.
|
||
;--------------------------------------------------------------------
|
||
??setup_procs:
|
||
mov ebx,[flags] ; load flags value
|
||
and ebx,07h ; clip high bits
|
||
add ebx,ebx ; mult by 4 to get DWORD offset
|
||
add ebx,ebx
|
||
mov eax,[LSkipTable + ebx] ; get table value
|
||
mov [LSkipRout],eax ; store it in the function pointer
|
||
mov eax,[RSkipTable + ebx] ; get table value
|
||
mov [RSkipRout],eax ; store it in the function pointer
|
||
mov eax,[DrawTable + ebx] ; get table value
|
||
mov [DrawRout],eax ; store it in the function pointer
|
||
|
||
??compute_scalevals:
|
||
;====================================================================
|
||
; Now compute scaled width & height. If the shape scales down to 0
|
||
; either horizontally or vertically, exit.
|
||
;====================================================================
|
||
test [flags],SHAPE_SCALING ; skip if no scaling
|
||
jz ??no_scaling
|
||
;
|
||
;........................ scaled width: .............................
|
||
;
|
||
mov eax,[ShapeWidth] ; get byte width
|
||
mov ebx,[ScaleX] ; prepare for register mul
|
||
mul ebx ; EDX:EAX = result
|
||
shrd eax,edx,8 ; EAX = result rounded down
|
||
or eax,eax
|
||
jz ??exit ; exit if EAX is 0
|
||
mov [ScaledWidth],eax ; save the scaled width
|
||
;
|
||
;........................ scaled height: ............................
|
||
;
|
||
mov eax,[ShapeHeight] ; get byte height
|
||
mov ebx,[ScaleY] ; prepare for register mul
|
||
mul ebx ; EDX:EAX = result
|
||
shrd eax,edx,8 ; EAX = result rounded down
|
||
or eax,eax
|
||
jz ??exit ; exit if EAX is 0
|
||
mov [ScaledHeight],eax ; save the scaled height
|
||
jmp ??handle_centering
|
||
;
|
||
;......................... no scaling: ..............................
|
||
;
|
||
??no_scaling:
|
||
mov eax,[ShapeWidth]
|
||
mov [ScaledWidth],eax ; pixel width = byte width
|
||
mov eax,[ShapeHeight]
|
||
mov [ScaledHeight],eax ; pixel height = byte height
|
||
|
||
;====================================================================
|
||
; Allow for SHAPE_CENTER by adjusting the draw_x & draw_y arguments:
|
||
; draw_x -= ScaledWidth / 2
|
||
; draw_y -= ScaledHeight / 2
|
||
;====================================================================
|
||
??handle_centering:
|
||
;
|
||
;........................ adjust draw_x .............................
|
||
;
|
||
test [flags],SHAPE_CENTER ; skip if not centered
|
||
jz ??handle_vp_rel
|
||
mov eax,[draw_x] ; load in draw_x
|
||
mov edx,[ScaledWidth] ; load in ScaledWidth
|
||
shr edx,1 ; divide it by 2
|
||
sub eax,edx ; subract it from eax
|
||
mov [draw_x],eax ; store it back into draw_x
|
||
;
|
||
;........................ adjust draw_y .............................
|
||
;
|
||
mov eax,[draw_y] ; load in draw_y
|
||
mov edx,[ScaledHeight] ; load in ScaledHeight
|
||
shr edx,1 ; divide it by 2
|
||
sub eax,edx ; subract it from eax
|
||
mov [draw_y],eax ; store it back into draw_y
|
||
|
||
;====================================================================
|
||
; Allow for SHAPE_VIEWPORT_REL by adjusting draw_x & draw_y by the
|
||
; viewport's coordinates
|
||
;====================================================================
|
||
??handle_vp_rel:
|
||
test [flags],SHAPE_VIEWPORT_REL ; skip if not vp-relative
|
||
jz ??compute_horz_clip
|
||
mov eax,[viewport_x]
|
||
add [draw_x],eax ; draw_x += viewport_x
|
||
mov eax,[viewport_y]
|
||
add [draw_y],eax ; draw_y += viewport_y
|
||
|
||
;====================================================================
|
||
; Now that we have the scaled size and adjusted x & y drawing
|
||
; coordinates, we can compute the clipped areas of the shape:
|
||
; LeftClipPixels = viewport_x - draw_x
|
||
; - if negative, set to 0
|
||
; RightClipPixels = (draw_x + ScaledWidth) -
|
||
; (viewport_x + viewport_width)
|
||
; - if negative, set to 0
|
||
;
|
||
; TopClipPixels = viewport_y - draw_y
|
||
; - if negative, set to 0
|
||
; BotClipPixels = (draw_y + ScaledHeight) -
|
||
; (viewport_y + viewport_height)
|
||
; - if negative, set to 0
|
||
;====================================================================
|
||
??compute_horz_clip:
|
||
;
|
||
;...................... left-clipped pixels .........................
|
||
;
|
||
mov eax,[viewport_x]
|
||
sub eax,[draw_x] ; EAX = viewport_x - draw_x
|
||
jge ??set_left_clip
|
||
mov eax,0 ; if EAX<0, set to 0
|
||
??set_left_clip:
|
||
mov [LeftClipPixels],eax ; store # left-clipped pixels
|
||
;
|
||
;...................... right-clipped pixels ........................
|
||
;
|
||
mov eax,[draw_x]
|
||
add eax,[ScaledWidth] ; EAX = draw_x + ScaledWidth
|
||
mov edx,[viewport_x]
|
||
add edx,[viewport_width] ; EDX = viewport_x + viewport_width
|
||
sub eax,edx
|
||
jge ??set_right_clip
|
||
mov eax,0 ; if EAX<0, set to 0
|
||
??set_right_clip:
|
||
mov [RightClipPixels],eax ; store # right-clipped pixels
|
||
;
|
||
;...................... top-clipped pixels ..........................
|
||
;
|
||
??compute_vert_clip:
|
||
mov eax,[viewport_y]
|
||
sub eax,[draw_y] ; EAX = viewport_y - draw_y
|
||
jge ??set_top_clip
|
||
mov eax,0 ; if EAX<0, set to 0
|
||
??set_top_clip:
|
||
mov [TopClipPixels],eax ; store # top-clipped pixels
|
||
;
|
||
;.................... bottom-clipped pixels .........................
|
||
;
|
||
mov eax,[draw_y]
|
||
add eax,[ScaledHeight] ; EAX = draw_y + ScaledHeight
|
||
mov edx,[viewport_y]
|
||
add edx,[viewport_height] ; EDX = viewport_y + viewport_height
|
||
sub eax,edx
|
||
jge ??set_bottom_clip
|
||
mov eax,0 ; if EAX<0, set to 0
|
||
??set_bottom_clip:
|
||
mov [BotClipPixels],eax ; store # bottom-clipped pixels
|
||
|
||
;====================================================================
|
||
; Now compute the number of pixels actually drawn, horizontally and
|
||
; vertically; exit if either is <= 0
|
||
;====================================================================
|
||
??compute_drawn_pixels:
|
||
;
|
||
;.................... pixel width of drawn area .....................
|
||
;
|
||
mov eax,[ScaledWidth] ; get total width in pixels
|
||
sub eax,[LeftClipPixels] ; subtract off left-clipped pixels
|
||
sub eax,[RightClipPixels] ; subtract off right-clipped pixels
|
||
jle ??exit ; exit if no horizontal pixels drawn
|
||
mov [PixelWidth],eax ; store drawn pixel width
|
||
;
|
||
;.................... pixel height of drawn area ....................
|
||
;
|
||
mov eax,[ScaledHeight] ; get total height in pixels
|
||
sub eax,[TopClipPixels] ; subtract off top-clipped pixels
|
||
sub eax,[BotClipPixels] ; subtract off bottom-clipped pixels
|
||
jle ??exit ; exit if no horizontal pixels drawn
|
||
mov [PixelHeight],eax ; store drawn pixel height
|
||
|
||
;====================================================================
|
||
; So, we're actually going to draw something; if (ShapeType &
|
||
; MAKESHAPE_NOCOMP == 0) decompress the shape data into _ShapeBuffer:
|
||
; LCW_Uncompress(ShapeData, _ShapeBuffer, UncompDataLen);
|
||
; shape.DataLength
|
||
; &_ShapeBuffer
|
||
; &(shape's data)
|
||
; - otherwise the shape data is already uncompressed
|
||
;====================================================================
|
||
test [ShapeType],MAKESHAPE_NOCOMP
|
||
jnz ??uncompressed
|
||
|
||
mov eax,[UncompDataLen]
|
||
push eax ; push arg 3
|
||
mov eax,[_ShapeBuffer]
|
||
push eax ; push arg 2
|
||
mov eax,[ShapeData]
|
||
push eax ; push arg 1
|
||
call LCW_Uncompress ; call routine
|
||
add esp,12 ; restore stack
|
||
mov eax,[_ShapeBuffer]
|
||
mov [ShapeData],eax
|
||
jmp ??copy_flags
|
||
|
||
??uncompressed:
|
||
; mov eax,[ShapeData] ; set up pointer to shape data
|
||
; mov [_ShapeBuffer],eax
|
||
|
||
|
||
;--------------------------------------------------------------------
|
||
; Set the global Flags variable
|
||
;--------------------------------------------------------------------
|
||
??copy_flags:
|
||
mov eax,[flags]
|
||
mov [Flags],eax
|
||
|
||
;====================================================================
|
||
; Now compute the actual buffer offset where drawing (not skipping)
|
||
; will begin
|
||
;====================================================================
|
||
;--------------------------------------------------------------------
|
||
; First, compute the x & y offsets of the shape's clipped upper-left
|
||
; corner, relative to the viewport's upper-left corner:
|
||
; x-offset = draw_x + LeftClipPixels - viewport_x
|
||
; y-offset = draw_y + TopClipPixels - viewport_y
|
||
;--------------------------------------------------------------------
|
||
mov ebx,[draw_x]
|
||
add ebx,[LeftClipPixels]
|
||
sub ebx,[viewport_x] ; EBX = viewport x-offset
|
||
|
||
mov eax,[draw_y]
|
||
add eax,[TopClipPixels]
|
||
sub eax,[viewport_y] ; EAX = viewport y-offset
|
||
|
||
;--------------------------------------------------------------------
|
||
; Then, adjust the viewport offsets due to horizontal & vertical
|
||
; reversal:
|
||
; if HORZ_REV, x-offset += (PixelWidth - 1)
|
||
; if VERT_REV, y-offset += (PixelHeight - 1)
|
||
;--------------------------------------------------------------------
|
||
;
|
||
;................. Adjust for horizontal reversal ...................
|
||
;
|
||
test [flags],SHAPE_HORZ_REV
|
||
jz ??adjust_vert_offset
|
||
add ebx,[PixelWidth]
|
||
dec ebx ; EBX = true x-offset
|
||
;
|
||
;................ Swap LeftClip & RightClip pixels ..................
|
||
;
|
||
mov edx,[LeftClipPixels] ; exchange left & right-clipped pixels
|
||
xchg edx,[RightClipPixels]
|
||
mov [LeftClipPixels],edx
|
||
|
||
;
|
||
;.................. Adjust for vertical reversal ....................
|
||
;
|
||
??adjust_vert_offset:
|
||
test [flags],SHAPE_VERT_REV
|
||
jz ??adjust_pointer
|
||
add eax,[PixelHeight]
|
||
dec eax ; EAX = true y-offset
|
||
;
|
||
;.................. Swap TopClip & BotClip pixels ...................
|
||
;
|
||
mov edx,[TopClipPixels]
|
||
xchg edx,[BotClipPixels]
|
||
mov [TopClipPixels],edx
|
||
|
||
;--------------------------------------------------------------------
|
||
; Now, adjust the starting position pointer:
|
||
;--------------------------------------------------------------------
|
||
??adjust_pointer: ;!!!!!!! convert to register mul for speed !!!!!!!!
|
||
add ebx,[viewport_ptr] ; add initial ptr to x-offset
|
||
mul [viewport_yadd] ; convert y-offset (EAX) to bytes
|
||
add ebx,eax ; add those bytes in
|
||
mov [StartDraw],ebx ; store the starting pointer
|
||
|
||
;--------------------------------------------------------------------
|
||
; Finally, if VERT_REV, negate yadd to move up not down:
|
||
;--------------------------------------------------------------------
|
||
test [flags],SHAPE_VERT_REV
|
||
jz ??init_xtotal
|
||
neg [viewport_yadd] ; move up, not down
|
||
|
||
;====================================================================
|
||
; Initialize the horizontal scale accumulation value:
|
||
; If there are any left-clipped pixels, the scale accumulator will
|
||
; have to be initialized with the value it >would< have by stepping
|
||
; over that many pixels. This initial value can be computed by
|
||
; dividing the # of left-clipped pixels by the x-scale value itself,
|
||
; picking off the remainder from this division & negating it. This
|
||
; sets the low byte of the remainder to the correct accumulation
|
||
; value (the high bytes will be garbage).
|
||
; (The alternative to this approach would be to multiply the
|
||
; scale factor by the # clipped bytes, which is the result of the
|
||
; division; however, negating the remainder is much faster than
|
||
; the multiply would be.)
|
||
;====================================================================
|
||
??init_xtotal:
|
||
mov edx,0 ; prepare for divide
|
||
mov eax,[LeftClipPixels] ; get # left-clipped pixels
|
||
shl eax,8 ; multiply by 100h
|
||
mov ebx,[ScaleX] ; load ScaleX value
|
||
div bx ; 16-bit div: AX = rslt, DX = rem
|
||
mov [LeftClipBytes],eax ; save # left-clipped bytes
|
||
neg edx ; generate roundoff bits
|
||
and edx,0Fh ; only save low byte
|
||
mov [XTotalInit],edx ; save initial roundoff value
|
||
|
||
;====================================================================
|
||
; Initialize drawing variables:
|
||
;====================================================================
|
||
mov esi,[ShapeData] ; ESI = shape buffer starting point
|
||
mov edi,[StartDraw] ; EDI = drawing address
|
||
mov [YTotal],0 ; initialize accumulated scale
|
||
|
||
;====================================================================
|
||
; Clip the top-clipped lines. The object here is to set ESI to the
|
||
; first drawable line in the _ShapeBuffer, and YTotal to:
|
||
; high byte = # times to draw that line,
|
||
; low byte = roundoff bits
|
||
;
|
||
; - Initialize values (ESI, HeightCount, YTotal)
|
||
; - Skip loop if no top lines to clip
|
||
; - Loop:
|
||
; - save this line's byte position in _ShapeBuffer, in case we
|
||
; overrun
|
||
; - call RSkipRout with ECX set to # bytes to skip (one row)
|
||
; - accumulate ScaleY into YTotal
|
||
; - if high byte is non-zero, there are that many drawn lines:
|
||
; - decrement HeightCount by that many lines
|
||
; - clear the high byte in YTotal, but keep the roundoff bits
|
||
; - if HeightCount > 0, loop again to clip more lines
|
||
; - if HeightCount is 0, start drawing:
|
||
; - ESI points to first non-clipped line in _ShapeBuffer
|
||
; - YTotal contains 0 in high byte, roundoff bits in low byte
|
||
; - otherwise, we've clipped too many lines:
|
||
; - put ESI back to the line we just clipped
|
||
; - set high byte of YTotal to # lines overrun
|
||
; - subtract ScaleY from YTotal, to set it up for drawing loop
|
||
;====================================================================
|
||
;
|
||
;..................... skip if nothing to clip ......................
|
||
;
|
||
mov eax,[TopClipPixels]
|
||
cmp eax,0 ; see if any top-clipped pixels
|
||
jz ??draw_loop ; if not, skip this
|
||
mov [HeightCount],eax ; save off # lines to clip
|
||
|
||
??clip_y_loop:
|
||
;
|
||
;...................... skip this row of bytes ......................
|
||
;
|
||
mov [LineStart],esi ; save this line's byte position
|
||
mov ecx,[ShapeWidth] ; set up ECX for RSkipRout
|
||
call [RSkipRout] ; skip 'ShapeWidth' bytes
|
||
;
|
||
;............... see if this row would have been drawn ..............
|
||
;
|
||
mov eax,[ScaleY]
|
||
add [YTotal],eax ; accumulate scale factor
|
||
test [YTotal],0FF00h ; check to see if we draw the line
|
||
jz ??clip_y_loop ; if not loop again
|
||
;
|
||
;...................... decrement HeightCount .......................
|
||
;
|
||
mov eax,0 ; clear EAX
|
||
xchg al,[BYTE PTR YTotal+1] ; get # lines, clear it in YTotal
|
||
sub [HeightCount],eax ; subtract # drawn lines from HtCt
|
||
jg ??clip_y_loop ; if more lines remain, loop again
|
||
jns ??draw_loop ; is exactly 0; we're done clipping
|
||
;
|
||
;....................... adjust for overrun .........................
|
||
;
|
||
mov esi,[LineStart] ; point ESI back to this line
|
||
mov eax,[HeightCount]
|
||
neg eax ; EAX = # lines overrun
|
||
shl eax,8 ; multiply by 100h
|
||
add eax,[YTotal] ; add in roundoff bits
|
||
sub eax,[ScaleY] ; adjust down by y-scale
|
||
mov [YTotal],eax ; store in YTotal
|
||
|
||
;====================================================================
|
||
; The drawing loop (at long last!):
|
||
; - Accumulate YTotal; if high byte is 0, skip this row of bytes &
|
||
; loop again
|
||
; - Skip left-clipped pixels:
|
||
; - If we've skipped all the bytes on the line, just go to the
|
||
; next line
|
||
; - Draw middle pixels:
|
||
; - Add the shape's pixel width to ECX (which could be negative
|
||
; if we left-skipped into the drawable area)
|
||
; - If ECX is still 0, there are no pixels to draw
|
||
; - Otherwise, leave ECX as is & draw the pixels
|
||
; - Skip right-clipped pixels:
|
||
; - Add # right-clipped pixels to ECX (which could be negative if
|
||
; the draw routine uncompressed 0's into the right-clipped
|
||
; region)
|
||
; - if ECX > 0, skip the remaining bytes
|
||
; - Go to the next line:
|
||
; - point EDI to the start of the next line in the viewport
|
||
; - decrement the height counter, exit if it's 0
|
||
; - decrement YTotal's high byte
|
||
; - if it's 0, go to the loop top
|
||
; - otherwise, reset ESI to this line's start & redraw the line,
|
||
; starting at left-clipped pixels
|
||
; (NOTE: why not start drawing at middle pixels??????????)
|
||
;====================================================================
|
||
??draw_loop:
|
||
;
|
||
;................... accumulate YTotal & test it ....................
|
||
;
|
||
mov eax,[ScaleY] ; get y scaling factor
|
||
add [YTotal],eax ; accumulate YTotal
|
||
test [YTotal],0FF00h ; see if we need to draw anything
|
||
jnz ??draw_line ; draw this line
|
||
;
|
||
;......................... skip this line ...........................
|
||
;
|
||
mov ecx,[ShapeWidth] ; load shape's width in bytes
|
||
call [RSkipRout] ; skip this row & loop again
|
||
jmp ??draw_loop
|
||
|
||
;
|
||
;--------------------- start drawing this line ----------------------
|
||
;
|
||
??draw_line:
|
||
mov [LineStart],esi ; save current byte position
|
||
;....................................................................
|
||
; Skip left-clipped pixels:
|
||
; - initialize [WidthCount] to total shape width in bytes
|
||
; - set ECX to # >bytes< to clip
|
||
; When LSkipRout returns:
|
||
; - ECX will contain # >pixels< overrun
|
||
; - EDX will contain the XTotal init value
|
||
; - [WidthCount] will be decremented by total bytes skipped
|
||
;....................................................................
|
||
??draw_left:
|
||
mov eax,[ShapeWidth] ; load shape width
|
||
mov [WidthCount],eax ; set up for LSkipRout
|
||
mov ecx,[LeftClipBytes] ; bytes, not pixels!
|
||
call [LSkipRout] ; skip the bytes
|
||
cmp [WidthCount],0
|
||
jz ??next_line ; The whole line was 0's
|
||
;....................................................................
|
||
; Draw middle pixels:
|
||
; - add PixelWidth to ECX (which may be negative)
|
||
; - if ECX is 0, don't bother drawing
|
||
; When DrawRout returns:
|
||
; - ECX will contain # >pixels< overrun
|
||
; - [WidthCount] will be decremented by # bytes drawn
|
||
;....................................................................
|
||
??draw_middle:
|
||
add ecx,[PixelWidth] ; since ECX could overrun, add width
|
||
jle ??draw_right ; if ECX<=0, no middle pixels to draw
|
||
call [DrawRout] ; draw the pixels
|
||
;
|
||
;................... skip past right-clipped pixels .................
|
||
;
|
||
??draw_right:
|
||
mov ecx,[WidthCount] ; ECX = remaining # bytes
|
||
jecxz ??next_line ; don't bother if no bytes remain
|
||
call [RSkipRout] ; skip right-clipped bytes
|
||
;
|
||
;----------------------- go to the next line ------------------------
|
||
;
|
||
??next_line:
|
||
;
|
||
;................. adjust EDI to start of next line .................
|
||
;
|
||
mov eax,[viewport_yadd] ; get yadd
|
||
add [StartDraw],eax ; add it to this line's position
|
||
mov edi,[StartDraw] ; EDI = next line
|
||
;
|
||
;................. decrement our pixel row counter ..................
|
||
;
|
||
dec [PixelHeight] ; count down a line
|
||
jz ??exit ; we're done!
|
||
;
|
||
;.................. decrement YTotal's high byte ....................
|
||
;
|
||
dec [BYTE PTR YTotal + 1] ; decrement high byte
|
||
jz ??draw_loop ; draw next line if 0
|
||
;
|
||
;....................... re-draw this line ..........................
|
||
;
|
||
mov esi,[LineStart] ; reset to this line's start
|
||
jmp ??draw_left ; redraw this line
|
||
|
||
??exit:
|
||
ret
|
||
|
||
ENDP Draw_Shape
|
||
|
||
|
||
;***************************************************************************
|
||
;* Not_Supported -- Replacement function for Draw_Shape routines not used. *
|
||
;* *
|
||
;* INPUT: *
|
||
;* none. *
|
||
;* *
|
||
;* OUTPUT: *
|
||
;* none. *
|
||
;* *
|
||
;* WARNINGS: *
|
||
;* none. *
|
||
;* *
|
||
;* HISTORY: *
|
||
;* 08/24/1993 SKB : Created. *
|
||
;*=========================================================================*
|
||
PROC Not_Supported NOLANGUAGE NEAR
|
||
|
||
ret
|
||
|
||
ENDP Not_Supported
|
||
|
||
END
|
||
|
||
;************************** End of drawshp.asm *****************************
|
||
|
||
|