| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458 |
- /*
- ** 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
- *
- *----------------------------------------------------------------------------
- *
- * FILE
- * captoken.c
- *
- * DESCRIPTION
- * Tokenize a caption script for playback processing.
- *
- * PROGRAMMER
- * Denzil E. Long, Jr.
- *
- * DATE
- * July 26, 1995
- *
- ****************************************************************************/
- #include <stdlib.h>
- #include <stdio.h>
- #include <errno.h>
- #include <string.h>
- #include <ctype.h>
- #include "captoken.h"
- /*---------------------------------------------------------------------------
- * PRIVATE DECLARATIONS
- *-------------------------------------------------------------------------*/
- #define STRING_LENGTH 256
- #define PADSIZE(size) (((size)+1)&(~1))
- typedef enum {
- TOKEN_NULL = 0,
- TOKEN_BGCOL,
- TOKEN_FGCOL,
- TOKEN_XPOS,
- TOKEN_YPOS,
- TOKEN_ABS,
- TOKEN_LEFT,
- TOKEN_RIGHT,
- TOKEN_CENTER,
- TOKEN_FLASH,
- TOKEN_CPF,
- TOKEN_END
- } TokenTag;
- typedef struct _Token {
- char *name;
- long tag;
- } Token;
- /* Script tokens:
- * BG/BGCOL - Background pen color (EX: BG=<color name>)
- * FG/FGCOL - Foreground pen color (EX: FG=<color name>)
- * X/XPOS - X pixel position of text (EX: X=<pixel cord>)
- * Y/YPOS - Y pixel position of text (EX: Y=<pixel cord>)
- * ABS/ABSOLUTE - Absolute justification
- * LEFT - Left side justification
- * RIGHT - Right side justification
- * CENTER - Center justification
- * FLASH - Enable flashing of text
- * CPF - Print rate in characters per frame (EX: CPF=<rate>)
- * END - Terminate compilation of caption script
- */
- Token tokens[] = {
- "BG", TOKEN_BGCOL,
- "BGCOL", TOKEN_BGCOL,
- "FG", TOKEN_FGCOL,
- "FGCOL", TOKEN_FGCOL,
- "X", TOKEN_XPOS,
- "XPOS", TOKEN_XPOS,
- "Y", TOKEN_YPOS,
- "YPOS", TOKEN_YPOS,
- "ABS", TOKEN_ABS,
- "ABSOLUTE", TOKEN_ABS,
- "LEFT", TOKEN_LEFT,
- "RIGHT", TOKEN_RIGHT,
- "CENTER", TOKEN_CENTER,
- "FLASH", TOKEN_FLASH,
- "CPF", TOKEN_CPF,
- "END", TOKEN_END,
- NULL, TOKEN_NULL,
- };
- Token colors[] = {
- "BLACK", 0,
- "WHITE", 251,
- "RED", 252,
- "GREEN", 253,
- "SHADOW", 254,
- "CYCLE", 255,
- NULL, -1,
- };
- /* Prototypes. */
- static long GetColorNum(char *name);
- static long IsNumeric(char *string);
- static void FormatString(char *string);
- /****************************************************************************
- *
- * NAME
- * BuildCaptions - Compile a caption script.
- *
- * SYNOPSIS
- * Size = BuildCaptions(Name, Buffer)
- *
- * long BuildCaptions(char *, char *);
- *
- * FUNCTION
- * Generate a compiled caption script for use in VQA playback.
- *
- * INPUTS
- * Name - Name of caption script file to compile.
- * Buffer - Buffer to put compiled captions into.
- *
- * RESULT
- * Size - Size of compiled captions (in bytes).
- *
- ****************************************************************************/
- long BuildCaptions(char *name, char *buffer)
- {
- FILE *fp;
- char *ptr;
- char *ptr1;
- long size = 0;
- long error;
- long i;
- long tag;
- CaptionText caption;
- char string[STRING_LENGTH];
- /* Initialize the caption parameters. */
- memset(&caption, 0, sizeof(CaptionText));
- /* Open the captions script file. */
- fp = fopen(name, "r");
- if (fp != NULL) {
- error = 0;
- while (!error) {
- if (fgets(string, STRING_LENGTH, fp) == NULL) {
- if (errno == 0) {
- error = 1;
- }
- break;
- }
-
- /* Replace the newline with a NULL terminator. */
- string[strlen(string) - 1] = 0;
- /* Ignore comment lines. */
- if (string[0] == ';') continue;
- ptr = strtok(string, "=");
- if (ptr != NULL) {
- /* Check for a comma */
- ptr1 = strchr(ptr, ',');
- if (ptr1 != NULL) {
- *ptr1++ = 0;
- }
- /* Is this a frame number. */
- if (IsNumeric(ptr) && IsNumeric(ptr1)) {
- i = atoi(ptr);
- /* Frames must be defined in ascending order. */
- if ((unsigned short)i >= caption.OnFrame) {
- caption.OnFrame = i;
- caption.OffFrame = atoi(ptr1);
- caption.Size = sizeof(CaptionText);
- /* Get caption text. */
- ptr = strtok(NULL, "");
- if (ptr != NULL) {
- FormatString(ptr);
- i = strlen(ptr) + 1;
- caption.Size += PADSIZE(i);
- size += caption.Size;
- /* Copy the caption structure. */
- memcpy(buffer, &caption, sizeof(CaptionText));
- buffer += sizeof(CaptionText);
- /* Copy the caption text. */
- memcpy(buffer, ptr, i);
- buffer += i;
- /* WORD align */
- if (PADSIZE(i) > i) {
- *buffer++ = 0;
- }
- }
- } else {
- error = 1;
- break;
- }
- } else {
- /* Search for matching token. */
- tag = TOKEN_NULL;
- i = 0;
- while (tokens[i].name != NULL) {
- if (strcmpi(tokens[i].name, ptr) == 0) {
- tag = tokens[i].tag;
- break;
- }
- i++;
- }
- /* Get the data element. */
- ptr = strtok(NULL, "");
- switch (tag) {
- case TOKEN_BGCOL:
- caption.BgPen = (char)GetColorNum(ptr);
- break;
- case TOKEN_FGCOL:
- caption.FgPen = (char)GetColorNum(ptr);
- break;
- case TOKEN_XPOS:
- caption.Xpos = (unsigned short)atoi(ptr);
- break;
- case TOKEN_YPOS:
- caption.Ypos = (unsigned short)atoi(ptr);
- break;
- case TOKEN_ABS:
- caption.Flags &= ~CTF_JUSTIFY;
- caption.Flags |= CTF_ABS;
- break;
- case TOKEN_LEFT:
- caption.Flags &= ~CTF_JUSTIFY;
- caption.Flags |= CTF_LEFT;
- break;
- case TOKEN_RIGHT:
- caption.Flags &= ~CTF_JUSTIFY;
- caption.Flags |= CTF_RIGHT;
- break;
- case TOKEN_CENTER:
- caption.Flags &= ~CTF_JUSTIFY;
- caption.Flags |= CTF_CENTER;
- break;
- case TOKEN_FLASH:
- if (strcmpi(ptr, "OFF") == 0) {
- caption.Flags &= ~CTF_FLASH;
- } else {
- caption.Flags |= CTF_FLASH;
- }
- break;
- case TOKEN_CPF:
- caption.CPF = (char)atoi(ptr);
- break;
- /* Termination captions */
- case TOKEN_END:
- caption.Size = sizeof(CaptionText);
- caption.OnFrame = (unsigned short)-1;
- memcpy(buffer, &caption, sizeof(CaptionText));
- buffer += sizeof(CaptionText);
- break;
- default:
- break;
- }
- }
- }
- }
- /* Close the script file. */
- fclose(fp);
- }
- return (size);
- }
- /****************************************************************************
- *
- * NAME
- * GetColorNum - Get the color number from the color name.
- *
- * SYNOPSIS
- * Color = GetColorNum(Name)
- *
- * long GetColorNum(char *);
- *
- * FUNCTION
- * Look the color number that corresponds to the color name.
- *
- * INPUTS
- * Name - Name of color.
- *
- * RESULT
- * Color - Color number.
- *
- ****************************************************************************/
- static long GetColorNum(char *name)
- {
- long color = -1;
- long i;
- i = 0;
- /* Scan for a matching name and return the corresponding color number. */
- while (colors[i].name != NULL) {
- if (strcmpi(colors[i].name, name) == 0) {
- color = colors[i].tag;
- }
- i++;
- }
- return (color);
- }
- /****************************************************************************
- *
- * NAME
- * IsNumeric - Check if a string is numeric.
- *
- * SYNOPSIS
- * Condition = IsNumeric(String)
- *
- * long IsNumeric(char *);
- *
- * FUNCTION
- * Interogate the string to see if it represents a numeric value. Each
- * byte of the string must be between 0x30 and 0x39 inclusively.
- *
- * INPUTS
- * String - String to check.
- *
- * RESULT
- * Condition - 1 if numeric, 0 if not.
- *
- ****************************************************************************/
- static long IsNumeric(char *string)
- {
- long flag = 1;
- /* Ignore any proceeding sign designation. */
- if ((*string == '-') || (*string == '+')) {
- string++;
- }
- /* Check to see if every byte in the string is a digit. */
- while (flag && (*string != 0)) {
- if (!isdigit(*string++)) {
- flag = 0;
- }
- }
- return (flag);
- }
- /****************************************************************************
- *
- * NAME
- * FormatString - Parse any format codes in the string.
- *
- * SYNOPSIS
- * FormatString(String)
- *
- * void FormatString(char *);
- *
- * FUNCTION
- * Format a string with any embedded format commands contained in the
- * input string.
- *
- * Supported format commands:
- * /n - Insert carriage return. (0x0D)
- * /r - Insert carriage return. (0x0D)
- * // - Literal backslash.
- *
- * INPUTS
- * String - Pointer to string to format.
- *
- * RESULT
- * NONE
- *
- ****************************************************************************/
- static void FormatString(char *string)
- {
- char *ptr;
- /* NULL strings are invalid. */
- if (string != NULL) {
- ptr = string;
- /* Scan the string for embedded format commands. */
- while ((ptr = strchr(ptr, '/')) != NULL) {
- switch (*(ptr + 1)) {
- /* Carriage return. */
- case 'n':
- case 'r':
- *ptr = 0x0D;
- break;
- /* Literal backslash. */
- case '/':
- break;
- default:
- break;
- }
- /* Remove the unwanted character. */
- strcpy((ptr + 1), (ptr + 2));
- }
- }
- }
|