DEADSOFTWARE

ppc: fix saves and more map loading improvements
[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 "error.h"
29 #include "view.h"
30 #include "items.h"
31 #include "switch.h"
32 #include "files.h"
33 #include "map.h"
35 char *S_getinfo(void);
37 extern void *snd_drv;
39 typedef struct{
40 byte n,i,v,d;
41 }dmv;
43 byte seq[255],seqn;
44 dmv *pat=NULL;
45 unsigned *patp;
46 void **dmi;
48 static int inum=0;
50 void G_savegame(FILE*);
51 void W_savegame(FILE*);
52 void DOT_savegame(FILE*);
53 void SMK_savegame(FILE*);
54 void FX_savegame(FILE*);
55 void IT_savegame(FILE*);
56 void MN_savegame(FILE*);
57 void PL_savegame(FILE*);
58 void SW_savegame(FILE*);
59 void WP_savegame(FILE*);
61 void G_loadgame(FILE*);
62 void W_loadgame(FILE*);
63 void DOT_loadgame(FILE*);
64 void SMK_loadgame(FILE*);
65 void FX_loadgame(FILE*);
66 void IT_loadgame(FILE*);
67 void MN_loadgame(FILE*);
68 void PL_loadgame(FILE*);
69 void SW_loadgame(FILE*);
70 void WP_loadgame(FILE*);
72 byte savname[7][24],savok[7];
74 int d_start,d_end,m_start,m_end,s_start,s_end,wad_num;
75 mwad_t wad[MAX_WAD];
77 char wads[MAX_WADS][__MAX_PATH];
78 static FILE* wadh[MAX_WADS];
80 char f_drive[__MAX_DRIVE],f_dir[__MAX_DIR],f_name[__MAX_FNAME],f_ext[__MAX_EXT],
81 f_path[__MAX_PATH];
83 void F_startup(void) {
84 logo("F_startup: настройка файловой системы\n");
85 memset(wads,0,sizeof(wads));
86 }
88 char *getsavfpname(int n, int ro)
89 {
90 static char fn[]="savgame0.dat";
91 fn[7]=n+'0';
92 #ifndef WIN32
93 static char p[100];
94 char *e = getenv("HOME");
95 strncpy(p,e,60);
96 strcat(p,"/.doom2d-rembo");
97 if (!ro) mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
98 strcat(p,"/");
99 strcat(p,fn);
100 #else
101 strcpy(p,fn);
102 #endif
103 return p;
106 void F_getsavnames (void) {
107 int i;
108 FILE *h;
109 short ver;
110 char *p;
111 for (i = 0; i < 7; ++i) {
112 p = getsavfpname(i, 1);
113 memset(savname[i], 0, 24);
114 savok[i] = 0;
115 h = fopen(p, "rb");
116 if (h != NULL) {
117 ver = -1;
118 myfread(savname[i], 24, 1, h);
119 myfread16(&ver, h);
120 savname[i][23] = 0;
121 savok[i] = (ver == 3) ? 1 : 0;
122 fclose(h);
127 void F_savegame (int n, char *s) {
128 char *p = getsavfpname(n, 0);
129 FILE *h = fopen(p, "wb");
130 if (h != NULL) {
131 myfwrite(s, 24, 1, h); // slot name
132 myfwrite16(3, h); // version
133 G_savegame(h);
134 W_savegame(h);
135 DOT_savegame(h);
136 SMK_savegame(h);
137 FX_savegame(h);
138 IT_savegame(h);
139 MN_savegame(h);
140 PL_savegame(h);
141 SW_savegame(h);
142 WP_savegame(h);
143 fclose(h);
147 void F_loadgame (int n) {
148 short ver;
149 char *p = getsavfpname(n, 1);
150 FILE *h = fopen(p, "rb");
151 if (h != NULL) {
152 fseek(h, 24, SEEK_SET); // skip name
153 myfread16(&ver, h); // version
154 if (ver == 3) {
155 G_loadgame(h);
156 W_loadgame(h);
157 DOT_loadgame(h);
158 SMK_loadgame(h);
159 FX_loadgame(h);
160 IT_loadgame(h);
161 MN_loadgame(h);
162 PL_loadgame(h);
163 SW_loadgame(h);
164 WP_loadgame(h);
166 fclose(h);
170 void F_addwad(char *fn) {
171 int i;
173 for(i=0;i<MAX_WADS;++i) if(wads[i][0]==0) {
174 strcpy(wads[i],fn);return;
176 ERR_failinit("Не могу добавить WAD %s",fn);
180 int myfilelength(FILE *h)
182 int pos = ftell(h);
183 fseek (h, 0, SEEK_END);
184 int len = ftell(h);
185 fseek (h, pos, SEEK_SET);
186 return len;
189 extern void mysplitpath(const char* path, char* drv, char* dir, char* name, char* ext);
191 static int myread_int32 (FILE *f) {
192 int x;
193 myfread(&x, 4, 1, f);
194 return int2host(x);
197 // build wad directory
198 void F_initwads (void) {
199 int i, j, k, p;
200 FILE *h;
201 char s[4];
202 int n, o;
203 wad_t w;
205 logo("F_initwads: подключение WAD-файлов\n");
206 for (i = 0; i < MAX_WAD; ++i) {
207 wad[i].n[0] = 0;
210 logo(" подключается %s\n", wads[0]);
211 if ((wadh[0] = h = fopen(wads[0], "rb")) == NULL) {
212 ERR_failinit("Не могу открыть файл: %s", wads[0]);
215 s[0] = '\0';
216 myfread(s, 1, 4, h);
217 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
218 ERR_failinit("Нет подписи IWAD или PWAD (1)");
221 p = 0; // wad number
222 n = myread_int32(h); // num
223 o = myread_int32(h); // offset
224 fseek(h, o, SEEK_SET);
225 for (j = 0; j < n; ++j) {
226 w.o = myread_int32(h); // offset
227 w.l = myread_int32(h); // len
228 myfread(w.n, 1, 8, h); // name
229 if (p >= MAX_WAD) {
230 ERR_failinit("Слишком много элементов WAD'а");
232 wad[p].o = w.o;
233 wad[p].l = w.l;
234 memcpy(wad[p].n, w.n, 8);
235 wad[p].f = 0;
236 ++p;
239 //fclose(h);
241 for (i = 1; i < MAX_WADS; ++i) {
242 if (wads[i][0] != 0) {
243 logo(" подключается %s\n", wads[i]);
244 if ((wadh[i] = h = fopen(wads[i], "rb")) == NULL) {
245 ERR_failinit("Не могу открыть файл2: %s", wads[i]);
247 mysplitpath(wads[i], f_drive, f_dir, f_name, f_ext);
248 if (strcasecmp(f_ext, ".lmp") == 0) {
249 for (k = 0; k < MAX_WAD; ++k) {
250 if (strncasecmp(wad[k].n, f_name, 8) == 0) {
251 wad[k].o = 0;
252 wad[k].l = myfilelength(h);
253 wad[k].f = i;
254 break;
256 if (k >= MAX_WAD) {
257 if (p >= MAX_WAD) {
258 ERR_failinit("Слишком много элементов WAD'а");
260 memset(wad[p].n, 0, 8);
261 strncpy(wad[p].n, f_name, 8);
262 wad[p].o = 0;
263 wad[p].l = myfilelength(h);
264 wad[p].f = i;
265 ++p;
269 s[0] = '\0';
270 myfread(s, 1, 4, h);
271 if (strncmp(s, "IWAD", 4) != 0 && strncmp(s, "PWAD", 4) != 0) {
272 ERR_failinit("Нет подписи IWAD или PWAD (2)");
274 n = myread_int32(h); // num
275 o = myread_int32(h); // offset
276 fseek(h, o, SEEK_SET);
277 for (j = 0; j < n; ++j) {
278 w.o = myread_int32(h); // offset
279 w.l = myread_int32(h); // len
280 myfread(w.n, 1, 8, h); // name
281 for (k = 0; k < MAX_WAD; ++k) {
282 if (strncasecmp(wad[k].n, w.n, 8) == 0) {
283 wad[k].o = w.o;
284 wad[k].l = w.l;
285 wad[k].f = i;
286 break;
288 if (k >= MAX_WAD) {
289 if (p >= MAX_WAD) {
290 ERR_failinit("Слишком много элементов WAD'а");
292 memcpy(wad[p].n, w.n, 8);
293 wad[p].o = w.o;
294 wad[p].l = w.l;
295 wad[p].f = i;
296 ++p;
304 wad_num = p;
307 // allocate resources
308 // (called from M_startup)
309 void F_allocres(void) {
310 d_start=F_getresid("D_START");
311 d_end=F_getresid("D_END");
312 m_start=F_getresid("M_START");
313 m_end=F_getresid("M_END");
314 s_start=F_getresid("S_START");
315 s_end=F_getresid("S_END");
318 // load resource
319 void F_loadres(int r,void *p,dword o,dword l) {
321 int oo;
322 FILE *fh;
325 oo=ftell(fh=wadh[wad[r].f]);
327 if(fseek(fh,wad[r].o+o,SEEK_SET)!=0)
328 ERR_fatal("Ошибка при чтении файла");
330 if((dword)myfreadc(p,1,l,fh)!=l)
331 ERR_fatal("Ошибка при загрузке ресурса %.8s",wad[r].n);
333 fseek(fh,oo,SEEK_SET);
338 void F_saveres(int r,void *p,dword o,dword l) {
340 int oo;
341 FILE* fh;
342 oo=ftell(fh=wadh[wad[r].f]);
343 if(fseek(fh,wad[r].o+o,SEEK_SET)!=0)
344 ERR_fatal("Ошибка при чтении файла");
345 myfwrite(p,l,1,fh);
346 fseek(fh,oo,SEEK_SET);
350 // get resource id
351 int F_getresid(char *n) {
352 int i;
354 for(i=0;i<wad_num;++i) if(strncasecmp(wad[i].n,n,8)==0) return i;
355 ERR_fatal("F_getresid: ресурс %.8s не найден",n);
356 return -1;
359 // get resource id
360 int F_findres(char *n) {
361 int i;
363 for(i=0;i<wad_num;++i) if(strncasecmp(wad[i].n,n,8)==0) return i;
364 return -1;
367 void F_getresname(char *n,int r) {
368 memcpy(n,wad[r].n,8);
371 // get sprite id
372 int F_getsprid(char n[4],int s,int d) {
373 int i;
374 byte a,b;
376 s+='A';d+='0';
377 for(i=s_start+1;i<s_end;++i)
378 if(strncasecmp(wad[i].n,n,4)==0 && (wad[i].n[4]==s || wad[i].n[6]==s)) {
379 if(wad[i].n[4]==s) a=wad[i].n[5]; else a=0;
380 if(wad[i].n[6]==s) b=wad[i].n[7]; else b=0;
381 if(a=='0') return i;
382 if(b=='0') return(i|0x8000);
383 if(a==d) return i;
384 if(b==d) return(i|0x8000);
386 ERR_fatal("F_getsprid: изображение %.4s%c%c не найдено",n,(byte)s,(byte)d);
387 return -1;
390 int F_getreslen(int r) {
391 return wad[r].l;
394 void F_nextmus(char *s) {
395 int i;
396 i=F_findres(s);
397 if(i<=m_start || i>=m_end) i=m_start;
398 for(++i;;++i) {
399 if(i>=m_end) i=m_start+1;
401 if (strcasecmp(wad[i].n,"MENU") == 0 ||
402 strcasecmp(wad[i].n,"INTERMUS") == 0 ||
403 strcasecmp(wad[i].n,"\x8a\x8e\x8d\x85\x96\x0") == 0)
404 continue;
406 if(strncasecmp(wad[i].n,"DMI",3)!=0) break;
408 memcpy(s,wad[i].n,8);
411 void F_randmus(char *s) {
412 int n = myrand(10);
413 int i;
414 for (i=0; i<n; i++) {
415 F_nextmus(s);
419 // reads bytes from file until CR
420 void F_readstr(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 = 13;
426 len = myfreadc(&c, 1, 1, h);
427 if (len == 0 || c == 13 || c == 10) {
428 break;
430 s[i] = c;
431 i++;
433 s[i] = 0;
436 // reads bytes from file until NUL
437 void F_readstrz(FILE* h,char *s,int m) {
438 int i = 0;
439 size_t len = 0;
440 static char c = 0;
441 while (i < m) {
442 c = 0;
443 len = myfreadc(&c, 1, 1, h);
444 if (len == 0 || c == 0) {
445 break;
447 s[i] = c;
448 i++;
450 s[i] = 0;
453 map_block_t blk;
455 void F_loadmap(char n[8]) {
456 int r, o;
457 FILE *h;
458 map_header_t hdr;
459 W_init();
460 r = F_getresid(n);
461 h = wadh[wad[r].f];
462 fseek(h, wad[r].o, SEEK_SET);
463 myfread(hdr.id, 8, 1, h);
464 myfread16(&hdr.ver, h);
465 if (memcmp(hdr.id, "Doom2D\x1A", 8) != 0) {
466 ERR_fatal("%.8s не является уровнем", n);
468 for(;;) {
469 myfread16(&blk.t, h);
470 myfread16(&blk.st, h);
471 myfread32(&blk.sz, h);
472 if(blk.t == MB_END) {
473 break;
475 if(blk.t == MB_COMMENT) {
476 fseek(h, blk.sz, SEEK_CUR);
477 continue;
479 o = ftell(h) + blk.sz;
480 if(!G_load(h)) {
481 if(!W_load(h)) {
482 if(!IT_load(h)) {
483 if(!SW_load(h)) {
484 ERR_fatal("Неизвестный блок %d(%d) в уровне %.8s", blk.t, blk.st, n);
489 fseek(h, o, SEEK_SET);
493 /*void F_freemus(void) {
495 int i;
497 if(!pat) return;
498 S_stopmusic();
499 free(pat);free(patp);
500 for(i=0;i<inum;++i) if(dmi[i]!=NULL) free(dmi[i]);
501 free(dmi);
502 pat=NULL;
505 */
507 /*void F_loadmus(char n[8]) {
508 int r,i,j;
509 FILE *h;
510 int o;
511 struct{
512 char id[4];
513 byte ver,pat;
514 word psz;
515 }d;
516 struct{byte t;char n[13];word r;}di;
518 if((r=F_findres(n))==-1) return;
519 fseek(h=wadh[wad[r].f],wad[r].o,SEEK_SET);
520 myfread(&d,1,sizeof(d),h);
521 if(memcmp(d.id,"DMM",4)!=0) return;
522 if(!(pat=malloc(d.psz<<2))) return;
523 myfread(pat,1,d.psz<<2,h);
524 myfread(&seqn,1,1,h);if(seqn) myfread(seq,1,seqn,h);
525 inum=0;myfread(&inum,1,1,h);
526 if(!(dmi=malloc(inum*4))) {free(pat);pat=NULL;return;}
527 if(!(patp=malloc((word)d.pat*32))) {free(pat);free(dmi);pat=NULL;return;}
528 for(i=0;i<inum;++i) {
529 dmi[i]=NULL;
530 myfread(&di,1,16,h);o=ftell(h);
531 for(r=0;r<12;++r) if(di.n[r]=='.') di.n[r]=0;
532 if((r=F_findres(di.n))==-1) continue;
533 if(!(dmi[i]=malloc(wad[r].l+8))) continue;
534 memset(dmi[i],0,16);
535 F_loadres(r,dmi[i],0,2);
536 F_loadres(r,(int*)dmi[i]+1,2,2);
537 F_loadres(r,(int*)dmi[i]+2,4,2);
538 F_loadres(r,(int*)dmi[i]+3,6,2);
539 F_loadres(r,(int*)dmi[i]+4,8,wad[r].l-8);
540 fseek(h,o,SEEK_SET);
542 for(i=r=0,j=(word)d.pat<<3;i<j;++i) {
543 patp[i]=r<<2;
544 while(pat[r++].v!=0x80);
547 */