CnC_Remastered_Collection

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

2TXTPRNT.ASM (20581B)


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