DEADSOFTWARE

portability: use posix functions only on unix
[flatwaifu.git] / src / save.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 "save.h"
20 #include "dots.h"
21 #include "fx.h"
22 #include "game.h"
23 #include "items.h"
24 #include "monster.h"
25 #include "player.h"
26 #include "smoke.h"
27 #include "switch.h"
28 #include "view.h"
29 #include "weapons.h"
31 #include "render.h"
32 #include "music.h"
34 #include <stdio.h> // FILE
35 #include <string.h>
36 #ifdef UNIX
37 # include <sys/stat.h>
38 #endif
39 #include "files.h"
40 #include "my.h"
42 char savname[SAVE_MAX][SAVE_MAXLEN];
43 char savok[SAVE_MAX];
45 static void DOT_savegame (FILE *h) {
46 int i, n;
47 for (i = n = 0; i < MAXDOT; ++i) {
48 if (dot[i].t) {
49 ++n;
50 }
51 }
52 myfwrite32(n, h);
53 for (i = 0; i < MAXDOT; ++i) {
54 if (dot[i].t) {
55 myfwrite32(dot[i].o.x, h);
56 myfwrite32(dot[i].o.y, h);
57 myfwrite32(dot[i].o.xv, h);
58 myfwrite32(dot[i].o.yv, h);
59 myfwrite32(dot[i].o.vx, h);
60 myfwrite32(dot[i].o.vy, h);
61 myfwrite32(dot[i].o.r, h);
62 myfwrite32(dot[i].o.h, h);
63 myfwrite8(dot[i].c, h);
64 myfwrite8(dot[i].t, h);
65 }
66 }
67 }
69 static void DOT_loadgame (FILE *h) {
70 int i, n;
71 n = myfread32(h);
72 for (i = 0; i < n; i++) {
73 dot[i].o.x = myfread32(h);
74 dot[i].o.y = myfread32(h);
75 dot[i].o.xv = myfread32(h);
76 dot[i].o.yv = myfread32(h);
77 dot[i].o.vx = myfread32(h);
78 dot[i].o.vy = myfread32(h);
79 dot[i].o.r = myfread32(h);
80 dot[i].o.h = myfread32(h);
81 dot[i].c = myfread8(h);
82 dot[i].t = myfread8(h);
83 }
84 }
86 static void FX_savegame (FILE *h) {
87 int i, n;
88 for (i = n = 0; i < MAXFX; ++i) {
89 if (fx[i].t) {
90 ++n;
91 }
92 }
93 myfwrite32(n, h);
94 for (i = 0; i < MAXFX; ++i) {
95 if (fx[i].t) {
96 myfwrite32(fx[i].x, h);
97 myfwrite32(fx[i].y, h);
98 myfwrite32(fx[i].xv, h);
99 myfwrite32(fx[i].yv, h);
100 myfwrite8(fx[i].t, h);
101 myfwrite8(fx[i].s, h);
106 static void FX_loadgame (FILE *h) {
107 int i, n;
108 n = myfread32(h);
109 for (i = 0; i < n; i++) {
110 fx[i].x = myfread32(h);
111 fx[i].y = myfread32(h);
112 fx[i].xv = myfread32(h);
113 fx[i].yv = myfread32(h);
114 fx[i].t = myfread8(h);
115 fx[i].s = myfread8(h);
119 static void G_savegame (FILE *h) {
120 myfwrite8(_2pl, h);
121 myfwrite8(g_dm, h);
122 myfwrite8(g_exit, h);
123 myfwrite8(g_map, h);
124 myfwrite32(g_time, h);
125 myfwrite32(dm_pl1p, h);
126 myfwrite32(dm_pl2p, h);
127 myfwrite32(dm_pnum, h);
128 int i = 0;
129 while (i < dm_pnum) {
130 myfwrite32(dm_pos[i].x, h);
131 myfwrite32(dm_pos[i].y, h);
132 myfwrite8(dm_pos[i].d, h);
133 i += 1;
135 myfwrite8(cheat, h);
136 myfwrite(g_music, 8, 1, h);
139 static void G_loadgame (FILE *h) {
140 _2pl = myfread8(h);
141 g_dm = myfread8(h);
142 g_exit = myfread8(h);
143 g_map = myfread8(h);
144 g_time = myfread32(h);
145 dm_pl1p = myfread32(h);
146 dm_pl2p = myfread32(h);
147 dm_pnum = myfread32(h);
148 int i = 0;
149 while (i < dm_pnum) {
150 dm_pos[i].x = myfread32(h);
151 dm_pos[i].y = myfread32(h);
152 dm_pos[i].d = myfread8(h);
153 i += 1;
155 cheat = myfread8(h);
156 myfread(g_music, 8, 1, h);
157 MUS_load(g_music);
160 static void IT_savegame (FILE *h) {
161 int i, n;
162 for (n = MAXITEM - 1; n >= 0 && it[n].t == 0; n--) {
163 // empty
165 n += 1;
166 myfwrite32(n, h);
167 for (i = 0; i < n; i++) {
168 myfwrite32(it[i].o.x, h);
169 myfwrite32(it[i].o.y, h);
170 myfwrite32(it[i].o.xv, h);
171 myfwrite32(it[i].o.yv, h);
172 myfwrite32(it[i].o.vx, h);
173 myfwrite32(it[i].o.vy, h);
174 myfwrite32(it[i].o.r, h);
175 myfwrite32(it[i].o.h, h);
176 myfwrite32(it[i].t, h);
177 myfwrite32(it[i].s, h);
179 myfwrite32(itm_rtime, h);
182 static void IT_loadgame (FILE *h) {
183 int i, n;
184 n = myfread32(h);
185 for (i = 0; i < n; i++) {
186 it[i].o.x = myfread32(h);
187 it[i].o.y = myfread32(h);
188 it[i].o.xv = myfread32(h);
189 it[i].o.yv = myfread32(h);
190 it[i].o.vx = myfread32(h);
191 it[i].o.vy = myfread32(h);
192 it[i].o.r = myfread32(h);
193 it[i].o.h = myfread32(h);
194 it[i].t = myfread32(h);
195 it[i].s = myfread32(h);
197 itm_rtime = myfread32(h);
200 static void MN_savegame (FILE *h) {
201 int i, n;
202 for (n = MAXMN - 1; n >= 0 && mn[n].t == 0; n--) {
203 // empty
205 n += 1;
206 myfwrite32(n, h);
207 for (i = 0; i < n; i++) {
208 myfwrite32(mn[i].o.x, h);
209 myfwrite32(mn[i].o.y, h);
210 myfwrite32(mn[i].o.xv, h);
211 myfwrite32(mn[i].o.yv, h);
212 myfwrite32(mn[i].o.vx, h);
213 myfwrite32(mn[i].o.vy, h);
214 myfwrite32(mn[i].o.r, h);
215 myfwrite32(mn[i].o.h, h);
216 myfwrite8(mn[i].t, h);
217 myfwrite8(mn[i].d, h);
218 myfwrite8(mn[i].st, h);
219 myfwrite8(mn[i].ftime, h);
220 myfwrite32(mn[i].fobj, h);
221 myfwrite32(mn[i].s, h);
222 myfwrite32(0, h); // mn[i].ap useless, changed after load
223 myfwrite32(mn[i].aim, h);
224 myfwrite32(mn[i].life, h);
225 myfwrite32(mn[i].pain, h);
226 myfwrite32(mn[i].ac, h);
227 myfwrite32(mn[i].tx, h);
228 myfwrite32(mn[i].ty, h);
229 myfwrite32(mn[i].ammo, h);
230 myfwrite16(mn[i].atm, h);
232 myfwrite32(mnum, h);
233 myfwrite32(gsndt, h);
236 static void MN_loadgame (FILE *h) {
237 int i, n, c;
238 n = myfread32(h);
239 for (i = 0; i < n; i++) {
240 mn[i].o.x = myfread32(h);
241 mn[i].o.y = myfread32(h);
242 mn[i].o.xv = myfread32(h);
243 mn[i].o.yv = myfread32(h);
244 mn[i].o.vx = myfread32(h);
245 mn[i].o.vy = myfread32(h);
246 mn[i].o.r = myfread32(h);
247 mn[i].o.h = myfread32(h);
248 mn[i].t = myfread8(h);
249 mn[i].d = myfread8(h);
250 mn[i].st = myfread8(h);
251 mn[i].ftime = myfread8(h);
252 mn[i].fobj = myfread32(h);
253 mn[i].s = myfread32(h);
254 mn[i].ap = NULL; myfread32(h); // useless, changed after loading
255 mn[i].aim = myfread32(h);
256 mn[i].life = myfread32(h);
257 mn[i].pain = myfread32(h);
258 mn[i].ac = myfread32(h);
259 mn[i].tx = myfread32(h);
260 mn[i].ty = myfread32(h);
261 mn[i].ammo = myfread32(h);
262 mn[i].atm = myfread16(h);
264 mnum = myfread32(h);
265 gsndt = myfread32(h);
266 for (n = 0; n < MAXMN; n++) {
267 if (mn[n].t) {
268 c = mn[n].ac;
269 setst(n, mn[n].st);
270 mn[n].ac = c;
275 static void PL_save_player (player_t *p, FILE *h) {
276 myfwrite32(p->o.x, h);
277 myfwrite32(p->o.y, h);
278 myfwrite32(p->o.xv, h);
279 myfwrite32(p->o.yv, h);
280 myfwrite32(p->o.vx, h);
281 myfwrite32(p->o.vy, h);
282 myfwrite32(p->o.r, h);
283 myfwrite32(p->o.h, h);
284 myfwrite32(p->looky, h);
285 myfwrite32(p->st, h);
286 myfwrite32(p->s, h);
287 myfwrite32(p->life, h);
288 myfwrite32(p->armor, h);
289 myfwrite32(p->hit, h);
290 myfwrite32(p->hito, h);
291 myfwrite32(p->pain, h);
292 myfwrite32(p->air, h);
293 myfwrite32(p->invl, h);
294 myfwrite32(p->suit, h);
295 myfwrite8(p->d, h);
296 myfwrite32(p->frag, h);
297 myfwrite32(p->ammo, h);
298 myfwrite32(p->shel, h);
299 myfwrite32(p->rock, h);
300 myfwrite32(p->cell, h);
301 myfwrite32(p->fuel, h);
302 myfwrite32(p->kills, h);
303 myfwrite32(p->secrets, h);
304 myfwrite8(p->fire, h);
305 myfwrite8(p->cwpn, h);
306 myfwrite8(p->csnd, h);
307 myfwrite8(p->amul, h);
308 myfwrite16(p->wpns, h);
309 myfwrite8(p->wpn, h);
310 myfwrite8(p->f, h);
311 myfwrite8(p->drawst, h);
312 myfwrite8(p->color, h);
313 myfwrite32(p->id, h);
314 myfwrite8(p->keys, h);
315 myfwrite8(p->lives, h);
316 // k* not saved
319 static void PL_savegame (FILE *h) {
320 PL_save_player(&pl1, h);
321 if (_2pl) {
322 PL_save_player(&pl2, h);
324 myfwrite32(PL_JUMP, h);
325 myfwrite32(PL_RUN, h);
326 myfwrite8(p_immortal, h);
329 static void PL_load_player (player_t *p, FILE *h) {
330 p->o.x = myfread32(h);
331 p->o.y = myfread32(h);
332 p->o.xv = myfread32(h);
333 p->o.yv = myfread32(h);
334 p->o.vx = myfread32(h);
335 p->o.vy = myfread32(h);
336 p->o.r = myfread32(h);
337 p->o.h = myfread32(h);
338 p->looky = myfread32(h);
339 p->st = myfread32(h);
340 p->s = myfread32(h);
341 p->life = myfread32(h);
342 p->armor = myfread32(h);
343 p->hit = myfread32(h);
344 p->hito = myfread32(h);
345 p->pain = myfread32(h);
346 p->air = myfread32(h);
347 p->invl = myfread32(h);
348 p->suit = myfread32(h);
349 p->d = myfread8(h);
350 p->frag = myfread32(h);
351 p->ammo = myfread32(h);
352 p->shel = myfread32(h);
353 p->rock = myfread32(h);
354 p->cell = myfread32(h);
355 p->fuel = myfread32(h);
356 p->kills = myfread32(h);
357 p->secrets = myfread32(h);
358 p->fire = myfread8(h);
359 p->cwpn = myfread8(h);
360 p->csnd = myfread8(h);
361 p->amul = myfread8(h);
362 p->wpns = myfread16(h);
363 p->wpn = myfread8(h);
364 p->f = myfread8(h);
365 p->drawst = myfread8(h);
366 p->color = myfread8(h);
367 p->id = myfread32(h);
368 p->keys = myfread8(h);
369 p->lives = myfread8(h);
370 // k* not saved
373 static void PL_loadgame (FILE *h) {
374 PL_load_player(&pl1, h);
375 if (_2pl) {
376 PL_load_player(&pl2, h);
378 PL_JUMP = myfread32(h);
379 PL_RUN = myfread32(h);
380 p_immortal = myfread8(h);
383 static void SMK_savegame (FILE *h) {
384 int i, n;
385 for (i = n = 0; i < MAXSMOK; ++i) {
386 if (sm[i].t) {
387 ++n;
390 myfwrite32(n, h);
391 for (i = 0; i < MAXSMOK; ++i) {
392 if (sm[i].t) {
393 myfwrite32(sm[i].x, h);
394 myfwrite32(sm[i].y, h);
395 myfwrite32(sm[i].xv, h);
396 myfwrite32(sm[i].xv, h);
397 myfwrite8(sm[i].t, h);
398 myfwrite8(sm[i].s, h);
399 myfwrite16(sm[i].o, h);
404 static void SMK_loadgame (FILE *h) {
405 int i, n;
406 n = myfread32(h);
407 for (i = 0; i < n; ++i) {
408 sm[i].x = myfread32(h);
409 sm[i].y = myfread32(h);
410 sm[i].xv = myfread32(h);
411 sm[i].xv = myfread32(h);
412 sm[i].t = myfread8(h);
413 sm[i].s = myfread8(h);
414 sm[i].o = myfread16(h);
418 static void SW_savegame (FILE *h) {
419 int i, n;
420 for (n = MAXSW - 1; n >= 0 && sw[n].t == 0; n--) {
421 // empty
423 n += 1;
424 myfwrite32(n, h);
425 for (i = 0; i < n; i++) {
426 myfwrite8(sw[i].x, h);
427 myfwrite8(sw[i].y, h);
428 myfwrite8(sw[i].t, h);
429 myfwrite8(sw[i].tm, h);
430 myfwrite8(sw[i].a, h);
431 myfwrite8(sw[i].b, h);
432 myfwrite8(sw[i].c, h);
433 myfwrite8(sw[i].d, h);
434 myfwrite8(sw[i].f, h);
436 myfwrite32(sw_secrets, h);
439 static void SW_loadgame (FILE *h) {
440 int i, n;
441 n = myfread32(h);
442 for (i = 0; i < n; i++) {
443 sw[i].x = myfread8(h);
444 sw[i].y = myfread8(h);
445 sw[i].t = myfread8(h);
446 sw[i].tm = myfread8(h);
447 sw[i].a = myfread8(h);
448 sw[i].b = myfread8(h);
449 sw[i].c = myfread8(h);
450 sw[i].d = myfread8(h);
451 sw[i].f = myfread8(h);
453 sw_secrets = myfread32(h);
456 static void W_savegame (FILE* h) {
457 char s[8];
458 int i;
459 myfwrite32(sky_type, h);
460 for(i = 1; i < 256; ++i) {
461 R_get_name(i, s);
462 myfwrite(s, 8, 1, h);
464 for (i = 0; i < 256; i++) {
465 myfwrite32(walf[i], h);
467 for (i = 0; i < 256; i++) {
468 myfwrite8(R_get_swp(i), h);
470 myfwrite(fldb, FLDW*FLDH, 1, h);
471 myfwrite(fld, FLDW*FLDH, 1, h);
472 myfwrite(fldf, FLDW*FLDH, 1, h);
475 static void W_loadgame (FILE* h) {
476 int i;
477 char s[8];
478 sky_type = myfread32(h);
479 R_loadsky(sky_type);
480 R_begin_load();
481 for (i = 1; i < 256; ++i) {
482 myfread(s, 8, 1, h);
483 if (s[0]) {
484 R_load(s);
487 R_end_load();
488 for (i = 0; i < 256; i++) {
489 myfread32(h); // useless
491 for (i = 0; i < 256; i++) {
492 walf[i] = myfread8(h);
494 myfread(fldb, FLDW*FLDH, 1, h);
495 myfread(fld, FLDW*FLDH, 1, h);
496 myfread(fldf, FLDW*FLDH, 1, h);
499 static void WP_savegame (FILE *h) {
500 int i, n;
501 for (n = MAXWPN - 1; n >= 0 && wp[n].t == 0; n--) {
502 // empty
504 n += 1;
505 myfwrite32(n, h);
506 for (i = 0; i < n; i++) {
507 myfwrite32(wp[i].o.x, h);
508 myfwrite32(wp[i].o.y, h);
509 myfwrite32(wp[i].o.xv, h);
510 myfwrite32(wp[i].o.yv, h);
511 myfwrite32(wp[i].o.vx, h);
512 myfwrite32(wp[i].o.vy, h);
513 myfwrite32(wp[i].o.r, h);
514 myfwrite32(wp[i].o.h, h);
515 myfwrite8(wp[i].t, h);
516 myfwrite8(wp[i].s, h);
517 myfwrite32(wp[i].own, h);
518 myfwrite16(wp[i].target, h);
522 static void WP_loadgame (FILE *h) {
523 int i, n;
524 n = myfread32(h);
525 for (i = 0; i < n; i++) {
526 wp[i].o.x = myfread32(h);
527 wp[i].o.y = myfread32(h);
528 wp[i].o.xv = myfread32(h);
529 wp[i].o.yv = myfread32(h);
530 wp[i].o.vx = myfread32(h);
531 wp[i].o.vy = myfread32(h);
532 wp[i].o.r = myfread32(h);
533 wp[i].o.h = myfread32(h);
534 wp[i].t = myfread8(h);
535 wp[i].s = myfread8(h);
536 wp[i].own = myfread32(h);
537 wp[i].target = myfread16(h);
541 static char *getsavfpname (int n, int ro) {
542 static char fn[] = "savgame0.dat";
543 static char p[100];
544 fn[7] = n + '0';
545 #ifdef UNIX
546 char *e = getenv("HOME");
547 strncpy(p, e, 60);
548 strcat(p, "/.flatwaifu");
549 if (!ro) {
550 mkdir(p, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
552 strcat(p, "/");
553 strcat(p, fn);
554 #else
555 strcpy(p, fn);
556 #endif
557 return p;
560 void F_getsavnames (void) {
561 int i;
562 FILE *h;
563 short ver;
564 char *p;
565 for (i = 0; i < 7; ++i) {
566 p = getsavfpname(i, 1);
567 memset(savname[i], 0, 24);
568 savok[i] = 0;
569 h = fopen(p, "rb");
570 if (h != NULL) {
571 ver = -1;
572 myfread(savname[i], 24, 1, h);
573 ver = myfread16(h);
574 savname[i][23] = 0;
575 savok[i] = (ver == 3) ? 1 : 0;
576 fclose(h);
581 void F_savegame (int n, char *s) {
582 char *p = getsavfpname(n, 0);
583 FILE *h = fopen(p, "wb");
584 if (h != NULL) {
585 myfwrite(s, 24, 1, h); // slot name
586 myfwrite16(3, h); // version
587 G_savegame(h);
588 W_savegame(h);
589 DOT_savegame(h);
590 SMK_savegame(h);
591 FX_savegame(h);
592 IT_savegame(h);
593 MN_savegame(h);
594 PL_savegame(h);
595 SW_savegame(h);
596 WP_savegame(h);
597 fclose(h);
601 void F_loadgame (int n) {
602 short ver;
603 char *p = getsavfpname(n, 1);
604 FILE *h = fopen(p, "rb");
605 if (h != NULL) {
606 fseek(h, 24, SEEK_SET); // skip name
607 ver = myfread16(h); // version
608 if (ver == 3) {
609 G_loadgame(h);
610 W_loadgame(h);
611 DOT_loadgame(h);
612 SMK_loadgame(h);
613 FX_loadgame(h);
614 IT_loadgame(h);
615 MN_loadgame(h);
616 PL_loadgame(h);
617 SW_loadgame(h);
618 WP_loadgame(h);
620 fclose(h);