c5dcb76d66404c84dff790595cfed8fccc012c73
1 /* Copyright (C) 1996-1997 Aleksey Volynskov
2 * Copyright (C) 2011 Rambo
3 * Copyright (C) 2020 SovietPony
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.
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.
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/>.
36 # include <sys/stat.h>
41 #include "common/streams.h"
42 #include "common/files.h"
44 char savname
[SAVE_MAX
][SAVE_MAXLEN
];
47 static void DOT_savegame (Writer
*h
) {
49 for (i
= n
= 0; i
< MAXDOT
; ++i
) {
55 for (i
= 0; i
< MAXDOT
; ++i
) {
57 stream_write32(dot
[i
].o
.x
, h
);
58 stream_write32(dot
[i
].o
.y
, h
);
59 stream_write32(dot
[i
].o
.xv
, h
);
60 stream_write32(dot
[i
].o
.yv
, h
);
61 stream_write32(dot
[i
].o
.vx
, h
);
62 stream_write32(dot
[i
].o
.vy
, h
);
63 stream_write32(dot
[i
].o
.r
, h
);
64 stream_write32(dot
[i
].o
.h
, h
);
65 stream_write8(dot
[i
].c
, h
);
66 stream_write8(dot
[i
].t
, h
);
71 static void DOT_loadgame (Reader
*h
) {
74 for (i
= 0; i
< n
; i
++) {
75 dot
[i
].o
.x
= stream_read32(h
);
76 dot
[i
].o
.y
= stream_read32(h
);
77 dot
[i
].o
.xv
= stream_read32(h
);
78 dot
[i
].o
.yv
= stream_read32(h
);
79 dot
[i
].o
.vx
= stream_read32(h
);
80 dot
[i
].o
.vy
= stream_read32(h
);
81 dot
[i
].o
.r
= stream_read32(h
);
82 dot
[i
].o
.h
= stream_read32(h
);
83 dot
[i
].c
= stream_read8(h
);
84 dot
[i
].t
= stream_read8(h
);
88 static void FX_savegame (Writer
*h
) {
90 for (i
= n
= 0; i
< MAXFX
; ++i
) {
96 for (i
= 0; i
< MAXFX
; ++i
) {
98 stream_write32(fx
[i
].x
, h
);
99 stream_write32(fx
[i
].y
, h
);
100 stream_write32(fx
[i
].xv
, h
);
101 stream_write32(fx
[i
].yv
, h
);
102 stream_write8(fx
[i
].t
, h
);
103 stream_write8(fx
[i
].s
, h
);
108 static void FX_loadgame (Reader
*h
) {
110 n
= stream_read32(h
);
111 for (i
= 0; i
< n
; i
++) {
112 fx
[i
].x
= stream_read32(h
);
113 fx
[i
].y
= stream_read32(h
);
114 fx
[i
].xv
= stream_read32(h
);
115 fx
[i
].yv
= stream_read32(h
);
116 fx
[i
].t
= stream_read8(h
);
117 fx
[i
].s
= stream_read8(h
);
121 static void G_savegame (Writer
*h
) {
122 stream_write8(_2pl
, h
);
123 stream_write8(g_dm
, h
);
124 stream_write8(g_exit
, h
);
125 stream_write8(g_map
, h
);
126 stream_write32(g_time
, h
);
127 stream_write32(dm_pl1p
, h
);
128 stream_write32(dm_pl2p
, h
);
129 stream_write32(dm_pnum
, h
);
131 while (i
< dm_pnum
) {
132 stream_write32(dm_pos
[i
].x
, h
);
133 stream_write32(dm_pos
[i
].y
, h
);
134 stream_write8(dm_pos
[i
].d
, h
);
137 stream_write8(cheat
, h
);
138 stream_write(g_music
, 8, 1, h
);
141 static void G_loadgame (Reader
*h
) {
142 _2pl
= stream_read8(h
);
143 g_dm
= stream_read8(h
);
144 g_exit
= stream_read8(h
);
145 g_map
= stream_read8(h
);
146 g_time
= stream_read32(h
);
147 dm_pl1p
= stream_read32(h
);
148 dm_pl2p
= stream_read32(h
);
149 dm_pnum
= stream_read32(h
);
151 while (i
< dm_pnum
) {
152 dm_pos
[i
].x
= stream_read32(h
);
153 dm_pos
[i
].y
= stream_read32(h
);
154 dm_pos
[i
].d
= stream_read8(h
);
157 cheat
= stream_read8(h
);
158 stream_read(g_music
, 8, 1, h
);
162 static void IT_savegame (Writer
*h
) {
164 for (n
= MAXITEM
- 1; n
>= 0 && it
[n
].t
== 0; n
--) {
168 stream_write32(n
, h
);
169 for (i
= 0; i
< n
; i
++) {
170 stream_write32(it
[i
].o
.x
, h
);
171 stream_write32(it
[i
].o
.y
, h
);
172 stream_write32(it
[i
].o
.xv
, h
);
173 stream_write32(it
[i
].o
.yv
, h
);
174 stream_write32(it
[i
].o
.vx
, h
);
175 stream_write32(it
[i
].o
.vy
, h
);
176 stream_write32(it
[i
].o
.r
, h
);
177 stream_write32(it
[i
].o
.h
, h
);
178 stream_write32(it
[i
].t
, h
);
179 stream_write32(it
[i
].s
, h
);
181 stream_write32(itm_rtime
, h
);
184 static void IT_loadgame (Reader
*h
) {
186 n
= stream_read32(h
);
187 for (i
= 0; i
< n
; i
++) {
188 it
[i
].o
.x
= stream_read32(h
);
189 it
[i
].o
.y
= stream_read32(h
);
190 it
[i
].o
.xv
= stream_read32(h
);
191 it
[i
].o
.yv
= stream_read32(h
);
192 it
[i
].o
.vx
= stream_read32(h
);
193 it
[i
].o
.vy
= stream_read32(h
);
194 it
[i
].o
.r
= stream_read32(h
);
195 it
[i
].o
.h
= stream_read32(h
);
196 it
[i
].t
= stream_read32(h
);
197 it
[i
].s
= stream_read32(h
);
199 itm_rtime
= stream_read32(h
);
202 static void MN_savegame (Writer
*h
) {
204 for (n
= MAXMN
- 1; n
>= 0 && mn
[n
].t
== 0; n
--) {
208 stream_write32(n
, h
);
209 for (i
= 0; i
< n
; i
++) {
210 stream_write32(mn
[i
].o
.x
, h
);
211 stream_write32(mn
[i
].o
.y
, h
);
212 stream_write32(mn
[i
].o
.xv
, h
);
213 stream_write32(mn
[i
].o
.yv
, h
);
214 stream_write32(mn
[i
].o
.vx
, h
);
215 stream_write32(mn
[i
].o
.vy
, h
);
216 stream_write32(mn
[i
].o
.r
, h
);
217 stream_write32(mn
[i
].o
.h
, h
);
218 stream_write8(mn
[i
].t
, h
);
219 stream_write8(mn
[i
].d
, h
);
220 stream_write8(mn
[i
].st
, h
);
221 stream_write8(mn
[i
].ftime
, h
);
222 stream_write32(mn
[i
].fobj
, h
);
223 stream_write32(mn
[i
].s
, h
);
224 stream_write32(0, h
); // mn[i].ap useless, changed after load
225 stream_write32(mn
[i
].aim
, h
);
226 stream_write32(mn
[i
].life
, h
);
227 stream_write32(mn
[i
].pain
, h
);
228 stream_write32(mn
[i
].ac
, h
);
229 stream_write32(mn
[i
].tx
, h
);
230 stream_write32(mn
[i
].ty
, h
);
231 stream_write32(mn
[i
].ammo
, h
);
232 stream_write16(mn
[i
].atm
, h
);
234 stream_write32(mnum
, h
);
235 stream_write32(gsndt
, h
);
238 static void MN_loadgame (Reader
*h
) {
240 n
= stream_read32(h
);
241 for (i
= 0; i
< n
; i
++) {
242 mn
[i
].o
.x
= stream_read32(h
);
243 mn
[i
].o
.y
= stream_read32(h
);
244 mn
[i
].o
.xv
= stream_read32(h
);
245 mn
[i
].o
.yv
= stream_read32(h
);
246 mn
[i
].o
.vx
= stream_read32(h
);
247 mn
[i
].o
.vy
= stream_read32(h
);
248 mn
[i
].o
.r
= stream_read32(h
);
249 mn
[i
].o
.h
= stream_read32(h
);
250 mn
[i
].t
= stream_read8(h
);
251 mn
[i
].d
= stream_read8(h
);
252 mn
[i
].st
= stream_read8(h
);
253 mn
[i
].ftime
= stream_read8(h
);
254 mn
[i
].fobj
= stream_read32(h
);
255 mn
[i
].s
= stream_read32(h
);
256 mn
[i
].ap
= NULL
; stream_read32(h
); // useless, changed after loading
257 mn
[i
].aim
= stream_read32(h
);
258 mn
[i
].life
= stream_read32(h
);
259 mn
[i
].pain
= stream_read32(h
);
260 mn
[i
].ac
= stream_read32(h
);
261 mn
[i
].tx
= stream_read32(h
);
262 mn
[i
].ty
= stream_read32(h
);
263 mn
[i
].ammo
= stream_read32(h
);
264 mn
[i
].atm
= stream_read16(h
);
266 mnum
= stream_read32(h
);
267 gsndt
= stream_read32(h
);
268 for (n
= 0; n
< MAXMN
; n
++) {
277 static void PL_save_player (player_t
*p
, Writer
*h
) {
278 stream_write32(p
->o
.x
, h
);
279 stream_write32(p
->o
.y
, h
);
280 stream_write32(p
->o
.xv
, h
);
281 stream_write32(p
->o
.yv
, h
);
282 stream_write32(p
->o
.vx
, h
);
283 stream_write32(p
->o
.vy
, h
);
284 stream_write32(p
->o
.r
, h
);
285 stream_write32(p
->o
.h
, h
);
286 stream_write32(p
->looky
, h
);
287 stream_write32(p
->st
, h
);
288 stream_write32(p
->s
, h
);
289 stream_write32(p
->life
, h
);
290 stream_write32(p
->armor
, h
);
291 stream_write32(p
->hit
, h
);
292 stream_write32(p
->hito
, h
);
293 stream_write32(p
->pain
, h
);
294 stream_write32(p
->air
, h
);
295 stream_write32(p
->invl
, h
);
296 stream_write32(p
->suit
, h
);
297 stream_write8(p
->d
, h
);
298 stream_write32(p
->frag
, h
);
299 stream_write32(p
->ammo
, h
);
300 stream_write32(p
->shel
, h
);
301 stream_write32(p
->rock
, h
);
302 stream_write32(p
->cell
, h
);
303 stream_write32(p
->fuel
, h
);
304 stream_write32(p
->kills
, h
);
305 stream_write32(p
->secrets
, h
);
306 stream_write8(p
->fire
, h
);
307 stream_write8(p
->cwpn
, h
);
308 stream_write8(p
->csnd
, h
);
309 stream_write8(p
->amul
, h
);
310 stream_write16(p
->wpns
, h
);
311 stream_write8(p
->wpn
, h
);
312 stream_write8(p
->f
, h
);
313 stream_write8(p
->drawst
, h
);
314 stream_write8(p
->color
, h
);
315 stream_write32(p
->id
, h
);
316 stream_write8(p
->keys
, h
);
317 stream_write8(p
->lives
, h
);
321 static void PL_savegame (Writer
*h
) {
322 PL_save_player(&pl1
, h
);
324 PL_save_player(&pl2
, h
);
326 stream_write32(PL_JUMP
, h
);
327 stream_write32(PL_RUN
, h
);
328 stream_write8(p_immortal
, h
);
331 static void PL_load_player (player_t
*p
, Reader
*h
) {
332 p
->o
.x
= stream_read32(h
);
333 p
->o
.y
= stream_read32(h
);
334 p
->o
.xv
= stream_read32(h
);
335 p
->o
.yv
= stream_read32(h
);
336 p
->o
.vx
= stream_read32(h
);
337 p
->o
.vy
= stream_read32(h
);
338 p
->o
.r
= stream_read32(h
);
339 p
->o
.h
= stream_read32(h
);
340 p
->looky
= stream_read32(h
);
341 p
->st
= stream_read32(h
);
342 p
->s
= stream_read32(h
);
343 p
->life
= stream_read32(h
);
344 p
->armor
= stream_read32(h
);
345 p
->hit
= stream_read32(h
);
346 p
->hito
= stream_read32(h
);
347 p
->pain
= stream_read32(h
);
348 p
->air
= stream_read32(h
);
349 p
->invl
= stream_read32(h
);
350 p
->suit
= stream_read32(h
);
351 p
->d
= stream_read8(h
);
352 p
->frag
= stream_read32(h
);
353 p
->ammo
= stream_read32(h
);
354 p
->shel
= stream_read32(h
);
355 p
->rock
= stream_read32(h
);
356 p
->cell
= stream_read32(h
);
357 p
->fuel
= stream_read32(h
);
358 p
->kills
= stream_read32(h
);
359 p
->secrets
= stream_read32(h
);
360 p
->fire
= stream_read8(h
);
361 p
->cwpn
= stream_read8(h
);
362 p
->csnd
= stream_read8(h
);
363 p
->amul
= stream_read8(h
);
364 p
->wpns
= stream_read16(h
);
365 p
->wpn
= stream_read8(h
);
366 p
->f
= stream_read8(h
);
367 p
->drawst
= stream_read8(h
);
368 p
->color
= stream_read8(h
);
369 p
->id
= stream_read32(h
);
370 p
->keys
= stream_read8(h
);
371 p
->lives
= stream_read8(h
);
375 static void PL_loadgame (Reader
*h
) {
376 PL_load_player(&pl1
, h
);
378 PL_load_player(&pl2
, h
);
380 PL_JUMP
= stream_read32(h
);
381 PL_RUN
= stream_read32(h
);
382 p_immortal
= stream_read8(h
);
385 static void SMK_savegame (Writer
*h
) {
387 for (i
= n
= 0; i
< MAXSMOK
; ++i
) {
392 stream_write32(n
, h
);
393 for (i
= 0; i
< MAXSMOK
; ++i
) {
395 stream_write32(sm
[i
].x
, h
);
396 stream_write32(sm
[i
].y
, h
);
397 stream_write32(sm
[i
].xv
, h
);
398 stream_write32(sm
[i
].xv
, h
);
399 stream_write8(sm
[i
].t
, h
);
400 stream_write8(sm
[i
].s
, h
);
401 stream_write16(sm
[i
].o
, h
);
406 static void SMK_loadgame (Reader
*h
) {
408 n
= stream_read32(h
);
409 for (i
= 0; i
< n
; ++i
) {
410 sm
[i
].x
= stream_read32(h
);
411 sm
[i
].y
= stream_read32(h
);
412 sm
[i
].xv
= stream_read32(h
);
413 sm
[i
].xv
= stream_read32(h
);
414 sm
[i
].t
= stream_read8(h
);
415 sm
[i
].s
= stream_read8(h
);
416 sm
[i
].o
= stream_read16(h
);
420 static void SW_savegame (Writer
*h
) {
422 for (n
= MAXSW
- 1; n
>= 0 && sw
[n
].t
== 0; n
--) {
426 stream_write32(n
, h
);
427 for (i
= 0; i
< n
; i
++) {
428 stream_write8(sw
[i
].x
, h
);
429 stream_write8(sw
[i
].y
, h
);
430 stream_write8(sw
[i
].t
, h
);
431 stream_write8(sw
[i
].tm
, h
);
432 stream_write8(sw
[i
].a
, h
);
433 stream_write8(sw
[i
].b
, h
);
434 stream_write8(sw
[i
].c
, h
);
435 stream_write8(sw
[i
].d
, h
);
436 stream_write8(sw
[i
].f
, h
);
438 stream_write32(sw_secrets
, h
);
441 static void SW_loadgame (Reader
*h
) {
443 n
= stream_read32(h
);
444 for (i
= 0; i
< n
; i
++) {
445 sw
[i
].x
= stream_read8(h
);
446 sw
[i
].y
= stream_read8(h
);
447 sw
[i
].t
= stream_read8(h
);
448 sw
[i
].tm
= stream_read8(h
);
449 sw
[i
].a
= stream_read8(h
);
450 sw
[i
].b
= stream_read8(h
);
451 sw
[i
].c
= stream_read8(h
);
452 sw
[i
].d
= stream_read8(h
);
453 sw
[i
].f
= stream_read8(h
);
455 sw_secrets
= stream_read32(h
);
458 static void W_savegame (Writer
* h
) {
461 stream_write32(sky_type
, h
);
462 for(i
= 1; i
< 256; ++i
) {
464 stream_write(s
, 8, 1, h
);
466 for (i
= 0; i
< 256; i
++) {
467 stream_write32(walf
[i
], h
);
469 for (i
= 0; i
< 256; i
++) {
470 stream_write8(R_get_swp(i
), h
);
472 stream_write(fldb
, FLDW
*FLDH
, 1, h
);
473 stream_write(fld
, FLDW
*FLDH
, 1, h
);
474 stream_write(fldf
, FLDW
*FLDH
, 1, h
);
477 static void W_loadgame (Reader
*h
) {
480 sky_type
= stream_read32(h
);
483 for (i
= 1; i
< 256; ++i
) {
484 stream_read(s
, 8, 1, h
);
490 for (i
= 0; i
< 256; i
++) {
491 stream_read32(h
); // useless
493 for (i
= 0; i
< 256; i
++) {
494 walf
[i
] = stream_read8(h
);
496 stream_read(fldb
, FLDW
*FLDH
, 1, h
);
497 stream_read(fld
, FLDW
*FLDH
, 1, h
);
498 stream_read(fldf
, FLDW
*FLDH
, 1, h
);
501 static void WP_savegame (Writer
*h
) {
503 for (n
= MAXWPN
- 1; n
>= 0 && wp
[n
].t
== 0; n
--) {
507 stream_write32(n
, h
);
508 for (i
= 0; i
< n
; i
++) {
509 stream_write32(wp
[i
].o
.x
, h
);
510 stream_write32(wp
[i
].o
.y
, h
);
511 stream_write32(wp
[i
].o
.xv
, h
);
512 stream_write32(wp
[i
].o
.yv
, h
);
513 stream_write32(wp
[i
].o
.vx
, h
);
514 stream_write32(wp
[i
].o
.vy
, h
);
515 stream_write32(wp
[i
].o
.r
, h
);
516 stream_write32(wp
[i
].o
.h
, h
);
517 stream_write8(wp
[i
].t
, h
);
518 stream_write8(wp
[i
].s
, h
);
519 stream_write32(wp
[i
].own
, h
);
520 stream_write16(wp
[i
].target
, h
);
524 static void WP_loadgame (Reader
*h
) {
526 n
= stream_read32(h
);
527 for (i
= 0; i
< n
; i
++) {
528 wp
[i
].o
.x
= stream_read32(h
);
529 wp
[i
].o
.y
= stream_read32(h
);
530 wp
[i
].o
.xv
= stream_read32(h
);
531 wp
[i
].o
.yv
= stream_read32(h
);
532 wp
[i
].o
.vx
= stream_read32(h
);
533 wp
[i
].o
.vy
= stream_read32(h
);
534 wp
[i
].o
.r
= stream_read32(h
);
535 wp
[i
].o
.h
= stream_read32(h
);
536 wp
[i
].t
= stream_read8(h
);
537 wp
[i
].s
= stream_read8(h
);
538 wp
[i
].own
= stream_read32(h
);
539 wp
[i
].target
= stream_read16(h
);
543 static char *getsavfpname (int n
, int ro
) {
544 static char fn
[] = "savgame0.dat";
548 char *e
= getenv("HOME");
550 strcat(p
, "/.flatwaifu");
552 mkdir(p
, S_IRWXU
| S_IRWXG
| S_IROTH
| S_IXOTH
);
562 void SAVE_save (Writer
*w
, const char name
[24]) {
564 stream_write(name
, 24, 1, w
); // slot name
565 stream_write16(3, w
); // version
578 void F_savegame (int n
, char *s
) {
580 char *p
= getsavfpname(n
, 0);
581 if (FILE_OpenWriter(&wr
, p
)) {
582 SAVE_save(&wr
.base
, s
);
583 FILE_CloseWriter(&wr
);
587 void SAVE_load (Reader
*h
) {
589 h
->setpos(h
, 24); // skip name
590 version
= stream_read16(h
);
605 void F_getsavnames (void) {
610 for (i
= 0; i
< 7; ++i
) {
611 p
= getsavfpname(i
, 1);
612 memset(savname
[i
], 0, 24);
614 if (FILE_OpenReader(&rd
, p
)) {
616 stream_read(savname
[i
], 24, 1, &rd
.base
);
617 version
= stream_read16(&rd
.base
);
619 savok
[i
] = version
== 3;
620 FILE_CloseReader(&rd
);
625 void F_loadgame (int n
) {
627 char *p
= getsavfpname(n
, 1);
628 if (FILE_OpenReader(&rd
, p
)) {
630 FILE_CloseReader(&rd
);