2 //**************************************************************************
\r
6 //**************************************************************************
\r
8 // HEADER FILES ------------------------------------------------------------
\r
13 #include "strlist.h"
\r
18 // MACROS ------------------------------------------------------------------
\r
20 // TYPES -------------------------------------------------------------------
\r
31 stringInfo_t strings[MAX_STRINGS];
\r
40 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
\r
42 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
\r
44 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
\r
46 static int STR_PutStringInSomeList(stringList_t *list, int index, char *name);
\r
47 static int STR_FindInSomeList(stringList_t *list, char *name);
\r
48 static int STR_FindInSomeListInsensitive(stringList_t *list, char *name);
\r
49 static void DumpStrings(stringList_t *list, int lenadr, boolean quad, boolean crypt);
\r
50 static void Encrypt(void *data, int key, int len);
\r
52 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
\r
54 // PUBLIC DATA DEFINITIONS -------------------------------------------------
\r
56 int NumLanguages, NumStringLists;
\r
58 // PRIVATE DATA DEFINITIONS ------------------------------------------------
\r
60 static languageInfo_t *LanguageInfo[MAX_LANGUAGES];
\r
61 static stringList_t *StringLists[NUM_STRLISTS];
\r
63 // CODE --------------------------------------------------------------------
\r
65 //==========================================================================
\r
69 //==========================================================================
\r
73 NumLanguages = NumStringLists = 0;
\r
74 STR_FindLanguage(NULL); // Default language is always number 0
\r
77 //==========================================================================
\r
81 //==========================================================================
\r
83 int STR_FindLanguage(char *name)
\r
89 if (NumLanguages > 0)
\r
97 for(i = 0; i < NumLanguages; i++)
\r
99 if (strcmp (name, LanguageInfo[i]->name) == 0)
\r
105 if(i == NumLanguages)
\r
107 LanguageInfo[i] = MS_Alloc(sizeof(languageInfo_t), ERR_OUT_OF_MEMORY);
\r
108 memset(LanguageInfo[i]->name, 0, 4);
\r
111 strncpy(LanguageInfo[i]->name, name, 3);
\r
113 LanguageInfo[i]->list.stringCount = 0;
\r
115 if(NumLanguages > 1 && pc_EnforceHexen)
\r
117 ERR_Error(ERR_HEXEN_COMPAT, YES);
\r
123 //==========================================================================
\r
127 //==========================================================================
\r
129 int STR_Find(char *name)
\r
131 return STR_FindInLanguage(0, name);
\r
134 //==========================================================================
\r
136 // STR_FindInLanguage
\r
138 //==========================================================================
\r
140 int STR_FindInLanguage(int language, char *name)
\r
142 return STR_FindInSomeList (&LanguageInfo[language]->list, name);
\r
145 //==========================================================================
\r
149 //==========================================================================
\r
151 int STR_FindInList(int list, char *name)
\r
153 if (StringLists[list] == NULL)
\r
155 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);
\r
156 StringLists[list]->stringCount = 0;
\r
158 if(pc_EnforceHexen)
\r
160 ERR_Error(ERR_HEXEN_COMPAT, YES);
\r
163 return STR_FindInSomeList (StringLists[list], name);
\r
166 //==========================================================================
\r
168 // STR_FindInSomeList
\r
170 //==========================================================================
\r
172 static int STR_FindInSomeList(stringList_t *list, char *name)
\r
176 for(i = 0; i < list->stringCount; i++)
\r
178 if(strcmp(list->strings[i].name, name) == 0)
\r
184 return STR_PutStringInSomeList(list, i, name);
\r
187 //==========================================================================
\r
189 // STR_FindInListInsensitive
\r
191 //==========================================================================
\r
193 int STR_FindInListInsensitive(int list, char *name)
\r
195 if (StringLists[list] == NULL)
\r
197 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);
\r
198 StringLists[list]->stringCount = 0;
\r
200 if(pc_EnforceHexen)
\r
202 ERR_Error(ERR_HEXEN_COMPAT, YES);
\r
205 return STR_FindInSomeListInsensitive (StringLists[list], name);
\r
208 //==========================================================================
\r
210 // STR_FindInSomeListInsensitive
\r
212 //==========================================================================
\r
214 static int STR_FindInSomeListInsensitive(stringList_t *list, char *name)
\r
218 for(i = 0; i < list->stringCount; i++)
\r
220 if(strcasecmp(list->strings[i].name, name) == 0)
\r
226 return STR_PutStringInSomeList(list, i, name);
\r
229 //==========================================================================
\r
233 //==========================================================================
\r
235 const char *STR_GetString(int list, int index)
\r
237 if (StringLists[list] == NULL)
\r
241 if (index < 0 || index >= StringLists[list]->stringCount)
\r
245 return StringLists[list]->strings[index].name;
\r
248 //==========================================================================
\r
250 // STR_AppendToList
\r
252 //==========================================================================
\r
254 int STR_AppendToList(int list, char *name)
\r
256 if (StringLists[list] == NULL)
\r
258 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);
\r
259 StringLists[list]->stringCount = 0;
\r
261 if(pc_EnforceHexen)
\r
263 ERR_Error(ERR_HEXEN_COMPAT, YES);
\r
266 return STR_PutStringInSomeList(StringLists[list], StringLists[list]->stringCount, name);
\r
269 //==========================================================================
\r
271 // STR_PutStringInSomeList
\r
273 //==========================================================================
\r
275 static int STR_PutStringInSomeList(stringList_t *list, int index, char *name)
\r
279 if(index >= MAX_STRINGS)
\r
281 ERR_Error(ERR_TOO_MANY_STRINGS, YES, MAX_STRINGS);
\r
284 MS_Message(MSG_DEBUG, "Adding string %d:\n \"%s\"\n",
\r
285 list->stringCount, name);
\r
286 if(index >= list->stringCount)
\r
288 for(i = list->stringCount; i <= index; i++)
\r
290 list->strings[i].name = NULL;
\r
292 list->stringCount = index + 1;
\r
294 if(list->strings[index].name != NULL)
\r
296 free(list->strings[index].name);
\r
300 list->strings[index].name = MS_Alloc(strlen(name)+1, ERR_OUT_OF_MEMORY);
\r
301 strcpy(list->strings[index].name, name);
\r
305 list->strings[index].name = NULL;
\r
310 //==========================================================================
\r
314 //==========================================================================
\r
316 int STR_ListSize(int list)
\r
318 return LanguageInfo[list]->list.stringCount;
\r
321 //==========================================================================
\r
323 // STR_WriteStrings
\r
325 // Writes all the strings to the p-code buffer.
\r
327 //==========================================================================
\r
329 void STR_WriteStrings(void)
\r
334 MS_Message(MSG_DEBUG, "---- STR_WriteStrings ----\n");
\r
335 for(i = 0; i < LanguageInfo[0]->list.stringCount; i++)
\r
337 LanguageInfo[0]->list.strings[i].address = pc_Address;
\r
338 PC_AppendString(LanguageInfo[0]->list.strings[i].name);
\r
340 if(pc_Address%4 != 0)
\r
343 PC_Append((void *)&pad, 4-(pc_Address%4));
\r
347 //==========================================================================
\r
351 //==========================================================================
\r
353 void STR_WriteList(void)
\r
357 MS_Message(MSG_DEBUG, "---- STR_WriteList ----\n");
\r
358 PC_AppendInt((U_INT)LanguageInfo[0]->list.stringCount);
\r
359 for(i = 0; i < LanguageInfo[0]->list.stringCount; i++)
\r
361 PC_AppendInt((U_INT)LanguageInfo[0]->list.strings[i].address);
\r
365 //==========================================================================
\r
369 //==========================================================================
\r
371 void STR_WriteChunk(int language, boolean encrypt)
\r
373 languageInfo_t *lang = LanguageInfo[language];
\r
376 MS_Message(MSG_DEBUG, "---- STR_WriteChunk %d ----\n", language);
\r
377 PC_Append(encrypt ? "STRE" : "STRL", 4);
\r
378 lenadr = pc_Address;
\r
380 PC_Append(&lang->name, 4);
\r
381 PC_AppendInt(lang->list.stringCount);
\r
382 PC_AppendInt(0); // Used in-game for stringing lists together
\r
384 DumpStrings (&lang->list, lenadr, NO, encrypt);
\r
387 //==========================================================================
\r
389 // STR_WriteListChunk
\r
391 //==========================================================================
\r
393 void STR_WriteListChunk(int list, int id, boolean quad)
\r
397 if (StringLists[list] != NULL && StringLists[list]->stringCount > 0)
\r
399 MS_Message(MSG_DEBUG, "---- STR_WriteListChunk %d %c%c%c%c----\n", list,
\r
400 id&255, (id>>8)&255, (id>>16)&255, (id>>24)&255);
\r
401 PC_AppendInt((U_INT)id);
\r
402 lenadr = pc_Address;
\r
404 PC_AppendInt(StringLists[list]->stringCount);
\r
405 if (quad && pc_Address%8 != 0)
\r
406 { // If writing quadword indices, align the indices to an
\r
407 // 8-byte boundary.
\r
409 PC_Append (&pad, 4);
\r
411 DumpStrings(StringLists[list], lenadr, quad, NO);
\r
415 //==========================================================================
\r
419 //==========================================================================
\r
421 static void DumpStrings(stringList_t *list, int lenadr, boolean quad, boolean crypt)
\r
423 int i, ofs, startofs;
\r
425 startofs = ofs = pc_Address - lenadr - 4 + list->stringCount*(quad?8:4);
\r
427 for(i = 0; i < list->stringCount; i++)
\r
429 if (list->strings[i].name != NULL)
\r
431 PC_AppendInt((U_INT)ofs);
\r
432 ofs += strlen(list->strings[i].name) + 1;
\r
446 for(i = 0; i < list->stringCount; i++)
\r
448 if(list->strings[i].name != NULL)
\r
450 int stringlen = strlen(list->strings[i].name) + 1;
\r
453 int cryptkey = ofs*157135;
\r
455 Encrypt(list->strings[i].name, cryptkey, stringlen);
\r
456 PC_Append(list->strings[i].name, stringlen);
\r
458 Encrypt(list->strings[i].name, cryptkey, stringlen);
\r
462 PC_AppendString(list->strings[i].name);
\r
466 if(pc_Address%4 != 0)
\r
469 PC_Append((void *)&pad, 4-(pc_Address%4));
\r
472 PC_WriteInt(pc_Address - lenadr - 4, lenadr);
\r
475 static void Encrypt(void *data, int key, int len)
\r
477 int p = (byte)key, i;
\r
479 for(i = 0; i < len; ++i)
\r
481 ((byte *)data)[i] ^= (byte)(p+(i>>1));
\r