166 lines
6.1 KiB
NASM
166 lines
6.1 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 A S S O C I A T E S **
|
||
;***************************************************************************
|
||
;* *
|
||
;* Project Name : Support Library *
|
||
;* *
|
||
;* File Name : FACINGFF.ASM *
|
||
;* *
|
||
;* Programmer : Joe L. Bostic *
|
||
;* *
|
||
;* Start Date : May 8, 1991 *
|
||
;* *
|
||
;* Last Update : February 6, 1995 [BWG] *
|
||
;* *
|
||
;*-------------------------------------------------------------------------*
|
||
;* Functions: *
|
||
;* Desired_Facing256 -- Determines facing to reach a position. *
|
||
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
|
||
|
||
|
||
IDEAL
|
||
P386
|
||
MODEL USE32 FLAT
|
||
|
||
GLOBAL Desired_Facing256 :NEAR
|
||
; INCLUDE "wwlib.i"
|
||
INCLUDE ".\gbuffer.inc"
|
||
|
||
CODESEG
|
||
|
||
;***************************************************************************
|
||
;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution. *
|
||
;* *
|
||
;* This is a desired facing algorithm that has a resolution of 0 *
|
||
;* through 255. *
|
||
;* *
|
||
;* INPUT: srcx,srcy -- Source coordinate. *
|
||
;* *
|
||
;* dstx,dsty -- Destination coordinate. *
|
||
;* *
|
||
;* OUTPUT: Returns with the desired facing to face the destination *
|
||
;* coordinate from the position of the source coordinate. North *
|
||
;* is 0, East is 64, etc. *
|
||
;* *
|
||
;* WARNINGS: This routine is slower than the other forms of desired *
|
||
;* facing calculation. Use this routine when accuracy is *
|
||
;* required. *
|
||
;* *
|
||
;* HISTORY: *
|
||
;* 12/24/1991 JLB : Adapted. *
|
||
;*=========================================================================*/
|
||
; LONG cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty)
|
||
PROC Desired_Facing256 C near
|
||
USES ebx, ecx, edx
|
||
|
||
ARG srcx:DWORD
|
||
ARG srcy:DWORD
|
||
ARG dstx:DWORD
|
||
ARG dsty:DWORD
|
||
|
||
xor ebx,ebx ; Facing number.
|
||
|
||
; Determine absolute X delta and left/right direction.
|
||
mov ecx,[dstx]
|
||
sub ecx,[srcx]
|
||
jge short ??xnotneg
|
||
neg ecx
|
||
mov ebx,11000000b ; Set bit 7 and 6 for leftward.
|
||
??xnotneg:
|
||
|
||
; Determine absolute Y delta and top/bottom direction.
|
||
mov eax,[srcy]
|
||
sub eax,[dsty]
|
||
jge short ??ynotneg
|
||
xor ebx,01000000b ; Complement bit 6 for downward.
|
||
neg eax
|
||
??ynotneg:
|
||
|
||
; Set DX=64 for quadrants 0 and 2.
|
||
mov edx,ebx
|
||
and edx,01000000b
|
||
xor edx,01000000b
|
||
|
||
; Determine if the direction is closer to the Y axis and make sure that
|
||
; CX holds the larger of the two deltas. This is in preparation for the
|
||
; divide.
|
||
cmp eax,ecx
|
||
jb short ??gotaxis
|
||
xchg eax,ecx
|
||
xor edx,01000000b ; Closer to Y axis so make DX=64 for quad 0 and 2.
|
||
??gotaxis:
|
||
|
||
; If closer to the X axis then add 64 for quadrants 0 and 2. If
|
||
; closer to the Y axis then add 64 for quadrants 1 and 3. Determined
|
||
; add value is in DX and save on stack.
|
||
push edx
|
||
|
||
; Make sure that the division won't overflow. Reduce precision until
|
||
; the larger number is less than 256 if it appears that an overflow
|
||
; will occur. If the high byte of the divisor is not zero, then this
|
||
; guarantees no overflow, so just abort shift operation.
|
||
test eax,0FFFFFF00h
|
||
jnz short ??nooverflow
|
||
??again:
|
||
test ecx,0FFFFFF00h
|
||
jz short ??nooverflow
|
||
shr ecx,1
|
||
shr eax,1
|
||
jmp short ??again
|
||
??nooverflow:
|
||
|
||
; Make sure that the division won't underflow (divide by zero). If
|
||
; this would occur, then set the quotient to $FF and skip divide.
|
||
or ecx,ecx
|
||
jnz short ??nounderflow
|
||
mov eax,0FFFFFFFFh
|
||
jmp short ??divcomplete
|
||
|
||
; Derive a pseudo angle number for the octant. The angle is based
|
||
; on $00 = angle matches long axis, $00 = angle matches $FF degrees.
|
||
??nounderflow:
|
||
xor edx,edx
|
||
shld edx,eax,8 ; shift high byte of eax into dl
|
||
shl eax,8
|
||
div ecx
|
||
??divcomplete:
|
||
|
||
; Integrate the 5 most significant bits into the angle index. If DX
|
||
; is not zero, then it is 64. This means that the dividend must be negated
|
||
; before it is added into the final angle value.
|
||
shr eax,3
|
||
pop edx
|
||
or edx,edx
|
||
je short ??noneg
|
||
dec edx
|
||
neg eax
|
||
??noneg:
|
||
add eax,edx
|
||
add eax,ebx
|
||
and eax,0FFH
|
||
ret
|
||
|
||
ENDP Desired_Facing256
|
||
|
||
|
||
|
||
END
|
||
|