389 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
			
		
		
	
	
			389 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			NASM
		
	
	
	
	
	
| ;
 | ||
| ;	Command & Conquer Red Alert(tm)
 | ||
| ;	Copyright 2025 Electronic Arts Inc.
 | ||
| ;
 | ||
| ;	This program 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.
 | ||
| ;
 | ||
| ;	This program is distributed in the hope that it will be useful,
 | ||
| ;	but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
| ;	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | ||
| ;	GNU General Public License for more details.
 | ||
| ;
 | ||
| ;	You should have received a copy of the GNU General Public License
 | ||
| ;	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | ||
| ;
 | ||
| 
 | ||
| ;***************************************************************************
 | ||
| ;**   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   **
 | ||
| ;***************************************************************************
 | ||
| ;*                                                                         *
 | ||
| ;*                 Project Name : Westwood Library                         *
 | ||
| ;*                                                                         *
 | ||
| ;*                    File Name : PAL.ASM                                  *
 | ||
| ;*                                                                         *
 | ||
| ;*                   Programmer : Joe L. Bostic                            *
 | ||
| ;*                                                                         *
 | ||
| ;*                   Start Date : May 30, 1992                             *
 | ||
| ;*                                                                         *
 | ||
| ;*                  Last Update : April 27, 1994   [BR]                    *
 | ||
| ;*                                                                         *
 | ||
| ;*-------------------------------------------------------------------------*
 | ||
| ;* Functions:                                                              *
 | ||
| ;*   Set_Palette_Range -- Sets changed values in the palette.              *
 | ||
| ;*   Bump_Color -- adjusts specified color in specified palette            *
 | ||
| ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
 | ||
| ;********************** Model & Processor Directives ************************
 | ||
| IDEAL
 | ||
| P386
 | ||
| MODEL USE32 FLAT
 | ||
| 
 | ||
| 
 | ||
| include "keyboard.inc"
 | ||
| 
 | ||
| 
 | ||
| ;****************************** Declarations ********************************
 | ||
| GLOBAL 		Set_Palette_Range:NEAR
 | ||
| GLOBAL 		Bump_Color:NEAR
 | ||
| GLOBAL  	CurrentPalette:BYTE:768
 | ||
| GLOBAL		PaletteTable:byte:1024
 | ||
| 
 | ||
| 
 | ||
| ;********************************** Data ************************************
 | ||
| LOCALS ??
 | ||
| 
 | ||
| 	DATASEG
 | ||
| 
 | ||
| CurrentPalette	DB	768 DUP(255)	; copy of current values of DAC regs
 | ||
| PaletteTable	DB	1024 DUP(0)
 | ||
| 
 | ||
| IFNDEF LIB_EXTERNS_RESOLVED
 | ||
| VertBlank	DW	0		; !!!! this should go away
 | ||
| ENDIF
 | ||
| 
 | ||
| 
 | ||
| ;********************************** Code ************************************
 | ||
| 	CODESEG
 | ||
| 
 | ||
| 
 | ||
| IF 1
 | ||
| ;***************************************************************************
 | ||
| ;* SET_PALETTE_RANGE -- Sets a palette range to the new pal                *
 | ||
| ;*                                                                         *
 | ||
| ;* INPUT:                                                                  *
 | ||
| ;*                                                                         *
 | ||
| ;* OUTPUT:                                                                 *
 | ||
| ;*                                                                         *
 | ||
| ;* PROTO:                                                                  *
 | ||
| ;*                                                                         *
 | ||
| ;* WARNINGS:	This routine is optimized for changing a small number of   *
 | ||
| ;*		colors in the palette.
 | ||
| ;*                                                                         *
 | ||
| ;* HISTORY:                                                                *
 | ||
| ;*   03/07/1995 PWG : Created.                                             *
 | ||
| ;*=========================================================================*
 | ||
| 
 | ||
| 	PROC	Set_Palette_Range C NEAR
 | ||
| 	USES	eax,ebx,ecx,edx,edi,esi
 | ||
| 	ARG	palette:DWORD
 | ||
| 
 | ||
| 	cld
 | ||
| 
 | ||
| 	;*=================================================================*/
 | ||
| 	;* Set up pointers to begin making palette comparison		   */
 | ||
| 	;*=================================================================*/
 | ||
| 	mov	esi, [palette]
 | ||
| 	mov	edi, OFFSET CurrentPalette
 | ||
| 	mov	ebx, OFFSET PaletteTable
 | ||
| 	mov	ecx, 0
 | ||
| 
 | ||
| ??loop_top:
 | ||
