CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

TXTPRNT.ASM (20537B)


      1 ;
      2 ; Copyright 2020 Electronic Arts Inc.
      3 ;
      4 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is free 
      5 ; software: you can redistribute it and/or modify it under the terms of 
      6 ; the GNU General Public License as published by the Free Software Foundation, 
      7 ; either version 3 of the License, or (at your option) any later version.
      8 
      9 ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed 
     10 ; in the hope that it will be useful, but with permitted additional restrictions 
     11 ; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT 
     12 ; distributed with this program. You should have received a copy of the 
     13 ; GNU General Public License along with permitted additional restrictions 
     14 ; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
     15 
     16 ;***************************************************************************
     17 ;**      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      **
     18 ;***************************************************************************
     19 ;*                                                                         *
     20 ;*                 Project Name : Westwood 32 bit Library                  *
     21 ;*                                                                         *
     22 ;*                    File Name : TXTPRNT.ASM                              *
     23 ;*                                                                         *
     24 ;*                   Programmer : Phil W. Gorrow                           *
     25 ;*                                                                         *
     26 ;*                   Start Date : January 17, 1995                         *
     27 ;*                                                                         *
     28 ;*                  Last Update : January 17, 1995   [PWG]                 *
     29 ;*                                                                         *
     30 ;*-------------------------------------------------------------------------*
     31 ;* Functions:                                                              *
     32 ;*   Buffer_Print -- Assembly text print to a buffer                       *
     33 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
     34 
     35 ;IDEAL
     36 ;P386
     37 ;MODEL USE32 FLAT
     38 .MODEL FLAT
     39 
     40 
     41 ;INCLUDE "mcgaprim.inc"
     42 ;INCLUDE ".\gbuffer.inc"
     43 
     44 externdef C Buffer_Print : NEAR
     45 
     46 GraphicViewPort STRUCT 
     47 GVPOffset		DD		?		; offset to virtual viewport
     48 GVPWidth		DD		?		; width of virtual viewport
     49 GVPHeight		DD		?		; height of virtual viewport
     50 GVPXAdd			DD		?		; x mod to get to next line
     51 GVPXPos			DD		?		; x pos relative to Graphic Buff
     52 GVPYPos			DD		?		; y pos relative to Graphic Buff
     53 GVPPitch		DD		?		; modulo of graphic view port
     54 GVPBuffPtr		DD		?		; ptr to associated Graphic Buff
     55 GraphicViewPort ENDS
     56 
     57 
     58 ;*=========================================================================*
     59 ;* Extern the font pointer which is defined by the font class		   *
     60 ;*=========================================================================*
     61 extern C	FontPtr:DWORD
     62 extern C	FontXSpacing:DWORD
     63 extern C	FontYSpacing:DWORD
     64 externdef C	ColorXlat:byte
     65 
     66 ;*=========================================================================*
     67 ;* Define the necessary equates for structures and bounds checking	   *
     68 ;*=========================================================================*
     69 ; The header of the font file looks like this:
     70 ; 	UWORD	FontLength;		0
     71 ; 	BYTE	FontCompress;		2
     72 ;	BYTE	FontDataBlocks;		3
     73 ;	UWORD	InfoBlockOffset;	4
     74 ;	UWORD	OffsetBlockOffset;	6
     75 ;	UWORD	WidthBlockOffset;	8
     76 ;	UWORD	DataBlockOffset;	10
     77 ;	UWORD	HeightOffset;		12
     78 ; For this reason the following equates have these values:
     79 FONTINFOBLOCK		EQU	4
     80 FONTOFFSETBLOCK		EQU	6
     81 FONTWIDTHBLOCK		EQU	8
     82 FONTDATABLOCK		EQU	10
     83 FONTHEIGHTBLOCK		EQU	12
     84 
     85 FONTINFOMAXHEIGHT	EQU	4
     86 FONTINFOMAXWIDTH	EQU	5
     87 
     88 
     89 ;LOCALS ??
     90 ;*=========================================================================*
     91 ;* Define the color xlate table in the data segment			   *
     92 ;*=========================================================================*
     93 	;DATASEG
     94 	.data
     95 
     96 ColorXlat	DB	00H,01H,02H,03H,04H,05H,06H,07H
     97 		DB	08H,09H,0AH,0BH,0CH,0DH,0EH,0FH
     98 
     99 		DB	01H,00H,00H,00H,00H,00H,00H,00H
    100 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    101 
    102 		DB	02H,00H,00H,00H,00H,00H,00H,00H
    103 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    104 
    105 		DB	03H,00H,00H,00H,00H,00H,00H,00H
    106 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    107 
    108 		DB	04H,00H,00H,00H,00H,00H,00H,00H
    109 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    110 
    111 		DB	05H,00H,00H,00H,00H,00H,00H,00H
    112 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    113 
    114 		DB	06H,00H,00H,00H,00H,00H,00H,00H
    115 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    116 
    117 		DB	07H,00H,00H,00H,00H,00H,00H,00H
    118 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    119 
    120 		DB	08H,00H,00H,00H,00H,00H,00H,00H
    121 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    122 
    123 		DB	09H,00H,00H,00H,00H,00H,00H,00H
    124 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    125 
    126 		DB	0AH,00H,00H,00H,00H,00H,00H,00H
    127 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    128 
    129 		DB	0BH,00H,00H,00H,00H,00H,00H,00H
    130 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    131 
    132 		DB	0CH,00H,00H,00H,00H,00H,00H,00H
    133 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    134 
    135 		DB	0DH,00H,00H,00H,00H,00H,00H,00H
    136 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    137 
    138 		DB	0EH,00H,00H,00H,00H,00H,00H,00H
    139 		DB	00H,00H,00H,00H,00H,00H,00H,00H
    140 
    141 		DB	0FH
    142 
    143 	;CODESEG
    144 	.code
    145 	
    146 
    147 
    148 ;***************************************************************************
    149 ;* Buffer_Print -- Assembly text print to graphic buffer routine           *
    150 ;*                                                                         *
    151 ;*                                                                         *
    152 ;*                                                                         *
    153 ;* INPUT:                                                                  *
    154 ;*                                                                         *
    155 ;* OUTPUT:                                                                 *
    156 ;*                                                                         *
    157 ;* PROTO:                                                                  *
    158 ;*                                                                         *
    159 ;* WARNINGS:                                                               *
    160 ;*                                                                         *
    161 ;* HISTORY:                                                                *
    162 ;*   01/17/1995 PWG : Created.                                             *
    163 ;*=========================================================================*
    164 Buffer_Print proc C public USES ebx ecx edx esi edi this_object:DWORD, string:DWORD, x_pixel:DWORD, y_pixel:DWORD, fcolor:DWORD, bcolor:DWORD
    165 
    166 	;PROC	Buffer_Print C near
    167 	;USES	ebx,ecx,edx,esi,edi
    168 
    169 	;ARG	this_object:DWORD
    170 	;ARG	string:DWORD
    171 	;ARG	x_pixel:DWORD
    172 	;ARG	y_pixel:DWORD
    173 	;ARG	fcolor:DWORD
    174 	;ARG	bcolor:DWORD
    175 
    176 	LOCAL	infoblock:DWORD		; pointer to info block
    177 	LOCAL	offsetblock:DWORD	; pointer to offset block  (UWORD *)
    178 	LOCAL	widthblock:DWORD	; pointer to width block   (BYTE  *)
    179 	LOCAL	heightblock:DWORD	; pointer to height block  (UWORD *)
    180 
    181 	LOCAL	curline:DWORD		; pointer to first column of current row.
    182 	LOCAL	bufferwidth:DWORD    	; width of buffer (vpwidth + Xadd)
    183 	LOCAL	nextdraw:DWORD		; bufferwidth - width of cur character.
    184 	LOCAL	startdraw:DWORD		; where next character will start being drawn.
    185 
    186 	LOCAL	char:DWORD		; current character value.
    187 
    188 	LOCAL	maxheight:BYTE		; max height of characters in font.
    189 	LOCAL	bottomblank:BYTE	; amount of empty space below current character.
    190 	LOCAL	charheight:BYTE		; true height of current character.
    191 	LOCAL	vpwidth:DWORD
    192 	LOCAL	vpheight:DWORD
    193 	LOCAL	original_x:DWORD	; Starting X position.
    194 
    195 
    196 ;-------------------------------- Where to draw -----------------------------------------------
    197 	; Set up memory location to start drawing.
    198 	mov  	ebx,[this_object]			; get a pointer to dest
    199 	mov	eax,[ebx].GraphicViewPort.GVPHeight	; get height of viewport
    200 	mov	[vpheight],eax				; save off height of viewport
    201 	mov	eax,[ebx].GraphicViewPort.GVPWidth	; get width of viewport
    202 	mov	[vpwidth],eax				; save it off for later
    203 	add	eax,[ebx].GraphicViewPort.GVPXAdd	; add in xadd for bytes_per_line
    204 	add	eax,[ebx].GraphicViewPort.GVPPitch	; add in pitch for direct daraw
    205 	mov	[bufferwidth],eax     			; save it off for later use.
    206 
    207 	mul	[y_pixel]				; multiply rowsize * y_pixel start.
    208 	mov	edi,[ebx].GraphicViewPort.GVPOffset	; get start of the viewport
    209 	add	edi,eax					; add y position to start of vp
    210 	mov	[curline],edi				; save 0,y address for line feed stuff.
    211 	add	edi,[x_pixel]				; add to get starting column in starting row.
    212 	mov	[startdraw],edi				; save it off.
    213 
    214 	mov	eax,[x_pixel]
    215 	mov	[original_x],eax
    216 
    217 ;-------------------------------- Create block pointers ----------------------------------------
    218 	; Get the pointer to the font.
    219 	; We could check for NULL but why waste the time.
    220 	; It is up to programmer to make sure it is set.
    221 	mov	esi,[FontPtr]		; Get the font pointer
    222 	or	esi,esi
    223 	jz	overflow
    224 
    225 	; Set up some pointers to the different memory blocks.
    226 	; esi (FontPtr) is added to each to get the true address of each block.
    227 	; Many registers are used for P5 optimizations.
    228 	; ebx is used for InfoBlock which is then used in the next section.
    229 	movzx	eax,WORD PTR [esi+FONTOFFSETBLOCK]	; get offset to offset block
    230 	movzx	ebx,WORD PTR [esi+FONTINFOBLOCK]      	; get offset to info block (must be ebx for height test)
    231 	movzx	ecx,WORD PTR [esi+FONTWIDTHBLOCK] 	; get offset to width block
    232 	movzx	edx,WORD PTR [esi+FONTHEIGHTBLOCK]	; get offset to height block
    233 
    234 	add	eax,esi				; add offset of FontPtr to offset block
    235 	add	ebx,esi				; add offset of FontPtr to info block
    236 	add	ecx,esi				; add offset of FontPtr to width block
    237 	add	edx,esi				; add offset of FontPtr to height block
    238 
    239 	mov	[offsetblock],eax		; save offset to offset block
    240 	mov	[infoblock],ebx			; save offset to info block
    241 	mov	[widthblock],ecx   		; save offset to width block
    242 	mov	[heightblock],edx		; save offset to height block
    243 
    244 ;------------------------------------------ Test for fit ----------------------------------------------
    245 	; Test to make sure the height of the max character will fit on this line
    246 	; and and not fall out of the viewport.
    247 	; remember we set ebx to FONTINFOBLOCK above.
    248 	movzx	eax,BYTE PTR [ebx + FONTINFOMAXHEIGHT]; get the max height in font.
    249 	mov	[maxheight],al			; save it for later use.
    250 	add	eax,[y_pixel]			; add current y_value.
    251 	cmp	eax,[vpheight]			; are we over the edge?
    252 	jg	overflow			; if so, we're outa here.
    253 
    254 	mov	[y_pixel],eax			; save for next line feed. y value for next line.
    255 
    256 	cld					; Make sure we are always forward copying.
    257 
    258 ;------------------------ Set palette foreground and background ----------------------------------
    259 	mov	eax,[fcolor]		; foreground color
    260 	mov	byte ptr [ColorXlat+1],al
    261 	mov	byte ptr [ColorXlat+16],al
    262 
    263 	mov	eax,[bcolor]		; background color
    264 	mov	byte ptr [ColorXlat],al
    265 
    266 ;-------------------------------------------------------------------------------------------------
    267 ;----------------------------------------- Main loop ----------------------------------------------
    268 	; Now we go into the main loop of reading each character in the string and doing
    269 	; something with it.
    270 next_char:
    271 	; while (*string++)
    272 	xor	eax,eax				; zero out since we will just load al.
    273 	mov	esi,[string]			; get address on next character.
    274 	lodsb					; load the character into al.
    275 	test	eax,0FFH			; test to see if character is a NULL
    276 	jz	done				; character is NULL, get outa here.
    277 
    278 	mov	edi,[startdraw]			; Load the starting address.
    279 
    280 	mov	[string],esi			; save index into string. (incremented by lodsb)
    281 
    282 	cmp	al,10				; is the character a line feed?
    283 	je	line_feed			; if so, go to special case.
    284 
    285 	cmp	al,13				; is the character a line feed?
    286 	je	line_feed			; if so, go to special case.
    287 
    288 	mov	[char],eax			; save the character off for later reference.
    289 	mov	ebx,eax				; save it in ebx for later use also.
    290 
    291 	add	eax,[widthblock]		; figure address of width of character.
    292 	mov	ecx,[x_pixel]			; get current x_pixel.
    293 	movzx	edx,BYTE PTR [eax]	 	; get the width of the character in dl.
    294 	add	ecx,edx				; add width of char to current x_pixel.
    295 	mov	eax,[FontXSpacing]
    296 	add	ecx,eax
    297 	add	[startdraw],edx			; save start draw for next character.
    298 	add	[startdraw],eax			; adjust for the font spacing value
    299 
    300 	cmp	ecx,[vpwidth]			; is the pixel greater then the vp width?
    301 	jg	force_line_feed		; if so, force a line feed.
    302 
    303 	mov	[x_pixel],ecx			; save value of start of next character.
    304 	mov	ecx,[bufferwidth]		; get amount to next y same x (one row down)
    305 	sub	ecx,edx				; take the current width off.
    306 	mov	[nextdraw],ecx			; save it to add to edi when done with a row.
    307 
    308 	; At this point we got the character. It is now time to find out specifics
    309 	; about drawing the darn thing.
    310 	; ebx = char so they can be used as an indexes.
    311 	; edx = width of character for loop later.
    312 
    313 	; get offset of data for character into esi.
    314 	shl	ebx,1				; mult by 2 to later use as a WORD index.
    315 	mov	esi,[offsetblock]		; get pointer to begining of offset block.
    316 	add	esi,ebx				; index into offset block.
    317 	movzx	esi,WORD PTR [esi]		; get true offset into data block from FontPtr.
    318 	add	esi,[FontPtr]			; Now add FontPtr address to get true address.
    319 
    320 	; Get top and bottom blank sizes and the true height of the character.
    321 	add	ebx,[heightblock]		; point ebx to element in height array.
    322 	mov	al,[ebx+1]			; load the data height into dl.
    323 	mov	cl,[ebx]			; load the first data row into cl.
    324 	mov	bl,[maxheight]			; get the max height of characters.
    325 	mov	[charheight],al			; get number of rows with data.
    326 	add	al,cl				; add the two heights.
    327 	sub	bl,al				; subract topblank + char height from maxheight.
    328 	mov	[bottomblank],bl		; save off the number of blank rows on the bottom.
    329 	; leaving this section:
    330 	; dl is still the width of the character.
    331 	; cl is the height of the top blank area.
    332 
    333 	mov	ebx,OFFSET ColorXlat		; setup ebx for xlat commands.
    334 	mov	dh,dl				; save the width of the character to restore each loop.
    335 
    336 	cmp	cl,0				; is there any blank rows on top?
    337 	jz	draw_char			; if not go and draw the real character.
    338 
    339 	xor	eax,eax				; get color 0 for background.
    340 	xlat	;[ebx]				; get translated color into al
    341 	test	al,al				; is it transparent black
    342 	jnz	loop_top			; if not go and write the color
    343 
    344 ;----------------------------------------- skip Top blank area ----------------------------------------
    345 	; this case, the top is transparrent, but we need to increase our dest pointer to correct row.
    346 	movzx	eax,cl				; get number of rows into eax;
    347 	mov	ecx,edx				; save width since edx will be destroyed by mul.
    348 	mul	[bufferwidth]			; multiply that by the width of the buffer.
    349 	mov	edx,ecx				; restore the width
    350 	add	edi,eax				; update the pointer.
    351 	jmp	short draw_char		; now go draw the character.
    352 
    353 ;----------------------------------------- fill Top blank area ----------------------------------------
    354 	; edi was set a long time ago.
    355 	; al is the translated color
    356 loop_top:
    357 	stosb					; store the value
    358 	dec	dh				; decrement our width.
    359 	jnz	loop_top			; if more width, continue on.
    360 
    361 	add	edi,[nextdraw]			; add amount for entire row.
    362 
    363 	dec	cl				; decrement or row count
    364 	mov	dh,dl				; restore width in dh for loop.
    365 	jz	draw_char			; we are done here, go draw the character.
    366 	jmp	short loop_top		; go back to top of loop.
    367 
    368 
    369 ;----------------------------------------- Draw character ----------------------------------------------
    370 draw_char:
    371 	movzx	ecx,[charheight]		; get the height of character to count down rows.
    372 	test	ecx,ecx				; is there any data? (blank would not have any)
    373 	jz	next_char			; if no data, go on to next character.
    374 
    375 while_data:
    376 	lodsb					; get byte value from font data
    377 	mov	ah,al				; save hinibble
    378 	and	eax,0F00FH	       		; mask of low nibble in al hi nibble in ah.
    379 	xlat	;[ebx]				; get new color
    380 
    381 	test	al,al				; is it a transparent?
    382 	jz	short skiplo			; skip over write
    383 	mov	[edi],al			; write it out
    384 skiplo:
    385 	inc	edi
    386 	dec	dh				; decrement our width.
    387 	jz	short nextrow			; check if done with width of char
    388 
    389 	mov	al,ah				; restore to get
    390 	; test the time difference between looking up in a large table when shr al,4 is not done as
    391 	; compared to using only a 16 byte table when using the shr al,4
    392 	;shr	al,4				; shift the hi nibble down to low nibble
    393 	xlat	;[ebx]				; get new color
    394 
    395 	test	al,al				; is it a transparent?
    396 	jz	short skiphi			; skip over write
    397 	mov	[edi],al			; write it out
    398 skiphi:
    399 
    400 	inc	edi
    401 	dec	dh				; decrement our width.
    402 	jnz	short while_data		; check if done with width of char
    403 
    404 nextrow:
    405 	add	edi,[nextdraw]			; go to next line.
    406 	dec	ecx				; decrement the number of rows to go
    407 	mov	dh,dl				; restore our column count for row.
    408 	jnz	while_data			; more data for character.
    409 
    410 	; Now it is time to setup for clearing out the bottom of the character.
    411 	movzx	ecx,[bottomblank]		; get amount on bottom that is blank
    412 	cmp	ecx,0				; if there is no blank bottom...
    413 	jz	next_char			; then skip to go to next character
    414 
    415 	xor	eax,eax				; get color 0 for background.
    416 	xlat	;[ebx]				; get translated color into al
    417 	test	al,al				; is it transparent black
    418 	jz	next_char			; skip the top black section to let the background through
    419 
    420 	mov	dh,dl				; restore width in dh for loop.
    421 
    422 ;----------------------------------------- Blank below character -----------------------------------
    423 loop_bottom:
    424 	stosb					; store the value
    425 	dec	dh				; decrement our width.
    426 	jnz	loop_bottom			; if more width, continue on.
    427 
    428 	add	edi,[nextdraw]			; add amount for entire row.
    429 
    430 	mov	dh,dl				; restore width in dh for loop.
    431 	dec	cl				; decrement or row count
    432 	jz	next_char			; we are done here, go to the next character.
    433 	jmp	short loop_bottom		; go back to top of loop.
    434 
    435 ;----------------------------------- end of next_char (main) loop ------------------------------------
    436 ;-------------------------------------------------------------------------------------------------
    437 
    438 
    439 ;----------------------------------- special case line feeds ----------------------------------------
    440 
    441 force_line_feed:
    442 	; decrement pointer *string so that it will be back at same character
    443 	; when it goes through the loop.
    444 	mov	eax,[string]			; get string pointer.
    445 	dec	eax				; decrement it to point to previos char
    446 	mov	[string],eax			; save it back off.
    447 	xor	eax,eax
    448 	; Now go into the line feed code.....
    449 
    450 line_feed:
    451 	mov	bl,al
    452 	mov	edx,[y_pixel]			; get the current y pixel value.
    453 	movzx	ecx,[maxheight]			; get max height for later use.
    454 	add	ecx,[FontYSpacing]
    455 	add	edx,ecx				; add max height to y_pixel
    456 	cmp	edx,[vpheight]			; are we over the edge?
    457 	jg	overflow			; if so, we are outa here.
    458 
    459 	mov	eax,[bufferwidth]      		; get bytes to next line.
    460 	mov	edi,[curline]			; get start of current line.
    461 	mul	ecx				; mult max height * next line.
    462 
    463 	add	edi,eax				; add adjustment to current line.
    464 	add	[y_pixel],ecx			; increment to our next y position.
    465 ;;; DRD
    466 	mov	[curline],edi			; save it off for next line_feed.
    467 
    468 	; Move the cursor to either the left edge of the screen
    469 	; or the left margin of the print position depending
    470 	; on whether <CR> or <LF> was specified. <CR> = left margin
    471 	; <LF> = left edge of screen
    472 	xor	eax,eax
    473 	cmp	bl,10
    474 	je	lfeed
    475 	mov	eax,[original_x]
    476 lfeed:
    477 	mov	[x_pixel],eax			; zero out x_pixel
    478 
    479 	add	edi,eax
    480 ;;; DRD	mov	[curline],edi			; save it off for next line_feed.
    481 	mov	[startdraw],edi			; save it off so we know where to draw next char.w
    482 
    483 	jmp	next_char
    484 
    485 overflow:
    486 	mov	[startdraw],0			; Indicate that there is no valid next pos.
    487 done:
    488 	mov	eax,[startdraw]			; return this so calling routine
    489 	ret					; can figure out where to draw next.
    490 
    491 Buffer_Print endp
    492 
    493 
    494 
    495 ;***************************************************************************
    496 ;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette  *
    497 ;*                                                                         *
    498 ;* INPUT:	none                                                       *
    499 ;*                                                                         *
    500 ;* OUTPUT:      none                                                       *
    501 ;*                                                                         *
    502 ;* PROTO:	void *Get_Font_Palette_Ptr(void);                          *
    503 ;*                                                                         *
    504 ;* HISTORY:								   *
    505 ;*   08/18/1995 PWG : Created.                                             *
    506 ;*=========================================================================*
    507 
    508 Get_Font_Palette_Ptr proc C public
    509 
    510 	;GLOBAL 	C Get_Font_Palette_Ptr:NEAR
    511 
    512 	;PROC	Get_Font_Palette_Ptr C near
    513 
    514 	mov	eax, OFFSET ColorXlat
    515 	ret
    516 
    517 Get_Font_Palette_Ptr endp
    518 
    519 
    520 END