OSDN Git Service

- Add new HUD message definitions to zdefs.acs.
[zandronum/zandronum-acc.git] / strlist.c
1 \r
2 //**************************************************************************\r
3 //**\r
4 //** strlist.c\r
5 //**\r
6 //**************************************************************************\r
7 \r
8 // HEADER FILES ------------------------------------------------------------\r
9 \r
10 #include <string.h>\r
11 #include <malloc.h>\r
12 #include "common.h"\r
13 #include "strlist.h"\r
14 #include "error.h"\r
15 #include "misc.h"\r
16 #include "pcode.h"\r
17 \r
18 // MACROS ------------------------------------------------------------------\r
19 \r
20 // TYPES -------------------------------------------------------------------\r
21 \r
22 typedef struct\r
23 {\r
24         char *name;\r
25         int address;\r
26 } stringInfo_t;\r
27 \r
28 typedef struct\r
29 {\r
30         int stringCount;\r
31         stringInfo_t strings[MAX_STRINGS];\r
32 } stringList_t;\r
33 \r
34 typedef struct\r
35 {\r
36         char name[4];\r
37         stringList_t list;\r
38 } languageInfo_t;\r
39 \r
40 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------\r
41 \r
42 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------\r
43 \r
44 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------\r
45 \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
51 \r
52 // EXTERNAL DATA DECLARATIONS ----------------------------------------------\r
53 \r
54 // PUBLIC DATA DEFINITIONS -------------------------------------------------\r
55 \r
56 int NumLanguages, NumStringLists;\r
57 \r
58 // PRIVATE DATA DEFINITIONS ------------------------------------------------\r
59 \r
60 static languageInfo_t *LanguageInfo[MAX_LANGUAGES];\r
61 static stringList_t *StringLists[NUM_STRLISTS];\r
62 \r
63 // CODE --------------------------------------------------------------------\r
64 \r
65 //==========================================================================\r
66 //\r
67 // STR_Init\r
68 //\r
69 //==========================================================================\r
70 \r
71 void STR_Init(void)\r
72 {\r
73         NumLanguages = NumStringLists = 0;\r
74         STR_FindLanguage(NULL); // Default language is always number 0\r
75 }\r
76 \r
77 //==========================================================================\r
78 //\r
79 // STR_FindLanguage\r
80 //\r
81 //==========================================================================\r
82 \r
83 int STR_FindLanguage(char *name)\r
84 {\r
85         int i;\r
86 \r
87         if (name == NULL)\r
88         {\r
89                 if (NumLanguages > 0)\r
90                 {\r
91                         return 0;\r
92                 }\r
93                 i = 0;\r
94         }\r
95         else\r
96         {\r
97                 for(i = 0; i < NumLanguages; i++)\r
98                 {\r
99                         if (strcmp (name, LanguageInfo[i]->name) == 0)\r
100                         {\r
101                                 return i;\r
102                         }\r
103                 }\r
104         }\r
105         if(i == NumLanguages)\r
106         {\r
107                 LanguageInfo[i] = MS_Alloc(sizeof(languageInfo_t), ERR_OUT_OF_MEMORY);\r
108                 memset(LanguageInfo[i]->name, 0, 4);\r
109                 if(name != NULL)\r
110                 {\r
111                         strncpy(LanguageInfo[i]->name, name, 3);\r
112                 }\r
113                 LanguageInfo[i]->list.stringCount = 0;\r
114                 NumLanguages++;\r
115                 if(NumLanguages > 1 && pc_EnforceHexen)\r
116                 {\r
117                         ERR_Error(ERR_HEXEN_COMPAT, YES);\r
118                 }\r
119         }\r
120         return i;\r
121 }\r
122  \r
123 //==========================================================================\r
124 //\r
125 // STR_Find\r
126 //\r
127 //==========================================================================\r
128 \r
129 int STR_Find(char *name)\r
130 {\r
131         return STR_FindInLanguage(0, name);\r
132 }\r
133 \r
134 //==========================================================================\r
135 //\r
136 // STR_FindInLanguage\r
137 //\r
138 //==========================================================================\r
139 \r
140 int STR_FindInLanguage(int language, char *name)\r
141 {\r
142         return STR_FindInSomeList (&LanguageInfo[language]->list, name);\r
143 }\r
144 \r
145 //==========================================================================\r
146 //\r
147 // STR_FindInList\r
148 //\r
149 //==========================================================================\r
150 \r
151 int STR_FindInList(int list, char *name)\r
152 {\r
153         if (StringLists[list] == NULL)\r
154         {\r
155                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
156                 StringLists[list]->stringCount = 0;\r
157                 NumStringLists++;\r
158                 if(pc_EnforceHexen)\r
159                 {\r
160                         ERR_Error(ERR_HEXEN_COMPAT, YES);\r
161                 }\r
162         }\r
163         return STR_FindInSomeList (StringLists[list], name);\r
164 }\r
165 \r
166 //==========================================================================\r
167 //\r
168 // STR_FindInSomeList\r
169 //\r
170 //==========================================================================\r
171 \r
172 static int STR_FindInSomeList(stringList_t *list, char *name)\r
173 {\r
174         int i;\r
175 \r
176         for(i = 0; i < list->stringCount; i++)\r
177         {\r
178                 if(strcmp(list->strings[i].name, name) == 0)\r
179                 {\r
180                         return i;\r
181                 }\r
182         }\r
183         // Add to list\r
184         return STR_PutStringInSomeList(list, i, name);\r
185 }\r
186 \r
187 //==========================================================================\r
188 //\r
189 // STR_FindInListInsensitive\r
190 //\r
191 //==========================================================================\r
192 \r
193 int STR_FindInListInsensitive(int list, char *name)\r
194 {\r
195         if (StringLists[list] == NULL)\r
196         {\r
197                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
198                 StringLists[list]->stringCount = 0;\r
199                 NumStringLists++;\r
200                 if(pc_EnforceHexen)\r
201                 {\r
202                         ERR_Error(ERR_HEXEN_COMPAT, YES);\r
203                 }\r
204         }\r
205         return STR_FindInSomeListInsensitive (StringLists[list], name);\r
206 }\r
207 \r
208 //==========================================================================\r
209 //\r
210 // STR_FindInSomeListInsensitive\r
211 //\r
212 //==========================================================================\r
213 \r
214 static int STR_FindInSomeListInsensitive(stringList_t *list, char *name)\r
215 {\r
216         int i;\r
217 \r
218         for(i = 0; i < list->stringCount; i++)\r
219         {\r
220                 if(strcasecmp(list->strings[i].name, name) == 0)\r
221                 {\r
222                         return i;\r
223                 }\r
224         }\r
225         // Add to list\r
226         return STR_PutStringInSomeList(list, i, name);\r
227 }\r
228 \r
229 //==========================================================================\r
230 //\r
231 // STR_GetString\r
232 //\r
233 //==========================================================================\r
234 \r
235 const char *STR_GetString(int list, int index)\r
236 {\r
237         if (StringLists[list] == NULL)\r
238         {\r
239                 return NULL;\r
240         }\r
241         if (index < 0 || index >= StringLists[list]->stringCount)\r
242         {\r
243                 return NULL;\r
244         }\r
245         return StringLists[list]->strings[index].name;\r
246 }\r
247 \r
248 //==========================================================================\r
249 //\r
250 // STR_AppendToList\r
251 //\r
252 //==========================================================================\r
253 \r
254 int STR_AppendToList(int list, char *name)\r
255 {\r
256         if (StringLists[list] == NULL)\r
257         {\r
258                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
259                 StringLists[list]->stringCount = 0;\r
260                 NumStringLists++;\r
261                 if(pc_EnforceHexen)\r
262                 {\r
263                         ERR_Error(ERR_HEXEN_COMPAT, YES);\r
264                 }\r
265         }\r
266         return STR_PutStringInSomeList(StringLists[list], StringLists[list]->stringCount, name);\r
267 }\r
268 \r
269 //==========================================================================\r
270 //\r
271 // STR_PutStringInSomeList\r
272 //\r
273 //==========================================================================\r
274 \r
275 static int STR_PutStringInSomeList(stringList_t *list, int index, char *name)\r
276 {\r
277         int i;\r
278 \r
279         if(index >= MAX_STRINGS)\r
280         {\r
281                 ERR_Error(ERR_TOO_MANY_STRINGS, YES, MAX_STRINGS);\r
282                 return 0;\r
283         }\r
284         MS_Message(MSG_DEBUG, "Adding string %d:\n  \"%s\"\n",\r
285                 list->stringCount, name);\r
286         if(index >= list->stringCount)\r
287         {\r
288                 for(i = list->stringCount; i <= index; i++)\r
289                 {\r
290                         list->strings[i].name = NULL;\r
291                 }\r
292                 list->stringCount = index + 1;\r
293         }\r
294         if(list->strings[index].name != NULL)\r
295         {\r
296                 free(list->strings[index].name);\r
297         }\r
298         if(name != NULL)\r
299         {\r
300                 list->strings[index].name = MS_Alloc(strlen(name)+1, ERR_OUT_OF_MEMORY);\r
301                 strcpy(list->strings[index].name, name);\r
302         }\r
303         else\r
304         {\r
305                 list->strings[index].name = NULL;\r
306         }\r
307         return index;\r
308 }\r
309 \r
310 //==========================================================================\r
311 //\r
312 // STR_ListSize\r
313 //\r
314 //==========================================================================\r
315 \r
316 int STR_ListSize(int list)\r
317 {\r
318         return LanguageInfo[list]->list.stringCount;\r
319 }\r
320 \r
321 //==========================================================================\r
322 //\r
323 // STR_WriteStrings\r
324 //\r
325 // Writes all the strings to the p-code buffer.\r
326 //\r
327 //==========================================================================\r
328 \r
329 void STR_WriteStrings(void)\r
330 {\r
331         int i;\r
332         U_INT pad;\r
333 \r
334         MS_Message(MSG_DEBUG, "---- STR_WriteStrings ----\n");\r
335         for(i = 0; i < LanguageInfo[0]->list.stringCount; i++)\r
336         {\r
337                 LanguageInfo[0]->list.strings[i].address = pc_Address;\r
338                 PC_AppendString(LanguageInfo[0]->list.strings[i].name);\r
339         }\r
340         if(pc_Address%4 != 0)\r
341         { // Need to align\r
342                 pad = 0;\r
343                 PC_Append((void *)&pad, 4-(pc_Address%4));\r
344         }\r
345 }\r
346 \r
347 //==========================================================================\r
348 //\r
349 // STR_WriteList\r
350 //\r
351 //==========================================================================\r
352 \r
353 void STR_WriteList(void)\r
354 {\r
355         int i;\r
356 \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
360         {\r
361                 PC_AppendInt((U_INT)LanguageInfo[0]->list.strings[i].address);\r
362         }\r
363 }\r
364 \r
365 //==========================================================================\r
366 //\r
367 // STR_WriteChunk\r
368 //\r
369 //==========================================================================\r
370 \r
371 void STR_WriteChunk(int language, boolean encrypt)\r
372 {\r
373         languageInfo_t *lang = LanguageInfo[language];\r
374         int lenadr;\r
375 \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
379         PC_SkipInt();\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
383 \r
384         DumpStrings (&lang->list, lenadr, NO, encrypt);\r
385 }\r
386 \r
387 //==========================================================================\r
388 //\r
389 // STR_WriteListChunk\r
390 //\r
391 //==========================================================================\r
392 \r
393 void STR_WriteListChunk(int list, int id, boolean quad)\r
394 {\r
395         int lenadr;\r
396 \r
397         if (StringLists[list] != NULL && StringLists[list]->stringCount > 0)\r
398         {\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
403                 PC_SkipInt();\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
408                         U_INT pad = 0;\r
409                         PC_Append (&pad, 4);\r
410                 }\r
411                 DumpStrings(StringLists[list], lenadr, quad, NO);\r
412         }\r
413 }\r
414 \r
415 //==========================================================================\r
416 //\r
417 // DumpStrings\r
418 //\r
419 //==========================================================================\r
420 \r
421 static void DumpStrings(stringList_t *list, int lenadr, boolean quad, boolean crypt)\r
422 {\r
423         int i, ofs, startofs;\r
424 \r
425         startofs = ofs = pc_Address - lenadr - 4 + list->stringCount*(quad?8:4);\r
426 \r
427         for(i = 0; i < list->stringCount; i++)\r
428         {\r
429                 if (list->strings[i].name != NULL)\r
430                 {\r
431                         PC_AppendInt((U_INT)ofs);\r
432                         ofs += strlen(list->strings[i].name) + 1;\r
433                 }\r
434                 else\r
435                 {\r
436                         PC_AppendInt(0);\r
437                 }\r
438                 if (quad)\r
439                 {\r
440                         PC_AppendInt(0);\r
441                 }\r
442         }\r
443 \r
444         ofs = startofs;\r
445 \r
446         for(i = 0; i < list->stringCount; i++)\r
447         {\r
448                 if(list->strings[i].name != NULL)\r
449                 {\r
450                         int stringlen = strlen(list->strings[i].name) + 1;\r
451                         if(crypt)\r
452                         {\r
453                                 int cryptkey = ofs*157135;\r
454 \r
455                                 Encrypt(list->strings[i].name, cryptkey, stringlen);\r
456                                 PC_Append(list->strings[i].name, stringlen);\r
457                                 ofs += stringlen;\r
458                                 Encrypt(list->strings[i].name, cryptkey, stringlen);\r
459                         }\r
460                         else\r
461                         {\r
462                                 PC_AppendString(list->strings[i].name);\r
463                         }\r
464                 }\r
465         }\r
466         if(pc_Address%4 != 0)\r
467         { // Need to align\r
468                 U_INT pad = 0;\r
469                 PC_Append((void *)&pad, 4-(pc_Address%4));\r
470         }\r
471 \r
472         PC_WriteInt(pc_Address - lenadr - 4, lenadr);\r
473 }\r
474 \r
475 static void Encrypt(void *data, int key, int len)\r
476 {\r
477         int p = (byte)key, i;\r
478 \r
479         for(i = 0; i < len; ++i)\r
480         {\r
481                 ((byte *)data)[i] ^= (byte)(p+(i>>1));\r
482         }\r
483 }\r