16 # define DATA_DIR "/usr/local/share/awish"
24 static const char *getMyDir (void) {
25 static char myDir
[8192];
26 static int inited
= 0;
33 sprintf(buf
, "/proc/%u/exe", (unsigned int)pid
);
34 if (readlink(buf
, myDir
, sizeof(myDir
)-1) < 0) {
37 char *p
= (char *)strrchr(myDir
, '/');
39 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
41 strcat(myDir
, "/data");
45 memset(myDir
, 0, sizeof(myDir
));
46 GetModuleFileName(GetModuleHandle(NULL
), myDir
, sizeof(myDir
)-1);
47 for (p
= myDir
; *p
; ++p
) if (*p
== '/') *p
= '\\';
48 p
= strrchr(myDir
, '\\');
49 if (!p
) strcpy(myDir
, "."); else *p
= '\0';
50 strcat(myDir
, "\\data");
58 static const char *getHomeDir (void) {
59 static char homeDir
[8192];
60 static int inited
= 0;
64 const char *h
= getenv("HOME");
66 strcpy(homeDir
, (h
&& h
[0]) ? h
: ".");
67 strcat(homeDir
, "/.local/awish/data");
78 int initResFile (ResFile
*resfile
, const char *fname
) {
81 FILE *fl
= fopen(fname
, "rb");
85 if (!resfile
) goto quit
;
86 memset(resfile
, 0, sizeof(resfile
));
88 if (fread(sign
, 3, 1, fl
) != 1) goto quit
;
89 if (memcmp(sign
, "RES", 3) != 0) goto quit
;
90 if (fread(&fcnt
, 1, 1, fl
) != 1) goto quit
;
91 if (fcnt
!= 93) goto quit
;
94 resfile
->count
= fcnt
;
96 if ((resfile
->offsets
= malloc(4*resfile
->count
)) == NULL
) goto quit
;
97 if ((resfile
->sizes
= malloc(4*resfile
->count
)) == NULL
) goto quit
;
99 if (fread(resfile
->offsets
, 4*resfile
->count
, 1, fl
) != 1) goto quit
;
100 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
101 for (int f
= 0; f
< resfile
->count
; ++f
) resfile
->offsets
[f
] = SDL_SwapLE32(resfile
->offsets
[f
]);
103 if (fseek(fl
, 0, SEEK_END
) != 0) goto quit
;
105 for (int f
= 0; f
< resfile
->count
-1; ++f
) resfile
->sizes
[f
] = resfile
->offsets
[f
+1]-resfile
->offsets
[f
];
106 resfile
->sizes
[resfile
->count
-1] = sz
-resfile
->offsets
[resfile
->count
-1];
113 if (resfile
->sizes
) free(resfile
->sizes
);
114 if (resfile
->offsets
) free(resfile
->offsets
);
115 memset(resfile
, 0, sizeof(resfile
));
121 void deinitResFile (ResFile
*resfile
) {
123 if (resfile
->fl
) fclose(resfile
->fl
);
124 if (resfile
->sizes
) free(resfile
->sizes
);
125 if (resfile
->offsets
) free(resfile
->offsets
);
126 memset(resfile
, 0, sizeof(resfile
));
131 typedef int (*UnpackCB
) (unsigned char *dest
, const unsigned char *data
, int size
);
134 static int unpackFNTFont (unsigned char *dest
, const unsigned char *data
, int size
) {
138 memset(dest
, 0, 256*8);
139 if (size
< 6) goto quit
;
140 if (memcmp(data
, "FNT0", 4) != 0) goto quit
;
143 if (fc
> lc
) goto quit
;
145 for (int f
= fc
; f
<= lc
; ++f
) {
146 if (pos
+8 > size
) goto quit
;
147 memcpy(dest
+f
*8, data
+pos
, 8);
152 memset(dest
, 0, 256*8);
157 static int unpackBINFont (unsigned char *dest
, const unsigned char *data
, int size
) {
158 memset(dest
, 0, 256*8);
159 if (size
< 90*8) return -1;
160 memcpy(dest
+33*8, data
, 90*8);
165 static int unpackVPI (unsigned char *dest
, const unsigned char *data
, int size
) {
166 if (size
>= 320*200) {
167 memcpy(dest
, data
, 320*200);
169 int pos
= 0; // in packed
170 int opos
= 0; // in unpacked
171 int cpos
= 0; // meaningless here (position of colormap)
173 while (opos
< 320*200 && pos
+2 <= size
) {
174 int csz
= ((uint32_t)(data
[pos
]))+256*((uint32_t)(data
[pos
+1])); // picture chunk size
176 cpos
= (pos
+= 2); // colormap
177 pos
+= 512; // skip colormap
178 while (opos
< 320*200 && pos
< size
&& csz
> 0) {
179 int idx
= data
[pos
++];
181 dest
[opos
++] = data
[cpos
+idx
*2+0];
182 dest
[opos
++] = data
[cpos
+idx
*2+1];
191 static uint8_t *tryDiskFile (const char *fname
, int *rsz
) {
192 FILE *fl
= fopen(fname
, "rb");
197 if (fl
== NULL
) return NULL
;
198 if (goobers
) fprintf(stderr
, "trying disk resource: '%s'\n", fname
);
199 if (fseek(fl
, 0, SEEK_END
) != 0) goto quit
;
202 if (size
< 0) goto quit
;
204 res
= calloc(1, size
+16);
205 if (res
== NULL
) goto quit
;
206 if (fread(res
, size
, 1, fl
) != 1) goto quit
;
208 if (size
>= 18 && memcmp(res
, "RNC\x01", 4) == 0) {
213 ulen
= rnc_ulen(res
);
214 if (ulen
< 1) goto quit
;
215 udata
= malloc(ulen
+16);
216 if (udata
== NULL
) goto quit
;
217 uplen
= rnc_unpack(res
, udata
, NULL
);
220 if (uplen
!= ulen
) goto quit
;
229 if (res
!= NULL
) { free(res
); res
= NULL
; }
231 if (res
!= NULL
&& rsz
) *rsz
= size
;
237 static uint8_t *tryDiskFileEx (const char *fname
, int *rsz
, UnpackCB unp
, int destsize
) {
241 if ((res
= tryDiskFile(fname
, &sz
)) == NULL
) return NULL
;
244 if (destsize
>= 0 && sz
< destsize
) { free(res
); return NULL
; }
247 if (destsize
< 0) { free(res
); return NULL
; }
248 if ((up
= calloc(1, destsize
+16)) == NULL
) { free(res
); return NULL
; }
249 if (unp(up
, res
, sz
) != 0) { free(up
); free(res
); return NULL
; }
259 #define TRY_FILE(upk,usz,fmt,srcdir,...) do { \
260 sprintf(fname, (fmt), (srcdir), __VA_ARGS__); \
261 if ((res = tryDiskFileEx(fname, rsz, (upk), (usz))) != NULL) return res; \
267 #define TRY_FILES(upk,usz,fmt,...) do { \
268 TRY_FILE((upk), (usz), "%s/" fmt, getHomeDir(), __VA_ARGS__); \
269 TRY_FILE((upk), (usz), "%s/" fmt, getMyDir(), __VA_ARGS__); \
270 TRY_FILE((upk), (usz), "%s/" fmt, DATA_DIR, __VA_ARGS__); \
275 #define TRY_FILES(upk,usz,fmt,...) do { \
276 TRY_FILE((upk), (usz), "%s/" fmt, getMyDir(), __VA_ARGS__); \
282 static uint8_t *loadDiskFile (int idx
, int *rsz
) {
283 static char fname
[512];
287 if (idx
< 0) return NULL
;
289 if (idx
>= 0 && idx
<= 6) {
290 TRY_FILES(unpackVPI
, 64000, "pics/back%02d.vpi", idx
+1);
295 TRY_FILES(unpackVPI
, 64000, "pics/title.vpi%s", "");
300 TRY_FILES(unpackVPI
, 64000, "pics/interback.vpi%s", "");
304 if (idx
>= 9 && idx
<= 82) {
305 TRY_FILES(NULL
, 3700, "maps/level%02d.lvl", idx
-8);
310 TRY_FILES(NULL
, 768, "pics/palette.vga%s", "");
315 TRY_FILES(NULL
, 50568, "sprites/professor.spr%s", "");
320 TRY_FILES(NULL
, 3468, "sprites/fgtiles.spr%s", "");
325 TRY_FILES(NULL
, 2652, "sprites/bgtiles.spr%s", "");
330 TRY_FILES(NULL
, 588, "sprites/maptiles.spr%s", "");
335 TRY_FILES(NULL
, 19796, "sprites/items.spr%s", "");
340 TRY_FILES(NULL
, 620, "sprites/mapitems.spr%s", "");
345 TRY_FILES(NULL
, 44940, "sprites/professorim.spr%s", "");
350 TRY_FILES(NULL
, 9441, "sprites/himenu.spr%s", "");
355 TRY_FILES(unpackFNTFont
, 256*8, "fonts/namco.fnt%s", "");
356 TRY_FILES(unpackFNTFont
, 256*8, "fonts/font.fnt%s", "");
357 TRY_FILES(unpackBINFont
, 256*8, "fonts/font.bin%s", "");
365 strcpy(fname
, getMyDir());
366 t
= strrchr(fname
, '/');
368 strcat(fname
, "/awish.vmd");
369 if ((res
= tryDiskFileEx(fname
, rsz
, NULL
, 8)) != NULL
) return res
;
371 TRY_FILES(NULL
, 8, "code/awish.vmd%s", "");
378 static uint8_t *tryResFile (ResFile
*resfile
, int idx
, int *rsz
, UnpackCB unp
, int destsize
) {
379 uint8_t *res
= NULL
, *up
;
383 if (!resfile
|| !resfile
->fl
|| idx
< 0 || idx
>= resfile
->count
) return NULL
;
385 if (goobers
) fprintf(stderr
, "trying RES resource: %d\n", idx
);
386 //fprintf(stderr, "idx=%d; ofs=%u; size=%u\n", idx, resfile->offsets[idx], resfile->sizes[idx]);
387 size
= resfile
->sizes
[idx
];
388 if (fseek(resfile
->fl
, resfile
->offsets
[idx
], SEEK_SET
) != 0) return NULL
;
389 if ((res
= (uint8_t *)calloc(1, size
+16)) == NULL
) return NULL
;
391 if (fread(res
, size
, 1, resfile
->fl
) != 1) { free(res
); return NULL
; }
394 if (size
>= 18 && memcmp(res
, "RNC\x01", 4) == 0) {
399 ulen
= rnc_ulen(res
);
400 if (ulen
< 1) { free(res
); return NULL
; }
401 udata
= malloc(ulen
+16);
402 if (udata
== NULL
) { free(res
); return NULL
; }
403 uplen
= rnc_unpack(res
, udata
, NULL
);
406 if (uplen
!= ulen
) { free(res
); return NULL
; }
411 if (destsize
>= 0 && size
< destsize
) { free(res
); return NULL
; }
413 if (destsize
< 0) { free(res
); return NULL
; }
414 if ((up
= calloc(1, destsize
+16)) == NULL
) { free(res
); return NULL
; }
415 if (unp(up
, res
, size
) != 0) { free(up
); free(res
); return NULL
; }
421 if (rsz
) *rsz
= size
;
426 uint8_t *loadResFile (ResFile
*resfile
, int idx
, int *rsz
) {
429 if (!datfirst
) res
= loadDiskFile(idx
, rsz
);
431 if (res
!= NULL
|| resfile
== NULL
) return res
;
433 if (idx
>= 0 && idx
<= 8) {
434 return tryResFile(resfile
, idx
, rsz
, (resfile
->sizes
[idx
] < 320*200) ? unpackVPI
: NULL
, 320*200);
437 if (idx
>= 9 && idx
<= 82) {
438 return tryResFile(resfile
, idx
, rsz
, NULL
, 3700);
442 return tryResFile(resfile
, idx
, rsz
, NULL
, 768);
446 return tryResFile(resfile
, idx
, rsz
, NULL
, 50568);
450 return tryResFile(resfile
, idx
, rsz
, NULL
, 3468);
454 return tryResFile(resfile
, idx
, rsz
, NULL
, 2652);
458 return tryResFile(resfile
, idx
, rsz
, NULL
, 588);
462 return tryResFile(resfile
, idx
, rsz
, NULL
, 19796);
466 return tryResFile(resfile
, idx
, rsz
, NULL
, 620);
470 return tryResFile(resfile
, idx
, rsz
, NULL
, 44940);
474 return tryResFile(resfile
, idx
, rsz
, NULL
, 9441);
478 return tryResFile(resfile
, idx
, rsz
, unpackBINFont
, 256*8);
481 if (datfirst
) res
= loadDiskFile(idx
, rsz
);