| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- /*
- ** Command & Conquer Red Alert(tm)
- ** Copyright 2025 Electronic Arts Inc.
- **
- ** This program 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.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **
- ** You should have received a copy of the GNU General Public License
- ** along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- /****************************************************************************
- *
- * 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
- * VQA player library (32 bit protected mode)
- *
- * FILE
- * caption.c
- *
- * DESCRIPTION
- * Text caption process/display manager.
- *
- * PROGRAMMER
- * Denzil E. Long, Jr.
- *
- * DATE
- * July 26, 1995
- *
- ****************************************************************************/
- #include <mem.h>
- #include <malloc.h>
- #include <vqm32\font.h>
- #include <vqm32\text.h>
- #include <vqm32\graphics.h>
- #include <vqm32\captoken.h>
- #include "caption.h"
- #if( VQACAPTIONS_ON )
- /*---------------------------------------------------------------------------
- * PRIVATE DECLARATIONS
- *-------------------------------------------------------------------------*/
- #define NUM_NODES 3
- /* Function prototypes. */
- static CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext);
- static void RemCaptionNode(CaptionList *list, CaptionNode *node);
- /****************************************************************************
- *
- * NAME
- * OpenCaptions - Initialize the caption system.
- *
- * SYNOPSIS
- * OpenCaptions(Captions, Font)
- *
- * CaptionInfo *OpenCaptions(void *, void *);
- *
- * FUNCTION
- * Allocate and initialize resources used by the caption system.
- *
- * INPUTS
- * Captions - Captions to process.
- * Font - Font to use to display captions.
- *
- * RESULT
- * CaptionInfo - Caption information structure.
- *
- * SEE ALSO
- * CloseCaption
- *
- ****************************************************************************/
- CaptionInfo *OpenCaptions(void *captions, void *font)
- {
- CaptionInfo *cap = NULL;
- CaptionNode *node;
- FontInfo *fi;
- long i;
- /* Allocate memory for the captioning system. */
- cap = (CaptionInfo *)malloc(sizeof(CaptionInfo) + (sizeof(CaptionNode)
- * NUM_NODES));
- if (cap != NULL) {
- memset(cap,0,(sizeof(CaptionInfo) + (sizeof(CaptionNode) * NUM_NODES)));
- cap->Buffer = captions;
- cap->Next = (CaptionText *)captions;
- /* Initialize font */
- fi = (FontInfo *)((char *)font + ((Font *)font)->InfoBlk);
- cap->Font = font;
- cap->FontHeight = fi->MaxHeight;
- cap->FontWidth = fi->MaxWidth;
- /* Initialize list header. */
- cap->List.Head = (CaptionNode *)&cap->List.Tail;
- cap->List.Tail = NULL;
- cap->List.TailPred = (CaptionNode *)&cap->List.Head;
- /* Link nodes. */
- node = (CaptionNode *)((char *)cap + sizeof(CaptionInfo));
- for (i = 0; i < NUM_NODES; i++) {
- node->Succ = cap->List.Head;
- cap->List.Head = node;
- node->Pred = (CaptionNode *)&cap->List.Head;
- node->Succ->Pred = node;
- /* Next node. */
- node = (CaptionNode *)((char *)node + sizeof(CaptionNode));
- }
- }
- return (cap);
- }
- /****************************************************************************
- *
- * NAME
- * CloseCaptions - Shutdown the caption system.
- *
- * SYNOPSIS
- * CloseCaptions(CaptionInfo)
- *
- * void CloseCaptions(CaptionInfo *);
- *
- * FUNCTION
- * Free the resources allocated by the caption system.
- *
- * INPUTS
- * CaptionInfo - Caption information structure.
- *
- * RESULT
- * NONE
- *
- * SEE ALSO
- * OpenCaptions
- *
- ****************************************************************************/
- void CloseCaptions(CaptionInfo *cap)
- {
- free(cap);
- }
- /****************************************************************************
- *
- * NAME
- * DoCaption - Process and display caption text.
- *
- * SYNOPSIS
- * DoCaption(Captions, Frame)
- *
- * void DoCaption(CaptionInfo *, unsigned long);
- *
- * FUNCTION
- * Process the caption events.
- *
- * INPUTS
- * Captions - Pointer to CaptionInfo structure.
- * Frame - Current frame number being processed.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- void DoCaptions(CaptionInfo *cap, unsigned long frame)
- {
- CaptionText *captext;
- CaptionNode *node;
- void const *oldfont;
- long width;
- long i;
- /* Initialize variables. */
- oldfont = Set_Font((char *)cap->Font);
- /*-------------------------------------------------------------------------
- * Process the captions that are on the active queue.
- *-----------------------------------------------------------------------*/
- node = cap->List.Head;
- while ((node->Succ != NULL) && (node->Flags & CNF_USED)) {
- captext = node->Captext;
- /* Clear the any previous captions that have expired. */
- if (captext->OffFrame <= frame) {
- Fill_Rect(captext->Xpos, captext->Ypos,
- (captext->Xpos + node->BoundW - 1),
- (captext->Ypos + node->BoundH - 1), 0);
- /* Remove the caption from the active list. */
- node = node->Pred;
- RemCaptionNode(&cap->List, node->Succ);
- } else {
- if (captext->CPF != 0) {
- /* If a NULL terminator is not found then display the next set of
- * characters, otherwise remove the node.
- */
- if (*node->Char != 0) {
- Set_Font_Palette_Range(&captext->BgPen, 0, 1);
- for (i = 0; i < captext->CPF; i++) {
- /* Check for terminator. */
- if (*node->Char == 0) {
- captext->CPF = 0;
- break;
- }
- /* Check for newline. */
- else if (*node->Char == 0x0D) {
- node->Char++;
- node->CurX = captext->Xpos;
- node->CurY += cap->FontHeight;
- node->BoundH += cap->FontHeight;
- }
- Draw_Char(*node->Char, node->CurX, node->CurY);
- node->CurX += Char_Pixel_Width(*node->Char);
- node->Char++;
- }
- }
- } else if (captext->Flags & CTF_FLASH) {
- if (frame & 4) {
- Fill_Rect(captext->Xpos, captext->Ypos,
- (captext->Xpos + node->BoundW - 1),
- (captext->Ypos + node->BoundH - 1), 0);
- } else {
- Text_Print(captext->Text, captext->Xpos, captext->Ypos,
- captext->FgPen, captext->BgPen);
- }
- }
- }
- /* Next node. */
- node = node->Succ;
- }
- /*-------------------------------------------------------------------------
- * Process any captions that are waiting to be activated.
- *-----------------------------------------------------------------------*/
- captext = cap->Next;
- while (captext->OnFrame <= frame) {
- width = String_Pixel_Width(captext->Text);
- switch (captext->Flags & CTF_JUSTIFY) {
- case CTF_RIGHT:
- captext->Xpos = (319 - width);
- break;
- case CTF_LEFT:
- captext->Xpos = 0;
- break;
- case CTF_CENTER:
- captext->Xpos = (160 - (width / 2));
- break;
- default:
- break;
- }
- /* Display the text and record its bounding box. */
- if (captext->CPF == 0) {
- i = Text_Print(captext->Text, captext->Xpos, captext->Ypos,
- captext->FgPen, captext->BgPen);
- node = AddCaptionNode(&cap->List, captext);
- node->BoundW = width;
- node->BoundH = (cap->FontHeight * i);
- } else {
- node = AddCaptionNode(&cap->List, captext);
- node->BoundW = width;
- node->BoundH = cap->FontHeight;
- }
- /* Next */
- cap->Next = (CaptionText *)(((char *)captext) + captext->Size);
- captext = cap->Next;
- }
- Set_Font(oldfont);
- }
- /****************************************************************************
- *
- * NAME
- * AddCaptionNode - Add a caption to the processing list.
- *
- * SYNOPSIS
- * Node = AddCaptionNode(List, Caption)
- *
- * CaptionNode *AddCaptionNode(CaptionList *, CaptionText *);
- *
- * FUNCTION
- * Add a caption the caption processing list.
- *
- * INPUTS
- * List - Caption processing list.
- * Caption - Caption to add to the list.
- *
- * RESULT
- * Node - Pointer to node, otherwise NULL if error.
- *
- ****************************************************************************/
- static CaptionNode *AddCaptionNode(CaptionList *list, CaptionText *captext)
- {
- CaptionNode *node = NULL;
- /* If this list is not full. */
- node = list->TailPred;
- if (!(node->Flags & CNF_USED)) {
- /* Remove the node from the tail. */
- node->Pred->Succ = node->Succ;
- list->TailPred = node->Pred;
- node->Flags |= CNF_USED;
- node->Captext = captext;
- node->Char = captext->Text;
- node->CurX = captext->Xpos;
- node->CurY = captext->Ypos;
-
- /* Add the node to the head. */
- node->Succ = list->Head;
- list->Head = node;
- node->Pred = (CaptionNode *)&list->Head;
- node->Succ->Pred = node;
- }
- return (node);
- }
- /****************************************************************************
- *
- * NAME
- * RemCaptionNode - Remove a caption from the processing list.
- *
- * SYNOPSIS
- * RemCaptionNode(List, Node)
- *
- * void RemCaptionNode(CaptionList *, CaptionNode *);
- *
- * FUNCTION
- * Remove the caption from the processing list. Mark the node as unused
- * and put it at the tail of the list.
- *
- * INPUTS
- * List - Caption processing list.
- * Node - Caption node to remove.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- static void RemCaptionNode(CaptionList *list, CaptionNode *node)
- {
- /* If the nodes successor is null then we are at the tail. */
- if (node->Succ != NULL) {
- /* Mark the node as unused. */
- node->Flags = 0;
- /* Relink the node to the tail. */
- node->Succ->Pred = node->Pred;
- node->Pred->Succ = node->Succ;
- node->Succ = (CaptionNode *)&list->Tail;
- node->Pred = list->TailPred;
- list->TailPred->Succ = node;
- list->TailPred = node;
- }
- }
- #endif // VQACAPTIONS_ON
|