mirror of
https://github.com/electronicarts/CnC_Red_Alert.git
synced 2025-12-16 15:41:39 -05:00
Initial commit of Command & Conquer Red Alert source code.
This commit is contained in:
464
WIN32LIB/SRCDEBUG/DRAWLINE.ASM
Normal file
464
WIN32LIB/SRCDEBUG/DRAWLINE.ASM
Normal file
@@ -0,0 +1,464 @@
|
||||
;
|
||||
; 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 A S S O C I A T E S **
|
||||
;***************************************************************************
|
||||
;* *
|
||||
;* Project Name : Westwood 32 bit Library *
|
||||
;* *
|
||||
;* File Name : DRAWLINE.ASM *
|
||||
;* *
|
||||
;* Programmer : Phil W. Gorrow *
|
||||
;* *
|
||||
;* Start Date : June 16, 1994 *
|
||||
;* *
|
||||
;* Last Update : August 30, 1994 [IML] *
|
||||
;* *
|
||||
;*-------------------------------------------------------------------------*
|
||||
;* Functions: *
|
||||
;* VVC::Scale -- Scales a virtual viewport to another virtual viewport *
|
||||
;* Normal_Draw -- jump loc for drawing scaled line of normal pixel *
|
||||
;* __DRAW_LINE -- Assembly routine to draw a line *
|
||||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||||
|
||||
IDEAL
|
||||
P386
|
||||
MODEL USE32 FLAT
|
||||
|
||||
INCLUDE ".\drawbuff.inc"
|
||||
INCLUDE ".\gbuffer.inc"
|
||||
|
||||
|
||||
CODESEG
|
||||
|
||||
|
||||
|
||||
;***************************************************************************
|
||||
;* VVC::DRAW_LINE -- Scales a virtual viewport to another virtual viewport *
|
||||
;* *
|
||||
;* INPUT: WORD sx_pixel - the starting x pixel position *
|
||||
;* WORD sy_pixel - the starting y pixel position *
|
||||
;* WORD dx_pixel - the destination x pixel position *
|
||||
;* WORD dy_pixel - the destination y pixel position *
|
||||
;* WORD color - the color of the line to draw *
|
||||
;* *
|
||||
;* Bounds Checking: Compares sx_pixel, sy_pixel, dx_pixel and dy_pixel *
|
||||
;* with the graphic viewport it has been assigned to. *
|
||||
;* *
|
||||
;* HISTORY: *
|
||||
;* 06/16/1994 PWG : Created. *
|
||||
;* 08/30/1994 IML : Fixed clipping bug. *
|
||||
;*=========================================================================*
|
||||
PROC Buffer_Draw_Line C NEAR
|
||||
USES eax,ebx,ecx,edx,esi,edi
|
||||
|
||||
;*==================================================================
|
||||
;* Define the arguements that the function takes.
|
||||
;*==================================================================
|
||||
ARG this_object:DWORD ; associated graphic view port
|
||||
ARG x1_pixel:DWORD ; the start x pixel position
|
||||
ARG y1_pixel:DWORD ; the start y pixel position
|
||||
ARG x2_pixel:DWORD ; the dest x pixel position
|
||||
ARG y2_pixel:DWORD ; the dest y pixel position
|
||||
ARG color:DWORD ; the color we are drawing
|
||||
|
||||
;*==================================================================
|
||||
;* Define the local variables that we will use on the stack
|
||||
;*==================================================================
|
||||
LOCAL clip_min_x:DWORD
|
||||
LOCAL clip_max_x:DWORD
|
||||
LOCAL clip_min_y:DWORD
|
||||
LOCAL clip_max_y:DWORD
|
||||
LOCAL clip_var:DWORD
|
||||
LOCAL accum:DWORD
|
||||
LOCAL bpr:DWORD
|
||||
|
||||
;*==================================================================
|
||||
;* Take care of find the clip minimum and maximums
|
||||
;*==================================================================
|
||||
mov ebx,[this_object]
|
||||
xor eax,eax
|
||||
mov [clip_min_x],eax
|
||||
mov [clip_min_y],eax
|
||||
mov eax,[(GraphicViewPort ebx).GVPWidth]
|
||||
mov [clip_max_x],eax
|
||||
add eax,[(GraphicViewPort ebx).GVPXAdd]
|
||||
add eax,[(GraphicViewPort ebx).GVPPitch]
|
||||
mov [bpr],eax
|
||||
mov eax,[(GraphicViewPort ebx).GVPHeight]
|
||||
mov [clip_max_y],eax
|
||||
|
||||
;*==================================================================
|
||||
;* Adjust max pixels as they are tested inclusively.
|
||||
;*==================================================================
|
||||
dec [clip_max_x]
|
||||
dec [clip_max_y]
|
||||
|
||||
;*==================================================================
|
||||
;* Set the registers with the data for drawing the line
|
||||
;*==================================================================
|
||||
mov eax,[x1_pixel] ; eax = start x pixel position
|
||||
mov ebx,[y1_pixel] ; ebx = start y pixel position
|
||||
mov ecx,[x2_pixel] ; ecx = dest x pixel position
|
||||
mov edx,[y2_pixel] ; edx = dest y pixel position
|
||||
|
||||
;*==================================================================
|
||||
;* This is the section that "pushes" the line into bounds.
|
||||
;* I have marked the section with PORTABLE start and end to signify
|
||||
;* how much of this routine is 100% portable between graphics modes.
|
||||
;* It was just as easy to have variables as it would be for constants
|
||||
;* so the global vars ClipMaxX,ClipMinY,ClipMaxX,ClipMinY are used
|
||||
;* to clip the line (default is the screen)
|
||||
;* PORTABLE start
|
||||
;*==================================================================
|
||||
|
||||
cmp eax,[clip_min_x]
|
||||
jl short ??clip_it
|
||||
cmp eax,[clip_max_x]
|
||||
jg short ??clip_it
|
||||
cmp ebx,[clip_min_y]
|
||||
jl short ??clip_it
|
||||
cmp ebx,[clip_max_y]
|
||||
jg short ??clip_it
|
||||
cmp ecx,[clip_min_x]
|
||||
jl short ??clip_it
|
||||
cmp ecx,[clip_max_x]
|
||||
jg short ??clip_it
|
||||
cmp edx,[clip_min_y]
|
||||
jl short ??clip_it
|
||||
cmp edx,[clip_max_y]
|
||||
jle short ??on_screen
|
||||
|
||||
;*==================================================================
|
||||
;* Takes care off clipping the line.
|
||||
;*==================================================================
|
||||
??clip_it:
|
||||
call NEAR PTR ??set_bits
|
||||
xchg eax,ecx
|
||||
xchg ebx,edx
|
||||
mov edi,esi
|
||||
call NEAR PTR ??set_bits
|
||||
mov [clip_var],edi
|
||||
or [clip_var],esi
|
||||
jz short ??on_screen
|
||||
test edi,esi
|
||||
jne short ??off_screen
|
||||
shl esi,2
|
||||
call [DWORD PTR cs:??clip_tbl+esi]
|
||||
jc ??clip_it
|
||||
xchg eax,ecx
|
||||
xchg ebx,edx
|
||||
shl edi,2
|
||||
call [DWORD PTR cs:??clip_tbl+edi]
|
||||
jmp ??clip_it
|
||||
|
||||
??on_screen:
|
||||
jmp ??draw_it
|
||||
|
||||
??off_screen:
|
||||
jmp ??out
|
||||
|
||||
;*==================================================================
|
||||
;* Jump table for clipping conditions
|
||||
;*==================================================================
|
||||
??clip_tbl DD ??nada,??a_up,??a_dwn,??nada
|
||||
DD ??a_lft,??a_lft,??a_dwn,??nada
|
||||
DD ??a_rgt,??a_up,??a_rgt,??nada
|
||||
DD ??nada,??nada,??nada,??nada
|
||||
|
||||
??nada:
|
||||
clc
|
||||
retn
|
||||
|
||||
??a_up:
|
||||
mov esi,[clip_min_y]
|
||||
call NEAR PTR ??clip_vert
|
||||
stc
|
||||
retn
|
||||
|
||||
??a_dwn:
|
||||
mov esi,[clip_max_y]
|
||||
neg esi
|
||||
neg ebx
|
||||
neg edx
|
||||
call NEAR PTR ??clip_vert
|
||||
neg ebx
|
||||
neg edx
|
||||
stc
|
||||
retn
|
||||
|
||||
;*==================================================================
|
||||
;* xa'=xa+[(miny-ya)(xb-xa)/(yb-ya)]
|
||||
;*==================================================================
|
||||
??clip_vert:
|
||||
push edx
|
||||
push eax
|
||||
mov [clip_var],edx ; clip_var = yb
|
||||
sub [clip_var],ebx ; clip_var = (yb-ya)
|
||||
neg eax ; eax=-xa
|
||||
add eax,ecx ; (ebx-xa)
|
||||
mov edx,esi ; edx=miny
|
||||
sub edx,ebx ; edx=(miny-ya)
|
||||
imul edx
|
||||
idiv [clip_var]
|
||||
pop edx
|
||||
add eax,edx
|
||||
pop edx
|
||||
mov ebx,esi
|
||||
retn
|
||||
|
||||
??a_lft:
|
||||
mov esi,[clip_min_x]
|
||||
call NEAR PTR ??clip_horiz
|
||||
stc
|
||||
retn
|
||||
|
||||
??a_rgt:
|
||||
mov esi,[clip_max_x]
|
||||
neg eax
|
||||
neg ecx
|
||||
neg esi
|
||||
call NEAR PTR ??clip_horiz
|
||||
neg eax
|
||||
neg ecx
|
||||
stc
|
||||
retn
|
||||
|
||||
;*==================================================================
|
||||
;* ya'=ya+[(minx-xa)(yb-ya)/(xb-xa)]
|
||||
;*==================================================================
|
||||
??clip_horiz:
|
||||
push edx
|
||||
mov [clip_var],ecx ; clip_var = xb
|
||||
sub [clip_var],eax ; clip_var = (xb-xa)
|
||||
sub edx,ebx ; edx = (yb-ya)
|
||||
neg eax ; eax = -xa
|
||||
add eax,esi ; eax = (minx-xa)
|
||||
imul edx ; eax = (minx-xa)(yb-ya)
|
||||
idiv [clip_var] ; eax = (minx-xa)(yb-ya)/(xb-xa)
|
||||
add ebx,eax ; ebx = xa+[(minx-xa)(yb-ya)/(xb-xa)]
|
||||
pop edx
|
||||
mov eax,esi
|
||||
retn
|
||||
|
||||
;*==================================================================
|
||||
;* Sets the condition bits
|
||||
;*==================================================================
|
||||
??set_bits:
|
||||
xor esi,esi
|
||||
cmp ebx,[clip_min_y] ; if y >= top its not up
|
||||
jge short ??a_not_up
|
||||
or esi,1
|
||||
|
||||
??a_not_up:
|
||||
cmp ebx,[clip_max_y] ; if y <= bottom its not down
|
||||
jle short ??a_not_down
|
||||
or esi,2
|
||||
|
||||
??a_not_down:
|
||||
cmp eax,[clip_min_x] ; if x >= left its not left
|
||||
jge short ??a_not_left
|
||||
or esi,4
|
||||
|
||||
??a_not_left:
|
||||
cmp eax,[clip_max_x] ; if x <= right its not right
|
||||
jle short ??a_not_right
|
||||
or esi,8
|
||||
|
||||
??a_not_right:
|
||||
retn
|
||||
|
||||
;*==================================================================
|
||||
;* Draw the line to the screen.
|
||||
;* PORTABLE end
|
||||
;*==================================================================
|
||||
??draw_it:
|
||||
sub edx,ebx ; see if line is being draw down
|
||||
jnz short ??not_hline ; if not then its not a hline
|
||||
jmp short ??hline ; do special case h line
|
||||
|
||||
??not_hline:
|
||||
jg short ??down ; if so there is no need to rev it
|
||||
neg edx ; negate for actual pixel length
|
||||
xchg eax,ecx ; swap x's to rev line draw
|
||||
sub ebx,edx ; get old edx
|
||||
|
||||
??down:
|
||||
push edx
|
||||
push eax
|
||||
mov eax,[bpr]
|
||||
mul ebx
|
||||
mov ebx,eax
|
||||
mov eax,[this_object]
|
||||
add ebx,[(GraphicViewPort eax).GVPOffset]
|
||||
pop eax
|
||||
pop edx
|
||||
|
||||
mov esi,1 ; assume a right mover
|
||||
sub ecx,eax ; see if line is right
|
||||
jnz short ??not_vline ; see if its a vertical line
|
||||
jmp ??vline
|
||||
|
||||
??not_vline:
|
||||
jg short ??right ; if so, the difference = length
|
||||
|
||||
??left:
|
||||
neg ecx ; else negate for actual pixel length
|
||||
neg esi ; negate counter to move left
|
||||
|
||||
??right:
|
||||
cmp ecx,edx ; is it a horiz or vert line
|
||||
jge short ??horiz ; if ecx > edx then |x|>|y| or horiz
|
||||
|
||||
??vert:
|
||||
xchg ecx,edx ; make ecx greater and edx lesser
|
||||
mov edi,ecx ; set greater
|
||||
mov [accum],ecx ; set accumulator to 1/2 greater
|
||||
shr [accum],1
|
||||
|
||||
;*==================================================================
|
||||
;* at this point ...
|
||||
;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
|
||||
;* esi=adder; accum=accumulator
|
||||
;* in a vertical loop the adder is conditional and the inc constant
|
||||
;*==================================================================
|
||||
??vert_loop:
|
||||
add ebx,eax
|
||||
mov eax,[color]
|
||||
|
||||
??v_midloop:
|
||||
mov [ebx],al
|
||||
dec ecx
|
||||
jl ??out
|
||||
add ebx,[bpr]
|
||||
sub [accum],edx ; sub the lesser
|
||||
jge ??v_midloop ; any line could be new
|
||||
add [accum],edi ; add greater for new accum
|
||||
add ebx,esi ; next pixel over
|
||||
jmp ??v_midloop
|
||||
|
||||
??horiz:
|
||||
mov edi,ecx ; set greater
|
||||
mov [accum],ecx ; set accumulator to 1/2 greater
|
||||
shr [accum],1
|
||||
|
||||
;*==================================================================
|
||||
;* at this point ...
|
||||
;* eax=xpos ; ebx=page line offset; ecx=counter; edx=lesser; edi=greater;
|
||||
;* esi=adder; accum=accumulator
|
||||
;* in a vertical loop the adder is conditional and the inc constant
|
||||
;*==================================================================
|
||||
??horiz_loop:
|
||||
add ebx,eax
|
||||
mov eax,[color]
|
||||
|
||||
??h_midloop:
|
||||
mov [ebx],al
|
||||
dec ecx ; dec counter
|
||||
jl ??out ; end of line
|
||||
add ebx,esi
|
||||
sub [accum],edx ; sub the lesser
|
||||
jge ??h_midloop
|
||||
add [accum],edi ; add greater for new accum
|
||||
add ebx,[bpr] ; goto next line
|
||||
jmp ??h_midloop
|
||||
|
||||
;*==================================================================
|
||||
;* Special case routine for horizontal line draws
|
||||
;*==================================================================
|
||||
??hline:
|
||||
cmp eax,ecx ; make eax < ecx
|
||||
jl short ??hl_ac
|
||||
xchg eax,ecx
|
||||
|
||||
??hl_ac:
|
||||
sub ecx,eax ; get len
|
||||
inc ecx
|
||||
|
||||
push edx
|
||||
push eax
|
||||
mov eax,[bpr]
|
||||
mul ebx
|
||||
mov ebx,eax
|
||||
mov eax,[this_object]
|
||||
add ebx,[(GraphicViewPort eax).GVPOffset]
|
||||
pop eax
|
||||
pop edx
|
||||
add ebx,eax
|
||||
mov edi,ebx
|
||||
cmp ecx,15
|
||||
jg ??big_line
|
||||
mov al,[byte color]
|
||||
rep stosb ; write as many words as possible
|
||||
jmp short ??out ; get outt
|
||||
|
||||
|
||||
??big_line:
|
||||
mov al,[byte color]
|
||||
mov ah,al
|
||||
mov ebx,eax
|
||||
shl eax,16
|
||||
mov ax,bx
|
||||
test edi,3
|
||||
jz ??aligned
|
||||
mov [edi],al
|
||||
inc edi
|
||||
dec ecx
|
||||
test edi,3
|
||||
jz ??aligned
|
||||
mov [edi],al
|
||||
inc edi
|
||||
dec ecx
|
||||
test edi,3
|
||||
jz ??aligned
|
||||
mov [edi],al
|
||||
inc edi
|
||||
dec ecx
|
||||
|
||||
??aligned:
|
||||
mov ebx,ecx
|
||||
shr ecx,2
|
||||
rep stosd
|
||||
mov ecx,ebx
|
||||
and ecx,3
|
||||
rep stosb
|
||||
jmp ??out
|
||||
|
||||
|
||||
;*==================================================================
|
||||
;* a special case routine for vertical line draws
|
||||
;*==================================================================
|
||||
??vline:
|
||||
mov ecx,edx ; get length of line to draw
|
||||
inc ecx
|
||||
add ebx,eax
|
||||
mov eax,[color]
|
||||
|
||||
??vl_loop:
|
||||
mov [ebx],al ; store bit
|
||||
add ebx,[bpr]
|
||||
dec ecx
|
||||
jnz ??vl_loop
|
||||
|
||||
??out:
|
||||
ret
|
||||
ENDP Buffer_Draw_Line
|
||||
|
||||
|
||||
END
|
||||
Reference in New Issue
Block a user