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 *****************************
|
|||
|
|
|||
|
|