CnC_Red_Alert/WWFLAT32/PALETTE/PAL.ASM

389 lines
12 KiB
NASM
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;
; 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 ********************************