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