TXTPRNT.ASM 20 KB

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