1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | #define _text_public_c |
32 | |
33 | #include "system.h" |
34 | |
35 | #include "defs.h" |
36 | #include "struct.h" |
37 | #include "proto.h" |
38 | #include "global.h" |
39 | |
40 | #include <zlib.h> |
41 | |
42 | extern int debug_level; |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | void *MyMalloc(long Mamount) |
50 | { |
51 | void *Mptr = NULL((void*)0); |
52 | |
53 | |
54 | if (Mamount == 0) |
| 7 | | Assuming 'Mamount' is not equal to 0 | |
|
| |
55 | Mamount = 1; |
56 | |
57 | if ((Mptr = calloc(1, (size_t) Mamount)) == NULL((void*)0)) { |
| |
| |
58 | fprintf(stderrstderr, " MyMalloc(%ld) did not succeed!\n", Mamount); |
59 | fflush(stderrstderr); |
60 | Terminate(EXIT_FAILURE1); |
61 | } |
62 | |
63 | return Mptr; |
64 | |
65 | }; |
66 | |
67 | |
68 | |
69 | |
70 | |
71 | |
72 | void DebugPrintf(int db_level, const char *fmt, ...) |
73 | { |
74 | va_list args; |
75 | va_start(args, fmt)__builtin_va_start(args, fmt); |
76 | |
77 | if (db_level <= debug_level) { |
78 | vfprintf(stderrstderr, fmt, args); |
79 | } |
80 | |
81 | va_end(args)__builtin_va_end(args); |
82 | }; |
83 | |
84 | |
85 | |
86 | |
87 | |
88 | void error_message(const char *fn, const char *fmt, int error_type, ...) |
89 | { |
90 | if (error_type & SILENT) |
91 | return; |
92 | |
93 | va_list args; |
94 | va_start(args, error_type)__builtin_va_start(args, error_type); |
95 | |
96 | fprintf(stderrstderr, "\n---------------------------------------------------------------------------------\n" |
97 | "FreedroidRPG %s encountered a problem in function: %s\n", freedroid_version, fn); |
98 | vfprintf(stderrstderr, fmt, args); |
99 | fprintf(stderrstderr, "\n"); |
100 | |
101 | va_end(args)__builtin_va_end(args); |
102 | |
103 | if (error_type & PLEASE_INFORM) { |
104 | fprintf(stderrstderr, "\n\n" |
105 | "If you encounter this message, please inform the FreedroidRPG developers about it!\n" |
106 | "You can\n" |
107 | " send an e-mail to freedroid-discussion AT lists.sourceforge.net\n""" |
108 | " mention it on our IRC channel #freedroid on irc.freenode.net\n" |
109 | " or report the bug on our tracker at http://bugs.freedroid.org/\n" |
110 | "\n" |
111 | "Thank you!\n"); |
112 | } |
113 | |
114 | if (error_type & IS_FATAL) { |
115 | fprintf(stderrstderr, "\nFreedroidRPG will terminate now to draw attention to the problems it could\n" |
116 | "not resolve. We are sorry if that interrupts a major game of yours.\n" |
117 | "---------------------------------------------------------------------------------\n"); |
118 | } else { |
119 | fprintf(stderrstderr, "\nThe problem mentioned above is not fatal, we continue the execution.\n" |
120 | "---------------------------------------------------------------------------------\n"); |
121 | } |
122 | |
123 | if (error_type & IS_FATAL) |
124 | Terminate(EXIT_FAILURE1); |
125 | } |
126 | |
127 | |
128 | |
129 | |
130 | |
131 | |
132 | |
133 | |
134 | |
135 | |
136 | |
137 | |
138 | |
139 | void *MyMemmem(char *haystack, size_t haystacklen, char *needle, size_t needlelen) |
140 | { |
141 | char *NextFoundPointer; |
142 | void *MatchPointer; |
143 | size_t SearchPos = 0; |
144 | |
145 | while (haystacklen - SearchPos > 0) { |
146 | |
147 | |
148 | NextFoundPointer = memchr(haystack + SearchPos, needle[0], haystacklen - SearchPos); |
149 | |
150 | |
151 | |
152 | if (NextFoundPointer == NULL((void*)0)) |
153 | return (NULL((void*)0)); |
154 | |
155 | |
156 | |
157 | |
158 | MatchPointer = strstr(NextFoundPointer, needle); |
159 | if (MatchPointer != NULL((void*)0)) |
160 | return (MatchPointer); |
161 | |
162 | |
163 | |
164 | SearchPos = NextFoundPointer - haystack + 1; |
165 | } |
166 | |
167 | return (NULL((void*)0)); |
168 | }; |
169 | |
170 | |
171 | |
172 | |
173 | |
174 | |
175 | |
176 | |
177 | char *ReadAndMallocStringFromDataOptional(char *SearchString, const char *StartIndicationString, const char *EndIndicationString) |
178 | { |
179 | char *SearchPointer; |
180 | char *EndOfStringPointer; |
181 | char *ReturnString = NULL((void*)0); |
182 | int StringLength; |
183 | |
184 | SearchPointer = strstr(SearchString, StartIndicationString); |
185 | |
186 | if (!SearchPointer) |
| 2 | | Assuming 'SearchPointer' is non-null | |
|
| |
187 | return 0; |
188 | |
189 | |
190 | SearchPointer += strlen(StartIndicationString); |
191 | |
192 | |
193 | EndOfStringPointer = strstr(SearchPointer, EndIndicationString); |
194 | if (!EndOfStringPointer) |
| 4 | | Assuming 'EndOfStringPointer' is non-null | |
|
| |
195 | return 0; |
196 | |
197 | |
198 | StringLength = EndOfStringPointer - SearchPointer; |
199 | ReturnString = MyMalloc(StringLength + 1); |
| |
| 11 | | Returned allocated memory | |
|
200 | strncpy(ReturnString, SearchPointer, StringLength)__builtin_strncpy (ReturnString, SearchPointer, StringLength); |
201 | ReturnString[StringLength] = 0; |
202 | |
203 | return ReturnString; |
204 | } |
205 | |
206 | |
207 | |
208 | |
209 | |
210 | |
211 | |
212 | |
213 | char *ReadAndMallocStringFromData(char *SearchString, const char *StartIndicationString, const char *EndIndicationString) |
214 | { |
215 | char *result = ReadAndMallocStringFromDataOptional(SearchString, StartIndicationString, EndIndicationString); |
216 | if (!result) { |
217 | fprintf(stderrstderr, "\n\nStartIndicationString: '%s'\nEndIndicationString: '%s'\n", StartIndicationString, EndIndicationString); |
218 | error_message(__FUNCTION__, "\ |
219 | The string that is supposed to prefix an entry in a text data file\n\ |
220 | of FreedroidRPG was not found within this text data file.\n\ |
221 | This indicates some corruption in the data file in question.", PLEASE_INFORM | IS_FATAL); |
222 | } |
223 | return result; |
224 | }; |
225 | |
226 | |
227 | |
228 | |
229 | |
230 | int CountStringOccurences(char *SearchString, const char *TargetString) |
231 | { |
232 | int Counter = 0; |
233 | char *CountPointer; |
234 | |
235 | CountPointer = SearchString; |
236 | |
237 | while ((CountPointer = strstr(CountPointer, TargetString)) != NULL((void*)0)) { |
238 | CountPointer += strlen(TargetString); |
239 | Counter++; |
240 | } |
241 | return (Counter); |
242 | }; |
243 | |
244 | |
245 | |
246 | |
247 | |
248 | |
249 | |
250 | char *ReadAndMallocAndTerminateFile(const char *filename, const char *File_End_String) |
251 | { |
252 | FILE *DataFile; |
253 | char *Data; |
254 | char *ReadPointer; |
255 | long MemoryAmount; |
256 | |
257 | |
258 | |
259 | |
260 | |
261 | if ((DataFile = fopen(filename, "rb")) == NULL((void*)0)) { |
262 | fprintf(stderrstderr, "\n\nfilename: '%s'\n", filename); |
263 | |
264 | error_message(__FUNCTION__, "\ |
265 | FreedroidRPG was unable to open a given text file,\n\ |
266 | that should be there and should be accessible.\n\ |
267 | This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM | IS_FATAL); |
268 | } else { |
269 | DebugPrintf(1, "\nchar* ReadAndMallocAndTerminateFile ( char* filename ) : Opening file succeeded..."); |
270 | } |
271 | |
272 | int filelen = FS_filelength(DataFile); |
273 | MemoryAmount = filelen + 100; |
274 | Data = (char *)MyMalloc(MemoryAmount); |
275 | |
276 | if (fread(Data, 1, MemoryAmount, DataFile) < filelen && ferror(DataFile)) { |
277 | error_message(__FUNCTION__, "\ |
278 | FreedroidRPG was unable to read a given text file, that should be there and\n\ |
279 | should be accessible.\n\ |
280 | Filename: %s", PLEASE_INFORM | IS_FATAL, filename); |
281 | } else { |
282 | DebugPrintf(1, "\n%s(): Reading file succeeded...", __FUNCTION__); |
283 | } |
284 | |
285 | if (fclose(DataFile) == EOF(-1)) { |
286 | fprintf(stderrstderr, "\n\nfilename: '%s'\n", filename); |
287 | error_message(__FUNCTION__, "\ |
288 | FreedroidRPG was unable to close a given text file, that should be there and\n\ |
289 | should be accessible.\n\ |
290 | This indicates a strange bug in this installation of Freedroid, that is\n\ |
291 | very likely a problem with the file/directory permissions of the files\n\ |
292 | belonging to FreedroidRPG.", PLEASE_INFORM | IS_FATAL); |
293 | } else { |
294 | DebugPrintf(1, "\n%s(): file closed successfully...\n", __FUNCTION__); |
295 | } |
296 | |
297 | |
298 | |
299 | if (File_End_String) { |
300 | if ((ReadPointer = MyMemmem(Data, (size_t) MemoryAmount, (char *)File_End_String, (size_t) strlen(File_End_String))) == NULL((void*)0)) { |
301 | error_message(__FUNCTION__, "FreedroidRPG was unable to find the string, that should indicate the end of\n" |
302 | "the given text file within this file.\n" |
303 | "This indicates a corrupt or outdated data or saved game file." |
304 | " filename: '%s' - File_End_String: '%s'", |
305 | PLEASE_INFORM | IS_FATAL, filename, File_End_String); |
306 | } else { |
307 | ReadPointer[0] = 0; |
308 | } |
309 | } else |
310 | Data[MemoryAmount - 100] = 0; |
311 | |
312 | return (Data); |
313 | } |
314 | |
315 | |
316 | |
317 | |
318 | |
319 | |
320 | |
321 | |
322 | |
323 | char *LocateStringInData(char *SearchBeginPointer, const char *SearchTextPointer) |
324 | { |
325 | char *temp; |
326 | |
327 | if ((temp = strstr(SearchBeginPointer, SearchTextPointer)) == NULL((void*)0)) { |
328 | fprintf(stderrstderr, "\n\nSearchTextPointer: '%s'\n", SearchTextPointer); |
329 | error_message(__FUNCTION__, "\ |
330 | The string that was supposed to be in the text data file could not be found.\n\ |
331 | This indicates a corrupted or seriously outdated game data or saved game file.", PLEASE_INFORM | IS_FATAL); |
332 | } |
333 | |
334 | return (temp); |
335 | |
336 | }; |
337 | |
338 | |
339 | |
340 | |
341 | |
342 | void |
343 | ReadValueFromStringWithDefault(char *SearchBeginPointer, const char *ValuePreceedText, const char *FormatString, |
344 | const char *DefaultValueString, void *TargetValue, char *EndOfSearchSectionPointer) |
345 | { |
346 | char OldTerminaterCharValue = 0; |
347 | const char *SourceLocation; |
348 | |
349 | |
350 | if (EndOfSearchSectionPointer) { |
351 | OldTerminaterCharValue = EndOfSearchSectionPointer[0]; |
352 | EndOfSearchSectionPointer[0] = 0; |
353 | } |
354 | |
355 | |
356 | SourceLocation = strstr(SearchBeginPointer, ValuePreceedText); |
357 | if (SourceLocation) |
358 | SourceLocation += strlen(ValuePreceedText); |
359 | else |
360 | SourceLocation = DefaultValueString; |
361 | |
362 | |
363 | |
364 | |
365 | if (sscanf(SourceLocation, FormatString, TargetValue) == EOF(-1)) { |
366 | error_message(__FUNCTION__, "sscanf using a certain format string failed!\n" |
367 | "This indicates a corrupted or seriously outdated game data or saved game file.\n" |
368 | " FormatString: '%s' - ValuePreceedText: '%s'", |
369 | PLEASE_INFORM | IS_FATAL, FormatString, ValuePreceedText); |
370 | } |
371 | |
372 | if (EndOfSearchSectionPointer) { |
373 | EndOfSearchSectionPointer[0] = OldTerminaterCharValue; |
374 | } |
375 | } |
376 | |
377 | |
378 | |
379 | |
380 | |
381 | void |
382 | ReadValueFromString(char *SearchBeginPointer, const char *ValuePreceedText, const char *FormatString, void *TargetValue, |
383 | char *EndOfSearchSectionPointer) |
384 | { |
385 | char OldTerminaterCharValue = 0; |
386 | char *SourceLocation; |
387 | |
388 | |
389 | if (EndOfSearchSectionPointer) { |
390 | OldTerminaterCharValue = EndOfSearchSectionPointer[0]; |
391 | EndOfSearchSectionPointer[0] = 0; |
392 | } |
393 | |
394 | SourceLocation = LocateStringInData(SearchBeginPointer, ValuePreceedText); |
395 | SourceLocation += strlen(ValuePreceedText); |
396 | |
397 | |
398 | |
399 | |
400 | if (sscanf(SourceLocation, FormatString, TargetValue) == EOF(-1)) { |
401 | error_message(__FUNCTION__, "sscanf using a certain format string failed!\n" |
402 | "This indicates a corrupted or seriously outdated game data or saved game file.\n" |
403 | " FormatString: '%s' - ValuePreceedText: '%s'", |
404 | PLEASE_INFORM | IS_FATAL, FormatString, ValuePreceedText); |
405 | } |
406 | |
407 | if (EndOfSearchSectionPointer) { |
408 | |
409 | EndOfSearchSectionPointer[0] = OldTerminaterCharValue; |
410 | } |
411 | |
412 | }; |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | |
419 | |
420 | |
421 | |
422 | |
423 | |
424 | |
425 | |
426 | |
427 | int ReadRangeFromString(char *SearchString, const char *StartIndicationString, const char *EndIndicationString, int *min, int *max, int default_val) |
428 | { |
429 | int result; |
430 | |
431 | |
432 | char *search_ptr = ReadAndMallocStringFromDataOptional(SearchString, StartIndicationString, EndIndicationString); |
| 1 | Calling 'ReadAndMallocStringFromDataOptional' | |
|
| 12 | | Returned allocated memory | |
|
433 | |
434 | result = get_range_from_string(search_ptr, min, max, default_val); |
435 | |
436 | |
437 | if (*min < 0) { |
| |
438 | error_message(__FUNCTION__, "\ |
| 14 | | Potential leak of memory pointed to by 'search_ptr' |
|
439 | The value read in as a minimum (%d) is a negative number.\n\ |
440 | This most likely means corrupted data.\n\ |
441 | Setting both the maximum and minimum to the default value (%d).", NO_REPORT, *min, default_val); |
442 | *min = *max = default_val; |
443 | return FALSE(0); |
444 | } |
445 | |
446 | free(search_ptr); |
447 | |
448 | return result; |
449 | } |
450 | |
451 | |
452 | |
453 | |
454 | |
455 | |
456 | |
457 | |
458 | int get_range_from_string(const char *str, int *min, int *max, int default_value) |
459 | { |
460 | char *ptr; |
461 | |
462 | if (!str) { |
463 | |
464 | *min = *max = default_value; |
465 | return TRUE(1); |
466 | } |
467 | |
468 | *min = strtol(str, &ptr, 10); |
469 | |
470 | if (str == ptr) { |
471 | goto read_error; |
472 | } |
473 | |
474 | if (*ptr == '\0') { |
475 | |
476 | *max = *min; |
477 | return TRUE(1); |
478 | } |
479 | |
480 | if (*ptr != ':') { |
481 | goto read_error; |
482 | } |
483 | |
484 | |
485 | str = ++ptr; |
486 | *max = strtol(str, &ptr, 10); |
487 | |
488 | if (str == ptr) { |
489 | goto read_error; |
490 | } |
491 | |
492 | |
493 | if (*max >= *min) { |
494 | return TRUE(1); |
495 | } |
496 | |
497 | error_message(__FUNCTION__, "The value read in as a maximum (%d) is less than the minimum (%d).\n" |
498 | "This most likely means corrupted data.\n" |
499 | "Setting both the maximum and minimum to the default value (%d).", |
500 | NO_REPORT, *max, *min, default_value); |
501 | *min = *max = default_value; |
502 | return FALSE(0); |
503 | |
504 | read_error: |
505 | |
506 | error_message(__FUNCTION__, "The string (\"%s\") cannot be legaly converted to a range of integers.\n" |
507 | "This most likely means corrupted data.\n" |
508 | "Setting both the maximum and minimum to the default value (%d).", |
509 | NO_REPORT, str, default_value); |
510 | *min = *max = default_value; |
511 | return FALSE(0); |
512 | } |
513 | |
514 | |
515 | |
516 | |
517 | |
518 | |
519 | |
520 | void RotateVectorByAngle(moderately_finepoint * vector, float rot_angle) |
521 | { |
522 | moderately_finepoint new_vect; |
523 | float rad_angle; |
524 | |
525 | if (rot_angle == 0) |
526 | return; |
527 | |
528 | rad_angle = rot_angle * (M_PI3.14159265358979323846 / 180.0); |
529 | |
530 | DebugPrintf(2, "\n RAD_ANGLE : %f ", rad_angle); |
531 | new_vect.x = sin(rad_angle) * vector->y + cos(rad_angle) * vector->x; |
532 | new_vect.y = cos(rad_angle) * vector->y - sin(rad_angle) * vector->x; |
533 | vector->x = new_vect.x; |
534 | vector->y = new_vect.y; |
535 | |
536 | }; |
537 | |
538 | |
539 | |
540 | |
541 | |
542 | |
543 | |
544 | int FS_filelength(FILE * f) |
545 | { |
546 | int pos; |
547 | int end; |
548 | |
549 | pos = ftell(f); |
550 | fseek(f, 0, SEEK_END2); |
551 | end = ftell(f); |
552 | fseek(f, pos, SEEK_SET0); |
553 | |
554 | |
555 | |
556 | return end; |
557 | }; |
558 | |
559 | |
560 | |
561 | |
562 | |
563 | |
564 | |
565 | |
566 | |
567 | |
568 | int inflate_stream(FILE * DataFile, unsigned char **DataBuffer, int *size) |
569 | { |
570 | int filelen = FS_filelength(DataFile); |
571 | unsigned char *src = MyMalloc(filelen + 1); |
572 | int cursz = 1048576; |
573 | unsigned char *temp_dbuffer = malloc(cursz); |
574 | if (fread(src, filelen, 1, DataFile) != 1) { |
575 | error_message(__FUNCTION__, "Error reading compressed data stream.", PLEASE_INFORM); |
576 | free(temp_dbuffer); |
577 | free(src); |
578 | return -1; |
579 | } |
580 | |
581 | int ret; |
582 | z_stream strm; |
583 | |
584 | |
585 | |
586 | |
587 | strm.zalloc = Z_NULL0; |
588 | strm.zfree = Z_NULL0; |
589 | strm.opaque = Z_NULL0; |
590 | strm.avail_in = filelen; |
591 | strm.next_in = src; |
592 | strm.avail_out = cursz; |
593 | strm.next_out = (Bytef *) temp_dbuffer; |
594 | |
595 | ret = inflateInit2(&strm, 47)inflateInit2_((&strm), (47), "1.2.8", (int)sizeof(z_stream )); |
596 | if (ret != Z_OK0) { |
597 | error_message(__FUNCTION__, "\ |
598 | zlib was unable to start decompressing a stream.\n\ |
599 | This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM); |
600 | free(temp_dbuffer); |
601 | free(src); |
602 | return -1; |
603 | } |
604 | |
605 | do { |
606 | if (!strm.avail_out) { |
607 | temp_dbuffer = realloc(temp_dbuffer, cursz + 1048576); |
608 | strm.next_out = temp_dbuffer + cursz; |
609 | cursz += 1048576; |
610 | strm.avail_out += 1048576; |
611 | } |
612 | ret = inflate(&strm, Z_NO_FLUSH0); |
613 | switch (ret) { |
614 | case Z_OK0: |
615 | break; |
616 | case Z_NEED_DICT2: |
617 | case Z_DATA_ERROR(-3): |
618 | case Z_MEM_ERROR(-4): |
619 | (void)inflateEnd(&strm); |
620 | |
621 | error_message(__FUNCTION__, "\ |
622 | zlib was unable to decompress a stream\n\ |
623 | This indicates a serious bug in this installation of FreedroidRPG.", PLEASE_INFORM); |
624 | free(temp_dbuffer); |
625 | free(src); |
626 | return -1; |
627 | break; |
628 | } |
629 | } while (ret != Z_STREAM_END1); |
630 | |
631 | (*DataBuffer) = (unsigned char *)malloc(strm.total_out + 1); |
632 | memcpy(*DataBuffer, temp_dbuffer, strm.total_out); |
633 | (*DataBuffer)[strm.total_out] = 0; |
634 | |
635 | if (size != NULL((void*)0)) |
636 | *size = strm.total_out; |
637 | |
638 | (void)inflateEnd(&strm); |
639 | free(src); |
640 | free(temp_dbuffer); |
641 | |
642 | return 0; |
643 | } |
644 | |
645 | int deflate_to_stream(unsigned char *source_buffer, int size, FILE *dest) |
646 | { |
647 | int ret; |
648 | unsigned have; |
649 | z_stream strm; |
650 | #define CHUNK16384 16384 |
651 | unsigned char out[CHUNK16384]; |
652 | |
653 | |
654 | strm.zalloc = Z_NULL0; |
655 | strm.zfree = Z_NULL0; |
656 | strm.opaque = Z_NULL0; |
657 | strm.avail_in = size; |
658 | strm.next_in = source_buffer; |
659 | |
660 | ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY)deflateInit2_((&strm),((-1)),(8),(31),(8), (0), "1.2.8", ( int)sizeof(z_stream)); |
661 | if (ret != Z_OK0) { |
662 | error_message(__FUNCTION__, "\ |
663 | zlib was unable to start compressing a string.", PLEASE_INFORM); |
664 | return -1; |
665 | } |
666 | |
667 | |
668 | |
669 | do { |
670 | strm.avail_out = CHUNK16384; |
671 | strm.next_out = out; |
672 | ret = deflate(&strm, Z_FINISH4); |
673 | have = CHUNK16384 - strm.avail_out; |
674 | if (fwrite(out, 1, have, dest) != have || ferror(dest)) { |
675 | (void)deflateEnd(&strm); |
676 | return -1; |
677 | } |
678 | } while (strm.avail_out == 0); |
679 | |
680 | |
681 | (void)deflateEnd(&strm); |
682 | |
683 | return 0; |
684 | } |
685 | |
686 | #undef _text_public_c |