FACINGFF.ASM (6370B)
1 ; 2 ; Copyright 2020 Electronic Arts Inc. 3 ; 4 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 5 ; software: you can redistribute it and/or modify it under the terms of 6 ; the GNU General Public License as published by the Free Software Foundation, 7 ; either version 3 of the License, or (at your option) any later version. 8 9 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 10 ; in the hope that it will be useful, but with permitted additional restrictions 11 ; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 12 ; distributed with this program. You should have received a copy of the 13 ; GNU General Public License along with permitted additional restrictions 14 ; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>. 15 16 ;*************************************************************************** 17 ;** 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 ** 18 ;*************************************************************************** 19 ;* * 20 ;* Project Name : Support Library * 21 ;* * 22 ;* File Name : FACINGFF.ASM * 23 ;* * 24 ;* Programmer : Joe L. Bostic * 25 ;* * 26 ;* Start Date : May 8, 1991 * 27 ;* * 28 ;* Last Update : February 6, 1995 [BWG] * 29 ;* * 30 ;*-------------------------------------------------------------------------* 31 ;* Functions: * 32 ;* Desired_Facing256 -- Determines facing to reach a position. * 33 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * 34 35 36 ;IDEAL 37 ;P386 38 ;MODEL USE32 FLAT 39 40 GLOBAL C Desired_Facing256 :NEAR 41 ; INCLUDE "wwlib.i" 42 INCLUDE "..\include\gbuffer.inc" 43 44 CODESEG 45 46 ;*************************************************************************** 47 ;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution. * 48 ;* * 49 ;* This is a desired facing algorithm that has a resolution of 0 * 50 ;* through 255. * 51 ;* * 52 ;* INPUT: srcx,srcy -- Source coordinate. * 53 ;* * 54 ;* dstx,dsty -- Destination coordinate. * 55 ;* * 56 ;* OUTPUT: Returns with the desired facing to face the destination * 57 ;* coordinate from the position of the source coordinate. North * 58 ;* is 0, East is 64, etc. * 59 ;* * 60 ;* WARNINGS: This routine is slower than the other forms of desired * 61 ;* facing calculation. Use this routine when accuracy is * 62 ;* required. * 63 ;* * 64 ;* HISTORY: * 65 ;* 12/24/1991 JLB : Adapted. * 66 ;*=========================================================================*/ 67 ; LONG cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty) 68 PROC Desired_Facing256 C near 69 USES ebx, ecx, edx 70 71 ARG srcx:DWORD 72 ARG srcy:DWORD 73 ARG dstx:DWORD 74 ARG dsty:DWORD 75 76 xor ebx,ebx ; Facing number. 77 78 ; Determine absolute X delta and left/right direction. 79 mov ecx,[dstx] 80 sub ecx,[srcx] 81 jge short ??xnotneg 82 neg ecx 83 mov ebx,11000000b ; Set bit 7 and 6 for leftward. 84 ??xnotneg: 85 86 ; Determine absolute Y delta and top/bottom direction. 87 mov eax,[srcy] 88 sub eax,[dsty] 89 jge short ??ynotneg 90 xor ebx,01000000b ; Complement bit 6 for downward. 91 neg eax 92 ??ynotneg: 93 94 ; Set DX=64 for quadrants 0 and 2. 95 mov edx,ebx 96 and edx,01000000b 97 xor edx,01000000b 98 99 ; Determine if the direction is closer to the Y axis and make sure that 100 ; CX holds the larger of the two deltas. This is in preparation for the 101 ; divide. 102 cmp eax,ecx 103 jb short ??gotaxis 104 xchg eax,ecx 105 xor edx,01000000b ; Closer to Y axis so make DX=64 for quad 0 and 2. 106 ??gotaxis: 107 108 ; If closer to the X axis then add 64 for quadrants 0 and 2. If 109 ; closer to the Y axis then add 64 for quadrants 1 and 3. Determined 110 ; add value is in DX and save on stack. 111 push edx 112 113 ; Make sure that the division won't overflow. Reduce precision until 114 ; the larger number is less than 256 if it appears that an overflow 115 ; will occur. If the high byte of the divisor is not zero, then this 116 ; guarantees no overflow, so just abort shift operation. 117 test eax,0FFFFFF00h 118 jnz short ??nooverflow 119 ??again: 120 test ecx,0FFFFFF00h 121 jz short ??nooverflow 122 shr ecx,1 123 shr eax,1 124 jmp short ??again 125 ??nooverflow: 126 127 ; Make sure that the division won't underflow (divide by zero). If 128 ; this would occur, then set the quotient to $FF and skip divide. 129 or ecx,ecx 130 jnz short ??nounderflow 131 mov eax,0FFFFFFFFh 132 jmp short ??divcomplete 133 134 ; Derive a pseudo angle number for the octant. The angle is based 135 ; on $00 = angle matches long axis, $00 = angle matches $FF degrees. 136 ??nounderflow: 137 xor edx,edx 138 shld edx,eax,8 ; shift high byte of eax into dl 139 shl eax,8 140 div ecx 141 ??divcomplete: 142 143 ; Integrate the 5 most significant bits into the angle index. If DX 144 ; is not zero, then it is 64. This means that the dividend must be negated 145 ; before it is added into the final angle value. 146 shr eax,3 147 pop edx 148 or edx,edx 149 je short ??noneg 150 dec edx 151 neg eax 152 ??noneg: 153 add eax,edx 154 add eax,ebx 155 and eax,0FFH 156 ret 157 158 ENDP Desired_Facing256 159 160 161 162 END