DEADSOFTWARE

implement optional opengl render
[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"
43 typedef struct {
44 byte n, i, v, d;
45 } dmv;
47 int d_start, d_end;
48 byte savname[7][24];
49 byte savok[7];
50 mwad_t wad[MAX_WAD];
51 map_block_t blk;
53 static byte seq[255];
54 static byte seqn;
55 static int inum=0;
56 static dmv *pat=NULL;
57 static unsigned *patp;
58 static void **dmi;
60 static int m_start, m_end;
61 static int s_start, s_end;
62 static int wad_num;
64 static char wads[MAX_WADS][__MAX_PATH];
65 static FILE* wadh[MAX_WADS];
67 static char f_drive[__MAX_DRIVE];
68 static char f_dir[__MAX_DIR];
69 static char f_name[__MAX_FNAME];
70 static char f_ext[__MAX_EXT];
72 void F_startup (void) {
73 logo("F_startup: настройка файловой системы\n");
74 memset(wads,0,sizeof(wads));
75 }
77 static char *getsavfpname (int n, int ro) {
78 static char fn[]="savgame0.dat";
79 fn[7]=n+'0';
80 #ifndef WIN32
81 static char p[100];
82 char *e = getenv("HOME");
83 strncpy(p,e,60);
84 strcat(p,"/.doom2d-rembo");
85 if (!ro) mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
86 strcat(p,"/");
87 strcat(p,fn);
88 #else
89 strcpy(p,fn);
90 #endif
91 return p;
92 }
94 void F_getsavnames (void) {
95 int i;
96 FILE *h;
97 short ver;
98 char *p;
99 for (i = 0; i < 7; ++i) {
100 p = getsavfpname(i, 1);
101 memset(savname[i], 0, 24);
102 savok[i] = 0;
103 h = fopen(p, "rb");
104 if (h != NULL) {
105 ver = -1;
106 myfread(savname[i], 24, 1, h);
107 ver = myfread16(h);
108 savname[i][23] = 0;
109 savok[i] = (ver == 3) ? 1 : 0;
110 fclose(h);
115 void F_savegame (int n, char *s) {
116 char *p = getsavfpname(n, 0);
117 FILE *h = fopen(p, "wb");
118 if (h != NULL) {
119 myfwrite(s, 24, 1, h); // slot name
120 myfwrite16(3, h); // version
121 G_savegame(h);
122 W_savegame(h);
123 DOT_savegame(h);
124 SMK_savegame(h);
125 FX_savegame(h);
126 IT_savegame(h);
127 MN_savegame(h);
128 PL_savegame(h);
129 SW_savegame(h);
130 WP_savegame(h);
131 fclose(h);
135 void F_loadgame (int n) {
136 short ver;
137 char *p = getsavfpname(n, 1);
138 FILE *h = fopen(p, "rb");
139 if (h != NULL) {
140 fseek(h, 24, SEEK_SET); // skip name
141 ver = myfread16(h); // version
142 if (ver == 3) {
143 G_loadgame(h);
144 W_loadgame(h);
145 DOT_loadgame(h);
146 SMK_loadgame(h);
147 FX_loadgame(h);
148 IT_loadgame(h);
149 MN_loadgame(h);
150 PL_loadgame(h);
151 SW_loadgame(h);
152 WP_loadgame(h);
154 fclose(h);
158 void F_addwad (char *fn) {
159 int i;
161 for(i=0;i<MAX_WADS;++i) if(wads[i][0]==0) {
162 strcpy(wads[i],fn);return;
164 ERR_failinit("Не могу добавить WAD %s",fn);
167 static int myfilelength (FILE *h) {
168 int pos = ftell(h);
169 fseek (h, 0, SEEK_END);
170 int len = ftell(h);
171 fseek (h, pos, SEEK_SET);
172 return len;
175 // build wad directory
176 void F_initwads (void) {
177 int i, j, k, p;
178 FILE *h;
179 char s[4];
180 int n, o;
181 wad_t w;
183 logo("F_initwads: подключение WAD-файлов\n");
184 for (i = 0; i < MAX_WAD; ++i) {
185 wad[i].n[0] = 0;
188 logo(" подключается %s\n", wads[0]);
189 if ((wadh[0] = h = fopen(wads[0], "rb")) == NULL) {
190 ERR_failinit("Не могу открыть файл: %s", wads[0]);
193 s[0] = '\0';
194 myfread(s, 1, 4, h);
195 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
196 ERR_failinit("Нет подписи IWAD или PWAD (1)");
199 p = 0; // wad number
200 n = myfread32(h); // num
201 o = myfread32(h); // offset
202 fseek(h, o, SEEK_SET);
203 for (j = 0; j < n; ++j) {
204 w.o = myfread32(h); // offset
205 w.l = myfread32(h); // len
206 myfread(w.n, 1, 8, h); // name
207 if (p >= MAX_WAD) {
208 ERR_failinit("Слишком много элементов WAD'а");
210 wad[p].o = w.o;
211 wad[p].l = w.l;
212 memcpy(wad[p].n, w.n, 8);
213 wad[p].f = 0;
214 ++p;
217 //fclose(h);
219 for (i = 1; i < MAX_WADS; ++i) {
220 if (wads[i][0] != 0) {
221 logo(" подключается %s\n", wads[i]);
222 if ((wadh[i] = h = fopen(wads[i], "rb")) == NULL) {
223 ERR_failinit("Не могу открыть файл2: %s", wads[i]);
225 mysplitpath(wads[i], f_drive, f_dir, f_name, f_ext);
226 if (strcasecmp(f_ext, ".lmp") == 0) {
227 for (k = 0; k < MAX_WAD; ++k) {
228 if (strncasecmp(wad[k].n, f_name, 8) == 0) {
229 wad[k].o = 0;
230 wad[k].l = myfilelength(h);
231 wad[k].f = i;
232 break;
234 if (k >= MAX_WAD) {
235 if (p >= MAX_WAD) {
236 ERR_failinit("Слишком много элементов WAD'а");
238 memset(wad[p].n, 0, 8);
239 strncpy(wad[p].n, f_name, 8);
240 wad[p].o = 0;
241 wad[p].l = myfilelength(h);
242 wad[p].f = i;
243 ++p;
247 s[0] = '\0';
248 myfread(s, 1, 4, h);
249 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
250 ERR_failinit("Нет подписи IWAD или PWAD (2)");
252 n = myfread32(h); // num
253 o = myfread32(h); // offset
254 fseek(h, o, SEEK_SET);
255 for (j = 0; j < n; ++j) {
256 w.o = myfread32(h); // offset
257 w.o = myfread32(h); // len
258 myfread(w.n, 1, 8, h); // name
259 for (k = 0; k < MAX_WAD; ++k) {
260 if (strncasecmp(wad[k].n, w.n, 8) == 0) {
261 wad[k].o = w.o;
262 wad[k].l = w.l;
263 wad[k].f = i;
264 break;
266 if (k >= MAX_WAD) {
267 if (p >= MAX_WAD) {
268 ERR_failinit("Слишком много элементов WAD'а");
270 memcpy(wad[p].n, w.n, 8);
271 wad[p].o = w.o;
272 wad[p].l = w.l;
273 wad[p].f = i;
274 ++p;
282 wad_num = p;
285 // allocate resources
286 // (called from M_startup)
287 void F_allocres (void) {
288 d_start=F_getresid("D_START");
289 d_end=F_getresid("D_END");
290 m_start=F_getresid("M_START");
291 m_end=F_getresid("M_END");
292 s_start=F_getresid("S_START");
293 s_end=F_getresid("S_END");
296 // load resource
297 void F_loadres (int r, void *p, dword o, dword l) {
299 int oo;
300 FILE *fh;
303 oo=ftell(fh=wadh[wad[r].f]);
305 if(fseek(fh,wad[r].o+o,SEEK_SET)!=0)
306 ERR_fatal("Ошибка при чтении файла");
308 if((dword)myfreadc(p,1,l,fh)!=l)
309 ERR_fatal("Ошибка при загрузке ресурса %.8s",wad[r].n);
311 fseek(fh,oo,SEEK_SET);
315 /*
316 // unused
317 void F_saveres(int r, void *p, dword o, dword l) {
318 FILE* fh = wadh[wad[r].f];
319 int oo = ftell(fh);
320 if (fseek(fh, wad[r].o + o, SEEK_SET) != 0) {
321 ERR_fatal("Ошибка при чтении файла");
323 myfwrite(p, l, 1, fh);
324 fseek(fh, oo, SEEK_SET);
326 */
328 // get resource id
329 int F_findres (const char n[8]) {
330 int i;
331 for (i = 0; i < wad_num; i++) {
332 if (strncasecmp(wad[i].n, n, 8) == 0) {
333 return i;
336 return -1;
339 // get resource id
340 int F_getresid (const char n[8]) {
341 int i = F_findres(n);
342 if (i == -1) {
343 ERR_fatal("F_getresid: ресурс %.8s не найден", n);
345 return i;
348 void F_getresname (char n[8], int r) {
349 memcpy(n, wad[r].n, 8);
352 // get sprite id
353 int F_getsprid (const char n[4], int s, int d) {
354 int i;
355 byte a,b;
357 s+='A';d+='0';
358 for(i=s_start+1;i<s_end;++i)
359 if(strncasecmp(wad[i].n,n,4)==0 && (wad[i].n[4]==s || wad[i].n[6]==s)) {
360 if(wad[i].n[4]==s) a=wad[i].n[5]; else a=0;
361 if(wad[i].n[6]==s) b=wad[i].n[7]; else b=0;
362 if(a=='0') return i;
363 if(b=='0') return(i|0x8000);
364 if(a==d) return i;
365 if(b==d) return(i|0x8000);
367 ERR_fatal("F_getsprid: изображение %.4s%c%c не найдено",n,(byte)s,(byte)d);
368 return -1;
371 int F_getreslen (int r) {
372 return wad[r].l;
375 void F_nextmus (char *s) {
376 int i;
377 i=F_findres(s);
378 if(i<=m_start || i>=m_end) i=m_start;
379 for(++i;;++i) {
380 if(i>=m_end) i=m_start+1;
382 if (strcasecmp(wad[i].n,"MENU") == 0 ||
383 strcasecmp(wad[i].n,"INTERMUS") == 0 ||
384 strcasecmp(wad[i].n,"\x8a\x8e\x8d\x85\x96\x0") == 0)
385 continue;
387 if(strncasecmp(wad[i].n,"DMI",3)!=0) break;
389 memcpy(s,wad[i].n,8);
392 void F_randmus (char *s) {
393 int i;
394 int n = myrand(10);
395 for (i = 0; i < n; i++) {
396 F_nextmus(s);
400 // reads bytes from file until CR
401 void F_readstr (FILE* h, char *s, int m) {
402 int i = 0;
403 size_t len = 0;
404 static char c = 0;
405 while (i < m) {
406 c = 13;
407 len = myfreadc(&c, 1, 1, h);
408 if (len == 0 || c == 13 || c == 10) {
409 break;
411 s[i] = c;
412 i++;
414 s[i] = 0;
417 /*
418 // unused
419 // reads bytes from file until NUL
420 void F_readstrz (FILE* h,char *s,int m) {
421 int i = 0;
422 size_t len = 0;
423 static char c = 0;
424 while (i < m) {
425 c = 0;
426 len = myfreadc(&c, 1, 1, h);
427 if (len == 0 || c == 0) {
428 break;
430 s[i] = c;
431 i++;
433 s[i] = 0;
435 */
437 void F_loadmap (char n[8]) {
438 int r, o;
439 FILE *h;
440 map_header_t hdr;
441 W_init();
442 r = F_getresid(n);
443 h = wadh[wad[r].f];
444 fseek(h, wad[r].o, SEEK_SET);
445 myfread(hdr.id, 8, 1, h);
446 hdr.ver = myfread16(h);
447 if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) {
448 ERR_fatal("%.8s не является уровнем", n);
450 for(;;) {
451 blk.t = myfread16(h);
452 blk.st = myfread16(h);
453 blk.sz = myfread32(h);
454 if(blk.t == MB_END) {
455 break;
457 if(blk.t == MB_COMMENT) {
458 fseek(h, blk.sz, SEEK_CUR);
459 continue;
461 o = ftell(h) + blk.sz;
462 if(!G_load(h)) {
463 if(!W_load(h)) {
464 if(!IT_load(h)) {
465 if(!SW_load(h)) {
466 ERR_fatal("Неизвестный блок %d(%d) в уровне %.8s", blk.t, blk.st, n);
471 fseek(h, o, SEEK_SET);
475 /*void F_freemus(void) {
477 int i;
479 if(!pat) return;
480 S_stopmusic();
481 free(pat);free(patp);
482 for(i=0;i<inum;++i) if(dmi[i]!=NULL) free(dmi[i]);
483 free(dmi);
484 pat=NULL;
487 */
489 /*void F_loadmus(char n[8]) {
490 int r,i,j;
491 FILE *h;
492 int o;
493 struct{
494 char id[4];
495 byte ver,pat;
496 word psz;
497 }d;
498 struct{byte t;char n[13];word r;}di;
500 if((r=F_findres(n))==-1) return;
501 fseek(h=wadh[wad[r].f],wad[r].o,SEEK_SET);
502 myfread(&d,1,sizeof(d),h);
503 if(memcmp(d.id,"DMM",4)!=0) return;
504 if(!(pat=malloc(d.psz<<2))) return;
505 myfread(pat,1,d.psz<<2,h);
506 myfread(&seqn,1,1,h);if(seqn) myfread(seq,1,seqn,h);
507 inum=0;myfread(&inum,1,1,h);
508 if(!(dmi=malloc(inum*4))) {free(pat);pat=NULL;return;}
509 if(!(patp=malloc((word)d.pat*32))) {free(pat);free(dmi);pat=NULL;return;}
510 for(i=0;i<inum;++i) {
511 dmi[i]=NULL;
512 myfread(&di,1,16,h);o=ftell(h);
513 for(r=0;r<12;++r) if(di.n[r]=='.') di.n[r]=0;
514 if((r=F_findres(di.n))==-1) continue;
515 if(!(dmi[i]=malloc(wad[r].l+8))) continue;
516 memset(dmi[i],0,16);
517 F_loadres(r,dmi[i],0,2);
518 F_loadres(r,(int*)dmi[i]+1,2,2);
519 F_loadres(r,(int*)dmi[i]+2,4,2);
520 F_loadres(r,(int*)dmi[i]+3,6,2);
521 F_loadres(r,(int*)dmi[i]+4,8,wad[r].l-8);
522 fseek(h,o,SEEK_SET);
524 for(i=r=0,j=(word)d.pat<<3;i<j;++i) {
525 patp[i]=r<<2;
526 while(pat[r++].v!=0x80);
529 */