2SUPPORT.ASM 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564
  1. ;
  2. ; Command & Conquer Red Alert(tm)
  3. ; Copyright 2025 Electronic Arts Inc.
  4. ;
  5. ; This program is free software: you can redistribute it and/or modify
  6. ; it under the terms of the GNU General Public License as published by
  7. ; the Free Software Foundation, either version 3 of the License, or
  8. ; (at your option) any later version.
  9. ;
  10. ; This program is distributed in the hope that it will be useful,
  11. ; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ; GNU General Public License for more details.
  14. ;
  15. ; You should have received a copy of the GNU General Public License
  16. ; along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. ;
  18. ; $Header: F:\projects\c&c0\vcs\code\2support.asv 5.0 11 Nov 1996 09:40:36 JOE_BOSTIC $
  19. ;***************************************************************************
  20. ;** 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 **
  21. ;***************************************************************************
  22. ;* *
  23. ;* Project Name : Command & Conquer *
  24. ;* *
  25. ;* File Name : SUPPORT.ASM *
  26. ;* *
  27. ;* Programmer : Joe L. Bostic *
  28. ;* *
  29. ;* Start Date : September 23, 1993 *
  30. ;* *
  31. ;* Last Update : May 10, 1994 [JLB] *
  32. ;* *
  33. ;*-------------------------------------------------------------------------*
  34. ;* Functions: *
  35. ;* strtrim -- Remove the trailing white space from a string. *
  36. ;* Fat_Put_Pixel -- Draws a fat pixel. *
  37. ;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.*
  38. ;* Remove_From_List -- Removes a pointer from a list of pointers. *
  39. ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
  40. IDEAL
  41. P386
  42. MODEL USE32 FLAT
  43. INCLUDE "gbuffer.inc"
  44. DISPLAY "Command & Conquer assembly support routines."
  45. CODESEG
  46. ;***************************************************************************
  47. ;* Fat_Put_Pixel -- Draws a fat pixel. *
  48. ;* *
  49. ;* Use this routine to draw a "pixel" that is bigger than 1 pixel *
  50. ;* across. This routine is faster than drawing a similar small shape *
  51. ;* and faster than calling Fill_Rect. *
  52. ;* *
  53. ;* INPUT: x,y -- Screen coordinates to draw the pixel's upper *
  54. ;* left corner. *
  55. ;* *
  56. ;* color -- The color to render the pixel in. *
  57. ;* *
  58. ;* size -- The number of pixels width of the big "pixel". *
  59. ;* *
  60. ;* page -- The pointer to a GraphicBuffer class or something *
  61. ;* *
  62. ;* OUTPUT: none *
  63. ;* *
  64. ;* WARNINGS: none *
  65. ;* *
  66. ;* HISTORY: *
  67. ;* 03/17/1994 JLB : Created. *
  68. ;*=========================================================================*
  69. ; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)
  70. GLOBAL C Fat_Put_Pixel:NEAR
  71. PROC Fat_Put_Pixel C near
  72. USES eax, ebx, ecx, edx, edi, esi
  73. ARG x:DWORD ; X coordinate of upper left pixel corner.
  74. ARG y:DWORD ; Y coordinate of upper left pixel corner.
  75. ARG color:DWORD ; Color to use for the "pixel".
  76. ARG siz:DWORD ; Size of "pixel" to plot (square).
  77. ARG gpage:DWORD ; graphic page address to plot onto
  78. cmp [siz],0
  79. je short ??exit
  80. ; Set EDI to point to start of logical page memory.
  81. ;*===================================================================
  82. ; Get the viewport information and put bytes per row in ecx
  83. ;*===================================================================
  84. mov ebx,[gpage] ; get a pointer to viewport
  85. mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
  86. ; Verify the the Y pixel offset is legal.
  87. mov eax,[y]
  88. cmp eax,[(GraphicViewPort ebx).GVPHeight] ;YPIXEL_MAX
  89. jae short ??exit
  90. mov ecx,[(GraphicViewPort ebx).GVPWidth]
  91. add ecx,[(GraphicViewPort ebx).GVPXAdd]
  92. add ecx,[(GraphicViewPort ebx).GVPPitch]
  93. mul ecx
  94. add edi,eax
  95. ; Verify the the X pixel offset is legal.
  96. mov edx,[(GraphicViewPort ebx).GVPWidth]
  97. cmp edx,[x]
  98. mov edx,ecx
  99. jbe short ??exit
  100. add edi,[x]
  101. ; Write the pixel to the screen.
  102. mov ebx,[siz] ; Copy of pixel size.
  103. sub edx,ebx ; Modulo to reach start of next row.
  104. mov eax,[color]
  105. ??again:
  106. mov ecx,ebx
  107. rep stosb
  108. add edi,edx ; EDI points to start of next row.
  109. dec [siz]
  110. jnz short ??again
  111. ??exit:
  112. ret
  113. ENDP Fat_Put_Pixel
  114. if 0
  115. ;***************************************************************************
  116. ;* strtrim -- Remove the trailing white space from a string. *
  117. ;* *
  118. ;* Use this routine to remove white space characters from the beginning *
  119. ;* and end of the string. The string is modified in place by *
  120. ;* this routine. *
  121. ;* *
  122. ;* INPUT: buffer -- Pointer to the string to modify. *
  123. ;* *
  124. ;* OUTPUT: none *
  125. ;* *
  126. ;* WARNINGS: none *
  127. ;* *
  128. ;* HISTORY: *
  129. ;* 10/07/1992 JLB : Created. *
  130. ;*=========================================================================*
  131. ; VOID cdecl strtrim(BYTE *buffer);
  132. GLOBAL C strtrim :NEAR
  133. PROC strtrim C near
  134. USES ax, edi, esi
  135. ARG buffer:DWORD ; Pointer to string to modify.
  136. cmp [buffer],0
  137. je short ??fini
  138. ; Prepare for string scanning by loading pointers.
  139. cld
  140. mov esi,[buffer]
  141. mov edi,esi
  142. ; Strip white space from the start of the string.
  143. ??looper:
  144. lodsb
  145. cmp al,20h ; Space
  146. je short ??looper
  147. cmp al,9 ; TAB
  148. je short ??looper
  149. stosb
  150. ; Copy the rest of the string.
  151. ??gruntloop:
  152. lodsb
  153. stosb
  154. or al,al
  155. jnz short ??gruntloop
  156. dec edi
  157. ; Strip the white space from the end of the string.
  158. ??looper2:
  159. mov [edi],al
  160. dec edi
  161. mov ah,[edi]
  162. cmp ah,20h
  163. je short ??looper2
  164. cmp ah,9
  165. je short ??looper2
  166. ??fini:
  167. ret
  168. ENDP strtrim
  169. ;***************************************************************************
  170. ;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table. *
  171. ;* *
  172. ;* This routine is used to build a special fading table for C&C. There *
  173. ;* are certain colors that get faded to and cannot be faded again. *
  174. ;* With this rule, it is possible to draw a shadow multiple times and *
  175. ;* not have it get any lighter or darker. *
  176. ;* *
  177. ;* INPUT: palette -- Pointer to the 768 byte IBM palette to build from. *
  178. ;* *
  179. ;* dest -- Pointer to the 256 byte remap table. *
  180. ;* *
  181. ;* color -- Color index of the color to "fade to". *
  182. ;* *
  183. ;* frac -- The fraction to fade to the specified color *
  184. ;* *
  185. ;* OUTPUT: Returns with pointer to the remap table. *
  186. ;* *
  187. ;* WARNINGS: none *
  188. ;* *
  189. ;* HISTORY: *
  190. ;* 10/07/1992 JLB : Created. *
  191. ;*=========================================================================*/
  192. ;VOID * cdecl Conquer_Build_Fading_Table(VOID *palette, VOID *dest, long color, long frac);
  193. GLOBAL C Conquer_Build_Fading_Table : NEAR
  194. PROC Conquer_Build_Fading_Table C near
  195. USES ebx, ecx, edi, esi
  196. ARG palette:DWORD
  197. ARG dest:DWORD
  198. ARG color:DWORD
  199. ARG frac:DWORD
  200. LOCAL matchvalue:DWORD ; Last recorded match value.
  201. LOCAL targetred:BYTE ; Target gun red.
  202. LOCAL targetgreen:BYTE ; Target gun green.
  203. LOCAL targetblue:BYTE ; Target gun blue.
  204. LOCAL idealred:BYTE
  205. LOCAL idealgreen:BYTE
  206. LOCAL idealblue:BYTE
  207. LOCAL matchcolor:BYTE ; Tentative match color.
  208. ALLOWED_COUNT EQU 16
  209. ALLOWED_START EQU 256-ALLOWED_COUNT
  210. cld
  211. ; If the source palette is NULL, then just return with current fading table pointer.
  212. cmp [palette],0
  213. je ??fini1
  214. cmp [dest],0
  215. je ??fini1
  216. ; Fractions above 255 become 255.
  217. mov eax,[frac]
  218. cmp eax,0100h
  219. jb short ??ok
  220. mov [frac],0FFh
  221. ??ok:
  222. ; Record the target gun values.
  223. mov esi,[palette]
  224. mov ebx,[color]
  225. add esi,ebx
  226. add esi,ebx
  227. add esi,ebx
  228. lodsb
  229. mov [targetred],al
  230. lodsb
  231. mov [targetgreen],al
  232. lodsb
  233. mov [targetblue],al
  234. ; Main loop.
  235. xor ebx,ebx ; Remap table index.
  236. ; Transparent black never gets remapped.
  237. mov edi,[dest]
  238. mov [edi],bl
  239. inc edi
  240. ; EBX = source palette logical number (1..255).
  241. ; EDI = running pointer into dest remap table.
  242. ??mainloop:
  243. inc ebx
  244. mov esi,[palette]
  245. add esi,ebx
  246. add esi,ebx
  247. add esi,ebx
  248. mov edx,[frac]
  249. shr edx,1
  250. ; new = orig - ((orig-target) * fraction);
  251. lodsb ; orig
  252. mov dh,al ; preserve it for later.
  253. sub al,[targetred] ; al = (orig-target)
  254. imul dl ; ax = (orig-target)*fraction
  255. shl eax,1
  256. sub dh,ah ; dh = orig - ((orig-target) * fraction)
  257. mov [idealred],dh ; preserve ideal color gun value.
  258. lodsb ; orig
  259. mov dh,al ; preserve it for later.
  260. sub al,[targetgreen] ; al = (orig-target)
  261. imul dl ; ax = (orig-target)*fraction
  262. shl eax,1
  263. sub dh,ah ; dh = orig - ((orig-target) * fraction)
  264. mov [idealgreen],dh ; preserve ideal color gun value.
  265. lodsb ; orig
  266. mov dh,al ; preserve it for later.
  267. sub al,[targetblue] ; al = (orig-target)
  268. imul dl ; ax = (orig-target)*fraction
  269. shl eax,1
  270. sub dh,ah ; dh = orig - ((orig-target) * fraction)
  271. mov [idealblue],dh ; preserve ideal color gun value.
  272. ; Sweep through a limited set of existing colors to find the closest
  273. ; matching color.
  274. mov eax,[color]
  275. mov [matchcolor],al ; Default color (self).
  276. mov [matchvalue],-1 ; Ridiculous match value init.
  277. mov ecx,ALLOWED_COUNT
  278. mov esi,[palette] ; Pointer to original palette.
  279. add esi,(ALLOWED_START)*3
  280. ; BH = color index.
  281. mov bh,ALLOWED_START
  282. ??innerloop:
  283. xor edx,edx ; Comparison value starts null.
  284. ; Build the comparison value based on the sum of the differences of the color
  285. ; guns squared.
  286. lodsb
  287. sub al,[idealred]
  288. mov ah,al
  289. imul ah
  290. add edx,eax
  291. lodsb
  292. sub al,[idealgreen]
  293. mov ah,al
  294. imul ah
  295. add edx,eax
  296. lodsb
  297. sub al,[idealblue]
  298. mov ah,al
  299. imul ah
  300. add edx,eax
  301. jz short ??perfect ; If perfect match found then quit early.
  302. cmp edx,[matchvalue]
  303. jae short ??notclose
  304. mov [matchvalue],edx ; Record new possible color.
  305. mov [matchcolor],bh
  306. ??notclose:
  307. inc bh ; Checking color index.
  308. loop ??innerloop
  309. mov bh,[matchcolor]
  310. ??perfect:
  311. mov [matchcolor],bh
  312. xor bh,bh ; Make BX valid main index again.
  313. ; When the loop exits, we have found the closest match.
  314. mov al,[matchcolor]
  315. stosb
  316. cmp ebx,ALLOWED_START-1
  317. jne ??mainloop
  318. ; Fill the remainder of the remap table with values
  319. ; that will remap the color to itself.
  320. mov ecx,ALLOWED_COUNT
  321. ??fillerloop:
  322. inc bl
  323. mov al,bl
  324. stosb
  325. loop ??fillerloop
  326. ??fini1:
  327. mov esi,[dest]
  328. mov eax,esi
  329. ret
  330. ENDP Conquer_Build_Fading_Table
  331. ;***************************************************************************
  332. ;* Remove_From_List -- Removes a pointer from a list of pointers. *
  333. ;* *
  334. ;* This low level routine is used to remove a pointer from a list of *
  335. ;* pointers. The trailing pointers are moved downward to fill the *
  336. ;* hole. *
  337. ;* *
  338. ;* INPUT: list -- Pointer to list of pointer. *
  339. ;* *
  340. ;* index -- Pointer to length of pointer list. *
  341. ;* *
  342. ;* ptr -- The pointer value to search for and remove. *
  343. ;* *
  344. ;* OUTPUT: none *
  345. ;* *
  346. ;* WARNINGS: none *
  347. ;* *
  348. ;* HISTORY: *
  349. ;* 04/11/1994 JLB : Created. *
  350. ;* 04/22/1994 JLB : Convert to assembly language. *
  351. ;* 05/10/1994 JLB : Short pointers now. *
  352. ;*=========================================================================*/
  353. ;VOID cdecl Remove_From_List(VOID **list, long *index, long ptr);
  354. GLOBAL C Remove_From_List:NEAR
  355. PROC Remove_From_List C near
  356. USES edi, esi, ecx, eax
  357. ARG list:DWORD ; Pointer to list.
  358. ARG index:DWORD ; Pointer to count.
  359. ARG element:DWORD ; Element to remove.
  360. ; Fetch the number of elements in the list. If there are no
  361. ; elements, then just exit quickly.
  362. mov edi,[index]
  363. mov ecx,[edi]
  364. jcxz short ??fini2
  365. ; Fetch pointer to list.
  366. cmp [list],0
  367. je short ??fini2
  368. mov edi,[list]
  369. ; Loop through all elements searching for a match.
  370. mov eax,[element]
  371. repne scasd
  372. jne short ??fini2 ; No match found.
  373. ; Copy all remaining elements down. If this is the
  374. ; last element in the list then nothing needs to be
  375. ; copied -- just decrement the list size.
  376. jcxz short ??nocopy ; No copy necessary.
  377. mov esi,edi
  378. sub edi,4
  379. rep movsd
  380. ; Reduce the list count by one.
  381. ??nocopy:
  382. mov edi,[index]
  383. dec [DWORD PTR edi]
  384. ??fini2:
  385. ret
  386. ENDP Remove_From_List
  387. ; long cdecl Get_EAX();
  388. GLOBAL C Get_EAX :NEAR
  389. PROC Get_EAX C near
  390. ret
  391. ENDP Get_EAX
  392. endif
  393. DATASEG
  394. TabA DD 6949350
  395. DD 4913933
  396. DD 3474675
  397. DD 2456966
  398. DD 1737338
  399. DD 1228483
  400. DD 868669
  401. DD 614242
  402. DD 434334
  403. DD 307121
  404. DD 217167
  405. DD 153560
  406. DD 108584
  407. DD 76780
  408. DD 54292
  409. DD 38390
  410. DD 27146
  411. DD 19195
  412. DD 13573
  413. DD 9598
  414. DD 6786
  415. DD 4799
  416. DD 3393
  417. DD 2399
  418. DD 1697
  419. DD 1200
  420. DD 848
  421. DD 600
  422. DD 424
  423. DD 300
  424. DD 212
  425. DD 150
  426. DD 106
  427. TabB DD 154
  428. DD 218
  429. DD 309
  430. DD 437
  431. DD 618
  432. DD 874
  433. DD 1236
  434. DD 1748
  435. DD 2472
  436. DD 3496
  437. DD 4944
  438. DD 6992
  439. DD 9888
  440. DD 13983
  441. DD 19775
  442. DD 27967
  443. DD 39551
  444. DD 55933
  445. DD 79101
  446. DD 111866
  447. DD 158203
  448. DD 223732
  449. DD 316405
  450. DD 447465
  451. DD 632811
  452. DD 894929
  453. DD 1265621
  454. DD 1789859
  455. DD 2531243
  456. DD 3579718
  457. DD 5062486
  458. DD 7159436
  459. DD 10124971
  460. CODESEG
  461. ;***********************************************************************************************
  462. ;* Square_Root -- Finds the square root of the fixed pointer parameter. *
  463. ;* *
  464. ;* INPUT: val -- The fixed point (16:16) value to find the square root of. *
  465. ;* *
  466. ;* OUTPUT: Returns with the square root of the fixed pointer parameter. *
  467. ;* *
  468. ;* WARNINGS: none *
  469. ;* *
  470. ;* HISTORY: *
  471. ;* 10/04/1995 JLB : Adapted. *
  472. ;*=============================================================================================*/
  473. ;unsigned Square_Root(unsigned val);
  474. GLOBAL C Square_Root :NEAR
  475. PROC Square_Root C near
  476. USES ebx,edx
  477. bsr ebx,eax
  478. jz ??zero
  479. mul [DWORD 4*ebx + OFFSET TabA]
  480. shrd eax,edx,10h
  481. add eax, [4*ebx + OFFSET TabB]
  482. ??zero:
  483. ret
  484. ENDP Square_Root
  485. ;----------------------------------------------------------------------------
  486. END