sound system seems to work ok
[awish.git] / src / resfile.c
blob6c0cb12f46fa25a71a8e3d17c7a965a954302432
1 /*
2 * This program is free software: you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation, either version 3 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 #ifdef _WIN32
16 # include <windows.h>
17 #endif
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <unistd.h>
22 #include <sys/types.h>
24 #include "librnc/librnc.h"
25 #include "libwdx/libwdx.h"
27 #include "resfile.h"
29 #ifndef DATA_DIR
30 # define DATA_DIR "/usr/local/share/awish"
31 #endif
34 extern int goobers;
35 extern int datfirst;
38 static const char *getMyDir (void) {
39 static char myDir[8192];
40 static int inited = 0;
42 if (!inited) {
43 #ifndef _WIN32
44 pid_t pid = getpid();
45 char buf[128];
47 sprintf(buf, "/proc/%u/exe", (unsigned int)pid);
48 if (readlink(buf, myDir, sizeof(myDir)-1) < 0) {
49 strcpy(myDir, ".");
50 } else {
51 char *p = (char *)strrchr(myDir, '/');
53 if (!p) strcpy(myDir, "."); else *p = '\0';
55 strcat(myDir, "/data");
56 #else
57 char *p;
59 memset(myDir, 0, sizeof(myDir));
60 GetModuleFileName(GetModuleHandle(NULL), myDir, sizeof(myDir)-1);
61 for (p = myDir; *p; ++p) if (*p == '/') *p = '\\';
62 p = strrchr(myDir, '\\');
63 if (!p) strcpy(myDir, "."); else *p = '\0';
64 strcat(myDir, "\\data");
65 for (p = myDir; *p; ++p) if (*p == '\\') *p = '/';
66 #endif
67 inited = 1;
69 return myDir;
73 #ifndef _WIN32
74 static const char *getHomeDir (void) {
75 static char homeDir[8192];
76 static int inited = 0;
78 if (!inited) {
79 #ifndef _WIN32
80 const char *h = getenv("HOME");
82 strcpy(homeDir, (h && h[0]) ? h : ".");
83 strcat(homeDir, "/.local/awish/data");
84 #else
85 // fuck windoze
86 strcpy(homeDir, ".");
87 for (char *p = myDir; *p; ++p) if (*p == '\\') *p = '/';
88 #endif
89 inited = 1;
91 return homeDir;
93 #endif
96 static uint32_t getUInt (const uint8_t *buf) {
97 uint32_t res = 0;
99 for (int f = 3; f >= 0; --f) res = (res<<8)|buf[f];
100 return res;
104 static int tryInitResFile (ResFile *resfile, const char *fname) {
105 uint8_t fcnt;
106 uint8_t sign[3];
108 FILE *fl = fopen(fname, "rb");
109 int rr = -1, sz;
111 //fprintf(stderr, "RES: [%s]\n", fname);
112 if (!fl) return -1;
113 if (!resfile) goto quit;
114 memset(resfile, 0, sizeof(resfile));
116 if (fread(sign, 3, 1, fl) != 1) goto quit;
117 if (memcmp(sign, "RES", 3) != 0 && memcmp(sign, "SND", 3) != 0 && memcmp(sign, "MUS", 3) != 0) goto quit;
118 if (fread(&fcnt, 1, 1, fl) != 1) goto quit;
119 if (fcnt < 1/*93*/) goto quit;
121 resfile->fl = fl;
122 resfile->count = fcnt;
124 if ((resfile->offsets = malloc(4*resfile->count)) == NULL) goto quit;
125 if ((resfile->sizes = malloc(4*resfile->count)) == NULL) goto quit;
127 if (fread(resfile->offsets, 4*resfile->count, 1, fl) != 1) goto quit;
128 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
129 for (int f = 0; f < resfile->count; ++f) resfile->offsets[f] = SDL_SwapLE32(resfile->offsets[f]);
130 #endif
131 if (fseek(fl, 0, SEEK_END) != 0) goto quit;
132 sz = ftell(fl);
133 for (int f = 0; f < resfile->count-1; ++f) resfile->sizes[f] = resfile->offsets[f+1]-resfile->offsets[f];
134 resfile->sizes[resfile->count-1] = sz-resfile->offsets[resfile->count-1];
136 fl = NULL;
137 rr = 0;
138 //fprintf(stderr, "RES: [%s]: OK\n", fname);
139 quit:
140 if (fl != NULL) {
141 fclose(fl);
142 if (resfile->sizes) free(resfile->sizes);
143 if (resfile->offsets) free(resfile->offsets);
144 memset(resfile, 0, sizeof(resfile));
145 //fprintf(stderr, "RES: [%s]: FAIL\n", fname);
147 return rr;
151 int initResFile (ResFile *resfile, const char *rfname) {
152 static char fname[8192];
153 int res = -1;
155 #ifndef _WIN32
156 sprintf(fname, "%s/%s", getHomeDir(), rfname);
157 res = tryInitResFile(resfile, fname);
158 #endif
159 if (res != 0) {
160 sprintf(fname, "%s/%s", getMyDir(), rfname);
161 res = tryInitResFile(resfile, fname);
163 #ifndef _WIN32
164 if (res != 0) {
165 sprintf(fname, "%s/%s", DATA_DIR, rfname);
166 res = tryInitResFile(resfile, fname);
168 #endif
169 if (res != 0) {
170 char *t;
172 strcpy(fname, getMyDir());
173 t = strrchr(fname, '/');
174 if (t) t[1] = 0;
175 strcat(fname, rfname);
176 res = tryInitResFile(resfile, fname);
179 if (goobers) {
180 if (res == 0) fprintf(stderr, "using resource file '%s'\n", fname);
181 else fprintf(stderr, "can't find resource file '%s'\n", rfname);
183 return res;
187 void deinitResFile (ResFile *resfile) {
188 if (resfile) {
189 if (resfile->fl) fclose(resfile->fl);
190 if (resfile->sizes) free(resfile->sizes);
191 if (resfile->offsets) free(resfile->offsets);
192 memset(resfile, 0, sizeof(resfile));
197 typedef int (*UnpackCB) (unsigned char *dest, const unsigned char *data, int size);
200 static int unpackFNTFont (unsigned char *dest, const unsigned char *data, int size) {
201 Uint8 fc, lc;
202 int pos;
204 memset(dest, 0, 256*8);
205 if (size < 6) goto quit;
206 if (memcmp(data, "FNT0", 4) != 0) goto quit;
207 fc = data[4];
208 lc = data[5];
209 if (fc > lc) goto quit;
210 pos = 6;
211 for (int f = fc; f <= lc; ++f) {
212 if (pos+8 > size) goto quit;
213 memcpy(dest+f*8, data+pos, 8);
214 pos += 8;
216 return 0;
217 quit:
218 memset(dest, 0, 256*8);
219 return -1;
223 static int unpackBINFont (unsigned char *dest, const unsigned char *data, int size) {
224 memset(dest, 0, 256*8);
225 if (size < 90*8) return -1;
226 memcpy(dest+33*8, data, 90*8);
227 return 0;
231 static int unpackVPI (unsigned char *dest, const unsigned char *data, int size) {
232 if (size >= 320*200) {
233 memcpy(dest, data, 320*200);
234 } else {
235 int pos = 0; // in packed
236 int opos = 0; // in unpacked
237 int cpos = 0; // meaningless here (position of colormap)
239 while (opos < 320*200 && pos+2 <= size) {
240 int csz = ((uint32_t)(data[pos]))+256*((uint32_t)(data[pos+1])); // picture chunk size
242 cpos = (pos += 2); // colormap
243 pos += 512; // skip colormap
244 while (opos < 320*200 && pos < size && csz > 0) {
245 int idx = data[pos++];
247 dest[opos++] = data[cpos+idx*2+0];
248 dest[opos++] = data[cpos+idx*2+1];
249 --csz;
253 return 0;
257 uint8_t *tryDiskFile (const char *fname, int *rsz) {
258 FILE *fl = fopen(fname, "rb");
259 uint8_t *res = NULL;
260 long size;
262 if (rsz) *rsz = 0;
263 if (fl == NULL) return NULL;
264 if (goobers) fprintf(stderr, "trying disk resource: '%s'\n", fname);
265 if (fseek(fl, 0, SEEK_END) != 0) goto quit;
266 size = ftell(fl);
267 rewind(fl);
268 if (size < 0) goto quit;
270 res = calloc(1, size+16);
271 if (res == NULL) goto quit;
272 if (fread(res, size, 1, fl) != 1) goto quit;
274 if (size >= 18 && rnc_sign(res)) {
275 // unpack RNC file
276 int ulen, uplen;
277 uint8_t *udata;
279 ulen = rnc_ulen(res);
280 if (ulen < 1) goto quit;
281 udata = malloc(ulen+16);
282 if (udata == NULL) goto quit;
283 uplen = rnc_unpack(res, udata, NULL);
284 free(res);
285 res = udata;
286 //if (goobers) fprintf(stderr, "RNC: %d -> %d (%d)\n", (int)size, ulen, uplen);
287 if (uplen != ulen) goto quit;
288 size = ulen;
289 } else if (size >= 20 && memcmp(res, "WDX0", 4) == 0) {
290 uint32_t crc, ncrc;
291 const uint8_t *ibuf = (const uint8_t *)res;
292 uint8_t *obuf;
293 int osz, psz, xsz;
295 ibuf += 4; /* skip signature */
296 osz = getUInt(ibuf); ibuf += 4; /* unpacked size */
297 crc = getUInt(ibuf); ibuf += 4; /* crc */
298 psz = getUInt(ibuf); ibuf += 4; /* packed size */
299 if (psz+4*4 > size) goto quit;
300 obuf = malloc(osz);
301 if (obuf == NULL) goto quit;
302 xsz = wdxUnpack(obuf, osz, ibuf, psz);
303 if (xsz < 0 || xsz != osz) goto quit;
304 free(res);
305 res = obuf;
306 ncrc = wdxCRC32(obuf, xsz);
307 if (ncrc != crc) goto quit;
308 size = xsz;
310 fclose(fl);
311 fl = NULL;
313 quit:
314 if (fl != NULL) {
315 fclose(fl);
316 if (res != NULL) { free(res); res = NULL; }
317 } else {
318 if (res != NULL && rsz) *rsz = size;
320 return res;
324 static uint8_t *tryDiskFileEx (const char *fname, int *rsz, UnpackCB unp, int destsize) {
325 uint8_t *res, *up;
326 int sz;
328 if ((res = tryDiskFile(fname, &sz)) == NULL) return NULL;
330 if (!unp) {
331 if (destsize >= 0 && sz < destsize) { free(res); return NULL; }
332 } else {
334 if (destsize < 0) { free(res); return NULL; }
335 if ((up = calloc(1, destsize+16)) == NULL) { free(res); return NULL; }
336 if (unp(up, res, sz) != 0) { free(up); free(res); return NULL; }
337 free(res);
338 res = up;
339 sz = destsize;
341 if (rsz) *rsz = sz;
342 return res;
346 #define TRY_FILE(upk,usz,fmt,srcdir,...) do { \
347 sprintf(fname, (fmt), (srcdir), __VA_ARGS__); \
348 if ((res = tryDiskFileEx(fname, rsz, (upk), (usz))) != NULL) return res; \
349 } while (0)
352 #ifndef _WIN32
354 #define TRY_FILES(upk,usz,fmt,...) do { \
355 TRY_FILE((upk), (usz), "%s/" fmt, getHomeDir(), __VA_ARGS__); \
356 TRY_FILE((upk), (usz), "%s/" fmt, getMyDir(), __VA_ARGS__); \
357 TRY_FILE((upk), (usz), "%s/" fmt, DATA_DIR, __VA_ARGS__); \
358 } while (0)
360 #else
362 #define TRY_FILES(upk,usz,fmt,...) do { \
363 TRY_FILE((upk), (usz), "%s/" fmt, getMyDir(), __VA_ARGS__); \
364 } while (0)
366 #endif
369 static uint8_t *tryLocalCodeFile (int *rsz) {
370 static char fname[512];
371 char *t;
373 strcpy(fname, getMyDir());
374 t = strrchr(fname, '/');
375 if (t) *t = 0;
376 strcat(fname, "/awish.vmd");
377 return tryDiskFileEx(fname, rsz, NULL, 8);
381 static uint8_t *loadDiskFile (int idx, int *rsz) {
382 static char fname[512];
383 uint8_t *res;
385 if (rsz) *rsz = 0;
386 if (idx < 0) return NULL;
388 if (idx >= 0 && idx <= 6) {
389 TRY_FILES(unpackVPI, 64000, "pics/back%02d.vpi", idx+1);
390 return NULL;
393 if (idx == 7) {
394 TRY_FILES(unpackVPI, 64000, "pics/title.vpi%s", "");
395 return NULL;
398 if (idx == 8) {
399 TRY_FILES(unpackVPI, 64000, "pics/interback.vpi%s", "");
400 return NULL;
403 if (idx >= 9 && idx <= 82) {
404 TRY_FILES(NULL, 3700, "maps/level%02d.lvl", idx-8);
405 return NULL;
408 if (idx == 83) {
409 TRY_FILES(NULL, 768, "pics/palette.vga%s", "");
410 return NULL;
413 if (idx == 84) {
414 TRY_FILES(NULL, 50568, "sprites/professor.spr%s", "");
415 return NULL;
418 if (idx == 85) {
419 TRY_FILES(NULL, 3468, "sprites/fgtiles.spr%s", "");
420 return NULL;
423 if (idx == 86) {
424 TRY_FILES(NULL, 2652, "sprites/bgtiles.spr%s", "");
425 return NULL;
428 if (idx == 87) {
429 TRY_FILES(NULL, 588, "sprites/maptiles.spr%s", "");
430 return NULL;
433 if (idx == 88) {
434 TRY_FILES(NULL, 19796, "sprites/items.spr%s", "");
435 return NULL;
438 if (idx == 89) {
439 TRY_FILES(NULL, 620, "sprites/mapitems.spr%s", "");
440 return NULL;
443 if (idx == 90) {
444 TRY_FILES(NULL, 44940, "sprites/professorim.spr%s", "");
445 return NULL;
448 if (idx == 91) {
449 TRY_FILES(NULL, 9441, "sprites/himenu.spr%s", "");
450 return NULL;
453 if (idx == 92) {
454 TRY_FILES(unpackFNTFont, 256*8, "fonts/namco.fnt%s", "");
455 TRY_FILES(unpackFNTFont, 256*8, "fonts/font.fnt%s", "");
456 TRY_FILES(unpackBINFont, 256*8, "fonts/font.bin%s", "");
457 return NULL;
460 if (idx == 666 || idx == 93) {
461 if (goobers) {
462 if ((res = tryLocalCodeFile(rsz)) != NULL) return res;
465 TRY_FILES(NULL, 8, "code/awish.vmd%s", "");
467 if (!goobers) {
468 if ((res = tryLocalCodeFile(rsz)) != NULL) return res;
470 return NULL;
473 if (idx >= 94 && idx <= 94+73) {
474 TRY_FILES(NULL, -1, "maps/level%02d.vmd", idx-93);
476 return NULL;
480 static uint8_t *tryResFile (ResFile *resfile, int idx, int *rsz, UnpackCB unp, int destsize) {
481 uint8_t *res = NULL, *up;
482 int size;
484 if (rsz) *rsz = 0;
485 if (!resfile || !resfile->fl || idx < 0 || idx >= resfile->count) return NULL;
487 if (goobers) fprintf(stderr, "trying RES resource: %d\n", idx);
488 //fprintf(stderr, "idx=%d; ofs=%u; size=%u\n", idx, resfile->offsets[idx], resfile->sizes[idx]);
489 size = resfile->sizes[idx];
490 if (fseek(resfile->fl, resfile->offsets[idx], SEEK_SET) != 0) return NULL;
491 if ((res = (uint8_t *)calloc(1, size+16)) == NULL) return NULL;
492 if (size > 0) {
493 if (fread(res, size, 1, resfile->fl) != 1) { free(res); return NULL; }
496 if (size >= 18 && rnc_sign(res)) {
497 // unpack RNC file
498 int ulen, uplen;
499 uint8_t *udata;
501 ulen = rnc_ulen(res);
502 if (ulen < 1) { free(res); return NULL; }
503 udata = malloc(ulen+16);
504 if (udata == NULL) { free(res); return NULL; }
505 uplen = rnc_unpack(res, udata, NULL);
506 free(res);
507 res = udata;
508 if (uplen != ulen) { free(res); return NULL; }
509 size = ulen;
510 } else if (size >= 20 && memcmp(res, "WDX0", 4) == 0) {
511 uint32_t crc, ncrc;
512 const uint8_t *ibuf = (const uint8_t *)res;
513 uint8_t *obuf;
514 int osz, psz, xsz;
516 ibuf += 4; /* skip signature */
517 osz = getUInt(ibuf); ibuf += 4; /* unpacked size */
518 crc = getUInt(ibuf); ibuf += 4; /* crc */
519 psz = getUInt(ibuf); ibuf += 4; /* packed size */
520 if (psz+4*4 > size) return NULL;
521 obuf = malloc(osz);
522 if (obuf == NULL) return NULL;
523 xsz = wdxUnpack(obuf, osz, ibuf, psz);
524 if (xsz < 0 || xsz != osz) { free(obuf); return NULL; }
525 free(res);
526 res = obuf;
527 ncrc = wdxCRC32(obuf, xsz);
528 if (ncrc != crc) { free(res); return NULL; }
529 size = xsz;
532 if (!unp) {
533 if (destsize >= 0 && size < destsize) { free(res); return NULL; }
534 } else {
535 if (destsize < 0) { free(res); return NULL; }
536 if ((up = calloc(1, destsize+16)) == NULL) { free(res); return NULL; }
537 if (unp(up, res, size) != 0) { free(up); free(res); return NULL; }
538 free(res);
539 res = up;
540 size = destsize;
543 if (rsz) *rsz = size;
544 return res;
548 uint8_t *loadResFile (ResFile *resfile, int idx, int *rsz) {
549 uint8_t *res = NULL;
551 if (!datfirst) res = loadDiskFile(idx, rsz);
553 if (res != NULL || resfile == NULL) return res;
555 if (idx >= 0 && idx < resfile->count) {
556 switch (idx) {
557 case 0 ... 8:
558 if (resfile->sizes[idx] < 320*200) {
559 res = tryResFile(resfile, idx, rsz, unpackVPI, 320*200);
560 } else {
561 res = tryResFile(resfile, idx, rsz, NULL, 320*200);
563 break;
564 case 9 ... 82:
565 res = tryResFile(resfile, idx, rsz, NULL, 3700);
566 break;
567 case 83:
568 res = tryResFile(resfile, idx, rsz, NULL, 768);
569 break;
570 case 84:
571 res = tryResFile(resfile, idx, rsz, NULL, 50568);
572 break;
573 case 85:
574 res = tryResFile(resfile, idx, rsz, NULL, 3468);
575 break;
576 case 86:
577 res = tryResFile(resfile, idx, rsz, NULL, 2652);
578 break;
579 case 87:
580 res = tryResFile(resfile, idx, rsz, NULL, 588);
581 break;
582 case 88:
583 res = tryResFile(resfile, idx, rsz, NULL, 19796);
584 break;
585 case 89:
586 res = tryResFile(resfile, idx, rsz, NULL, 620);
587 break;
588 case 90:
589 res = tryResFile(resfile, idx, rsz, NULL, 44940);
590 break;
591 case 91:
592 res = tryResFile(resfile, idx, rsz, NULL, 9441);
593 break;
594 case 92:
595 res = tryResFile(resfile, idx, rsz, unpackBINFont, 256*8);
596 break;
597 default:
598 res = tryResFile(resfile, idx, rsz, NULL, -1);
599 break;
603 if (!res && datfirst) res = loadDiskFile(idx, rsz);
605 return res;
609 #ifndef AWISH_NO_SOUND
610 static Mix_Chunk *loadADS (const void *adata, int len) {
611 const unsigned char *src = (const unsigned char *)adata;
613 while (len > 4) {
614 int size = src[1]|(src[2]<<8)|(src[3]<<16);
616 if (src[0] == 1) {
617 // sound chunk
618 int rate;
619 SDL_RWops *rw;
620 Mix_Chunk *res;
621 int audio_rate, audio_channels;
622 Uint16 audio_format;
623 unsigned char *wav;
624 int newlen, sdatalen;
625 double delta;
627 Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
628 // skip block header
629 src += 4;
630 len -= 4;
631 if (size < 2 || size > len) return NULL;
632 rate = 1000000/(256-src[0]); // 'real' sample rate
633 // skip sample rate
634 ++src;
635 --size;
636 // very simple resampler
637 sdatalen = (long long)size*audio_rate/rate;
638 newlen = 2*4/*RIFF*/+4/*WAVE*/+2*4+16/*fmt*/+4*2+sdatalen/*data*/;
639 if ((wav = calloc(1, newlen)) == NULL) return NULL;
640 memcpy(wav+0, "RIFF", 4);
641 newlen -= 4*2; // w/o RIFF header
642 wav[4] = newlen&0xff;
643 wav[5] = (newlen>>8)&0xff;
644 wav[6] = (newlen>>16)&0xff;
645 wav[7] = (newlen>>24)&0xff;
646 newlen += 4*2; // with RIFF header
647 memcpy(wav+8, "WAVE", 4);
648 memcpy(wav+12, "fmt ", 4);
649 wav[16] = 16; // chunk size
650 wav[20+0] = 1; // PCM
651 wav[20+2] = 1; // mono
652 wav[20+4] = audio_rate&0xff;
653 wav[20+5] = (audio_rate>>8)&0xff;
654 wav[20+6] = (audio_rate>>16)&0xff;
655 wav[20+7] = (audio_rate>>24)&0xff;
656 memcpy(wav+20+8, wav+20+4, 4); // SampleRate * NumChannels * BitsPerSample/8
657 wav[20+12] = 1; // block align
658 wav[20+14] = 8; // bits per sample
659 memcpy(wav+36, "data", 4);
660 wav[40] = sdatalen&0xff;
661 wav[41] = (sdatalen>>8)&0xff;
662 wav[42] = (sdatalen>>16)&0xff;
663 wav[43] = (sdatalen>>24)&0xff;
664 //memcpy(wav+44, src, size);
665 // actual resampling
666 delta = (double)size/sdatalen;
667 //printf("size=%d; sdatalen=%d; delta=%f\n", size, sdatalen, delta);
668 for (int f = 0; f < sdatalen; ++f) {
669 double dpos = delta*f;
670 int ipos = (int)dpos;
672 dpos -= ipos; // fractional part
673 //fprintf(stderr, "f=%d; ipos=%d; dpos=%f\n", f, ipos, dpos);
674 if (f == 0) wav[44] = src[0];
675 else if (ipos+1 < size) {
676 int v = (((double)src[ipos])-128)*(1.0-dpos)+(((double)src[ipos+1])-128)*dpos;
678 if (v < -128) v = -128; else if (v > 127) v = 127;
679 wav[44+f] = v+128;
680 } else wav[44+f] = 0x7f;
682 wav[44+sdatalen-1] = src[size-1];
685 FILE *fo = fopen("z.wav", "wb");
686 fwrite(wav, newlen, 1, fo);
687 fclose(fo);
690 rw = SDL_RWFromMem(wav, newlen);
691 res = Mix_LoadWAV_RW(rw, 0); // autofree
692 SDL_RWclose(rw);
693 free(wav);
694 return res;
695 } else {
696 // skip this
697 src += size+4;
698 len -= size+4;
701 // alas, no sound
702 return NULL;
706 Mix_Chunk *loadDiskSoundFile (const char *fname) {
707 uint8_t *data;
708 int rsz;
710 data = tryDiskFile(fname, &rsz);
711 if (data != NULL) {
712 Mix_Chunk *res = loadADS(data, rsz);
714 //if (goobers) fprintf(stderr, "sound [%s]: %s\n", fname, res!=NULL?"OK":"BAD");
715 free(data);
716 return res;
718 //if (goobers) fprintf(stderr, "sound [%s]: MISSING\n", fname);
719 return NULL;
723 static Mix_Chunk *tryDiskSoundFile (int idx) {
724 static const char *extlist[] = {
725 "wav",
726 "ogg",
727 "ads",
728 NULL
731 if (idx < 0 || idx > 999) return NULL;
733 for (int extnum = 0; extlist[extnum] != NULL; ++extnum) {
734 static char fname[8192];
735 Mix_Chunk *res;
737 #ifndef _WIN32
738 sprintf(fname, "%s/sound%03d.%s", getHomeDir(), idx, extlist[extnum]);
739 if ((res = loadDiskSoundFile(fname)) != NULL) return res;
740 #endif
741 sprintf(fname, "%s/sound%03d.%s", getMyDir(), idx, extlist[extnum]);
742 if ((res = loadDiskSoundFile(fname)) != NULL) return res;
743 #ifndef _WIN32
744 sprintf(fname, "%s/sound%03d.%s", DATA_DIR, idx, extlist[extnum]);
745 if ((res = loadDiskSoundFile(fname)) != NULL) return res;
746 #endif
748 return NULL;
752 Mix_Chunk *loadSoundFile (ResFile *resfile, int idx) {
753 Mix_Chunk *res = NULL;
755 //fprintf(stderr, ":::%p:%d:%d\n", resfile, idx, resfile->count);
756 if (!datfirst) res = tryDiskSoundFile(idx);
757 if (res == NULL && resfile != NULL && idx >= 0 && idx < resfile->count) {
758 uint8_t *data;
759 int rsz;
761 data = tryResFile(resfile, idx, &rsz, NULL, -1);
762 if (data != NULL) {
763 res = loadADS(data, rsz);
764 //if (goobers) fprintf(stderr, "sound [%d]: %s\n", idx, res!=NULL?"OK":"BAD");
765 free(data);
766 } else {
767 //if (goobers) fprintf(stderr, "sound [%d]: MISSING\n", idx);
770 if (res == NULL && datfirst) res = tryDiskSoundFile(idx);
771 return res;
773 #endif