| 	mov	eax,[esi]			; read a dword from palette source
 | ||
| 	mov	edx,[edi]			; read a dword from compare palette
 | ||
| 	and	eax,00FFFFFFh			; palette entrys are only 3 bytes
 | ||
| 	and	edx,00FFFFFFh			;   long so and of extra
 | ||
| 	cmp	eax,edx				; if they are not the same then
 | ||
| 	jne	??set_table			;   add them into the table
 | ||
| 	add	esi,3
 | ||
| 	add	edi,3
 | ||
| 	inc	cl				; adjust to next palette entry
 | ||
| 	jnz	??loop_top			; if we dont wrap to zero we have more
 | ||
| 	jmp	??set_pal			; so now go set the palette
 | ||
| ??set_table:	
 | ||
| 	shl	eax,8				; shift bgr value up register
 | ||
| 	mov	al,cl				; store which palette entry num
 | ||
| 	mov	[ebx],eax
 | ||
| 	add	ebx,4
 | ||
| 	movsw					; copy the three gun values into
 | ||
| 	movsb					;  the shadow palette.  Use movsb
 | ||
| 	inc	cl				; adjust to next palette entry
 | ||
| 	jnz	??loop_top			; if we dont wrap to zero we have more
 | ||
| 
 | ||
| ??set_pal:
 | ||
| 	mov	esi,ebx
 | ||
| 	mov	ebx,OFFSET PaletteTable
 | ||
| 	sub	esi,ebx				; if ebx didn't change there
 | ||
| 	jz	??exit				;   is nothing to set
 | ||
| 	shr	esi,2				; find how many entrys
 | ||
| 
 | ||
| 	mov	eax,[ebx]
 | ||
| 
 | ||
| 	movzx	ecx,al				; we are currently on entry 0
 | ||
| 	add	ebx,4
 | ||
| 
 | ||
| 	; Tell DAC of the color gun to start setting.
 | ||
| 	mov	edx,03C8h
 | ||
| 	out	dx,al		; First color set.
 | ||
| 
 | ||
| 	; Set the colors only during a VSync.
 | ||
| 	mov	edx,03DAh	; CRTC register.
 | ||
| 
 | ||
| 	push	ebx
 | ||
| 	mov	bx,[VertBlank]
 | ||
| 	and	bl,001h
 | ||
| 	shl	bl,3
 | ||
| 
 | ||
| ??in_vbi:
 | ||
| 	in	al,dx				; read CRTC status
 | ||
| 	and	al,008h				; only vertical sync bit
 | ||
| 	xor	al,bl
 | ||
| 	je	??in_vbi			; in vertical sync
 | ||
| 
 | ||
| ??out_vbi:
 | ||
| 	in	al,dx				; read CRTC status
 | ||
| 	and	al,008h				; only vertical sync bit
 | ||
| 	xor	al,bl
 | ||
| 	jne	??out_vbi			; not in vertical sync
 | ||
| 	pop	ebx
 | ||
| 	; Update the DAC data register.
 | ||
| 	mov	dx,03C9h
 | ||
| 
 | ||
| ;**************** Time Critical Section Start ******************
 | ||
| 	cli
 | ||
| ??loop:
 | ||
| 	shr	eax,8		; shift down the red gun value
 | ||
| 	out	dx,al		; write it to the video card
 | ||
| 	jmp	$ + 2		; force cache to flush, to create a time
 | ||
| 	shr	eax,8		; shift down the blue gun value
 | ||
| 	out	dx,al		; write it to the video card
 | ||
| 	jmp	$ + 2		; force cache to flush, to create a time
 | ||
| 	shr	eax,8		; shift down the blue gun value
 | ||
| 	out	dx,al		; write the green value to video card
 | ||
| 	jmp	$ + 2		; force cache to flush, to create a time
 | ||
| 	inc	ecx		; move edx to next palette entry
 | ||
| 
 | ||
| 	mov	eax,[ebx]	; get next value to set
 | ||
| 	add	ebx,4		;  and post increment the palette value
 | ||
| 	cmp	al,cl		; check if DAC position already correct
 | ||
| 	je	??correct_pos
 | ||
| 
 | ||
| 	mov	edx,03C8h	; Tell DAC of the color gun to start setting.
 | ||
| 	out	dx,al		; First color set.
 | ||
| 	mov	dx,03C9h
 | ||
| 
 | ||
| ??correct_pos:
 | ||
| 	dec	esi
 | ||
| 	jnz	??loop
 | ||
| 	sti
 | ||
| ;***************** Time Critical Section End *******************
 | ||
| ??exit:
 | ||
| 	ret
 | ||
