Add an index to dialog string tables, so that we can refer to dialog lines by a string identifier instead of a volatile number.

This commit is contained in:
Serge van den Boom
2013-09-29 21:16:26 +02:00
parent c8527459c8
commit d490f70016
4 changed files with 230 additions and 107 deletions
+157 -99
View File
@@ -42,8 +42,9 @@ dword_convert (DWORD *dword_array, COUNT num_dwords)
} while (--num_dwords); } while (--num_dwords);
} }
static void static STRING
set_strtab_entry (STRING_TABLE_DESC *strtab, int index, const char *value, int len) set_strtab_entry (STRING_TABLE_DESC *strtab, int index, const char *value,
int len)
{ {
STRING str = &strtab->strings[index]; STRING str = &strtab->strings[index];
@@ -59,6 +60,22 @@ set_strtab_entry (STRING_TABLE_DESC *strtab, int index, const char *value, int l
str->length = len; str->length = len;
memcpy (str->data, value, len); memcpy (str->data, value, len);
} }
return str;
}
static void
copy_strings_to_strtab (STRING_TABLE_DESC *strtab, size_t firstIndex,
size_t count, const char *data, const DWORD *lens)
{
size_t stringI;
const char *off = data;
for (stringI = 0; stringI < count; stringI++)
{
set_strtab_entry(strtab, firstIndex + stringI,
off, lens[stringI]);
off += lens[stringI];
}
} }
// Check whether a buffer has a certain minimum size, and enlarge it // Check whether a buffer has a certain minimum size, and enlarge it
@@ -98,37 +115,52 @@ ensureBufSize (char **buf, size_t *curSize, size_t minSize, size_t increment)
void void
_GetConversationData (const char *path, RESOURCE_DATA *resdata) _GetConversationData (const char *path, RESOURCE_DATA *resdata)
{ {
uio_Stream *fp;
unsigned long dataLen; unsigned long dataLen;
void *result; void *result;
int n; int stringI;
int path_len; int path_len;
int num_data_sets; int num_data_sets;
DWORD opos; DWORD opos;
char *namedata = NULL;
// Contains the names (indexes) of the dialogs.
DWORD nlen[MAX_STRINGS];
// Length of each of the names.
DWORD NameOffs;
size_t tot_name_size;
char *strdata = NULL;
// Contains the dialog strings.
DWORD slen[MAX_STRINGS]; DWORD slen[MAX_STRINGS];
// Length of each of the dialog strings. // Length of each of the dialog strings.
DWORD StringOffs; DWORD StringOffs;
size_t tot_string_size; size_t tot_string_size;
char *clipdata = NULL;
// Contains the file names of the speech files.
DWORD clen[MAX_STRINGS]; DWORD clen[MAX_STRINGS];
// Length of each of the speech file names. // Length of each of the speech file names.
DWORD ClipOffs; DWORD ClipOffs;
size_t tot_clip_size; size_t tot_clip_size;
char *ts_data = NULL;
// Contains the timestamp data for synching the text with the
// speech.
DWORD tslen[MAX_STRINGS]; DWORD tslen[MAX_STRINGS];
// Length of each of the timestamp strings. // Length of each of the timestamp strings.
DWORD TSOffs; DWORD TSOffs;
size_t tot_ts_size = 0; size_t tot_ts_size = 0;
char CurrentLine[1024]; char CurrentLine[1024];
char paths[1024]; char paths[1024];
char *clip_path; char *clip_path;
char *ts_path; char *ts_path;
char *strdata = NULL;
// Contains the dialog strings. uio_Stream *fp = NULL;
char *clipdata = NULL;
// Contains the file names of the speech files.
char *ts_data = NULL;
// Contains the timestamp data for synching the text with the
// speech.
uio_Stream *timestamp_fp = NULL; uio_Stream *timestamp_fp = NULL;
StringHashTable_HashTable *nameHashTable = NULL;
// Hash table of string names (such as "GLAD_WHEN_YOU_COME_BACK")
// to a STRING.
/* Parse out the conversation components. */ /* Parse out the conversation components. */
strncpy (paths, path, 1023); strncpy (paths, path, 1023);
@@ -183,12 +215,22 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
if (strdata == 0) if (strdata == 0)
goto err; goto err;
tot_name_size = POOL_SIZE;
namedata = HMalloc (tot_name_size);
if (namedata == 0)
goto err;
tot_clip_size = POOL_SIZE; tot_clip_size = POOL_SIZE;
clipdata = HMalloc (tot_clip_size); clipdata = HMalloc (tot_clip_size);
if (clipdata == 0) if (clipdata == 0)
goto err; goto err;
ts_data = NULL; ts_data = NULL;
nameHashTable = StringHashTable_newHashTable(
NULL, NULL, NULL, NULL, NULL, 0, 0.85, 0.9);
if (nameHashTable == NULL)
goto err;
path_len = clip_path ? strlen (clip_path) : 0; path_len = clip_path ? strlen (clip_path) : 0;
if (ts_path) if (ts_path)
@@ -204,7 +246,8 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
} }
opos = uio_ftell (fp); opos = uio_ftell (fp);
n = -1; stringI = -1;
NameOffs = 0;
StringOffs = 0; StringOffs = 0;
ClipOffs = 0; ClipOffs = 0;
TSOffs = 0; TSOffs = 0;
@@ -218,7 +261,7 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
break; break;
} }
if (n >= MAX_STRINGS - 1) if (stringI >= MAX_STRINGS - 1)
{ {
// Too many strings. // Too many strings.
break; break;
@@ -229,25 +272,35 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
// String header, of the following form: // String header, of the following form:
// #(GLAD_WHEN_YOU_COME_BACK) commander-000.ogg // #(GLAD_WHEN_YOU_COME_BACK) commander-000.ogg
char CopyLine[1024]; char CopyLine[1024];
char *s; char *name;
char *ts;
strcpy (CopyLine, CurrentLine); strcpy (CopyLine, CurrentLine);
s = strtok (&CopyLine[1], "()"); name = strtok (&CopyLine[1], "()");
if (s) if (name)
{ {
if (n >= 0) if (stringI >= 0)
{ {
while (slen[n] > 1 && while (slen[stringI] > 1 &&
(strdata[StringOffs - 2] == '\n' || (strdata[StringOffs - 2] == '\n' ||
strdata[StringOffs - 2] == '\r')) strdata[StringOffs - 2] == '\r'))
{ {
--slen[n]; --slen[stringI];
--StringOffs; --StringOffs;
strdata[StringOffs - 1] = '\0'; strdata[StringOffs - 1] = '\0';
} }
} }
slen[++n] = 0; slen[++stringI] = 0;
// Store the string name.
l = strlen (name) + 1;
if (!ensureBufSize (&namedata, &tot_name_size,
NameOffs + l, POOL_SIZE))
goto err;
strcpy (&namedata[NameOffs], name);
NameOffs += l;
nlen[stringI] = l;
// now lets check for timestamp data // now lets check for timestamp data
if (timestamp_fp) if (timestamp_fp)
@@ -261,11 +314,11 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
{ {
// Line is of the following form: // Line is of the following form:
// #(GIVE_FUEL_AGAIN) 3304,3255 // #(GIVE_FUEL_AGAIN) 3304,3255
tslen[n] = 0; tslen[stringI] = 0;
tsptr = strstr (TimeStampLine, s); tsptr = strstr (TimeStampLine, name);
if (tsptr) if (tsptr)
{ {
tsptr += strlen(s) + 1; tsptr += strlen(name) + 1;
ts_ok = TRUE; ts_ok = TRUE;
while (! strcspn(tsptr," \t\r\n") && *tsptr) while (! strcspn(tsptr," \t\r\n") && *tsptr)
tsptr++; tsptr++;
@@ -278,7 +331,7 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
strcpy (&ts_data[TSOffs], tsptr); strcpy (&ts_data[TSOffs], tsptr);
TSOffs += l; TSOffs += l;
tslen[n] = l; tslen[stringI] = l;
} }
} }
} }
@@ -286,7 +339,7 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
{ {
// timestamp data is invalid, remove all of it // timestamp data is invalid, remove all of it
log_add (log_Warning, "Invalid timestamp data " log_add (log_Warning, "Invalid timestamp data "
"for '%s'. Disabling timestamps", s); "for '%s'. Disabling timestamps", name);
HFree (ts_data); HFree (ts_data);
ts_data = NULL; ts_data = NULL;
uio_fclose (timestamp_fp); uio_fclose (timestamp_fp);
@@ -294,24 +347,24 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
TSOffs = 0; TSOffs = 0;
} }
} }
clen[n] = 0; clen[stringI] = 0;
s = strtok (NULL, " \t\r\n)"); ts = strtok (NULL, " \t\r\n)");
if (s) if (ts)
{ {
l = path_len + strlen (s) + 1; l = path_len + strlen (ts) + 1;
if (!ensureBufSize (&clipdata, &tot_clip_size, if (!ensureBufSize (&clipdata, &tot_clip_size,
ClipOffs + l, POOL_SIZE)) ClipOffs + l, POOL_SIZE))
goto err; goto err;
if (clip_path) if (clip_path)
strcpy (&clipdata[ClipOffs], clip_path); strcpy (&clipdata[ClipOffs], clip_path);
strcpy (&clipdata[ClipOffs + path_len], s); strcpy (&clipdata[ClipOffs + path_len], ts);
ClipOffs += l; ClipOffs += l;
clen[n] = l; clen[stringI] = l;
} }
} }
} }
else if (n >= 0) else if (stringI >= 0)
{ {
char *s; char *s;
l = strlen (CurrentLine) + 1; l = strlen (CurrentLine) + 1;
@@ -320,13 +373,13 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
POOL_SIZE)) POOL_SIZE))
goto err; goto err;
if (slen[n]) if (slen[stringI])
{ {
--slen[n]; --slen[stringI];
--StringOffs; --StringOffs;
} }
s = &strdata[StringOffs]; s = &strdata[StringOffs];
slen[n] += l; slen[stringI] += l;
StringOffs += l; StringOffs += l;
strcpy (s, CurrentLine); strcpy (s, CurrentLine);
@@ -335,12 +388,12 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
if ((int)uio_ftell (fp) - (int)opos >= (int)dataLen) if ((int)uio_ftell (fp) - (int)opos >= (int)dataLen)
break; break;
} }
if (n >= 0) if (stringI >= 0)
{ {
while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n' while (slen[stringI] > 1 && (strdata[StringOffs - 2] == '\n'
|| strdata[StringOffs - 2] == '\r')) || strdata[StringOffs - 2] == '\r'))
{ {
--slen[n]; --slen[stringI];
--StringOffs; --StringOffs;
strdata[StringOffs - 1] = '\0'; strdata[StringOffs - 1] = '\0';
} }
@@ -351,59 +404,75 @@ _GetConversationData (const char *path, RESOURCE_DATA *resdata)
result = NULL; result = NULL;
num_data_sets = (ClipOffs ? 1 : 0) + (TSOffs ? 1 : 0) + 1; num_data_sets = (ClipOffs ? 1 : 0) + (TSOffs ? 1 : 0) + 1;
if (++n) if (++stringI)
{ {
int flags = 0; int flags = 0;
int stringCount = stringI;
if (ClipOffs) if (ClipOffs)
flags |= HAS_SOUND_CLIPS; flags |= HAS_SOUND_CLIPS;
if (TSOffs) if (TSOffs)
flags |= HAS_TIMESTAMP; flags |= HAS_TIMESTAMP;
flags |= HAS_NAMEINDEX;
result = AllocStringTable (n, flags); result = AllocStringTable (stringCount, flags);
if (result) if (result)
{ {
int StringIndex; // Copy all the gatherered data in a STRING_TABLE
int ClipIndex; STRING_TABLE_DESC *lpST = (STRING_TABLE) result;
int TSIndex; STRING str;
STRING_TABLE_DESC *lpST; stringI = 0;
lpST = (STRING_TABLE) result; // Store the dialog string.
copy_strings_to_strtab (
lpST, stringI, stringCount, strdata, slen);
stringI += stringCount;
StringIndex = 0; // Store the dialog names.
ClipIndex = n; copy_strings_to_strtab (
TSIndex = n * ((flags & HAS_SOUND_CLIPS) ? 2 : 1); lpST, stringI, stringCount, namedata, nlen);
stringI += stringCount;
StringOffs = 0; // Store sound clip file names.
ClipOffs = 0; if (lpST->flags & HAS_SOUND_CLIPS)
TSOffs = 0;
for (n = 0; n < (int)lpST->size;
++n, ++StringIndex, ++ClipIndex, ++TSIndex)
{ {
set_strtab_entry(lpST, StringIndex, strdata + StringOffs, slen[n]); copy_strings_to_strtab (
StringOffs += slen[n]; lpST, stringI, stringCount, clipdata, clen);
if (lpST->flags & HAS_SOUND_CLIPS) stringI += stringCount;
{
set_strtab_entry(lpST, ClipIndex, clipdata + ClipOffs, clen[n]);
ClipOffs += clen[n];
}
if (lpST->flags & HAS_TIMESTAMP)
{
set_strtab_entry(lpST, TSIndex, ts_data + TSOffs, tslen[n]);
TSOffs += tslen[n];
}
} }
// Store time stamp data.
if (lpST->flags & HAS_TIMESTAMP)
{
copy_strings_to_strtab (
lpST, stringI, stringCount, ts_data, tslen);
//stringI += stringCount;
}
// Store the STRING in the hash table indexed by the dialog
// name.
str = &lpST->strings[stringCount];
for (stringI = 0; stringI < stringCount; stringI++)
{
StringHashTable_add (nameHashTable, str[stringI].data,
&str[stringI]);
}
lpST->nameIndex = nameHashTable;
} }
} }
HFree (strdata); HFree (strdata);
HFree (clipdata); if (clipdata != NULL)
if (ts_data) HFree (clipdata);
if (ts_data != NULL)
HFree (ts_data); HFree (ts_data);
resdata->ptr = result; resdata->ptr = result;
return; return;
err: err:
if (nameHashTable != NULL)
StringHashTable_deleteHashTable (nameHashTable);
if (ts_data != NULL) if (ts_data != NULL)
HFree (ts_data); HFree (ts_data);
if (clipdata != NULL) if (clipdata != NULL)
@@ -419,7 +488,7 @@ _GetStringData (uio_Stream *fp, DWORD length)
{ {
void *result; void *result;
int n; int stringI;
DWORD opos; DWORD opos;
DWORD slen[MAX_STRINGS]; DWORD slen[MAX_STRINGS];
DWORD StringOffs; DWORD StringOffs;
@@ -433,7 +502,7 @@ _GetStringData (uio_Stream *fp, DWORD length)
goto err; goto err;
opos = uio_ftell (fp); opos = uio_ftell (fp);
n = -1; stringI = -1;
StringOffs = 0; StringOffs = 0;
for (;;) for (;;)
{ {
@@ -445,7 +514,7 @@ _GetStringData (uio_Stream *fp, DWORD length)
break; break;
} }
if (n >= MAX_STRINGS - 1) if (stringI >= MAX_STRINGS - 1)
{ {
// Too many strings. // Too many strings.
break; break;
@@ -460,22 +529,22 @@ _GetStringData (uio_Stream *fp, DWORD length)
s = strtok (&CopyLine[1], "()"); s = strtok (&CopyLine[1], "()");
if (s) if (s)
{ {
if (n >= 0) if (stringI >= 0)
{ {
while (slen[n] > 1 && while (slen[stringI] > 1 &&
(strdata[StringOffs - 2] == '\n' || (strdata[StringOffs - 2] == '\n' ||
strdata[StringOffs - 2] == '\r')) strdata[StringOffs - 2] == '\r'))
{ {
--slen[n]; --slen[stringI];
--StringOffs; --StringOffs;
strdata[StringOffs - 1] = '\0'; strdata[StringOffs - 1] = '\0';
} }
} }
slen[++n] = 0; slen[++stringI] = 0;
} }
} }
else if (n >= 0) else if (stringI >= 0)
{ {
char *s; char *s;
l = strlen (CurrentLine) + 1; l = strlen (CurrentLine) + 1;
@@ -484,13 +553,13 @@ _GetStringData (uio_Stream *fp, DWORD length)
POOL_SIZE)) POOL_SIZE))
goto err; goto err;
if (slen[n]) if (slen[stringI])
{ {
--slen[n]; --slen[stringI];
--StringOffs; --StringOffs;
} }
s = &strdata[StringOffs]; s = &strdata[StringOffs];
slen[n] += l; slen[stringI] += l;
StringOffs += l; StringOffs += l;
strcpy (s, CurrentLine); strcpy (s, CurrentLine);
@@ -499,39 +568,28 @@ _GetStringData (uio_Stream *fp, DWORD length)
if ((int)uio_ftell (fp) - (int)opos >= (int)length) if ((int)uio_ftell (fp) - (int)opos >= (int)length)
break; break;
} }
if (n >= 0) if (stringI >= 0)
{ {
while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n' while (slen[stringI] > 1 && (strdata[StringOffs - 2] == '\n'
|| strdata[StringOffs - 2] == '\r')) || strdata[StringOffs - 2] == '\r'))
{ {
--slen[n]; --slen[stringI];
--StringOffs; --StringOffs;
strdata[StringOffs - 1] = '\0'; strdata[StringOffs - 1] = '\0';
} }
} }
result = NULL; result = NULL;
if (++n) if (++stringI)
{ {
int flags = 0; int flags = 0;
result = AllocStringTable (n, flags); int stringCount = stringI;
result = AllocStringTable (stringI, flags);
if (result) if (result)
{ {
int StringIndex; STRING_TABLE_DESC *lpST = (STRING_TABLE) result;
STRING_TABLE_DESC *lpST; copy_strings_to_strtab (lpST, 0, stringCount, strdata, slen);
lpST = (STRING_TABLE) result;
StringIndex = 0;
StringOffs = 0;
for (n = 0; n < (int)lpST->size;
++n, ++StringIndex)
{
set_strtab_entry(lpST, StringIndex, strdata + StringOffs, slen[n]);
StringOffs += slen[n];
}
} }
} }
HFree (strdata); HFree (strdata);
+64 -4
View File
@@ -25,6 +25,10 @@ AllocStringTable (int num_entries, int flags)
STRING_TABLE strtab = HMalloc (sizeof (STRING_TABLE_DESC)); STRING_TABLE strtab = HMalloc (sizeof (STRING_TABLE_DESC));
int i, multiplier = 1; int i, multiplier = 1;
if (flags & HAS_NAMEINDEX)
{
multiplier++;
}
if (flags & HAS_SOUND_CLIPS) if (flags & HAS_SOUND_CLIPS)
{ {
multiplier++; multiplier++;
@@ -44,6 +48,7 @@ AllocStringTable (int num_entries, int flags)
strtab->strings[i].parent = strtab; strtab->strings[i].parent = strtab;
strtab->strings[i].index = i; strtab->strings[i].index = i;
} }
strtab->nameIndex = NULL;
return strtab; return strtab;
} }
@@ -208,6 +213,40 @@ GetStringLengthBin (STRING String)
return String->length; return String->length;
} }
STRINGPTR
GetStringName (STRING String)
{
STRING_TABLE StringTablePtr;
COUNT StringIndex;
if (String == NULL)
{
return NULL;
}
StringTablePtr = String->parent;
if (StringTablePtr == NULL)
{
return NULL;
}
StringIndex = String->index;
if (!(StringTablePtr->flags & HAS_NAMEINDEX))
{
return NULL;
}
StringIndex += StringTablePtr->size;
String = &StringTablePtr->strings[StringIndex];
if (String->length == 0)
{
return NULL;
}
return String->data;
}
STRINGPTR STRINGPTR
GetStringSoundClip (STRING String) GetStringSoundClip (STRING String)
{ {
@@ -230,8 +269,13 @@ GetStringSoundClip (STRING String)
{ {
return NULL; return NULL;
} }
StringIndex += StringTablePtr->size; StringIndex += StringTablePtr->size;
if (StringTablePtr->flags & HAS_NAMEINDEX)
{
StringIndex += StringTablePtr->size;
}
String = &StringTablePtr->strings[StringIndex]; String = &StringTablePtr->strings[StringIndex];
if (String->length == 0) if (String->length == 0)
{ {
@@ -246,7 +290,6 @@ GetStringTimeStamp (STRING String)
{ {
STRING_TABLE StringTablePtr; STRING_TABLE StringTablePtr;
COUNT StringIndex; COUNT StringIndex;
int offset;
if (String == NULL) if (String == NULL)
{ {
@@ -264,9 +307,18 @@ GetStringTimeStamp (STRING String)
{ {
return NULL; return NULL;
} }
StringIndex += StringTablePtr->size;
if (StringTablePtr->flags & HAS_NAMEINDEX)
{
StringIndex += StringTablePtr->size;
}
if (StringTablePtr->flags & HAS_SOUND_CLIPS)
{
StringIndex += StringTablePtr->size;
}
offset = (StringTablePtr->flags & HAS_SOUND_CLIPS) ? 1 : 0;
StringIndex += StringTablePtr->size << offset;
String = &StringTablePtr->strings[StringIndex]; String = &StringTablePtr->strings[StringIndex];
if (String->length == 0) if (String->length == 0)
{ {
@@ -285,3 +337,11 @@ GetStringAddress (STRING String)
} }
return String->data; return String->data;
} }
STRING
GetStringByName (STRING_TABLE StringTable, const char *index)
{
return (STRING) StringHashTable_find (StringTable->nameIndex, index);
}
+5 -2
View File
@@ -23,6 +23,7 @@
#include <string.h> #include <string.h>
#include "libs/strlib.h" #include "libs/strlib.h"
#include "libs/reslib.h" #include "libs/reslib.h"
#include "stringhashtable.h"
struct string_table_entry struct string_table_entry
{ {
@@ -37,10 +38,12 @@ struct string_table
unsigned short flags; unsigned short flags;
int size; int size;
STRING_TABLE_ENTRY_DESC *strings; STRING_TABLE_ENTRY_DESC *strings;
StringHashTable_HashTable *nameIndex;
}; };
#define HAS_SOUND_CLIPS (1 << 0) #define HAS_SOUND_CLIPS (1 << 0)
#define HAS_TIMESTAMP (1 << 1) #define HAS_TIMESTAMP (1 << 1)
#define HAS_NAMEINDEX (1 << 2)
STRING_TABLE AllocStringTable (int num_entries, int flags); STRING_TABLE AllocStringTable (int num_entries, int flags);
void FreeStringTable (STRING_TABLE strtab); void FreeStringTable (STRING_TABLE strtab);
+2
View File
@@ -57,8 +57,10 @@ extern STRING SetRelStringTableIndex (STRING String, SIZE
extern COUNT GetStringLength (STRING String); extern COUNT GetStringLength (STRING String);
extern COUNT GetStringLengthBin (STRING String); extern COUNT GetStringLengthBin (STRING String);
extern STRINGPTR GetStringAddress (STRING String); extern STRINGPTR GetStringAddress (STRING String);
extern STRINGPTR GetStringName (STRING String);
extern STRINGPTR GetStringSoundClip (STRING String); extern STRINGPTR GetStringSoundClip (STRING String);
extern STRINGPTR GetStringTimeStamp (STRING String); extern STRINGPTR GetStringTimeStamp (STRING String);
extern STRING GetStringByName (STRING_TABLE StringTable, const char *index);
#define UNICHAR_DEGREE_SIGN 0x00b0 #define UNICHAR_DEGREE_SIGN 0x00b0
#define STR_DEGREE_SIGN "\xC2\xB0" #define STR_DEGREE_SIGN "\xC2\xB0"