DEADSOFTWARE

manager: remove flag 0x8000 from resource handle id
[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, char *dir) {
355 int i;
356 byte a, b;
357 s += 'A';
358 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 a = wad[i].n[4] == s ? wad[i].n[5] : 0;
362 b = wad[i].n[6] == s ? wad[i].n[7] : 0;
363 if (a == '0' || b == '0' || a == d || b == d) {
364 if (dir != NULL) {
365 *dir = a != '0' && b == '0' || a != d && b == d;
367 return i;
371 ERR_fatal("F_getsprid: image %.4s%c%c not found", n, s, d);
372 return -1;
375 int F_getreslen (int r) {
376 return wad[r].l;
379 void F_nextmus (char *s) {
380 int i;
381 i=F_findres(s);
382 if(i<=m_start || i>=m_end) i=m_start;
383 for(++i;;++i) {
384 if(i>=m_end) i=m_start+1;
386 if (cp866_strcasecmp(wad[i].n,"MENU") == 0 ||
387 cp866_strcasecmp(wad[i].n,"INTERMUS") == 0 ||
388 cp866_strcasecmp(wad[i].n,"\x8a\x8e\x8d\x85\x96\x0") == 0)
389 continue;
391 if(cp866_strncasecmp(wad[i].n,"DMI",3)!=0) break;
393 memcpy(s,wad[i].n,8);
396 void F_randmus (char *s) {
397 int i;
398 int n = myrand(10);
399 for (i = 0; i < n; i++) {
400 F_nextmus(s);
404 // reads bytes from file until CR
405 void F_readstr (FILE* h, char *s, int m) {
406 int i = 0;
407 size_t len = 0;
408 static char c = 0;
409 while (i < m) {
410 c = 13;
411 len = myfreadc(&c, 1, 1, h);
412 if (len == 0 || c == 13 || c == 10) {
413 break;
415 s[i] = c;
416 i++;
418 s[i] = 0;
421 /*
422 // unused
423 // reads bytes from file until NUL
424 void F_readstrz (FILE* h,char *s,int m) {
425 int i = 0;
426 size_t len = 0;
427 static char c = 0;
428 while (i < m) {
429 c = 0;
430 len = myfreadc(&c, 1, 1, h);
431 if (len == 0 || c == 0) {
432 break;
434 s[i] = c;
435 i++;
437 s[i] = 0;
439 */
441 void F_loadmap (char n[8]) {
442 int r, o;
443 FILE *h;
444 map_header_t hdr;
445 W_init();
446 r = F_getresid(n);
447 h = wadh[wad[r].f];
448 fseek(h, wad[r].o, SEEK_SET);
449 myfread(hdr.id, 8, 1, h);
450 hdr.ver = myfread16(h);
451 if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) {
452 ERR_fatal("%.8s не является уровнем", n);
454 for(;;) {
455 blk.t = myfread16(h);
456 blk.st = myfread16(h);
457 blk.sz = myfread32(h);
458 if(blk.t == MB_END) {
459 break;
461 if(blk.t == MB_COMMENT) {
462 fseek(h, blk.sz, SEEK_CUR);
463 continue;
465 o = ftell(h) + blk.sz;
466 if(!G_load(h)) {
467 if(!W_load(h)) {
468 if(!IT_load(h)) {
469 if(!SW_load(h)) {
470 ERR_fatal("Неизвестный блок %d(%d) в уровне %.8s", blk.t, blk.st, n);
475 fseek(h, o, SEEK_SET);
479 /*void F_freemus(void) {
481 int i;
483 if(!pat) return;
484 S_stopmusic();
485 free(pat);free(patp);
486 for(i=0;i<inum;++i) if(dmi[i]!=NULL) free(dmi[i]);
487 free(dmi);
488 pat=NULL;
491 */
493 /*void F_loadmus(char n[8]) {
494 int r,i,j;
495 FILE *h;
496 int o;
497 struct{
498 char id[4];
499 byte ver,pat;
500 word psz;
501 }d;
502 struct{byte t;char n[13];word r;}di;
504 if((r=F_findres(n))==-1) return;
505 fseek(h=wadh[wad[r].f],wad[r].o,SEEK_SET);
506 myfread(&d,1,sizeof(d),h);
507 if(memcmp(d.id,"DMM",4)!=0) return;
508 if(!(pat=malloc(d.psz<<2))) return;
509 myfread(pat,1,d.psz<<2,h);
510 myfread(&seqn,1,1,h);if(seqn) myfread(seq,1,seqn,h);
511 inum=0;myfread(&inum,1,1,h);
512 if(!(dmi=malloc(inum*4))) {free(pat);pat=NULL;return;}
513 if(!(patp=malloc((word)d.pat*32))) {free(pat);free(dmi);pat=NULL;return;}
514 for(i=0;i<inum;++i) {
515 dmi[i]=NULL;
516 myfread(&di,1,16,h);o=ftell(h);
517 for(r=0;r<12;++r) if(di.n[r]=='.') di.n[r]=0;
518 if((r=F_findres(di.n))==-1) continue;
519 if(!(dmi[i]=malloc(wad[r].l+8))) continue;
520 memset(dmi[i],0,16);
521 F_loadres(r,dmi[i],0,2);
522 F_loadres(r,(int*)dmi[i]+1,2,2);
523 F_loadres(r,(int*)dmi[i]+2,4,2);
524 F_loadres(r,(int*)dmi[i]+3,6,2);
525 F_loadres(r,(int*)dmi[i]+4,8,wad[r].l-8);
526 fseek(h,o,SEEK_SET);
528 for(i=r=0,j=(word)d.pat<<3;i<j;++i) {
529 patp[i]=r<<2;
530 while(pat[r++].v!=0x80);
533 */