| 
 | ||
| 	ENDP	Set_Palette_Range
 | ||
| ELSE
 | ||
| ;***************************************************************************
 | ||
| ;* Set_Palette_Range -- Sets changed values in the palette.                *
 | ||
| ;*                                                                         *
 | ||
| ;* INPUT: 								   *
 | ||
| ;*	VOID *palette - pointer to the new palette.                        *
 | ||
| ;*                                                                         *
 | ||
| ;* OUTPUT:                                                                 *
 | ||
| ;*	none								   *
 | ||
| ;*                                                                         *
 | ||
| ;* WARNINGS:                                                               *
 | ||
| ;*                                                                         *
 | ||
| ;* HISTORY:                                                                *
 | ||
| ;*   04/25/1994 SKB : Created.                                             *
 | ||
| ;*   04/27/1994 BR : Converted to 32-bit                                   *
 | ||
| ;*=========================================================================*
 | ||
| ; VOID cdecl Set_Palette_Range(VOID *palette);
 | ||
| 	PROC Set_Palette_Range	C NEAR
 | ||
| 	USES eax,ebx,ecx,edx,edi,esi
 | ||
| 	ARG	palette:DWORD
 | ||
| 	LOCAL	remain:DWORD	; 32-bit: converted to LONG
 | ||
| 
 | ||
| 	cld
 | ||
| 
 | ||
| 	mov	bx,[VertBlank]
 | ||
| 	and	bl,001h
 | ||
| 	shl	bl,3
 | ||
| 
 | ||
| 	; Make a copy of the palette passed in.
 | ||
| 	mov	edi,OFFSET CurrentPalette
 | ||
| 	mov	esi,[palette]
 | ||
| 	mov	[remain],768
 | ||
| 
 | ||
| 	; Search for differences between the current palette and the
 | ||
| 	; new palette.  When a difference is found, output a block
 | ||
| 	; of color registers and keep scanning.
 | ||
| ??bodyloop:
 | ||
| 	mov	ecx,[remain]
 | ||
| 
 | ||
| 	repe	cmpsb		; Search for differences.
 | ||
| 	je	short ??exit
 | ||
| 	dec	esi
 | ||
| 	dec	edi
 | ||
| 	inc	ecx
 | ||
| 
 | ||
| 	mov	edx,0		; clear EDX
 | ||
| 	mov	eax,ecx
 | ||
| 	mov	ecx,3
 | ||
| 	div	ecx		; EAX = # of colors to set, EDX = Fraction.
 | ||
| 	or	edx,edx
 | ||
| 	jz	short ??nofrac
 | ||
| 	neg	edx
 | ||
| 	add	edx,3		; Back offset skip needed.
 | ||
| 	inc	eax		; Fractional color rounds up to whole color to set.
 | ||
| ??nofrac:
 | ||
| 
 | ||
| 	; Set CX to be the number of color guns to set.
 | ||
| 	mov	ecx,eax		; Colors * 3 bytes per color.
 | ||
| 	add	ecx,eax
 | ||
| 	add	ecx,eax
 | ||
| 
 | ||
| 	; Chop this DAC dump short if necessary in order to reduce
 | ||
| 	; sparkling.
 | ||
| 	mov	[remain],0
 | ||
| 	cmp	ecx,86*3	; Number of color guns to set per vert retrace
 | ||
| 	jbe	short ??ok
 | ||
| 	sub	ecx,86*3
 | ||
| 	mov	[remain],ecx
 | ||
| 	mov	ecx,86*3
 | ||
| ??ok:
 | ||
| 
 | ||
| 	; Adjust the palette offsets back to point to the RED color gun.
 | ||
| 	sub	esi,edx
 | ||
| 	sub	edi,edx
 | ||
| 
 | ||
| 	; Determine the color number to start setting.
 | ||
| 	neg	eax
 | ||
| 	add	eax,256		; AX = Color to start setting (0..255).
 | ||
| 
 | ||
| 	; Tell DAC of the color gun to start setting.
 | ||
| 	mov	edx,03C8h
 | ||
| 	out	dx,al		; First color set.
 | ||
| 
 | ||
| 	; Set the colors only during a VSync.
 | ||
| 	mov	edx,03DAh	; CRTC register.
 | ||
| 
 | ||
| ??in_vbi:
 | ||
| 	in	al,dx		; read CRTC status
 | ||
| 	and	al,008h		; only vertical sync bit
 | ||
| 	xor	al,bl
 | ||
| 	je	??in_vbi	; in vertical sync
 | ||
| 
 | ||
| ??out_vbi:
 | ||
