;
;	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/>.
;

; $Header:   U:\vq\projects\vqm32\drawchar.asv   1.1   08 May 1995 10:48:32   DENZIL_LONG  $
;***************************************************************************
;**   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 : Westwood Library                         *
;*                                                                         *
;*                    File Name : DRAWCHAR.ASM                             *
;*                                                                         *
;*                   Programmer : Joe L. Bostic                            *
;*                                                                         *
;*                   Start Date : August 20, 1993                          *
;*                                                                         *
;*                  Last Update : August 20, 1993   [JLB]                  *
;*                                                                         *
;*-------------------------------------------------------------------------*
;* Functions:                                                              *
;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *

	IDEAL
	P386
	MODEL	USE32 FLAT
	LOCALS	??
	CODESEG

XPIXEL_MAX		EQU	320
YPIXEL_MAX		EQU	200

FONTINFOBLOCK		EQU	4
FONTOFFSETBLOCK	EQU	6
FONTWIDTHBLOCK	EQU	8
FONTDATABLOCK		EQU	10
FONTHEIGHTBLOCK	EQU	12

FONTINFOMAXHEIGHT	EQU	4
FONTINFOMAXWIDTH	EQU	5

	EXTRN	C FontPtr:NEAR PTR

;***********************************************************
; DRAW_CHAR
;
; VOID Draw_Char(BYTE fontchar, WORD x_pixel, WORD y_pixel);
;
; Draws a character to the screen only if given coordinates that will allow
; the entire character to be drawn on the screen else will exit.
; 
; NOTE: This is a routine called by Text_Print.
;
;*
	GLOBAL	C Draw_Char:NEAR
	PROC	Draw_Char C NEAR USES eax ebx ecx edx esi edi 
	ARG	fontchar:DWORD
	ARG	x_pixel:DWORD
	ARG	y_pixel:DWORD

	LOCAL	infoblock:DWORD
	LOCAL	offsetblock:DWORD
	LOCAL	widthblock:DWORD
	LOCAL	heightblock:DWORD
	LOCAL	fwidth:DWORD
	LOCAL	nextline:DWORD
	LOCAL	startv:BYTE
	LOCAL	dheight:BYTE
	LOCAL	wheight:BYTE

	mov	esi,[FontPtr]

	; Set up some working local variables.

	xor	eax,eax
	mov	ax,[esi+FONTINFOBLOCK]	; get offset to info block
	mov	[infoblock],eax		; save offset to info block
	mov	ax,[esi+FONTOFFSETBLOCK]	; get offset to offset block
	mov	[offsetblock],eax		; save offset to offset block
	mov	ax,[esi+FONTWIDTHBLOCK]	; get offset to width block
	mov	[widthblock],eax		; save offset to width block
	mov	ax,[esi+FONTHEIGHTBLOCK]	; get offset to height block
	mov	[heightblock],eax		; save offset to height block

	; Fetch character data offset -- if NULL then undefined character.

	mov	ebx,[fontchar]
	and	ebx,0FFh
	shl	ebx,1		; make word index
	add	ebx,[offsetblock]	; add offset to offset block
	xor	ecx,ecx
	mov	cx,[esi+ebx]		; load offset to font data
	or	ecx,ecx
	jz	??exit		; is this character a null? if so exit

	; If the character is off the left/right edge of the screen then abort.

	mov	edx,[x_pixel]
	cmp	edx,XPIXEL_MAX
	jae	??exit

	; If the character is off the top/bottom edge of the screen then abort.

	mov	ebx,[fontchar]		; get char
	and	ebx,0FFh
	add	ebx,[widthblock]	; add offset to width block
	xor	eax,eax
	mov	al,[esi+ebx]		; get width for character
	mov	[fwidth],eax		; save char width
	add	eax,edx		; ax = char len + x
	cmp	eax,XPIXEL_MAX
	ja	??exit

	mov	edi,edx		; save xpos in di

	mov	edx,[y_pixel]
	cmp	edx,YPIXEL_MAX
	jae	??exit

	mov	ebx,[infoblock]	; get offset to offset block
	xor	eax,eax
				; get font max height from info block
	mov	al,[esi+ebx+FONTINFOMAXHEIGHT]
	mov	[wheight],al		; save max height of character
	add	eax,edx		; add height to y pos
	cmp	eax,YPIXEL_MAX		; will it go off the bottom
	ja	??exit

??vdraw:
	mov	ebx,[fontchar]		; get char
	and	ebx,0FFh
	shl	ebx,1		; make 2 byte index
	add	ebx,[heightblock]	; add offset to height block
	mov	ah,[esi+ebx]		; get start vertical for character
	mov	[startv],ah		; save start vertical for later
	mov	al,[esi+ebx+1]		; get data height for character
	mov	[dheight],al		; save data height for later
	add	ah,al		; add background and data
	sub	[wheight],ah		; remaining background height

	add	esi,ecx		; add font offset to font data

	push	edx
	mov	eax,XPIXEL_MAX
	mul	edx
	add	edi,eax
	pop	edx

	mov	eax,XPIXEL_MAX
	sub	eax,[fwidth]
	mov	[nextline],eax		; ?? to add to index for the nextline

	add	edi,0A0000h
	mov	ebx,OFFSET ColorXlat	; setup up bx for xlat commands
	xor	ecx,ecx
	mov	cl,[startv]		; number of scan lines that are
				; background color
	or	ecx,ecx		; if starting vertical is zero
	je	short ??skiplead	; skip drawing top background lines

	mov	al,0
	xlat	[ebx]		; get background color

	or	al,al		; check for none zero color
	jne	short ??lheight	; update background color

	push	edx
	mov	eax,XPIXEL_MAX
	mul	ecx
	add	edi,eax
	pop	edx

	mov	ebx,OFFSET ColorXlat	; restore bx for xlat commands
	jmp	SHORT ??skiplead

