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