CAPTION.CPP 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. /*
  2. ** Command & Conquer Red Alert(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. *
  20. * 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
  21. *
  22. *----------------------------------------------------------------------------
  23. *
  24. * PROJECT
  25. * VQA player library (32 bit protected mode)
  26. *
  27. * FILE
  28. * caption.c
  29. *
  30. * DESCRIPTION
  31. * Text caption process/display manager.
  32. *
  33. * PROGRAMMER
  34. * Denzil E. Long, Jr.
  35. *
  36. * DATE
  37. * July 26, 1995
  38. *
  39. ****************************************************************************/
  40. #include <mem.h>
  41. #include <malloc.h>
  42. #include <vqm32\font.h>
  43. #include <vqm32\text.h>
  44. #include <vqm32\graphics.h>
  45. #include <vqm32\captoken.h>
  46. #include "caption.h"
  47. /*---------------------------------------------------------------------------
  48. * PRIVATE DECLARATIONS
  49. *-------------------------------------------------------------------------*/
  50. #define NUM_NODES 3
  51. /* Function prototypes. */
  52. static CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext);
  53. static void RemCaptionNode(CaptionList *list, CaptionNode *node);
  54. /****************************************************************************
  55. *
  56. * NAME
  57. * OpenCaptions - Initialize the caption system.
  58. *
  59. * SYNOPSIS
  60. * OpenCaptions(Captions, Font)
  61. *
  62. * CaptionInfo *OpenCaptions(void *, void *);
  63. *
  64. * FUNCTION
  65. * Allocate and initialize resources used by the caption system.
  66. *
  67. * INPUTS
  68. * Captions - Captions to process.
  69. * Font - Font to use to display captions.
  70. *
  71. * RESULT
  72. * CaptionInfo - Caption information structure.
  73. *
  74. * SEE ALSO
  75. * CloseCaption
  76. *
  77. ****************************************************************************/
  78. CaptionInfo *OpenCaptions(void *captions, void *font)
  79. {
  80. CaptionInfo *cap = NULL;
  81. CaptionNode *node;
  82. FontInfo *fi;
  83. long i;
  84. /* Allocate memory for the captioning system. */
  85. cap = (CaptionInfo *)malloc(sizeof(CaptionInfo) + (sizeof(CaptionNode)
  86. * NUM_NODES));
  87. if (cap != NULL) {
  88. memset(cap,0,(sizeof(CaptionInfo) + (sizeof(CaptionNode) * NUM_NODES)));
  89. cap->Buffer = captions;
  90. cap->Next = (CaptionText *)captions;
  91. /* Initialize font */
  92. fi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);
  93. cap->Font = font;
  94. cap->FontHeight = fi->MaxHeight;
  95. cap->FontWidth = fi->MaxWidth;
  96. /* Initialize list header. */
  97. cap->List.Head = (CaptionNode *)&cap->List.Tail;
  98. cap->List.Tail = NULL;
  99. cap->List.TailPred = (CaptionNode *)&cap->List.Head;
  100. /* Link nodes. */
  101. node = (CaptionNode *)((char *)cap + sizeof(CaptionInfo));
  102. for (i = 0; i < NUM_NODES; i++) {
  103. node->Succ = cap->List.Head;
  104. cap->List.Head = node;
  105. node->Pred = (CaptionNode *)&cap->List.Head;
  106. node->Succ->Pred = node;
  107. /* Next node. */
  108. node = (CaptionNode *)((char *)node + sizeof(CaptionNode));
  109. }
  110. }
  111. return (cap);
  112. }
  113. /****************************************************************************
  114. *
  115. * NAME
  116. * CloseCaptions - Shutdown the caption system.
  117. *
  118. * SYNOPSIS
  119. * CloseCaptions(CaptionInfo)
  120. *
  121. * void CloseCaptions(CaptionInfo *);
  122. *
  123. * FUNCTION
  124. * Free the resources allocated by the caption system.
  125. *
  126. * INPUTS
  127. * CaptionInfo - Caption information structure.
  128. *
  129. * RESULT
  130. * NONE
  131. *
  132. * SEE ALSO
  133. * OpenCaptions
  134. *
  135. ****************************************************************************/
  136. void CloseCaptions(CaptionInfo *cap)
  137. {
  138. free(cap);
  139. }
  140. /****************************************************************************
  141. *
  142. * NAME
  143. * DoCaption - Process and display caption text.
  144. *
  145. * SYNOPSIS
  146. * DoCaption(Captions, Frame)
  147. *
  148. * void DoCaption(CaptionInfo *, unsigned long);
  149. *
  150. * FUNCTION
  151. * Process the caption events.
  152. *
  153. * INPUTS
  154. * Captions - Pointer to CaptionInfo structure.
  155. * Frame - Current frame number being processed.
  156. *
  157. * RESULT
  158. * NONE
  159. *
  160. ****************************************************************************/
  161. void DoCaptions(CaptionInfo *cap, unsigned long frame)
  162. {
  163. CaptionText *captext;
  164. CaptionNode *node;
  165. void const *oldfont;
  166. long width;
  167. long i;
  168. /* Initialize variables. */
  169. oldfont = Set_Font((char *)cap->Font);
  170. /*-------------------------------------------------------------------------
  171. * Process the captions that are on the active queue.
  172. *-----------------------------------------------------------------------*/
  173. node = cap->List.Head;
  174. while ((node->Succ != NULL) && (node->Flags & CNF_USED)) {
  175. captext = node->Captext;
  176. /* Clear the any previous captions that have expired. */
  177. if (captext->OffFrame <= frame) {
  178. Fill_Rect(captext->Xpos, captext->Ypos,
  179. (captext->Xpos + node->BoundW - 1),
  180. (captext->Ypos + node->BoundH - 1), 0);
  181. /* Remove the caption from the active list. */
  182. node = node->Pred;
  183. RemCaptionNode(&cap->List, node->Succ);
  184. } else {
  185. if (captext->CPF != 0) {
  186. /* If a NULL terminator is not found then display the next set of
  187. * characters, otherwise remove the node.
  188. */
  189. if (*node->Char != 0) {
  190. Set_Font_Palette_Range(&captext->BgPen, 0, 1);
  191. for (i = 0; i < captext->CPF; i++) {
  192. /* Check for terminator. */
  193. if (*node->Char == 0) {
  194. captext->CPF = 0;
  195. break;
  196. }
  197. /* Check for newline. */
  198. else if (*node->Char == 0x0D) {
  199. node->Char++;
  200. node->CurX = captext->Xpos;
  201. node->CurY += cap->FontHeight;
  202. node->BoundH += cap->FontHeight;
  203. }
  204. Draw_Char(*node->Char, node->CurX, node->CurY);
  205. node->CurX += Char_Pixel_Width(*node->Char);
  206. node->Char++;
  207. }
  208. }
  209. } else if (captext->Flags & CTF_FLASH) {
  210. if (frame & 4) {
  211. Fill_Rect(captext->Xpos, captext->Ypos,
  212. (captext->Xpos + node->BoundW - 1),
  213. (captext->Ypos + node->BoundH - 1), 0);
  214. } else {
  215. Text_Print(captext->Text, captext->Xpos, captext->Ypos,
  216. captext->FgPen, captext->BgPen);
  217. }
  218. }
  219. }
  220. /* Next node. */
  221. node = node->Succ;
  222. }
  223. /*-------------------------------------------------------------------------
  224. * Process any captions that are waiting to be activated.
  225. *-----------------------------------------------------------------------*/
  226. captext = cap->Next;
  227. while (captext->OnFrame <= frame) {
  228. width = String_Pixel_Width(captext->Text);
  229. switch (captext->Flags & CTF_JUSTIFY) {
  230. case CTF_RIGHT:
  231. captext->Xpos = (319 - width);
  232. break;
  233. case CTF_LEFT:
  234. captext->Xpos = 0;
  235. break;
  236. case CTF_CENTER:
  237. captext->Xpos = (160 - (width / 2));
  238. break;
  239. default:
  240. break;
  241. }
  242. /* Display the text and record its bounding box. */
  243. if (captext->CPF == 0) {
  244. i = Text_Print(captext->Text, captext->Xpos, captext->Ypos,
  245. captext->FgPen, captext->BgPen);
  246. node = AddCaptionNode(&cap->List, captext);
  247. node->BoundW = width;
  248. node->BoundH = (cap->FontHeight * i);
  249. } else {
  250. node = AddCaptionNode(&cap->List, captext);
  251. node->BoundW = width;
  252. node->BoundH = cap->FontHeight;
  253. }
  254. /* Next */
  255. cap->Next = (CaptionText *)(((char *)captext) + captext->Size);
  256. captext = cap->Next;
  257. }
  258. Set_Font(oldfont);
  259. }
  260. /****************************************************************************
  261. *
  262. * NAME
  263. * AddCaptionNode - Add a caption to the processing list.
  264. *
  265. * SYNOPSIS
  266. * Node = AddCaptionNode(List, Caption)
  267. *
  268. * CaptionNode *AddCaptionNode(CaptionList *, CaptionText *);
  269. *
  270. * FUNCTION
  271. * Add a caption the caption processing list.
  272. *
  273. * INPUTS
  274. * List - Caption processing list.
  275. * Caption - Caption to add to the list.
  276. *
  277. * RESULT
  278. * Node - Pointer to node, otherwise NULL if error.
  279. *
  280. ****************************************************************************/
  281. static CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext)
  282. {
  283. CaptionNode *node = NULL;
  284. /* If this list is not full. */
  285. node = list->TailPred;
  286. if (!(node->Flags & CNF_USED)) {
  287. /* Remove the node from the tail. */
  288. node->Pred->Succ = node->Succ;
  289. list->TailPred = node->Pred;
  290. node->Flags |= CNF_USED;
  291. node->Captext = captext;
  292. node->Char = captext->Text;
  293. node->CurX = captext->Xpos;
  294. node->CurY = captext->Ypos;
  295. /* Add the node to the head. */
  296. node->Succ = list->Head;
  297. list->Head = node;
  298. node->Pred = (CaptionNode *)&list->Head;
  299. node->Succ->Pred = node;
  300. }
  301. return (node);
  302. }
  303. /****************************************************************************
  304. *
  305. * NAME
  306. * RemCaptionNode - Remove a caption from the processing list.
  307. *
  308. * SYNOPSIS
  309. * RemCaptionNode(List, Node)
  310. *
  311. * void RemCaptionNode(CaptionList *, CaptionNode *);
  312. *
  313. * FUNCTION
  314. * Remove the caption from the processing list. Mark the node as unused
  315. * and put it at the tail of the list.
  316. *
  317. * INPUTS
  318. * List - Caption processing list.
  319. * Node - Caption node to remove.
  320. *
  321. * RESULT
  322. * NONE
  323. *
  324. ****************************************************************************/
  325. static void RemCaptionNode(CaptionList *list, CaptionNode *node)
  326. {
  327. /* If the nodes successor is null then we are at the tail. */
  328. if (node->Succ != NULL) {
  329. /* Mark the node as unused. */
  330. node->Flags = 0;
  331. /* Relink the node to the tail. */
  332. node->Succ->Pred = node->Pred;
  333. node->Pred->Succ = node->Succ;
  334. node->Succ = (CaptionNode *)&list->Tail;
  335. node->Pred = list->TailPred;
  336. list->TailPred->Succ = node;
  337. list->TailPred = node;
  338. }
  339. }