OSDN Git Service

- Bio Hazard's ACC tweaks:
[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 void DumpStrings(stringList_t *list, int lenadr, boolean quad, boolean crypt);\r
49 static void Encrypt(void *data, int key, int len);\r
50 \r
51 // EXTERNAL DATA DECLARATIONS ----------------------------------------------\r
52 \r
53 // PUBLIC DATA DEFINITIONS -------------------------------------------------\r
54 \r
55 int NumLanguages, NumStringLists;\r
56 \r
57 // PRIVATE DATA DEFINITIONS ------------------------------------------------\r
58 \r
59 static languageInfo_t *LanguageInfo[MAX_LANGUAGES];\r
60 static stringList_t *StringLists[NUM_STRLISTS];\r
61 \r
62 // CODE --------------------------------------------------------------------\r
63 \r
64 //==========================================================================\r
65 //\r
66 // STR_Init\r
67 //\r
68 //==========================================================================\r
69 \r
70 void STR_Init(void)\r
71 {\r
72         NumLanguages = NumStringLists = 0;\r
73         STR_FindLanguage(NULL); // Default language is always number 0\r
74 }\r
75 \r
76 //==========================================================================\r
77 //\r
78 // STR_FindLanguage\r
79 //\r
80 //==========================================================================\r
81 \r
82 int STR_FindLanguage(char *name)\r
83 {\r
84         int i;\r
85 \r
86         if (name == NULL)\r
87         {\r
88                 if (NumLanguages > 0)\r
89                 {\r
90                         return 0;\r
91                 }\r
92                 i = 0;\r
93         }\r
94         else\r
95         {\r
96                 for(i = 0; i < NumLanguages; i++)\r
97                 {\r
98                         if (strcmp (name, LanguageInfo[i]->name) == 0)\r
99                         {\r
100                                 return i;\r
101                         }\r
102                 }\r
103         }\r
104         if(i == NumLanguages)\r
105         {\r
106                 LanguageInfo[i] = MS_Alloc(sizeof(languageInfo_t), ERR_OUT_OF_MEMORY);\r
107                 memset(LanguageInfo[i]->name, 0, 4);\r
108                 if(name != NULL)\r
109                 {\r
110                         strncpy(LanguageInfo[i]->name, name, 3);\r
111                 }\r
112                 LanguageInfo[i]->list.stringCount = 0;\r
113                 NumLanguages++;\r
114         }\r
115         return i;\r
116 }\r
117  \r
118 //==========================================================================\r
119 //\r
120 // STR_Find\r
121 //\r
122 //==========================================================================\r
123 \r
124 int STR_Find(char *name)\r
125 {\r
126         return STR_FindInLanguage(0, name);\r
127 }\r
128 \r
129 //==========================================================================\r
130 //\r
131 // STR_FindInLanguage\r
132 //\r
133 //==========================================================================\r
134 \r
135 int STR_FindInLanguage(int language, char *name)\r
136 {\r
137         return STR_FindInSomeList (&LanguageInfo[language]->list, name);\r
138 }\r
139 \r
140 //==========================================================================\r
141 //\r
142 // STR_FindInList\r
143 //\r
144 //==========================================================================\r
145 \r
146 int STR_FindInList(int list, char *name)\r
147 {\r
148         if (StringLists[list] == NULL)\r
149         {\r
150                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
151                 StringLists[list]->stringCount = 0;\r
152                 NumStringLists++;\r
153         }\r
154         return STR_FindInSomeList (StringLists[list], name);\r
155 }\r
156 \r
157 //==========================================================================\r
158 //\r
159 // STR_FindInSomeList\r
160 //\r
161 //==========================================================================\r
162 \r
163 static int STR_FindInSomeList(stringList_t *list, char *name)\r
164 {\r
165         int i;\r
166 \r
167         for(i = 0; i < list->stringCount; i++)\r
168         {\r
169                 if(strcmp(list->strings[i].name, name) == 0)\r
170                 {\r
171                         return i;\r
172                 }\r
173         }\r
174         // Add to list\r
175         return STR_PutStringInSomeList(list, i, name);\r
176 }\r
177 \r
178 //==========================================================================\r
179 //\r
180 // STR_GetString\r
181 //\r
182 //==========================================================================\r
183 \r
184 const char *STR_GetString(int list, int index)\r
185 {\r
186         if (StringLists[list] == NULL)\r
187         {\r
188                 return NULL;\r
189         }\r
190         if (index < 0 || index >= StringLists[list]->stringCount)\r
191         {\r
192                 return NULL;\r
193         }\r
194         return StringLists[list]->strings[index].name;\r
195 }\r
196 \r
197 //==========================================================================\r
198 //\r
199 // STR_AppendToList\r
200 //\r
201 //==========================================================================\r
202 \r
203 int STR_AppendToList(int list, char *name)\r
204 {\r
205         if (StringLists[list] == NULL)\r
206         {\r
207                 StringLists[list] = MS_Alloc(sizeof(stringList_t), ERR_OUT_OF_MEMORY);\r
208                 StringLists[list]->stringCount = 0;\r
209                 NumStringLists++;\r
210         }\r
211         return STR_PutStringInSomeList(StringLists[list], StringLists[list]->stringCount, name);\r
212 }\r
213 \r
214 //==========================================================================\r
215 //\r
216 // STR_PutStringInSomeList\r
217 //\r
218 //==========================================================================\r
219 \r
220 static int STR_PutStringInSomeList(stringList_t *list, int index, char *name)\r
221 {\r
222         int i;\r
223 \r
224         if(index >= MAX_STRINGS)\r
225         {\r
226                 ERR_Error(ERR_TOO_MANY_STRINGS, YES, MAX_STRINGS);\r
227                 return 0;\r
228         }\r
229         MS_Message(MSG_DEBUG, "Adding string %d:\n  \"%s\"\n",\r
230                 list->stringCount, name);\r
231         if(index >= list->stringCount)\r
232         {\r
233                 for(i = list->stringCount; i <= index; i++)\r
234                 {\r
235                         list->strings[i].name = NULL;\r
236                 }\r
237                 list->stringCount = index + 1;\r
238         }\r
239         if(list->strings[index].name != NULL)\r
240         {\r
241                 free(list->strings[index].name);\r
242         }\r
243         if(name != NULL)\r
244         {\r
245                 list->strings[index].name = MS_Alloc(strlen(name)+1, ERR_OUT_OF_MEMORY);\r
246                 strcpy(list->strings[index].name, name);\r
247         }\r
248         else\r
249         {\r
250                 list->strings[index].name = NULL;\r
251         }\r
252         return index;\r
253 }\r
254 \r
255 //==========================================================================\r
256 //\r
257 // STR_ListSize\r
258 //\r
259 //==========================================================================\r
260 \r
261 int STR_ListSize(int list)\r
262 {\r
263         return LanguageInfo[list]->list.stringCount;\r
264 }\r
265 \r
266 //==========================================================================\r
267 //\r
268 // STR_WriteStrings\r
269 //\r
270 // Writes all the strings to the p-code buffer.\r
271 //\r
272 //==========================================================================\r
273 \r
274 void STR_WriteStrings(void)\r
275 {\r
276         int i;\r
277         U_INT pad;\r
278 \r
279         MS_Message(MSG_DEBUG, "---- STR_WriteStrings ----\n");\r
280         for(i = 0; i < LanguageInfo[0]->list.stringCount; i++)\r
281         {\r
282                 LanguageInfo[0]->list.strings[i].address = pc_Address;\r
283                 PC_AppendString(LanguageInfo[0]->list.strings[i].name);\r
284         }\r
285         if(pc_Address%4 != 0)\r
286         { // Need to align\r
287                 pad = 0;\r
288                 PC_Append((void *)&pad, 4-(pc_Address%4));\r
289         }\r
290 }\r
291 \r
292 //==========================================================================\r
293 //\r
294 // STR_WriteList\r
295 //\r
296 //==========================================================================\r
297 \r
298 void STR_WriteList(void)\r
299 {\r
300         int i;\r
301 \r
302         MS_Message(MSG_DEBUG, "---- STR_WriteList ----\n");\r
303         PC_AppendInt((U_INT)LanguageInfo[0]->list.stringCount);\r
304         for(i = 0; i < LanguageInfo[0]->list.stringCount; i++)\r
305         {\r
306                 PC_AppendInt((U_INT)LanguageInfo[0]->list.strings[i].address);\r
307         }\r
308 }\r
309 \r
310 //==========================================================================\r
311 //\r
312 // STR_WriteChunk\r
313 //\r
314 //==========================================================================\r
315 \r
316 void STR_WriteChunk(int language, boolean encrypt)\r
317 {\r
318         languageInfo_t *lang = LanguageInfo[language];\r
319         int lenadr;\r
320 \r
321         MS_Message(MSG_DEBUG, "---- STR_WriteChunk %d ----\n", language);\r
322         PC_Append(encrypt ? "STRE" : "STRL", 4);\r
323         lenadr = pc_Address;\r
324         PC_SkipInt();\r
325         PC_Append(&lang->name, 4);\r
326         PC_AppendInt(lang->list.stringCount);\r
327         PC_AppendInt(0);        // Used in-game for stringing lists together\r
328 \r
329         DumpStrings (&lang->list, lenadr, NO, encrypt);\r
330 }\r
331 \r
332 //==========================================================================\r
333 //\r
334 // STR_WriteListChunk\r
335 //\r
336 //==========================================================================\r
337 \r
338 void STR_WriteListChunk(int list, int id, boolean quad)\r
339 {\r
340         int lenadr;\r
341 \r
342         if (StringLists[list] != NULL && StringLists[list]->stringCount > 0)\r
343         {\r
344                 MS_Message(MSG_DEBUG, "---- STR_WriteListChunk %d %c%c%c%c----\n", list,\r
345                         id&255, (id>>8)&255, (id>>16)&255, (id>>24)&255);\r
346                 PC_AppendInt((U_INT)id);\r
347                 lenadr = pc_Address;\r
348                 PC_SkipInt();\r
349                 PC_AppendInt(StringLists[list]->stringCount);\r
350                 if (quad && pc_Address%8 != 0)\r
351                 { // If writing quadword indices, align the indices to an\r
352                   // 8-byte boundary.\r
353                         U_INT pad = 0;\r
354                         PC_Append (&pad, 4);\r
355                 }\r
356                 DumpStrings(StringLists[list], lenadr, quad, NO);\r
357         }\r
358 }\r
359 \r
360 //==========================================================================\r
361 //\r
362 // DumpStrings\r
363 //\r
364 //==========================================================================\r
365 \r
366 static void DumpStrings(stringList_t *list, int lenadr, boolean quad, boolean crypt)\r
367 {\r
368         int i, ofs, startofs;\r
369 \r
370         startofs = ofs = pc_Address - lenadr - 4 + list->stringCount*(quad?8:4);\r
371 \r
372         for(i = 0; i < list->stringCount; i++)\r
373         {\r
374                 if (list->strings[i].name != NULL)\r
375                 {\r
376                         PC_AppendInt((U_INT)ofs);\r
377                         ofs += strlen(list->strings[i].name) + 1;\r
378                 }\r
379                 else\r
380                 {\r
381                         PC_AppendInt(0);\r
382                 }\r
383                 if (quad)\r
384                 {\r
385                         PC_AppendInt(0);\r
386                 }\r
387         }\r
388 \r
389         ofs = startofs;\r
390 \r
391         for(i = 0; i < list->stringCount; i++)\r
392         {\r
393                 if(list->strings[i].name != NULL)\r
394                 {\r
395                         int stringlen = strlen(list->strings[i].name) + 1;\r
396                         if(crypt)\r
397                         {\r
398                                 int cryptkey = ofs*157135;\r
399 \r
400                                 Encrypt(list->strings[i].name, cryptkey, stringlen);\r
401                                 PC_Append(list->strings[i].name, stringlen);\r
402                                 ofs += stringlen;\r
403                                 Encrypt(list->strings[i].name, cryptkey, stringlen);\r
404                         }\r
405                         else\r
406                         {\r
407                                 PC_AppendString(list->strings[i].name);\r
408                         }\r
409                 }\r
410         }\r
411         if(pc_Address%4 != 0)\r
412         { // Need to align\r
413                 U_INT pad = 0;\r
414                 PC_Append((void *)&pad, 4-(pc_Address%4));\r
415         }\r
416 \r
417         PC_WriteInt(pc_Address - lenadr - 4, lenadr);\r
418 }\r
419 \r
420 static void Encrypt(void *data, int key, int len)\r
421 {\r
422         int p = (byte)key, i;\r
423 \r
424         for(i = 0; i < len; ++i)\r
425         {\r
426                 ((byte *)data)[i] ^= (byte)(p+(i>>1));\r
427         }\r
428 }\r