DEADSOFTWARE

1b470913c6c4aaf56958889ddfe5c55f43dc730e
[flatwaifu.git] / src / files.c
1 /*
2 Copyright (C) Prikol Software 1996-1997
3 Copyright (C) Aleksey Volynskov 1996-1997
4 Copyright (C) <ARembo@gmail.com> 2011
6 This file is part of the Doom2D:Rembo project.
8 Doom2D:Rembo is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License version 2 as
10 published by the Free Software Foundation.
12 Doom2D:Rembo is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, see <http://www.gnu.org/licenses/> or
19 write to the Free Software Foundation, Inc.,
20 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
23 #include "glob.h"
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <sys/stat.h>
28 #include "files.h"
29 #include "map.h"
30 #include "my.h"
31 #include "game.h"
32 #include "view.h"
33 #include "dots.h"
34 #include "smoke.h"
35 #include "fx.h"
36 #include "items.h"
37 #include "monster.h"
38 #include "player.h"
39 #include "switch.h"
40 #include "weapons.h"
41 #include "error.h"
42 #include "cp866.h"
44 typedef struct {
45 byte n, i, v, d;
46 } dmv;
48 int d_start, d_end;
49 byte savname[7][24];
50 byte savok[7];
51 mwad_t wad[MAX_WAD];
52 map_block_t blk;
54 static byte seq[255];
55 static byte seqn;
56 static int inum=0;
57 static dmv *pat=NULL;
58 static unsigned *patp;
59 static void **dmi;
61 static int m_start, m_end;
62 static int s_start, s_end;
63 static int wad_num;
65 static char wads[MAX_WADS][__MAX_PATH];
66 static FILE* wadh[MAX_WADS];
68 static char f_drive[__MAX_DRIVE];
69 static char f_dir[__MAX_DIR];
70 static char f_name[__MAX_FNAME];
71 static char f_ext[__MAX_EXT];
73 void F_startup (void) {
74 logo("F_startup: настройка файловой системы\n");
75 memset(wads,0,sizeof(wads));
76 }
78 static char *getsavfpname (int n, int ro) {
79 static char fn[]="savgame0.dat";
80 fn[7]=n+'0';
81 #ifndef WIN32
82 static char p[100];
83 char *e = getenv("HOME");
84 strncpy(p,e,60);
85 strcat(p,"/.doom2d-rembo");
86 if (!ro) mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
87 strcat(p,"/");
88 strcat(p,fn);
89 #else
90 strcpy(p,fn);
91 #endif
92 return p;
93 }
95 void F_getsavnames (void) {
96 int i;
97 FILE *h;
98 short ver;
99 char *p;
100 for (i = 0; i < 7; ++i) {
101 p = getsavfpname(i, 1);
102 memset(savname[i], 0, 24);
103 savok[i] = 0;
104 h = fopen(p, "rb");
105 if (h != NULL) {
106 ver = -1;
107 myfread(savname[i], 24, 1, h);
108 ver = myfread16(h);
109 savname[i][23] = 0;
110 savok[i] = (ver == 3) ? 1 : 0;
111 fclose(h);
116 void F_savegame (int n, char *s) {
117 char *p = getsavfpname(n, 0);
118 FILE *h = fopen(p, "wb");
119 if (h != NULL) {
120 myfwrite(s, 24, 1, h); // slot name
121 myfwrite16(3, h); // version
122 G_savegame(h);
123 W_savegame(h);
124 DOT_savegame(h);
125 SMK_savegame(h);
126 FX_savegame(h);
127 IT_savegame(h);
128 MN_savegame(h);
129 PL_savegame(h);
130 SW_savegame(h);
131 WP_savegame(h);
132 fclose(h);
136 void F_loadgame (int n) {
137 short ver;
138 char *p = getsavfpname(n, 1);
139 FILE *h = fopen(p, "rb");
140 if (h != NULL) {
141 fseek(h, 24, SEEK_SET); // skip name
142 ver = myfread16(h); // version
143 if (ver == 3) {
144 G_loadgame(h);
145 W_loadgame(h);
146 DOT_loadgame(h);
147 SMK_loadgame(h);
148 FX_loadgame(h);
149 IT_loadgame(h);
150 MN_loadgame(h);
151 PL_loadgame(h);
152 SW_loadgame(h);
153 WP_loadgame(h);
155 fclose(h);
159 void F_addwad (const char *fn) {
160 int i;
162 for(i=0;i<MAX_WADS;++i) if(wads[i][0]==0) {
163 strcpy(wads[i],fn);return;
165 ERR_failinit("Не могу добавить WAD %s",fn);
168 static int myfilelength (FILE *h) {
169 int pos = ftell(h);
170 fseek (h, 0, SEEK_END);
171 int len = ftell(h);
172 fseek (h, pos, SEEK_SET);
173 return len;
176 // build wad directory
177 void F_initwads (void) {
178 int i, j, k, p;
179 FILE *h;
180 char s[4];
181 int n, o;
182 wad_t w;
184 logo("F_initwads: подключение WAD-файлов\n");
185 for (i = 0; i < MAX_WAD; ++i) {
186 wad[i].n[0] = 0;
189 logo(" подключается %s\n", wads[0]);
190 if ((wadh[0] = h = fopen(wads[0], "rb")) == NULL) {
191 ERR_failinit("Не могу открыть файл: %s", wads[0]);
194 s[0] = '\0';
195 myfread(s, 1, 4, h);
196 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
197 ERR_failinit("Нет подписи IWAD или PWAD (1)");
200 p = 0; // wad number
201 n = myfread32(h); // num
202 o = myfread32(h); // offset
203 fseek(h, o, SEEK_SET);
204 for (j = 0; j < n; ++j) {
205 w.o = myfread32(h); // offset
206 w.l = myfread32(h); // len
207 myfread(w.n, 1, 8, h); // name
208 if (p >= MAX_WAD) {
209 ERR_failinit("Слишком много элементов WAD'а");
211 wad[p].o = w.o;
212 wad[p].l = w.l;
213 memcpy(wad[p].n, w.n, 8);
214 wad[p].f = 0;
215 ++p;
218 //fclose(h);
220 for (i = 1; i < MAX_WADS; ++i) {
221 if (wads[i][0] != 0) {
222 logo(" подключается %s\n", wads[i]);
223 if ((wadh[i] = h = fopen(wads[i], "rb")) == NULL) {
224 ERR_failinit("Не могу открыть файл2: %s", wads[i]);
226 mysplitpath(wads[i], f_drive, f_dir, f_name, f_ext);
227 if (cp866_strcasecmp(f_ext, ".lmp") == 0) {
228 for (k = 0; k < MAX_WAD; ++k) {
229 if (cp866_strncasecmp(wad[k].n, f_name, 8) == 0) {
230 wad[k].o = 0;
231 wad[k].l = myfilelength(h);
232 wad[k].f = i;
233 break;
235 if (k >= MAX_WAD) {
236 if (p >= MAX_WAD) {
237 ERR_failinit("Слишком много элементов WAD'а");
239 memset(wad[p].n, 0, 8);
240 strncpy(wad[p].n, f_name, 8);
241 wad[p].o = 0;
242 wad[p].l = myfilelength(h);
243 wad[p].f = i;
244 ++p;
248 s[0] = '\0';
249 myfread(s, 1, 4, h);
250 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
251 ERR_failinit("Нет подписи IWAD или PWAD (2)");
253 n = myfread32(h); // num
254 o = myfread32(h); // offset
255 fseek(h, o, SEEK_SET);
256 for (j = 0; j < n; ++j) {
257 w.o = myfread32(h); // offset
258 w.o = myfread32(h); // len
259 myfread(w.n, 1, 8, h); // name
260 for (k = 0; k < MAX_WAD; ++k) {
261 if (cp866_strncasecmp(wad[k].n, w.n, 8) == 0) {
262 wad[k].o = w.o;
263 wad[k].l = w.l;
264 wad[k].f = i;
265 break;
267 if (k >= MAX_WAD) {
268 if (p >= MAX_WAD) {
269 ERR_failinit("Слишком много элементов WAD'а");
271 memcpy(wad[p].n, w.n, 8);
272 wad[p].o = w.o;
273 wad[p].l = w.l;
274 wad[p].f = i;
275 ++p;
283 wad_num = p;
286 // allocate resources
287 // (called from M_startup)
288 void F_allocres (void) {
289 d_start=F_getresid("D_START");
290 d_end=F_getresid("D_END");
291 m_start=F_getresid("M_START");
292 m_end=F_getresid("M_END");
293 s_start=F_getresid("S_START");
294 s_end=F_getresid("S_END");
297 // load resource
298 void F_loadres (int r, void *p, dword o, dword l) {
300 int oo;
301 FILE *fh;
304 oo=ftell(fh=wadh[wad[r].f]);
306 if(fseek(fh,wad[r].o+o,SEEK_SET)!=0)
307 ERR_fatal("Ошибка при чтении файла");
309 if((dword)myfreadc(p,1,l,fh)!=l)
310 ERR_fatal("Ошибка при загрузке ресурса %.8s",wad[r].n);
312 fseek(fh,oo,SEEK_SET);
316 /*
317 // unused
318 void F_saveres(int r, void *p, dword o, dword l) {
319 FILE* fh = wadh[wad[r].f];
320 int oo = ftell(fh);
321 if (fseek(fh, wad[r].o + o, SEEK_SET) != 0) {
322 ERR_fatal("Ошибка при чтении файла");
324 myfwrite(p, l, 1, fh);
325 fseek(fh, oo, SEEK_SET);
327 */
329 // get resource id
330 int F_findres (const char n[8]) {
331 int i;
332 for (i = 0; i < wad_num; i++) {
333 if (cp866_strncasecmp(wad[i].n, n, 8) == 0) {
334 return i;
337 return -1;
340 // get resource id
341 int F_getresid (const char n[8]) {
342 int i = F_findres(n);
343 if (i == -1) {
344 ERR_fatal("F_getresid: ресурс %.8s не найден", n);
346 return i;
349 void F_getresname (char n[8], int r) {
350 memcpy(n, wad[r].n, 8);
353 // get sprite id
354 int F_getsprid (const char n[4], int s, int d) {
355 int i;
356 byte a,b;
358 s+='A';d+='0';
359 for(i=s_start+1;i<s_end;++i)
360 if(cp866_strncasecmp(wad[i].n,n,4)==0 && (wad[i].n[4]==s || wad[i].n[6]==s)) {
361 if(wad[i].n[4]==s) a=wad[i].n[5]; else a=0;
362 if(wad[i].n[6]==s) b=wad[i].n[7]; else b=0;
363 if(a=='0') return i;
364 if(b=='0') return(i|0x8000);
365 if(a==d) return i;
366 if(b==d) return(i|0x8000);
368 ERR_fatal("F_getsprid: изображение %.4s%c%c не найдено",n,(byte)s,(byte)d);
369 return -1;
372 int F_getreslen (int r) {
373 return wad[r].l;
376 void F_nextmus (char *s) {
377 int i;
378 i=F_findres(s);
379 if(i<=m_start || i>=m_end) i=m_start;
380 for(++i;;++i) {
381 if(i>=m_end) i=m_start+1;
383 if (cp866_strcasecmp(wad[i].n,"MENU") == 0 ||
384 cp866_strcasecmp(wad[i].n,"INTERMUS") == 0 ||
385 cp866_strcasecmp(wad[i].n,"\x8a\x8e\x8d\x85\x96\x0") == 0)
386 continue;
388 if(cp866_strncasecmp(wad[i].n,"DMI",3)!=0) break;
390 memcpy(s,wad[i].n,8);
393 void F_randmus (char *s) {
394 int i;
395 int n = myrand(10);
396 for (i = 0; i < n; i++) {
397 F_nextmus(s);
401 // reads bytes from file until CR
402 void F_readstr (FILE* h, char *s, int m) {
403 int i = 0;
404 size_t len = 0;
405 static char c = 0;
406 while (i < m) {
407 c = 13;
408 len = myfreadc(&c, 1, 1, h);
409 if (len == 0 || c == 13 || c == 10) {
410 break;
412 s[i] = c;
413 i++;
415 s[i] = 0;
418 /*
419 // unused
420 // reads bytes from file until NUL
421 void F_readstrz (FILE* h,char *s,int m) {
422 int i = 0;
423 size_t len = 0;
424 static char c = 0;
425 while (i < m) {
426 c = 0;
427 len = myfreadc(&c, 1, 1, h);
428 if (len == 0 || c == 0) {
429 break;
431 s[i] = c;
432 i++;
434 s[i] = 0;
436 */
438 void F_loadmap (char n[8]) {
439 int r, o;
440 FILE *h;
441 map_header_t hdr;
442 W_init();
443 r = F_getresid(n);
444 h = wadh[wad[r].f];
445 fseek(h, wad[r].o, SEEK_SET);
446 myfread(hdr.id, 8, 1, h);
447 hdr.ver = myfread16(h);
448 if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) {
449 ERR_fatal("%.8s не является уровнем", n);
451 for(;;) {
452 blk.t = myfread16(h);
453 blk.st = myfread16(h);
454 blk.sz = myfread32(h);
455 if(blk.t == MB_END) {
456 break;
458 if(blk.t == MB_COMMENT) {
459 fseek(h, blk.sz, SEEK_CUR);
460 continue;
462 o = ftell(h) + blk.sz;
463 if(!G_load(h)) {
464 if(!W_load(h)) {
465 if(!IT_load(h)) {
466 if(!SW_load(h)) {
467 ERR_fatal("Неизвестный блок %d(%d) в уровне %.8s", blk.t, blk.st, n);
472 fseek(h, o, SEEK_SET);
476 /*void F_freemus(void) {
478 int i;
480 if(!pat) return;
481 S_stopmusic();
482 free(pat);free(patp);
483 for(i=0;i<inum;++i) if(dmi[i]!=NULL) free(dmi[i]);
484 free(dmi);
485 pat=NULL;
488 */
490 /*void F_loadmus(char n[8]) {
491 int r,i,j;
492 FILE *h;
493 int o;
494 struct{
495 char id[4];
496 byte ver,pat;
497 word psz;
498 }d;
499 struct{byte t;char n[13];word r;}di;
501 if((r=F_findres(n))==-1) return;
502 fseek(h=wadh[wad[r].f],wad[r].o,SEEK_SET);
503 myfread(&d,1,sizeof(d),h);
504 if(memcmp(d.id,"DMM",4)!=0) return;
505 if(!(pat=malloc(d.psz<<2))) return;
506 myfread(pat,1,d.psz<<2,h);
507 myfread(&seqn,1,1,h);if(seqn) myfread(seq,1,seqn,h);
508 inum=0;myfread(&inum,1,1,h);
509 if(!(dmi=malloc(inum*4))) {free(pat);pat=NULL;return;}
510 if(!(patp=malloc((word)d.pat*32))) {free(pat);free(dmi);pat=NULL;return;}
511 for(i=0;i<inum;++i) {
512 dmi[i]=NULL;
513 myfread(&di,1,16,h);o=ftell(h);
514 for(r=0;r<12;++r) if(di.n[r]=='.') di.n[r]=0;
515 if((r=F_findres(di.n))==-1) continue;
516 if(!(dmi[i]=malloc(wad[r].l+8))) continue;
517 memset(dmi[i],0,16);
518 F_loadres(r,dmi[i],0,2);
519 F_loadres(r,(int*)dmi[i]+1,2,2);
520 F_loadres(r,(int*)dmi[i]+2,4,2);
521 F_loadres(r,(int*)dmi[i]+3,6,2);
522 F_loadres(r,(int*)dmi[i]+4,8,wad[r].l-8);
523 fseek(h,o,SEEK_SET);
525 for(i=r=0,j=(word)d.pat<<3;i<j;++i) {
526 patp[i]=r<<2;
527 while(pat[r++].v!=0x80);
530 */