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