summaryrefslogtreecommitdiff
path: root/apps/plugins/xrick/resources.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/xrick/resources.c')
-rw-r--r--apps/plugins/xrick/resources.c1297
1 files changed, 1297 insertions, 0 deletions
diff --git a/apps/plugins/xrick/resources.c b/apps/plugins/xrick/resources.c
new file mode 100644
index 0000000000..d7b49e8f73
--- /dev/null
+++ b/apps/plugins/xrick/resources.c
@@ -0,0 +1,1297 @@
1/*
2 * xrick/resources.c
3 *
4 * Copyright (C) 2008-2014 Pierluigi Vicinanza. All rights reserved.
5 *
6 * The use and distribution terms for this software are contained in the file
7 * named README, which can be found in the root of this distribution. By
8 * using this software in any fashion, you are agreeing to be bound by the
9 * terms of this license.
10 *
11 * You must not remove this notice, or any other, from this software.
12 */
13
14#include "xrick/resources.h"
15
16#include "xrick/draw.h"
17#include "xrick/ents.h"
18#include "xrick/maps.h"
19#include "xrick/util.h"
20#include "xrick/data/sprites.h"
21#include "xrick/data/tiles.h"
22#include "xrick/data/pics.h"
23#include "xrick/system/basic_funcs.h"
24
25#include "xrick/system/miniz_config.h"
26#include "miniz/miniz.c"
27
28/*
29 * prototypes
30 */
31static bool readFile(const unsigned id);
32static bool checkCrc32(const unsigned id);
33static bool readHeader(file_t fp, const unsigned id);
34static bool loadString(file_t fp, char ** str, const char terminator);
35static void unloadString(char ** buffer);
36static bool loadResourceFilelist(file_t fp);
37static void unloadResourceFilelist(void);
38static bool loadResourceEntdata(file_t fp);
39static void unloadResourceEntdata(void);
40static bool loadRawData(file_t fp, void ** buffer, const size_t size, size_t * count);
41static void unloadRawData(void ** buffer, size_t * count);
42static bool loadResourceMaps(file_t fp);
43static void unloadResourceMaps(void);
44static bool loadResourceSubmaps(file_t fp);
45static void unloadResourceSubmaps(void);
46static bool loadResourceImapsteps(file_t fp);
47static void unloadResourceImapsteps(void);
48static bool loadResourceImaptext(file_t fp);
49static void unloadResourceImaptext(void);
50static bool loadResourceHighScores(file_t fp);
51static void unloadResourceHighScores(void);
52static bool loadResourceSpritesData(file_t fp);
53static void unloadResourceSpritesData(void);
54static bool loadResourceTilesData(file_t fp);
55static void unloadResourceTilesData(void);
56static bool loadImage(file_t fp, img_t ** image);
57static void unloadImage(img_t ** image);
58#ifdef GFXST
59static bool loadPicture(file_t fp, pic_t ** picture);
60static void unloadPicture(pic_t ** picture);
61#endif /* GFXST */
62#ifdef ENABLE_SOUND
63static bool fromResourceIdToSound(const unsigned id, sound_t *** sound);
64static bool loadSound(const unsigned id);
65static void unloadSound(const unsigned id);
66#endif /* ENABLE_SOUND */
67
68/*
69 * local vars
70 */
71static char * resourceFiles[Resource_MAX_COUNT] =
72{
73 BOOTSTRAP_RESOURCE_NAME,
74 /* the rest initialised to NULL by default */
75};
76
77/*
78 * load 16b length + not-terminated string
79 */
80static bool loadString(file_t fp, char ** buffer, const char terminator)
81{
82 size_t length;
83 U16 u16Temp;
84 char * bufferTemp;
85
86 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
87 {
88 return false;
89 }
90 length = letoh16(u16Temp);
91
92 bufferTemp = sysmem_push(length + 1);
93 *buffer = bufferTemp;
94 if (!bufferTemp)
95 {
96 return false;
97 }
98
99 if (length)
100 {
101 if (sysfile_read(fp, bufferTemp, length, 1) != 1)
102 {
103 return false;
104 }
105 }
106
107 bufferTemp[length] = terminator;
108
109 return true;
110}
111
112/*
113 *
114 */
115static void unloadString(char ** buffer)
116{
117 sysmem_pop(*buffer);
118 *buffer = NULL;
119}
120
121/*
122 *
123 */
124static bool loadResourceFilelist(file_t fp)
125{
126 unsigned id;
127
128 for (id = Resource_PALETTE; id < Resource_MAX_COUNT; ++id)
129 {
130 if (!loadString(fp, &(resourceFiles[id]), 0x00))
131 {
132 return false;
133 }
134 }
135 return true;
136}
137
138/*
139 *
140 */
141static void unloadResourceFilelist()
142{
143 unsigned id;
144
145 for (id = Resource_MAX_COUNT - 1; id >= Resource_PALETTE; --id)
146 {
147 unloadString(&(resourceFiles[id]));
148 }
149}
150
151/*
152 *
153 */
154static bool loadResourceEntdata(file_t fp)
155{
156 size_t i;
157 U16 u16Temp;
158 resource_entdata_t dataTemp;
159
160 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
161 {
162 return false;
163 }
164 ent_nbr_entdata = letoh16(u16Temp);
165
166 ent_entdata = sysmem_push(ent_nbr_entdata * sizeof(*ent_entdata));
167 if (!ent_entdata)
168 {
169 return false;
170 }
171
172 for (i = 0; i < ent_nbr_entdata; ++i)
173 {
174 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
175 {
176 return false;
177 }
178 ent_entdata[i].w = dataTemp.w;
179 ent_entdata[i].h = dataTemp.h;
180 memcpy(&u16Temp, dataTemp.spr, sizeof(U16));
181 ent_entdata[i].spr = letoh16(u16Temp);
182 memcpy(&u16Temp, dataTemp.sni, sizeof(U16));
183 ent_entdata[i].sni = letoh16(u16Temp);
184 ent_entdata[i].trig_w = dataTemp.trig_w;
185 ent_entdata[i].trig_h = dataTemp.trig_h;
186 ent_entdata[i].snd = dataTemp.snd;
187 }
188 return true;
189}
190
191/*
192 *
193 */
194static void unloadResourceEntdata()
195{
196 sysmem_pop(ent_entdata);
197 ent_entdata = NULL;
198 ent_nbr_entdata = 0;
199}
200
201/*
202 *
203 */
204static bool loadRawData(file_t fp, void ** buffer, const size_t size, size_t * count)
205{
206 U16 u16Temp;
207 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
208 {
209 return false;
210 }
211 *count = letoh16(u16Temp);
212
213 *buffer = sysmem_push((*count) * size);
214 if (!(*buffer))
215 {
216 return false;
217 }
218
219 if (sysfile_read(fp, *buffer, size, *count) != (int)(*count))
220 {
221 return false;
222 }
223 return true;
224}
225
226/*
227 *
228 */
229static void unloadRawData(void ** buffer, size_t * count)
230{
231 sysmem_pop(*buffer);
232 *buffer = NULL;
233 *count = 0;
234}
235
236/*
237 *
238 */
239static bool loadResourceMaps(file_t fp)
240{
241 size_t i;
242 U16 u16Temp;
243 resource_map_t dataTemp;
244
245 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
246 {
247 return false;
248 }
249 map_nbr_maps = letoh16(u16Temp);
250
251 map_maps = sysmem_push(map_nbr_maps * sizeof(*map_maps));
252 if (!map_maps)
253 {
254 return false;
255 }
256
257 for (i = 0; i < map_nbr_maps; ++i)
258 {
259#ifdef ENABLE_SOUND
260 sound_t **soundTemp;
261#endif
262 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
263 {
264 return false;
265 }
266 memcpy(&u16Temp, dataTemp.x, sizeof(U16));
267 map_maps[i].x = letoh16(u16Temp);
268 memcpy(&u16Temp, dataTemp.y, sizeof(U16));
269 map_maps[i].y = letoh16(u16Temp);
270 memcpy(&u16Temp, dataTemp.row, sizeof(U16));
271 map_maps[i].row = letoh16(u16Temp);
272 memcpy(&u16Temp, dataTemp.submap, sizeof(U16));
273 map_maps[i].submap = letoh16(u16Temp);
274#ifdef ENABLE_SOUND
275 memcpy(&u16Temp, dataTemp.tuneId, sizeof(U16));
276 if (!fromResourceIdToSound(letoh16(u16Temp), &soundTemp))
277 {
278 return false;
279 }
280 map_maps[i].tune = *soundTemp;
281#endif /* ENABLE_SOUND */
282 }
283 return true;
284}
285
286/*
287 *
288 */
289static void unloadResourceMaps()
290{
291 sysmem_pop(map_maps);
292 map_maps = NULL;
293 map_nbr_maps = 0;
294}
295
296/*
297 *
298 */
299static bool loadResourceSubmaps(file_t fp)
300{
301 size_t i;
302 U16 u16Temp;
303 resource_submap_t dataTemp;
304
305 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
306 {
307 return false;
308 }
309 map_nbr_submaps = letoh16(u16Temp);
310
311 map_submaps = sysmem_push(map_nbr_submaps * sizeof(*map_submaps));
312 if (!map_submaps)
313 {
314 return false;
315 }
316
317 for (i = 0; i < map_nbr_submaps; ++i)
318 {
319 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
320 {
321 return false;
322 }
323 memcpy(&u16Temp, dataTemp.page, sizeof(U16));
324 map_submaps[i].page = letoh16(u16Temp);
325 memcpy(&u16Temp, dataTemp.bnum, sizeof(U16));
326 map_submaps[i].bnum = letoh16(u16Temp);
327 memcpy(&u16Temp, dataTemp.connect, sizeof(U16));
328 map_submaps[i].connect = letoh16(u16Temp);
329 memcpy(&u16Temp, dataTemp.mark, sizeof(U16));
330 map_submaps[i].mark = letoh16(u16Temp);
331 }
332 return true;
333}
334
335/*
336 *
337 */
338static void unloadResourceSubmaps()
339{
340 sysmem_pop(map_submaps);
341 map_submaps = NULL;
342 map_nbr_submaps = 0;
343}
344
345/*
346 *
347 */
348static bool loadResourceImapsteps(file_t fp)
349{
350 size_t i;
351 U16 u16Temp;
352 resource_imapsteps_t dataTemp;
353
354 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
355 {
356 return false;
357 }
358 screen_nbr_imapstesps = letoh16(u16Temp);
359
360 screen_imapsteps = sysmem_push(screen_nbr_imapstesps * sizeof(*screen_imapsteps));
361 if (!screen_imapsteps)
362 {
363 return false;
364 }
365
366 for (i = 0; i < screen_nbr_imapstesps; ++i)
367 {
368 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
369 {
370 return false;
371 }
372 memcpy(&u16Temp, dataTemp.count, sizeof(U16));
373 screen_imapsteps[i].count = letoh16(u16Temp);
374 memcpy(&u16Temp, dataTemp.dx, sizeof(U16));
375 screen_imapsteps[i].dx = letoh16(u16Temp);
376 memcpy(&u16Temp, dataTemp.dy, sizeof(U16));
377 screen_imapsteps[i].dy = letoh16(u16Temp);
378 memcpy(&u16Temp, dataTemp.base, sizeof(U16));
379 screen_imapsteps[i].base = letoh16(u16Temp);
380 }
381 return true;
382}
383
384/*
385 *
386 */
387static void unloadResourceImapsteps()
388{
389 sysmem_pop(screen_imapsteps);
390 screen_imapsteps = NULL;
391 screen_nbr_imapstesps = 0;
392}
393
394/*
395 *
396 */
397static bool loadResourceImaptext(file_t fp)
398{
399 size_t i;
400 U16 u16Temp;
401
402 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
403 {
404 return false;
405 }
406 screen_nbr_imaptext = letoh16(u16Temp);
407
408 screen_imaptext = sysmem_push(screen_nbr_imaptext * sizeof(*screen_imaptext));
409 if (!screen_imapsteps)
410 {
411 return false;
412 }
413
414 for (i = 0; i < screen_nbr_imaptext; ++i)
415 {
416 if (!loadString(fp, (char **)(&(screen_imaptext[i])), 0xFE))
417 {
418 return false;
419 }
420 }
421 return true;
422}
423
424/*
425 *
426 */
427static void unloadResourceImaptext()
428{
429 int i;
430
431 for (i = screen_nbr_imaptext - 1; i >= 0; --i)
432 {
433 unloadString((char **)(&(screen_imaptext[i])));
434 }
435
436 sysmem_pop(screen_imaptext);
437 screen_imaptext = NULL;
438 screen_nbr_imaptext = 0;
439}
440
441/*
442 *
443 */
444static bool loadResourceHighScores(file_t fp)
445{
446 size_t i;
447 U16 u16Temp;
448 U32 u32Temp;
449 resource_hiscore_t dataTemp;
450
451 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
452 {
453 return false;
454 }
455 screen_nbr_hiscores = letoh16(u16Temp);
456
457 screen_highScores = sysmem_push(screen_nbr_hiscores * sizeof(*screen_highScores));
458 if (!screen_highScores)
459 {
460 return false;
461 }
462
463 for (i = 0; i < screen_nbr_hiscores; ++i)
464 {
465 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
466 {
467 return false;
468 }
469 memcpy(&u32Temp, dataTemp.score, sizeof(U32));
470 screen_highScores[i].score = letoh32(u32Temp);
471 memcpy(screen_highScores[i].name, dataTemp.name, HISCORE_NAME_SIZE);
472 }
473 return true;
474}
475
476/*
477 *
478 */
479static void unloadResourceHighScores()
480{
481 sysmem_pop(screen_highScores);
482 screen_highScores = NULL;
483 screen_nbr_hiscores = 0;
484}
485
486/*
487 *
488 */
489static bool loadResourceSpritesData(file_t fp)
490{
491 size_t i, j;
492 U16 u16Temp;
493
494 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
495 {
496 return false;
497 }
498 sprites_nbr_sprites = letoh16(u16Temp);
499
500 sprites_data = sysmem_push(sprites_nbr_sprites * sizeof(*sprites_data));
501 if (!sprites_data)
502 {
503 return false;
504 }
505
506#ifdef GFXST
507 for (i = 0; i < sprites_nbr_sprites; ++i)
508 {
509 for (j = 0; j < SPRITES_NBR_DATA; ++j)
510 {
511 U32 u32Temp;
512 if (sysfile_read(fp, &u32Temp, sizeof(u32Temp), 1) != 1)
513 {
514 return false;
515 }
516 sprites_data[i][j] = letoh32(u32Temp);
517 }
518 }
519#endif /* GFXST */
520
521#ifdef GFXPC
522 for (i = 0; i < sprites_nbr_sprites; ++i)
523 {
524 for (j = 0; j < SPRITES_NBR_COLS; ++j)
525 {
526 size_t k;
527 for (k = 0; k < SPRITES_NBR_ROWS; ++k)
528 {
529 resource_spriteX_t dataTemp;
530 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
531 {
532 return false;
533 }
534 memcpy(&u16Temp, dataTemp.mask, sizeof(U16));
535 sprites_data[i][j][k].mask = letoh16(u16Temp);
536 memcpy(&u16Temp, dataTemp.pict, sizeof(U16));
537 sprites_data[i][j][k].pict = letoh16(u16Temp);
538 }
539 }
540 }
541#endif /* GFXPC */
542
543 return true;
544}
545
546/*
547 *
548 */
549static void unloadResourceSpritesData()
550{
551 sysmem_pop(sprites_data);
552 sprites_data = NULL;
553 sprites_nbr_sprites = 0;
554}
555
556/*
557 *
558 */
559static bool loadResourceTilesData(file_t fp)
560{
561 size_t i, j, k;
562 U16 u16Temp;
563
564 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
565 {
566 return false;
567 }
568 tiles_nbr_banks = letoh16(u16Temp);
569
570 tiles_data = sysmem_push(tiles_nbr_banks * TILES_NBR_TILES * sizeof(*tiles_data));
571 if (!tiles_data)
572 {
573 return false;
574 }
575
576 for (i = 0; i < tiles_nbr_banks ; ++i)
577 {
578 for (j = 0; j < TILES_NBR_TILES; ++j)
579 {
580 for (k = 0; k < TILES_NBR_LINES ; ++k)
581 {
582#ifdef GFXPC
583 if (sysfile_read(fp, &u16Temp, sizeof(u16Temp), 1) != 1)
584 {
585 return false;
586 }
587 tiles_data[i * TILES_NBR_TILES + j][k] = letoh16(u16Temp);
588#endif /* GFXPC */
589#ifdef GFXST
590 U32 u32Temp;
591 if (sysfile_read(fp, &u32Temp, sizeof(u32Temp), 1) != 1)
592 {
593 return false;
594 }
595 tiles_data[i * TILES_NBR_TILES + j][k] = letoh32(u32Temp);
596#endif /* GFXST */
597 }
598 }
599 }
600 return true;
601}
602
603/*
604 *
605 */
606static void unloadResourceTilesData()
607{
608 sysmem_pop(tiles_data);
609 tiles_data = NULL;
610 tiles_nbr_banks = 0;
611}
612
613/*
614 *
615 */
616static bool loadImage(file_t fp, img_t ** image)
617{
618 U16 u16Temp;
619 size_t pixelCount, colorCount;
620 resource_pic_t dataTemp;
621 img_t * imgTemp;
622 void * vp;
623 bool success;
624
625 imgTemp = sysmem_push(sizeof(*imgTemp));
626 *image = imgTemp;
627 if (!imgTemp)
628 {
629 return false;
630 }
631
632 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
633 {
634 return false;
635 }
636 memcpy(&u16Temp, dataTemp.width, sizeof(U16));
637 imgTemp->width = letoh16(u16Temp);
638 memcpy(&u16Temp, dataTemp.height, sizeof(U16));
639 imgTemp->height = letoh16(u16Temp);
640 memcpy(&u16Temp, dataTemp.xPos, sizeof(U16));
641 imgTemp->xPos = letoh16(u16Temp);
642 memcpy(&u16Temp, dataTemp.yPos, sizeof(U16));
643 imgTemp->yPos = letoh16(u16Temp);
644
645 vp = imgTemp->colors;
646 success = loadRawData(fp, &vp, sizeof(*imgTemp->colors), &colorCount);
647 imgTemp->ncolors = colorCount;
648 imgTemp->colors = vp;
649 if (!success)
650 {
651 return false;
652 }
653
654 pixelCount = (imgTemp->width * imgTemp->height); /*we use 8b per pixel*/
655
656 imgTemp->pixels = sysmem_push(pixelCount * sizeof(U8));
657 if (!imgTemp->pixels)
658 {
659 return false;
660 }
661
662 if (sysfile_read(fp, imgTemp->pixels, sizeof(U8), pixelCount) != (int)pixelCount)
663 {
664 return false;
665 }
666 return true;
667}
668
669/*
670 *
671 */
672static void unloadImage(img_t ** image)
673{
674 if (*image)
675 {
676 sysmem_pop((*image)->pixels);
677 sysmem_pop((*image)->colors);
678 }
679 sysmem_pop(*image);
680 *image = NULL;
681}
682
683/*
684 *
685 */
686#ifdef GFXST
687static bool loadPicture(file_t fp, pic_t ** picture)
688{
689 U16 u16Temp;
690 size_t i, pixelWords32b;
691 resource_pic_t dataTemp;
692 pic_t * picTemp;
693
694 picTemp = sysmem_push(sizeof(*picTemp));
695 *picture = picTemp;
696 if (!picTemp)
697 {
698 return false;
699 }
700
701 if (sysfile_read(fp, &dataTemp, sizeof(dataTemp), 1) != 1)
702 {
703 return false;
704 }
705 memcpy(&u16Temp, dataTemp.width, sizeof(U16));
706 picTemp->width = letoh16(u16Temp);
707 memcpy(&u16Temp, dataTemp.height, sizeof(U16));
708 picTemp->height = letoh16(u16Temp);
709 memcpy(&u16Temp, dataTemp.xPos, sizeof(U16));
710 picTemp->xPos = letoh16(u16Temp);
711 memcpy(&u16Temp, dataTemp.yPos, sizeof(U16));
712 picTemp->yPos = letoh16(u16Temp);
713
714 pixelWords32b = (picTemp->width * picTemp->height) / 8; /*we use 4b per pixel*/
715
716 picTemp->pixels = sysmem_push(pixelWords32b * sizeof(U32));
717 if (!picTemp->pixels)
718 {
719 return false;
720 }
721
722 for (i = 0; i < pixelWords32b; ++i)
723 {
724 U32 u32Temp;
725 if (sysfile_read(fp, &u32Temp, sizeof(u32Temp), 1) != 1)
726 {
727 return false;
728 }
729 picTemp->pixels[i] = letoh32(u32Temp);
730 }
731 return true;
732}
733
734/*
735 *
736 */
737static void unloadPicture(pic_t ** picture)
738{
739 if (*picture)
740 {
741 sysmem_pop((*picture)->pixels);
742 }
743 sysmem_pop(*picture);
744 *picture = NULL;
745}
746#endif /* GFXST */
747
748#ifdef ENABLE_SOUND
749
750/*
751 *
752 */
753static bool fromResourceIdToSound(const unsigned id, sound_t *** sound)
754{
755 switch (id)
756 {
757 case Resource_SOUNDBOMBSHHT: *sound = &soundBombshht; return true;
758 case Resource_SOUNDBONUS: *sound = &soundBonus; return true;
759 case Resource_SOUNDBOX: *sound = &soundBox; return true;
760 case Resource_SOUNDBULLET: *sound = &soundBullet; return true;
761 case Resource_SOUNDCRAWL: *sound = &soundCrawl; return true;
762 case Resource_SOUNDDIE: *sound = &soundDie; return true;
763 case Resource_SOUNDENTITY0: *sound = &(soundEntity[0]); return true;
764 case Resource_SOUNDENTITY1: *sound = &(soundEntity[1]); return true;
765 case Resource_SOUNDENTITY2: *sound = &(soundEntity[2]); return true;
766 case Resource_SOUNDENTITY3: *sound = &(soundEntity[3]); return true;
767 case Resource_SOUNDENTITY4: *sound = &(soundEntity[4]); return true;
768 case Resource_SOUNDENTITY5: *sound = &(soundEntity[5]); return true;
769 case Resource_SOUNDENTITY6: *sound = &(soundEntity[6]); return true;
770 case Resource_SOUNDENTITY7: *sound = &(soundEntity[7]); return true;
771 case Resource_SOUNDENTITY8: *sound = &(soundEntity[8]); return true;
772 case Resource_SOUNDEXPLODE: *sound = &soundExplode; return true;
773 case Resource_SOUNDGAMEOVER: *sound = &soundGameover; return true;
774 case Resource_SOUNDJUMP: *sound = &soundJump; return true;
775 case Resource_SOUNDPAD: *sound = &soundPad; return true;
776 case Resource_SOUNDSBONUS1: *sound = &soundSbonus1; return true;
777 case Resource_SOUNDSBONUS2: *sound = &soundSbonus2; return true;
778 case Resource_SOUNDSTICK: *sound = &soundStick; return true;
779 case Resource_SOUNDTUNE0: *sound = &soundTune0; return true;
780 case Resource_SOUNDTUNE1: *sound = &soundTune1; return true;
781 case Resource_SOUNDTUNE2: *sound = &soundTune2; return true;
782 case Resource_SOUNDTUNE3: *sound = &soundTune3; return true;
783 case Resource_SOUNDTUNE4: *sound = &soundTune4; return true;
784 case Resource_SOUNDTUNE5: *sound = &soundTune5; return true;
785 case Resource_SOUNDWALK: *sound = &soundWalk; return true;
786 default:
787 {
788 sys_error("(resources) no associated sound found for ID %d", id);
789 return false;
790 }
791 }
792}
793
794/*
795 *
796 */
797static bool loadSound(const unsigned id)
798{
799 sound_t ** sound;
800 file_t fp;
801 wave_header_t header;
802 U16 u16Temp;
803 U32 u32Temp;
804 int bytesRead;
805 bool isHeaderValid;
806
807 if (!fromResourceIdToSound(id, &sound))
808 {
809 return false;
810 }
811
812 *sound = sysmem_push(sizeof(**sound));
813 if (!*sound)
814 {
815 return false;
816 }
817
818 (*sound)->buf = NULL;
819 (*sound)->dispose = true; /* sounds are "fire and forget" by default */
820
821 (*sound)->name = u_strdup(resourceFiles[id]);
822 if (!(*sound)->name)
823 {
824 return false;
825 }
826
827 fp = sysfile_open(resourceFiles[id]);
828 if (!fp)
829 {
830 sys_error("(resources) unable to open \"%s\"", resourceFiles[id]);
831 return false;
832 }
833
834 bytesRead = sysfile_read(fp, &header, sizeof(header), 1);
835 sysfile_close(fp);
836 if (bytesRead != 1)
837 {
838 sys_error("(resources) unable to read WAVE header from \"%s\"", resourceFiles[id]);
839 return false;
840 }
841
842 isHeaderValid = false;
843 for (;;)
844 {
845 if (memcmp(header.riffChunkId, "RIFF", 4) ||
846 memcmp(header.riffType, "WAVE", 4) ||
847 memcmp(header.formatChunkId, "fmt ", 4) ||
848 memcmp(header.dataChunkId, "data", 4))
849 {
850 break;
851 }
852 memcpy(&u16Temp, header.audioFormat, sizeof(u16Temp));
853 if (letoh16(u16Temp) != Wave_AUDIO_FORMAT)
854 {
855 break;
856 }
857 memcpy(&u16Temp, header.channelCount, sizeof(u16Temp));
858 if (letoh16(u16Temp) != Wave_CHANNEL_COUNT)
859 {
860 break;
861 }
862 memcpy(&u32Temp, header.sampleRate, sizeof(u32Temp));
863 if (letoh32(u32Temp) != Wave_SAMPLE_RATE)
864 {
865 isHeaderValid = false;
866 break;
867 }
868 memcpy(&u16Temp, header.bitsPerSample, sizeof(u16Temp));
869 if (letoh16(u16Temp) != Wave_BITS_PER_SAMPLE)
870 {
871 isHeaderValid = false;
872 break;
873 }
874
875 memcpy(&u32Temp, header.dataChunkSize, sizeof(u32Temp));
876 (*sound)->len = letoh32(u32Temp);
877
878 isHeaderValid = true;
879 break;
880 }
881 if (!isHeaderValid)
882 {
883 sys_error("(resources) incompatible WAVE header for \"%s\"", resourceFiles[id]);
884 return false;
885 }
886 return true;
887}
888
889/*
890 *
891 */
892static void unloadSound(const unsigned id)
893{
894 sound_t ** sound;
895
896 if (!fromResourceIdToSound(id, &sound))
897 {
898 return;
899 }
900
901 if (!*sound)
902 {
903 return;
904 }
905
906 sysmem_pop((*sound)->name);
907 sysmem_pop(*sound);
908 *sound = NULL;
909}
910#endif /* ENABLE_SOUND */
911
912
913/*
914 *
915 */
916static bool readHeader(file_t fp, const unsigned id)
917{
918 resource_header_t header;
919 U16 u16Temp;
920
921 if (sysfile_read(fp, &header, sizeof(header), 1) != 1)
922 {
923 sys_error("(resources) unable to read header from \"%s\"", resourceFiles[id]);
924 return false;
925 }
926
927 if (memcmp(header.magic, resource_magic, sizeof(header.magic)) != 0)
928 {
929 sys_error("(resources) wrong header for \"%s\"", resourceFiles[id]);
930 return false;
931 }
932
933 memcpy(&u16Temp, header.version, sizeof(u16Temp));
934 u16Temp = htole16(u16Temp);
935 if (u16Temp != DATA_VERSION)
936 {
937 sys_error("(resources) incompatible version for \"%s\"", resourceFiles[id]);
938 return false;
939 }
940
941 memcpy(&u16Temp, header.resourceId, sizeof(u16Temp));
942 u16Temp = htole16(u16Temp);
943 if (u16Temp != id)
944 {
945 sys_error("(resources) mismatching ID for \"%s\"", resourceFiles[id]);
946 return false;
947 }
948 return true;
949}
950
951/*
952 *
953 */
954static bool checkCrc32(const unsigned id)
955{
956 int bytesRead;
957 U8 tempBuffer[1024];
958 U32 expectedCrc32, calculatedCrc32 = MZ_CRC32_INIT;
959
960 file_t fp = sysfile_open(resourceFiles[id]);
961 if (fp == NULL)
962 {
963 sys_error("(resources) unable to open \"%s\"", resourceFiles[id]);
964 return false;
965 }
966
967 bytesRead = sysfile_read(fp, tempBuffer, sizeof(U32), 1); /* prepare beginning of buffer for the following loop */
968 if (bytesRead != 1)
969 {
970 sys_error("(resources) not enough data for \"%s\"", resourceFiles[id]);
971 sysfile_close(fp);
972 return false;
973 }
974 do
975 {
976 bytesRead = sysfile_read(fp, tempBuffer + sizeof(U32), sizeof(U8), sizeof(tempBuffer) - sizeof(U32));
977
978 calculatedCrc32 = mz_crc32(calculatedCrc32, tempBuffer, bytesRead);
979
980 memcpy(tempBuffer, tempBuffer + bytesRead, sizeof(U32));
981 } while (bytesRead == sizeof(tempBuffer) - sizeof(U32));
982
983 sysfile_close(fp);
984
985 memcpy(&expectedCrc32, tempBuffer, sizeof(U32));
986 expectedCrc32 = letoh32(expectedCrc32);
987 if (expectedCrc32 != calculatedCrc32)
988 {
989 sys_error("(resources) crc check failed for \"%s\"", resourceFiles[id]);
990 return false;
991 }
992 return true;
993}
994
995/*
996 *
997 */
998static bool readFile(const unsigned id)
999{
1000 bool success;
1001 file_t fp;
1002 void * vp;
1003
1004 switch (id)
1005 {
1006#ifndef GFXST
1007 case Resource_PICHAF: /* fallthrough */
1008 case Resource_PICCONGRATS: /* fallthrough */
1009 case Resource_PICSPLASH: return true;
1010#endif /* ndef GFXST */
1011#ifndef GFXPC
1012 case Resource_IMAINHOFT: /* fallthrough */
1013 case Resource_IMAINRDT: /* fallthrough */
1014 case Resource_IMAINCDC: /* fallthrough */
1015 case Resource_SCREENCONGRATS: return true;
1016#endif /* ndef GFXPC */
1017 default: break;
1018 }
1019
1020 if (resourceFiles[id] == NULL)
1021 {
1022 sys_error("(resources) resource ID %d not available", id);
1023 return false;
1024 }
1025
1026 if (!checkCrc32(id))
1027 {
1028 return false;
1029 }
1030
1031 fp = sysfile_open(resourceFiles[id]);
1032 if (fp == NULL)
1033 {
1034 if (id == Resource_FILELIST)
1035 sys_error("Please install resource files!");
1036 else
1037 sys_error("(resources) unable to open \"%s\"", resourceFiles[id]);
1038 return false;
1039 }
1040
1041 success = readHeader(fp, id);
1042
1043 if (success)
1044 {
1045 switch (id)
1046 {
1047 case Resource_FILELIST: success = loadResourceFilelist(fp); break;
1048 case Resource_PALETTE:
1049 {
1050 vp = game_colors;
1051 success = loadRawData(fp, &vp, sizeof(*game_colors), &game_color_count);
1052 game_colors = vp;
1053 break;
1054 }
1055 case Resource_ENTDATA: success = loadResourceEntdata(fp); break;
1056 case Resource_SPRSEQ:
1057 {
1058 vp = ent_sprseq;
1059 success = loadRawData(fp, &vp, sizeof(*ent_sprseq), &ent_nbr_sprseq);
1060 ent_sprseq = vp;
1061 break;
1062 }
1063 case Resource_MVSTEP:
1064 {
1065 vp = ent_mvstep;
1066 success = loadRawData(fp, &vp, sizeof(*ent_mvstep), &ent_nbr_mvstep);
1067 ent_mvstep = vp;
1068 break;
1069 }
1070 case Resource_MAPS: success = loadResourceMaps(fp); break;
1071 case Resource_SUBMAPS: success = loadResourceSubmaps(fp); break;
1072 case Resource_CONNECT:
1073 {
1074 vp = map_connect;
1075 success = loadRawData(fp, &vp, sizeof(*map_connect), &map_nbr_connect);
1076 map_connect = vp;
1077 break;
1078 }
1079 case Resource_BNUMS:
1080 {
1081 vp = map_bnums;
1082 success = loadRawData(fp, &vp, sizeof(*map_bnums), &map_nbr_bnums);
1083 map_bnums = vp;
1084 break;
1085 }
1086 case Resource_BLOCKS:
1087 {
1088 vp = map_blocks;
1089 success = loadRawData(fp, &vp, sizeof(*map_blocks), &map_nbr_blocks);
1090 map_blocks = vp;
1091 break;
1092 }
1093 case Resource_MARKS:
1094 {
1095 vp = map_marks;
1096 success = loadRawData(fp, &vp, sizeof(*map_marks), &map_nbr_marks);
1097 map_marks = vp;
1098 break;
1099 }
1100 case Resource_EFLGC:
1101 {
1102 vp = map_eflg_c;
1103 success = loadRawData(fp, &vp, sizeof(*map_eflg_c), &map_nbr_eflgc);
1104 map_eflg_c = vp;
1105 break;
1106 }
1107 case Resource_IMAPSL:
1108 {
1109 vp = screen_imapsl;
1110 success = loadRawData(fp, &vp, sizeof(*screen_imapsl), &screen_nbr_imapsl);
1111 screen_imapsl = vp;
1112 break;
1113 }
1114 case Resource_IMAPSTEPS: success = loadResourceImapsteps(fp); break;
1115 case Resource_IMAPSOFS:
1116 {
1117 vp = screen_imapsofs;
1118 success = loadRawData(fp, &vp, sizeof(*screen_imapsofs), &screen_nbr_imapsofs);
1119 screen_imapsofs = vp;
1120 break;
1121 }
1122 case Resource_IMAPTEXT: success = loadResourceImaptext(fp); break;
1123 case Resource_GAMEOVERTXT: success = loadString(fp, (char **)(&screen_gameovertxt), 0xFE); break;
1124 case Resource_PAUSEDTXT: success = loadString(fp, (char **)(&screen_pausedtxt), 0xFE); break;
1125 case Resource_SPRITESDATA: success = loadResourceSpritesData(fp); break;
1126 case Resource_TILESDATA: success = loadResourceTilesData(fp); break;
1127 case Resource_HIGHSCORES: success = loadResourceHighScores(fp); break;
1128 case Resource_IMGSPLASH: success = loadImage(fp, &img_splash); break;
1129#ifdef GFXST
1130 case Resource_PICHAF: success = loadPicture(fp, &pic_haf); break;
1131 case Resource_PICCONGRATS: success = loadPicture(fp, &pic_congrats); break;
1132 case Resource_PICSPLASH: success = loadPicture(fp, &pic_splash); break;
1133#endif /* GFXST */
1134#ifdef GFXPC
1135 case Resource_IMAINHOFT: success = loadString(fp, (char **)(&screen_imainhoft), 0xFE); break;
1136 case Resource_IMAINRDT: success = loadString(fp, (char **)(&screen_imainrdt), 0xFE); break;
1137 case Resource_IMAINCDC: success = loadString(fp, (char **)(&screen_imaincdc), 0xFE); break;
1138 case Resource_SCREENCONGRATS: success = loadString(fp, (char **)(&screen_congrats), 0xFE); break;
1139#endif /* GFXPC */
1140 default: success = false; break;
1141 }
1142 }
1143
1144 if (!success)
1145 {
1146 sys_error("(resources) error when parsing \"%s\"", resourceFiles[id]);
1147 }
1148
1149 sysfile_close(fp);
1150 return success;
1151}
1152
1153/*
1154 *
1155 */
1156bool resources_load()
1157{
1158 bool success;
1159 unsigned id;
1160
1161 /* note: loading order is important: file list first, then sounds, then the rest */
1162
1163 success = readFile(Resource_FILELIST);
1164
1165#ifdef ENABLE_SOUND
1166 for (id = Resource_SOUNDBOMBSHHT; (id <= Resource_SOUNDWALK) && success; ++id)
1167 {
1168 success = loadSound(id);
1169 }
1170#endif /* ENABLE_SOUND */
1171
1172 for (id = Resource_PALETTE; (id <= Resource_SCREENCONGRATS) && success; ++id)
1173 {
1174 success = readFile(id);
1175 }
1176 return success;
1177}
1178
1179/*
1180 *
1181 */
1182void resources_unload()
1183{
1184 int id;
1185 void * vp;
1186
1187 for (id = Resource_SCREENCONGRATS; id >= Resource_PALETTE; --id)
1188 {
1189 switch (id)
1190 {
1191 case Resource_PALETTE:
1192 {
1193 vp = game_colors;
1194 unloadRawData(&vp, &game_color_count);
1195 game_colors = vp;
1196 break;
1197 }
1198 case Resource_ENTDATA: unloadResourceEntdata(); break;
1199 case Resource_SPRSEQ:
1200 {
1201 vp = ent_sprseq;
1202 unloadRawData(&vp, &ent_nbr_sprseq);
1203 ent_sprseq = vp;
1204 break;
1205 }
1206 case Resource_MVSTEP:
1207 {
1208 vp = ent_mvstep;
1209 unloadRawData(&vp, &ent_nbr_mvstep);
1210 ent_mvstep = vp;
1211 break;
1212 }
1213 case Resource_MAPS: unloadResourceMaps(); break;
1214 case Resource_SUBMAPS: unloadResourceSubmaps(); break;
1215 case Resource_CONNECT:
1216 {
1217 vp = map_connect;
1218 unloadRawData(&vp, &map_nbr_connect);
1219 map_connect = vp;
1220 break;
1221 }
1222 case Resource_BNUMS:
1223 {
1224 vp = map_bnums;
1225 unloadRawData(&vp, &map_nbr_bnums);
1226 map_bnums = vp;
1227 break;
1228 }
1229 case Resource_BLOCKS:
1230 {
1231 vp = map_blocks;
1232 unloadRawData(&vp, &map_nbr_blocks);
1233 map_blocks = vp;
1234 break;
1235 }
1236 case Resource_MARKS:
1237 {
1238 vp = map_marks;
1239 unloadRawData(&vp, &map_nbr_marks);
1240 map_marks = vp;
1241 break;
1242 }
1243 case Resource_EFLGC:
1244 {
1245 vp = map_eflg_c;
1246 unloadRawData(&vp, &map_nbr_eflgc);
1247 map_eflg_c = vp;
1248 break;
1249 }
1250 case Resource_IMAPSL:
1251 {
1252 vp = screen_imapsl;
1253 unloadRawData(&vp, &screen_nbr_imapsl);
1254 screen_imapsl = vp;
1255 break;
1256 }
1257 case Resource_IMAPSTEPS: unloadResourceImapsteps(); break;
1258 case Resource_IMAPSOFS:
1259 {
1260 vp = screen_imapsofs;
1261 unloadRawData(&vp, &screen_nbr_imapsofs);
1262 screen_imapsofs = vp;
1263 break;
1264 }
1265 case Resource_IMAPTEXT: unloadResourceImaptext(); break;
1266 case Resource_GAMEOVERTXT: unloadString((char **)(&screen_gameovertxt)); break;
1267 case Resource_PAUSEDTXT: unloadString((char **)(&screen_pausedtxt)); break;
1268 case Resource_SPRITESDATA: unloadResourceSpritesData(); break;
1269 case Resource_TILESDATA: unloadResourceTilesData(); break;
1270 case Resource_HIGHSCORES: unloadResourceHighScores(); break;
1271 case Resource_IMGSPLASH: unloadImage(&img_splash); break;
1272#ifdef GFXST
1273 case Resource_PICHAF: unloadPicture(&pic_haf); break;
1274 case Resource_PICCONGRATS: unloadPicture(&pic_congrats); break;
1275 case Resource_PICSPLASH: unloadPicture(&pic_splash); break;
1276#endif /* GFXST */
1277#ifdef GFXPC
1278 case Resource_IMAINHOFT: unloadString((char **)(&screen_imainhoft)); break;
1279 case Resource_IMAINRDT: unloadString((char **)(&screen_imainrdt)); break;
1280 case Resource_IMAINCDC: unloadString((char **)(&screen_imaincdc)); break;
1281 case Resource_SCREENCONGRATS: unloadString((char **)(&screen_congrats)); break;
1282#endif /* GFXPC */
1283 default: break;
1284 }
1285 }
1286
1287#ifdef ENABLE_SOUND
1288 for (id = Resource_SOUNDWALK; id >= Resource_SOUNDBOMBSHHT; --id)
1289 {
1290 unloadSound(id);
1291 }
1292#endif /* ENABLE_SOUND */
1293
1294 unloadResourceFilelist();
1295}
1296
1297/* eof */