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