| 	in	al,dx		; read CRTC status
 | ||
| 	and	al,008h		; only vertical sync bit
 | ||
| 	xor	al,bl
 | ||
| 	jne	??out_vbi	; not in vertical sync
 | ||
| 
 | ||
| ;??wait:
 | ||
| ;	in	al,dx
 | ||
| ;	test	al,01000b
 | ||
| ;	jnz	??wait
 | ||
| 
 | ||
| ;??retrace:
 | ||
| ;	in	al,dx
 | ||
| ;	test	al,01000b
 | ||
| ;	jz	??retrace
 | ||
| 
 | ||
| 	; Update the DAC data register.
 | ||
| 	mov	dx,03C9h
 | ||
| 
 | ||
| ;**************** Time Critical Section Start ******************
 | ||
| 	pushf
 | ||
| 	cli
 | ||
| ??loop:
 | ||
| 	lodsb
 | ||
| 	stosb
 | ||
| 	out	dx,al
 | ||
| 	jmp	$ + 2		; force cache to flush, to create a time
 | ||
| 				;  delay to give DAC time to get value
 | ||
| 	loop	??loop
 | ||
| 	popf
 | ||
| ;***************** Time Critical Section End *******************
 | ||
| 
 | ||
| 	cmp	[remain],0
 | ||
| 	jnz	??bodyloop
 | ||
| 
 | ||
| ??exit:
 | ||
| 	ret
 | ||
| 
 | ||
| 	ENDP	Set_Palette_Range
 | ||
| ENDIF
 | ||
| 
 | ||
| 
 | ||
| ;***************************************************************************
 | ||
| ;* Bump_Color -- adjusts specified color in specified palette              *
 | ||
| ;*                                                                         *
 | ||
| ;* INPUT:                                                                  *
 | ||
| ;*	VOID *palette	- palette to modify				   *
 | ||
| ;*	WORD changable	- color # to change				   *
 | ||
| ;*	WORD target	- color to bend toward				   *
 | ||
| ;*                                                                         *
 | ||
| ;* OUTPUT:                                                                 *
 | ||
| ;*                                                                         *
 | ||
| ;* WARNINGS:                                                               *
 | ||
| ;*                                                                         *
 | ||
| ;* HISTORY:                                                                *
 | ||
| ;*   04/27/1994 BR : Converted to 32-bit.                                  *
 | ||
| ;*=========================================================================*
 | ||
| ; BOOL cdecl Bump_Color(VOID *palette, WORD changable, WORD target);
 | ||
| PROC Bump_Color C NEAR 
 | ||
| 	USES ebx,ecx,edi,esi
 | ||
| 	ARG	pal:DWORD, color:WORD, desired:WORD
 | ||
| 	LOCAL	changed:WORD		; Has palette changed?
 | ||
| 
 | ||
| 	mov	edi,[pal]		; Original palette pointer.
 | ||
| 	mov	esi,edi
 | ||
| 	mov	eax,0
 | ||
| 	mov	ax,[color]
 | ||
| 	add	edi,eax
 | ||
| 	add	edi,eax
 | ||
| 	add	edi,eax			; Offset to changable color.
 | ||
| 	mov	ax,[desired]
 | ||
| 	add	esi,eax
 | ||
| 	add	esi,eax
 | ||
| 	add	esi,eax			; Offset to target color.
 | ||
| 
 | ||
| 	mov	[changed],FALSE		; Presume no change.
 | ||
| 	mov	ecx,3			; Three color guns.
 | ||
| 
 | ||
| 	; Check the color gun.
 | ||
| ??colorloop:
 | ||
| 	mov	al,[BYTE PTR esi]
 | ||
| 	sub	al,[BYTE PTR edi]	; Carry flag is set if subtraction needed.
 | ||
| 	jz	short ??gotit
 | ||
| 	mov	[changed],TRUE
 | ||
| 	inc	[BYTE PTR edi]		; Presume addition.
 | ||
| 	jnc	short ??gotit		; oops, subtraction needed so dec twice.
 | ||
| 	dec	[BYTE PTR edi]
 | ||
| 	dec	[BYTE PTR edi]
 | ||
| ??gotit:
 | ||
| 	inc	edi
 | ||
| 	inc	esi
 | ||
| 	loop	??colorloop
 | ||
| 
 | ||
| 	mov	ax,[changed]
 | ||
| 	ret
 | ||
| 
 | ||
| 	ENDP	Bump_Color
 | ||
| 
 | ||
| 	END
 | ||
| 
 | ||
| ;*************************** End of pal.asm ********************************
 | ||
| 
 | 
