CAPTION.CPP 9.8 KB

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