A modern Music Player Daemon based on Rockbox open source high quality audio player
libadwaita audio rust zig deno mpris rockbox mpd
2
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 1297 lines 34 kB view raw
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 "xrick/3rd_party/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 */