DEADSOFTWARE

portability: use only english strings for debug
[flatwaifu.git] / src / files.c
1 /* Copyright (C) 1996-1997 Aleksey Volynskov
2 * Copyright (C) 2011 Rambo
3 * Copyright (C) 2020 SovietPony
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
18 #include "glob.h"
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #ifdef UNIX
23 # include <sys/stat.h>
24 #endif
25 #include "files.h"
26 #include "map.h"
27 #include "my.h"
28 #include "game.h"
29 #include "view.h"
30 #include "dots.h"
31 #include "smoke.h"
32 #include "fx.h"
33 #include "items.h"
34 #include "monster.h"
35 #include "player.h"
36 #include "switch.h"
37 #include "weapons.h"
38 #include "error.h"
39 #include "cp866.h"
41 typedef struct {
42 byte n, i, v, d;
43 } dmv;
45 int d_start, d_end;
46 mwad_t wad[MAX_WAD];
47 char wads[MAX_WADS][__MAX_PATH];
48 FILE* wadh[MAX_WADS];
50 static byte seq[255];
51 static byte seqn;
52 static int inum=0;
53 static dmv *pat=NULL;
54 static unsigned *patp;
55 static void **dmi;
57 static int m_start, m_end;
58 static int s_start, s_end;
59 static int wad_num;
61 static char f_drive[__MAX_DRIVE];
62 static char f_dir[__MAX_DIR];
63 static char f_name[__MAX_FNAME];
64 static char f_ext[__MAX_EXT];
66 void F_startup (void) {
67 logo("F_startup: setup file system\n");
68 memset(wads,0,sizeof(wads));
69 }
71 void F_addwad (const char *fn) {
72 int i;
74 for(i=0;i<MAX_WADS;++i) if(wads[i][0]==0) {
75 strcpy(wads[i],fn);return;
76 }
77 ERR_failinit("Unable to add WAD %s",fn);
78 }
80 static int myfilelength (FILE *h) {
81 int pos = ftell(h);
82 fseek (h, 0, SEEK_END);
83 int len = ftell(h);
84 fseek (h, pos, SEEK_SET);
85 return len;
86 }
88 // build wad directory
89 void F_initwads (void) {
90 int i, j, k, p;
91 FILE *h;
92 char s[4];
93 int n, o;
94 wad_t w;
96 logo("F_initwads: use WAD-files\n");
97 for (i = 0; i < MAX_WAD; ++i) {
98 wad[i].n[0] = 0;
99 }
101 logo(" add %s\n", wads[0]);
102 if ((wadh[0] = h = fopen(wads[0], "rb")) == NULL) {
103 ERR_failinit("Unable to open file: %s", wads[0]);
106 s[0] = '\0';
107 myfread(s, 1, 4, h);
108 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
109 ERR_failinit("Not IWAD or PWAD (1)");
112 p = 0; // wad number
113 n = myfread32(h); // num
114 o = myfread32(h); // offset
115 fseek(h, o, SEEK_SET);
116 for (j = 0; j < n; ++j) {
117 w.o = myfread32(h); // offset
118 w.l = myfread32(h); // len
119 myfread(w.n, 1, 8, h); // name
120 if (p >= MAX_WAD) {
121 ERR_failinit("Too many entries in the WAD");
123 wad[p].o = w.o;
124 wad[p].l = w.l;
125 memcpy(wad[p].n, w.n, 8);
126 wad[p].f = 0;
127 ++p;
130 //fclose(h);
132 for (i = 1; i < MAX_WADS; ++i) {
133 if (wads[i][0] != 0) {
134 logo(" add %s\n", wads[i]);
135 if ((wadh[i] = h = fopen(wads[i], "rb")) == NULL) {
136 ERR_failinit("Unable to open file (2): %s", wads[i]);
138 mysplitpath(wads[i], f_drive, f_dir, f_name, f_ext);
139 if (cp866_strcasecmp(f_ext, ".lmp") == 0) {
140 for (k = 0; k < MAX_WAD; ++k) {
141 if (cp866_strncasecmp(wad[k].n, f_name, 8) == 0) {
142 wad[k].o = 0;
143 wad[k].l = myfilelength(h);
144 wad[k].f = i;
145 break;
147 if (k >= MAX_WAD) {
148 if (p >= MAX_WAD) {
149 ERR_failinit("Too many entries in the WAD");
151 memset(wad[p].n, 0, 8);
152 strncpy(wad[p].n, f_name, 8);
153 wad[p].o = 0;
154 wad[p].l = myfilelength(h);
155 wad[p].f = i;
156 ++p;
160 s[0] = '\0';
161 myfread(s, 1, 4, h);
162 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
163 ERR_failinit("Not IWAD or PWAD (2)");
165 n = myfread32(h); // num
166 o = myfread32(h); // offset
167 fseek(h, o, SEEK_SET);
168 for (j = 0; j < n; ++j) {
169 w.o = myfread32(h); // offset
170 w.o = myfread32(h); // len
171 myfread(w.n, 1, 8, h); // name
172 for (k = 0; k < MAX_WAD; ++k) {
173 if (cp866_strncasecmp(wad[k].n, w.n, 8) == 0) {
174 wad[k].o = w.o;
175 wad[k].l = w.l;
176 wad[k].f = i;
177 break;
179 if (k >= MAX_WAD) {
180 if (p >= MAX_WAD) {
181 ERR_failinit("Too many entries in the WAD");
183 memcpy(wad[p].n, w.n, 8);
184 wad[p].o = w.o;
185 wad[p].l = w.l;
186 wad[p].f = i;
187 ++p;
195 wad_num = p;
198 // allocate resources
199 // (called from M_startup)
200 void F_allocres (void) {
201 d_start=F_getresid("D_START");
202 d_end=F_getresid("D_END");
203 m_start=F_getresid("M_START");
204 m_end=F_getresid("M_END");
205 s_start=F_getresid("S_START");
206 s_end=F_getresid("S_END");
209 // load resource
210 void F_loadres (int r, void *p, dword o, dword l) {
212 int oo;
213 FILE *fh;
216 oo=ftell(fh=wadh[wad[r].f]);
218 if(fseek(fh,wad[r].o+o,SEEK_SET)!=0)
219 ERR_fatal("Error while file reading");
221 if((dword)myfreadc(p,1,l,fh)!=l)
222 ERR_fatal("Error while loading resource %.8s", wad[r].n);
224 fseek(fh,oo,SEEK_SET);
228 /*
229 // unused
230 void F_saveres(int r, void *p, dword o, dword l) {
231 FILE* fh = wadh[wad[r].f];
232 int oo = ftell(fh);
233 if (fseek(fh, wad[r].o + o, SEEK_SET) != 0) {
234 ERR_fatal("Error while reading file");
236 myfwrite(p, l, 1, fh);
237 fseek(fh, oo, SEEK_SET);
239 */
241 // get resource id
242 int F_findres (const char n[8]) {
243 int i;
244 for (i = 0; i < wad_num; i++) {
245 if (cp866_strncasecmp(wad[i].n, n, 8) == 0) {
246 return i;
249 return -1;
252 // get resource id
253 int F_getresid (const char n[8]) {
254 int i = F_findres(n);
255 if (i == -1) {
256 ERR_fatal("F_getresid: resource %.8s not found", n);
258 return i;
261 void F_getresname (char n[8], int r) {
262 memcpy(n, wad[r].n, 8);
265 // get sprite id
266 int F_getsprid (const char n[4], int s, int d, char *dir) {
267 int i;
268 byte a, b;
269 s += 'A';
270 d += '0';
271 for (i = s_start + 1; i < s_end; i++) {
272 if (cp866_strncasecmp(wad[i].n, n, 4) == 0 && (wad[i].n[4] == s || wad[i].n[6] == s)) {
273 a = wad[i].n[4] == s ? wad[i].n[5] : 0;
274 b = wad[i].n[6] == s ? wad[i].n[7] : 0;
275 if (a == '0' || b == '0' || a == d || b == d) {
276 if (dir != NULL) {
277 *dir = a != '0' && b == '0' || a != d && b == d;
279 return i;
283 ERR_fatal("F_getsprid: image %.4s%c%c not found", n, s, d);
284 return -1;
287 int F_getreslen (int r) {
288 return wad[r].l;
291 void F_nextmus (char *s) {
292 int i;
293 i=F_findres(s);
294 if(i<=m_start || i>=m_end) i=m_start;
295 for(++i;;++i) {
296 if(i>=m_end) i=m_start+1;
298 if (cp866_strcasecmp(wad[i].n,"MENU") == 0 ||
299 cp866_strcasecmp(wad[i].n,"INTERMUS") == 0 ||
300 cp866_strcasecmp(wad[i].n,"\x8a\x8e\x8d\x85\x96\x0") == 0)
301 continue;
303 if(cp866_strncasecmp(wad[i].n,"DMI",3)!=0) break;
305 memcpy(s,wad[i].n,8);
308 void F_randmus (char *s) {
309 int i;
310 int n = myrand(10);
311 for (i = 0; i < n; i++) {
312 F_nextmus(s);
316 // reads bytes from file until CR
317 void F_readstr (FILE* h, char *s, int m) {
318 int i = 0;
319 size_t len = 0;
320 static char c = 0;
321 while (i < m) {
322 c = 13;
323 len = myfreadc(&c, 1, 1, h);
324 if (len == 0 || c == 13 || c == 10) {
325 break;
327 s[i] = c;
328 i++;
330 s[i] = 0;
333 /*
334 // unused
335 // reads bytes from file until NUL
336 void F_readstrz (FILE* h,char *s,int m) {
337 int i = 0;
338 size_t len = 0;
339 static char c = 0;
340 while (i < m) {
341 c = 0;
342 len = myfreadc(&c, 1, 1, h);
343 if (len == 0 || c == 0) {
344 break;
346 s[i] = c;
347 i++;
349 s[i] = 0;
351 */
353 /*void F_freemus(void) {
355 int i;
357 if(!pat) return;
358 S_stopmusic();
359 free(pat);free(patp);
360 for(i=0;i<inum;++i) if(dmi[i]!=NULL) free(dmi[i]);
361 free(dmi);
362 pat=NULL;
365 */
367 /*void F_loadmus(char n[8]) {
368 int r,i,j;
369 FILE *h;
370 int o;
371 struct{
372 char id[4];
373 byte ver,pat;
374 word psz;
375 }d;
376 struct{byte t;char n[13];word r;}di;
378 if((r=F_findres(n))==-1) return;
379 fseek(h=wadh[wad[r].f],wad[r].o,SEEK_SET);
380 myfread(&d,1,sizeof(d),h);
381 if(memcmp(d.id,"DMM",4)!=0) return;
382 if(!(pat=malloc(d.psz<<2))) return;
383 myfread(pat,1,d.psz<<2,h);
384 myfread(&seqn,1,1,h);if(seqn) myfread(seq,1,seqn,h);
385 inum=0;myfread(&inum,1,1,h);
386 if(!(dmi=malloc(inum*4))) {free(pat);pat=NULL;return;}
387 if(!(patp=malloc((word)d.pat*32))) {free(pat);free(dmi);pat=NULL;return;}
388 for(i=0;i<inum;++i) {
389 dmi[i]=NULL;
390 myfread(&di,1,16,h);o=ftell(h);
391 for(r=0;r<12;++r) if(di.n[r]=='.') di.n[r]=0;
392 if((r=F_findres(di.n))==-1) continue;
393 if(!(dmi[i]=malloc(wad[r].l+8))) continue;
394 memset(dmi[i],0,16);
395 F_loadres(r,dmi[i],0,2);
396 F_loadres(r,(int*)dmi[i]+1,2,2);
397 F_loadres(r,(int*)dmi[i]+2,4,2);
398 F_loadres(r,(int*)dmi[i]+3,6,2);
399 F_loadres(r,(int*)dmi[i]+4,8,wad[r].l-8);
400 fseek(h,o,SEEK_SET);
402 for(i=r=0,j=(word)d.pat<<3;i<j;++i) {
403 patp[i]=r<<2;
404 while(pat[r++].v!=0x80);
407 */