??lheight:
	mov	edx,[fwidth]		; width of char

??lwidth:
	stosb			; write out line of pixels for width
	dec	edx
	jne	??lwidth

??lnext:
	add	edi,[nextline]		; goto next line at the start of char
	loop	??lheight		; any more lines

??skiplead:
	mov	cl,[dheight]		; number of scan lines that are data
	or	ecx,ecx		; is there any data to be drawn
	je	short ??exit

??vheight:
	mov	edx,[fwidth]		; width of char

??vwidth:
	lodsb				; get byte value from font data
	mov	ah,al			; save hinibble
	and	al,00FH			; get lonibble
	xlat	[ebx]			; get new color
	or	al,al
	je	short ??chklowidth		; skip color zero

	mov	[edi],al		; write out pixel of lonibble

??chklowidth:
	inc	edi
	dec	edx
	je	short ??vnext			; check if done with width of char

	mov	al,ah			; get byte value
	and	al,0F0H			; get hinibble
	xlat	[ebx]			; get new color
	or	al,al
	je	short ??chkhiwidth		; skip color zero

	mov	[edi],al		; write out pixel of hinibble

??chkhiwidth:
	inc	edi
	dec	edx
	jne	??vwidth		; check if done with width of char

??vnext:
	add	edi,[nextline]		; next line at start of char
	loop	??vheight		; any more lines


??trail:
	mov	cl,[wheight]		; remaining height of background color
	or	ecx,ecx			; if trailing height is zero
	jle	short ??exit			; skip drawing bottom background lines

	mov	al,0
	xlat	[ebx]			; get background color
	or	al,al			; check for color zero
	je	short ??exit			; skip drawing

??theight:
	mov	edx,[fwidth]		; width of char

??twidth:
	stosb				; write out line of pixels for width
	dec	edx
	jne	??twidth

??tnext:
	add	edi,[nextline]		; next line at start of char
	loop	??theight		; any more lines


??exit:
	ret

	ENDP	Draw_Char

;***********************************************************


;***********************************************************
; SET_FONT_PALETTE_RANGE
;
; VOID Set_Font_Palette_Range(VOID *palette, WORD start, WORD end);
;
; This routine changes the local Draw_Char color translation table
; with the color numbers in palette.
;
; Bounds Checking: forces start and end to a range of 0-15
;*
	GLOBAL	C Set_Font_Palette_Range:NEAR
	PROC	Set_Font_Palette_Range C NEAR USES eax ebx ecx edi esi
	ARG	palette:NEAR PTR
	ARG	start:DWORD
	ARG	endval:DWORD

	cld
	mov	esi,[palette]
	mov	ebx,[start]
	and	ebx,0FH			; value 0-15

	mov	ecx,[endval]
	and	ecx,0FH			; value 0-15

	cmp	ecx,ebx			; if end < start then exit
	jl	short ??exit

	sub	ecx,ebx			; number of colors = end - start + 1
	inc	ecx

	mov	edi,OFFSET ColorXlat	; get start of xlat table
	add	edi,ebx			; add starting offset
	shl	ebx,4			; multiply start offset by 16
	add	ebx,OFFSET ColorXlat	; add start of xlat table

; updates 0-15 for lonibble xlat
; updates 0,16,32,...,240 for hinibble xlat

??setpal:
	lodsb				; get color number
	stosb				; save color number for lonibble xlat
	mov	[ebx],al		; save color number for hinibble xlat
	add	ebx,010H			; add 16 to index for hinibble offset
	loop	??setpal

??exit:
	ret

	ENDP	Set_Font_Palette_Range

;***********************************************************


;***********************************************************
; DRAW_CHAR_SETUP
;
; VOID Draw_Char_Setup(VOID);
;
; This routine sets up code segment variables for Draw_Char.
; 
; NOTE: This is a routine called by Set_Font.
;
;*
	GLOBAL	C Draw_Char_Setup:NEAR
	PROC	Draw_Char_Setup C NEAR

	ret

	ENDP	Draw_Char_Setup

	DATASEG

ColorXlat	DB	000H,001H,002H,003H,004H,005H,006H,007H
	DB	008H,009H,00AH,00BH,00CH,00DH,00EH,00FH

	DB	001H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	002H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	003H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	004H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	005H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	006H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	007H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	008H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	009H,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	00AH,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	00BH,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	00CH,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	00DH,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	00EH,000H,000H,000H,000H,000H,000H,000H
	DB	000H,000H,000H,000H,000H,000H,000H,000H

	DB	00FH

;***********************************************************
	END

