CnC_Remastered_Collection/REDALERT/SUPPORT.ASM

557 lines
18 KiB
NASM

;
; Copyright 2020 Electronic Arts Inc.
;
; TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
; in the hope that it will be useful, but with permitted additional restrictions
; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
; distributed with this program. You should have received a copy of the
; GNU General Public License along with permitted additional restrictions
; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
; $Header: F:\projects\c&c0\vcs\code\support.asv 5.0 11 Nov 1996 09:40:30 JOE_BOSTIC $
;***************************************************************************
;** 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 **
;***************************************************************************
;* *
;* Project Name : Command & Conquer *
;* *
;* File Name : SUPPORT.ASM *
;* *
;* Programmer : Joe L. Bostic *
;* *
;* Start Date : September 23, 1993 *
;* *
;* Last Update : May 10, 1994 [JLB] *
;* *
;*-------------------------------------------------------------------------*
;* Functions: *
;* strtrim -- Remove the trailing white space from a string. *
;* Fat_Put_Pixel -- Draws a fat pixel. *
;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table.*
;* Remove_From_List -- Removes a pointer from a list of pointers. *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
IDEAL
P386
MODEL USE32 FLAT
INCLUDE "gbuffer.inc"
DISPLAY "Command & Conquer assembly support routines."
CODESEG
;***************************************************************************
;* Fat_Put_Pixel -- Draws a fat pixel. *
;* *
;* Use this routine to draw a "pixel" that is bigger than 1 pixel *
;* across. This routine is faster than drawing a similar small shape *
;* and faster than calling Fill_Rect. *
;* *
;* INPUT: x,y -- Screen coordinates to draw the pixel's upper *
;* left corner. *
;* *
;* color -- The color to render the pixel in. *
;* *
;* size -- The number of pixels width of the big "pixel". *
;* *
;* page -- The pointer to a GraphicBuffer class or something *
;* *
;* OUTPUT: none *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 03/17/1994 JLB : Created. *
;*=========================================================================*
; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page)
GLOBAL C Fat_Put_Pixel:NEAR
PROC Fat_Put_Pixel C near
USES eax, ebx, ecx, edx, edi, esi
ARG x:DWORD ; X coordinate of upper left pixel corner.
ARG y:DWORD ; Y coordinate of upper left pixel corner.
ARG color:DWORD ; Color to use for the "pixel".
ARG siz:DWORD ; Size of "pixel" to plot (square).
ARG gpage:DWORD ; graphic page address to plot onto
cmp [siz],0
je short ??exit
; Set EDI to point to start of logical page memory.
;*===================================================================
; Get the viewport information and put bytes per row in ecx
;*===================================================================
mov ebx,[gpage] ; get a pointer to viewport
mov edi,[(GraphicViewPort ebx).GVPOffset] ; get the correct offset
; Verify the the Y pixel offset is legal.
mov eax,[y]
cmp eax,[(GraphicViewPort ebx).GVPHeight] ;YPIXEL_MAX
jae short ??exit
mul [(GraphicViewPort ebx).GVPWidth]
add edi,eax
; Verify the the X pixel offset is legal.
mov edx,[(GraphicViewPort ebx).GVPWidth]
cmp edx,[x]
jbe short ??exit
add edi,[x]
; Write the pixel to the screen.
mov ebx,[siz] ; Copy of pixel size.
sub edx,ebx ; Modulo to reach start of next row.
mov eax,[color]
??again:
mov ecx,ebx
rep stosb
add edi,edx ; EDI points to start of next row.
dec [siz]
jnz short ??again
??exit:
ret
ENDP Fat_Put_Pixel
if 0
;***************************************************************************
;* strtrim -- Remove the trailing white space from a string. *
;* *
;* Use this routine to remove white space characters from the beginning *
;* and end of the string. The string is modified in place by *
;* this routine. *
;* *
;* INPUT: buffer -- Pointer to the string to modify. *
;* *
;* OUTPUT: none *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 10/07/1992 JLB : Created. *
;*=========================================================================*
; VOID cdecl strtrim(BYTE *buffer);
GLOBAL C strtrim :NEAR
PROC strtrim C near
USES ax, edi, esi
ARG buffer:DWORD ; Pointer to string to modify.
cmp [buffer],0
je short ??fini
; Prepare for string scanning by loading pointers.
cld
mov esi,[buffer]
mov edi,esi
; Strip white space from the start of the string.
??looper:
lodsb
cmp al,20h ; Space
je short ??looper
cmp al,9 ; TAB
je short ??looper
stosb
; Copy the rest of the string.
??gruntloop:
lodsb
stosb
or al,al
jnz short ??gruntloop
dec edi
; Strip the white space from the end of the string.
??looper2:
mov [edi],al
dec edi
mov ah,[edi]
cmp ah,20h
je short ??looper2
cmp ah,9
je short ??looper2
??fini:
ret
ENDP strtrim
;***************************************************************************
;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table. *
;* *
;* This routine is used to build a special fading table for C&C. There *
;* are certain colors that get faded to and cannot be faded again. *
;* With this rule, it is possible to draw a shadow multiple times and *
;* not have it get any lighter or darker. *
;* *
;* INPUT: palette -- Pointer to the 768 byte IBM palette to build from. *
;* *
;* dest -- Pointer to the 256 byte remap table. *
;* *
;* color -- Color index of the color to "fade to". *
;* *
;* frac -- The fraction to fade to the specified color *
;* *
;* OUTPUT: Returns with pointer to the remap table. *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 10/07/1992 JLB : Created. *
;*=========================================================================*/
;VOID * cdecl Conquer_Build_Fading_Table(VOID *palette, VOID *dest, long color, long frac);
GLOBAL C Conquer_Build_Fading_Table : NEAR
PROC Conquer_Build_Fading_Table C near
USES ebx, ecx, edi, esi
ARG palette:DWORD
ARG dest:DWORD
ARG color:DWORD
ARG frac:DWORD
LOCAL matchvalue:DWORD ; Last recorded match value.
LOCAL targetred:BYTE ; Target gun red.
LOCAL targetgreen:BYTE ; Target gun green.
LOCAL targetblue:BYTE ; Target gun blue.
LOCAL idealred:BYTE
LOCAL idealgreen:BYTE
LOCAL idealblue:BYTE
LOCAL matchcolor:BYTE ; Tentative match color.
ALLOWED_COUNT EQU 16
ALLOWED_START EQU 256-ALLOWED_COUNT
cld
; If the source palette is NULL, then just return with current fading table pointer.
cmp [palette],0
je ??fini1
cmp [dest],0
je ??fini1
; Fractions above 255 become 255.
mov eax,[frac]
cmp eax,0100h
jb short ??ok
mov [frac],0FFh
??ok:
; Record the target gun values.
mov esi,[palette]
mov ebx,[color]
add esi,ebx
add esi,ebx
add esi,ebx
lodsb
mov [targetred],al
lodsb
mov [targetgreen],al
lodsb
mov [targetblue],al
; Main loop.
xor ebx,ebx ; Remap table index.
; Transparent black never gets remapped.
mov edi,[dest]
mov [edi],bl
inc edi
; EBX = source palette logical number (1..255).
; EDI = running pointer into dest remap table.
??mainloop:
inc ebx
mov esi,[palette]
add esi,ebx
add esi,ebx
add esi,ebx
mov edx,[frac]
shr edx,1
; new = orig - ((orig-target) * fraction);
lodsb ; orig
mov dh,al ; preserve it for later.
sub al,[targetred] ; al = (orig-target)
imul dl ; ax = (orig-target)*fraction
shl eax,1
sub dh,ah ; dh = orig - ((orig-target) * fraction)
mov [idealred],dh ; preserve ideal color gun value.
lodsb ; orig
mov dh,al ; preserve it for later.
sub al,[targetgreen] ; al = (orig-target)
imul dl ; ax = (orig-target)*fraction
shl eax,1
sub dh,ah ; dh = orig - ((orig-target) * fraction)
mov [idealgreen],dh ; preserve ideal color gun value.
lodsb ; orig
mov dh,al ; preserve it for later.
sub al,[targetblue] ; al = (orig-target)
imul dl ; ax = (orig-target)*fraction
shl eax,1
sub dh,ah ; dh = orig - ((orig-target) * fraction)
mov [idealblue],dh ; preserve ideal color gun value.
; Sweep through a limited set of existing colors to find the closest
; matching color.
mov eax,[color]
mov [matchcolor],al ; Default color (self).
mov [matchvalue],-1 ; Ridiculous match value init.
mov ecx,ALLOWED_COUNT
mov esi,[palette] ; Pointer to original palette.
add esi,(ALLOWED_START)*3
; BH = color index.
mov bh,ALLOWED_START
??innerloop:
xor edx,edx ; Comparison value starts null.
; Build the comparison value based on the sum of the differences of the color
; guns squared.
lodsb
sub al,[idealred]
mov ah,al
imul ah
add edx,eax
lodsb
sub al,[idealgreen]
mov ah,al
imul ah
add edx,eax
lodsb
sub al,[idealblue]
mov ah,al
imul ah
add edx,eax
jz short ??perfect ; If perfect match found then quit early.
cmp edx,[matchvalue]
jae short ??notclose
mov [matchvalue],edx ; Record new possible color.
mov [matchcolor],bh
??notclose:
inc bh ; Checking color index.
loop ??innerloop
mov bh,[matchcolor]
??perfect:
mov [matchcolor],bh
xor bh,bh ; Make BX valid main index again.
; When the loop exits, we have found the closest match.
mov al,[matchcolor]
stosb
cmp ebx,ALLOWED_START-1
jne ??mainloop
; Fill the remainder of the remap table with values
; that will remap the color to itself.
mov ecx,ALLOWED_COUNT
??fillerloop:
inc bl
mov al,bl
stosb
loop ??fillerloop
??fini1:
mov esi,[dest]
mov eax,esi
ret
ENDP Conquer_Build_Fading_Table
;***************************************************************************
;* Remove_From_List -- Removes a pointer from a list of pointers. *
;* *
;* This low level routine is used to remove a pointer from a list of *
;* pointers. The trailing pointers are moved downward to fill the *
;* hole. *
;* *
;* INPUT: list -- Pointer to list of pointer. *
;* *
;* index -- Pointer to length of pointer list. *
;* *
;* ptr -- The pointer value to search for and remove. *
;* *
;* OUTPUT: none *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 04/11/1994 JLB : Created. *
;* 04/22/1994 JLB : Convert to assembly language. *
;* 05/10/1994 JLB : Short pointers now. *
;*=========================================================================*/
;VOID cdecl Remove_From_List(VOID **list, long *index, long ptr);
GLOBAL C Remove_From_List:NEAR
PROC Remove_From_List C near
USES edi, esi, ecx, eax
ARG list:DWORD ; Pointer to list.
ARG index:DWORD ; Pointer to count.
ARG element:DWORD ; Element to remove.
; Fetch the number of elements in the list. If there are no
; elements, then just exit quickly.
mov edi,[index]
mov ecx,[edi]
jcxz short ??fini2
; Fetch pointer to list.
cmp [list],0
je short ??fini2
mov edi,[list]
; Loop through all elements searching for a match.
mov eax,[element]
repne scasd
jne short ??fini2 ; No match found.
; Copy all remaining elements down. If this is the
; last element in the list then nothing needs to be
; copied -- just decrement the list size.
jcxz short ??nocopy ; No copy necessary.
mov esi,edi
sub edi,4
rep movsd
; Reduce the list count by one.
??nocopy:
mov edi,[index]
dec [DWORD PTR edi]
??fini2:
ret
ENDP Remove_From_List
; long cdecl Get_EAX();
GLOBAL C Get_EAX :NEAR
PROC Get_EAX C near
ret
ENDP Get_EAX
endif
DATASEG
TabA DD 6949350
DD 4913933
DD 3474675
DD 2456966
DD 1737338
DD 1228483
DD 868669
DD 614242
DD 434334
DD 307121
DD 217167
DD 153560
DD 108584
DD 76780
DD 54292
DD 38390
DD 27146
DD 19195
DD 13573
DD 9598
DD 6786
DD 4799
DD 3393
DD 2399
DD 1697
DD 1200
DD 848
DD 600
DD 424
DD 300
DD 212
DD 150
DD 106
TabB DD 154
DD 218
DD 309
DD 437
DD 618
DD 874
DD 1236
DD 1748
DD 2472
DD 3496
DD 4944
DD 6992
DD 9888
DD 13983
DD 19775
DD 27967
DD 39551
DD 55933
DD 79101
DD 111866
DD 158203
DD 223732
DD 316405
DD 447465
DD 632811
DD 894929
DD 1265621
DD 1789859
DD 2531243
DD 3579718
DD 5062486
DD 7159436
DD 10124971
CODESEG
;***********************************************************************************************
;* Square_Root -- Finds the square root of the fixed pointer parameter. *
;* *
;* INPUT: val -- The fixed point (16:16) value to find the square root of. *
;* *
;* OUTPUT: Returns with the square root of the fixed pointer parameter. *
;* *
;* WARNINGS: none *
;* *
;* HISTORY: *
;* 10/04/1995 JLB : Adapted. *
;*=============================================================================================*/
;unsigned Square_Root(unsigned val);
GLOBAL C Square_Root :NEAR
PROC Square_Root C near
USES ebx,edx
bsr ebx,eax
jz ??zero
mul [DWORD 4*ebx + OFFSET TabA]
shrd eax,edx,10h
add eax, [4*ebx + OFFSET TabB]
??zero:
ret
ENDP Square_Root
;----------------------------------------------------------------------------
END