| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504 |
- ;
- ; Copyright 2020 Electronic Arts Inc.
- ;
- ; TiberianDawn.DLL and RedAlert.dll and corresponding source code 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.
- ; TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
- ; in the hope that it will be useful, but with permitted additional restrictions
- ; under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
- ; distributed with this program. You should have received a copy of the
- ; GNU General Public License along with permitted additional restrictions
- ; with this program. If not, see [https://github.com/electronicarts/CnC_Remastered_Collection]>.
- ;***************************************************************************
- ;** 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 32 bit Library *
- ;* *
- ;* File Name : TXTPRNT.ASM *
- ;* *
- ;* Programmer : Phil W. Gorrow *
- ;* *
- ;* Start Date : January 17, 1995 *
- ;* *
- ;* Last Update : January 17, 1995 [PWG] *
- ;* *
- ;*-------------------------------------------------------------------------*
- ;* Functions: *
- ;* MCGA_Print -- Assembly MCGA text print routine *
- ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - *
- IDEAL
- P386
- MODEL USE32 FLAT
- ;INCLUDE "mcgaprim.inc"
- ;INCLUDE ".\gbuffer.inc"
- GLOBAL C Buffer_Print : NEAR
- STRUC GraphicViewPort
- GVPOffset DD ? ; offset to virtual viewport
- GVPWidth DD ? ; width of virtual viewport
- GVPHeight DD ? ; height of virtual viewport
- GVPXAdd DD ? ; x mod to get to next line
- GVPXPos DD ? ; x pos relative to Graphic Buff
- GVPYPos DD ? ; y pos relative to Graphic Buff
- GVPPitch dd ? ; modulo of graphic view port
- GVPBuffPtr DD ? ; ptr to associated Graphic Buff
- ENDS
- ;*=========================================================================*
- ;* Extern the font pointer which is defined by the font class *
- ;*=========================================================================*
- GLOBAL C FontPtr:DWORD
- GLOBAL C FontXSpacing:DWORD
- GLOBAL C FontYSpacing:DWORD
- GLOBAL C ColorXlat:BYTE
- ;*=========================================================================*
- ;* Define the necessary equates for structures and bounds checking *
- ;*=========================================================================*
- ; The header of the font file looks like this:
- ; UWORD FontLength; 0
- ; BYTE FontCompress; 2
- ; BYTE FontDataBlocks; 3
- ; UWORD InfoBlockOffset; 4
- ; UWORD OffsetBlockOffset; 6
- ; UWORD WidthBlockOffset; 8
- ; UWORD DataBlockOffset; 10
- ; UWORD HeightOffset; 12
- ; For this reason the following equates have these values:
- FONTINFOBLOCK EQU 4
- FONTOFFSETBLOCK EQU 6
- FONTWIDTHBLOCK EQU 8
- FONTDATABLOCK EQU 10
- FONTHEIGHTBLOCK EQU 12
- FONTINFOMAXHEIGHT EQU 4
- FONTINFOMAXWIDTH EQU 5
- LOCALS ??
- ;*=========================================================================*
- ;* Define the color xlate table in the data segment *
- ;*=========================================================================*
- 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
- CODESEG
- ;***************************************************************************
- ;* MCGA_PRINT -- Assembly MCGA text print routine *
- ;* *
- ;* *
- ;* *
- ;* INPUT: *
- ;* *
- ;* OUTPUT: *
- ;* *
- ;* PROTO: *
- ;* *
- ;* WARNINGS: *
- ;* *
- ;* HISTORY: *
- ;* 01/17/1995 PWG : Created. *
- ;*=========================================================================*
- PROC Buffer_Print C near
- USES ebx,ecx,edx,esi,edi
- ARG this:DWORD
- ARG string:DWORD
- ARG x_pixel:DWORD
- ARG y_pixel:DWORD
- ARG fcolor:DWORD
- ARG bcolor:DWORD
- LOCAL infoblock:DWORD ; pointer to info block
- LOCAL offsetblock:DWORD ; pointer to offset block (UWORD *)
- LOCAL widthblock:DWORD ; pointer to width block (BYTE *)
- LOCAL heightblock:DWORD ; pointer to height block (UWORD *)
- LOCAL curline:DWORD ; pointer to first column of current row.
- LOCAL bufferwidth:DWORD ; width of buffer (vpwidth + Xadd)
- LOCAL nextdraw:DWORD ; bufferwidth - width of cur character.
- LOCAL startdraw:DWORD ; where next character will start being drawn.
- LOCAL char:DWORD ; current character value.
- LOCAL maxheight:BYTE ; max height of characters in font.
- LOCAL bottomblank:BYTE ; amount of empty space below current character.
- LOCAL charheight:BYTE ; true height of current character.
- LOCAL vpwidth:DWORD
- LOCAL vpheight:DWORD
- LOCAL original_x:DWORD ; Starting X position.
- ;-------------------------------- Where to draw -----------------------------------------------
- ; Set up memory location to start drawing.
- mov ebx,[this] ; get a pointer to dest
- mov eax,[(GraphicViewPort ebx).GVPHeight] ; get height of viewport
- mov [vpheight],eax ; save off height of viewport
- mov eax,[(GraphicViewPort ebx).GVPWidth] ; get width of viewport
- mov [vpwidth],eax ; save it off for later
- add eax,[(GraphicViewPort ebx).GVPXAdd] ; add in xadd for bytes_per_line
- add eax,[(GraphicViewPort ebx).GVPPitch] ; add in pitch of direct draw surface
- mov [bufferwidth],eax ; save it off for later use.
- mul [y_pixel] ; multiply rowsize * y_pixel start.
- mov edi,[(GraphicViewPort ebx).GVPOffset] ; get start of the viewport
- add edi,eax ; add y position to start of vp
- mov [curline],edi ; save 0,y address for line feed stuff.
- add edi,[x_pixel] ; add to get starting column in starting row.
- mov [startdraw],edi ; save it off.
- mov eax,[x_pixel]
- mov [original_x],eax
- ;-------------------------------- Create block pointers ----------------------------------------
- ; Get the pointer to the font.
- ; We could check for NULL but why waste the time.
- ; It is up to programmer to make sure it is set.
- mov esi,[FontPtr] ; Get the font pointer
- or esi,esi
- jz ??overflow
- ; Set up some pointers to the different memory blocks.
- ; esi (FontPtr) is added to each to get the true address of each block.
- ; Many registers are used for P5 optimizations.
- ; ebx is used for InfoBlock which is then used in the next section.
- movzx eax,[WORD PTR esi+FONTOFFSETBLOCK] ; get offset to offset block
- movzx ebx,[WORD PTR esi+FONTINFOBLOCK] ; get offset to info block (must be ebx for height test)
- movzx ecx,[WORD PTR esi+FONTWIDTHBLOCK] ; get offset to width block
- movzx edx,[WORD PTR esi+FONTHEIGHTBLOCK] ; get offset to height block
- add eax,esi ; add offset of FontPtr to offset block
- add ebx,esi ; add offset of FontPtr to info block
- add ecx,esi ; add offset of FontPtr to width block
- add edx,esi ; add offset of FontPtr to height block
- mov [offsetblock],eax ; save offset to offset block
- mov [infoblock],ebx ; save offset to info block
- mov [widthblock],ecx ; save offset to width block
- mov [heightblock],edx ; save offset to height block
- ;------------------------------------------ Test for fit ----------------------------------------------
- ; Test to make sure the height of the max character will fit on this line
- ; and and not fall out of the viewport.
- ; remember we set ebx to FONTINFOBLOCK above.
- movzx eax,[BYTE PTR ebx + FONTINFOMAXHEIGHT]; get the max height in font.
- mov [maxheight],al ; save it for later use.
- add eax,[y_pixel] ; add current y_value.
- cmp eax,[vpheight] ; are we over the edge?
- jg ??overflow ; if so, we're outa here.
- mov [y_pixel],eax ; save for next line feed. y value for next line.
- cld ; Make sure we are always forward copying.
- ;------------------------ Set palette foreground and background ----------------------------------
- mov eax,[fcolor] ; foreground color
- mov [ColorXlat+1],al
- mov [ColorXlat+16],al
- mov eax,[bcolor] ; background color
- mov [ColorXlat],al
- ;-------------------------------------------------------------------------------------------------
- ;----------------------------------------- Main loop ----------------------------------------------
- ; Now we go into the main loop of reading each character in the string and doing
- ; something with it.
- ??next_char:
- ; while (*string++)
- xor eax,eax ; zero out since we will just load al.
- mov esi,[string] ; get address on next character.
- lodsb ; load the character into al.
- test eax,0FFH ; test to see if character is a NULL
- jz ??done ; character is NULL, get outa here.
- mov edi,[startdraw] ; Load the starting address.
- mov [string],esi ; save index into string. (incremented by lodsb)
- cmp al,10 ; is the character a line feed?
- je ??line_feed ; if so, go to special case.
- cmp al,13 ; is the character a line feed?
- je ??line_feed ; if so, go to special case.
- mov [char],eax ; save the character off for later reference.
- mov ebx,eax ; save it in ebx for later use also.
- add eax,[widthblock] ; figure address of width of character.
- mov ecx,[x_pixel] ; get current x_pixel.
- movzx edx,[BYTE PTR eax] ; get the width of the character in dl.
- add ecx,edx ; add width of char to current x_pixel.
- mov eax,[FontXSpacing]
- add ecx,eax
- add [startdraw],edx ; save start draw for next character.
- add [startdraw],eax ; adjust for the font spacing value
- cmp ecx,[vpwidth] ; is the pixel greater then the vp width?
- jg ??force_line_feed ; if so, force a line feed.
- mov [x_pixel],ecx ; save value of start of next character.
- mov ecx,[bufferwidth] ; get amount to next y same x (one row down)
- sub ecx,edx ; take the current width off.
- mov [nextdraw],ecx ; save it to add to edi when done with a row.
- ; At this point we got the character. It is now time to find out specifics
- ; about drawing the darn thing.
- ; ebx = char so they can be used as an indexes.
- ; edx = width of character for loop later.
- ; get offset of data for character into esi.
- shl ebx,1 ; mult by 2 to later use as a WORD index.
- mov esi,[offsetblock] ; get pointer to begining of offset block.
- add esi,ebx ; index into offset block.
- movzx esi,[WORD PTR esi] ; get true offset into data block from FontPtr.
- add esi,[FontPtr] ; Now add FontPtr address to get true address.
- ; Get top and bottom blank sizes and the true height of the character.
- add ebx,[heightblock] ; point ebx to element in height array.
- mov al,[ebx+1] ; load the data height into dl.
- mov cl,[ebx] ; load the first data row into cl.
- mov bl,[maxheight] ; get the max height of characters.
- mov [charheight],al ; get number of rows with data.
- add al,cl ; add the two heights.
- sub bl,al ; subract topblank + char height from maxheight.
- mov [bottomblank],bl ; save off the number of blank rows on the bottom.
- ; leaving this section:
- ; dl is still the width of the character.
- ; cl is the height of the top blank area.
- mov ebx,OFFSET ColorXlat ; setup ebx for xlat commands.
- mov dh,dl ; save the width of the character to restore each loop.
- cmp cl,0 ; is there any blank rows on top?
- jz ??draw_char ; if not go and draw the real character.
- xor eax,eax ; get color 0 for background.
- xlat [ebx] ; get translated color into al
- test al,al ; is it transparent black
- jnz ??loop_top ; if not go and write the color
- ;----------------------------------------- skip Top blank area ----------------------------------------
- ; this case, the top is transparrent, but we need to increase our dest pointer to correct row.
- movzx eax,cl ; get number of rows into eax;
- mov ecx,edx ; save width since edx will be destroyed by mul.
- mul [bufferwidth] ; multiply that by the width of the buffer.
- mov edx,ecx ; restore the width
- add edi,eax ; update the pointer.
- jmp short ??draw_char ; now go draw the character.
- ;----------------------------------------- fill Top blank area ----------------------------------------
- ; edi was set a long time ago.
- ; al is the translated color
- ??loop_top:
- stosb ; store the value
- dec dh ; decrement our width.
- jnz ??loop_top ; if more width, continue on.
- add edi,[nextdraw] ; add amount for entire row.
- dec cl ; decrement or row count
- mov dh,dl ; restore width in dh for loop.
- jz ??draw_char ; we are done here, go draw the character.
- jmp short ??loop_top ; go back to top of loop.
- ;----------------------------------------- Draw character ----------------------------------------------
- ??draw_char:
- movzx ecx,[charheight] ; get the height of character to count down rows.
- test ecx,ecx ; is there any data? (blank would not have any)
- jz ??next_char ; if no data, go on to next character.
- ??while_data:
- lodsb ; get byte value from font data
- mov ah,al ; save hinibble
- and eax,0F00FH ; mask of low nibble in al hi nibble in ah.
- xlat [ebx] ; get new color
- test al,al ; is it a transparent?
- jz short ??skiplo ; skip over write
- mov [es:edi],al ; write it out
- ??skiplo:
- inc edi
- dec dh ; decrement our width.
- jz short ??nextrow ; check if done with width of char
- mov al,ah ; restore to get
- ; test the time difference between looking up in a large table when shr al,4 is not done as
- ; compared to using only a 16 byte table when using the shr al,4
- ;shr al,4 ; shift the hi nibble down to low nibble
- xlat [ebx] ; get new color
- test al,al ; is it a transparent?
- jz short ??skiphi ; skip over write
- mov [es:edi],al ; write it out
- ??skiphi:
- inc edi
- dec dh ; decrement our width.
- jnz short ??while_data ; check if done with width of char
- ??nextrow:
- add edi,[nextdraw] ; go to next line.
- dec ecx ; decrement the number of rows to go
- mov dh,dl ; restore our column count for row.
- jnz ??while_data ; more data for character.
- ; Now it is time to setup for clearing out the bottom of the character.
- movzx ecx,[bottomblank] ; get amount on bottom that is blank
- cmp ecx,0 ; if there is no blank bottom...
- jz ??next_char ; then skip to go to next character
- xor eax,eax ; get color 0 for background.
- xlat [ebx] ; get translated color into al
- test al,al ; is it transparent black
- jz ??next_char ; skip the top black section to let the background through
- mov dh,dl ; restore width in dh for loop.
- ;----------------------------------------- Blank below character -----------------------------------
- ??loop_bottom:
- stosb ; store the value
- dec dh ; decrement our width.
- jnz ??loop_bottom ; if more width, continue on.
- add edi,[nextdraw] ; add amount for entire row.
- mov dh,dl ; restore width in dh for loop.
- dec cl ; decrement or row count
- jz ??next_char ; we are done here, go to the next character.
- jmp short ??loop_bottom ; go back to top of loop.
- ;----------------------------------- end of next_char (main) loop ------------------------------------
- ;-------------------------------------------------------------------------------------------------
- ;----------------------------------- special case line feeds ----------------------------------------
- ??force_line_feed:
- ; decrement pointer *string so that it will be back at same character
- ; when it goes through the loop.
- mov eax,[string] ; get string pointer.
- dec eax ; decrement it to point to previos char
- mov [string],eax ; save it back off.
- xor eax,eax
- ; Now go into the line feed code.....
- ??line_feed:
- mov bl,al
- mov edx,[y_pixel] ; get the current y pixel value.
- movzx ecx,[maxheight] ; get max height for later use.
- add ecx,[FontYSpacing]
- add edx,ecx ; add max height to y_pixel
- cmp edx,[vpheight] ; are we over the edge?
- jg ??overflow ; if so, we are outa here.
- mov eax,[bufferwidth] ; get bytes to next line.
- mov edi,[curline] ; get start of current line.
- mul ecx ; mult max height * next line.
- add edi,eax ; add adjustment to current line.
- add [y_pixel],ecx ; increment to our next y position.
- ;;; DRD
- mov [curline],edi ; save it off for next line_feed.
- ; Move the cursor to either the left edge of the screen
- ; or the left margin of the print position depending
- ; on whether <CR> or <LF> was specified. <CR> = left margin
- ; <LF> = left edge of screen
- xor eax,eax
- cmp bl,10
- je ??lfeed
- mov eax,[original_x]
- ??lfeed:
- mov [x_pixel],eax ; zero out x_pixel
- add edi,eax
- ;;; DRD mov [curline],edi ; save it off for next line_feed.
- mov [startdraw],edi ; save it off so we know where to draw next char.w
- jmp ??next_char
- ??overflow:
- mov [startdraw],0 ; Indicate that there is no valid next pos.
- ??done:
- mov eax,[startdraw] ; return this so calling routine
- ret ; can figure out where to draw next.
- ENDP Buffer_Print
- ;***************************************************************************
- ;* GET_FONT_PALETTE_PTR -- Returns a pointer to the 256 byte font palette *
- ;* *
- ;* INPUT: none *
- ;* *
- ;* OUTPUT: none *
- ;* *
- ;* PROTO: void *Get_Font_Palette_Ptr(void); *
- ;* *
- ;* HISTORY: *
- ;* 08/18/1995 PWG : Created. *
- ;*=========================================================================*
- GLOBAL C Get_Font_Palette_Ptr:NEAR
- PROC Get_Font_Palette_Ptr C near
- mov eax, OFFSET ColorXlat
- ret
- ENDP Get_Font_Palette_Ptr
- END
|