CnC_Red_Alert/WWFLAT32/PALETTE/PAL.ASM

389 lines
12 KiB
NASM
Raw Permalink Normal View History

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