FACINGFF.ASM 6.2 KB

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