aboutsummaryrefslogtreecommitdiff
path: root/src/p_saveg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/p_saveg.c')
-rw-r--r--src/p_saveg.c1029
1 files changed, 1029 insertions, 0 deletions
diff --git a/src/p_saveg.c b/src/p_saveg.c
new file mode 100644
index 0000000..7e3d63b
--- /dev/null
+++ b/src/p_saveg.c
@@ -0,0 +1,1029 @@
1/* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * Archiving: SaveGame I/O.
31 *
32 *-----------------------------------------------------------------------------*/
33
34#include "doomstat.h"
35#include "r_main.h"
36#include "p_maputl.h"
37#include "p_spec.h"
38#include "p_tick.h"
39#include "p_saveg.h"
40#include "m_random.h"
41#include "am_map.h"
42#include "p_enemy.h"
43#include "lprintf.h"
44
45byte *save_p;
46
47// Pads save_p to a 4-byte boundary
48// so that the load/save works on SGI&Gecko.
49#define PADSAVEP() do { save_p += (4 - ((int) save_p & 3)) & 3; } while (0)
50//
51// P_ArchivePlayers
52//
53void P_ArchivePlayers (void)
54{
55 int i;
56
57 CheckSaveGame(sizeof(player_t) * MAXPLAYERS); // killough
58 for (i=0 ; i<MAXPLAYERS ; i++)
59 if (playeringame[i])
60 {
61 int j;
62 player_t *dest;
63
64 PADSAVEP();
65 dest = (player_t *) save_p;
66 memcpy(dest, &players[i], sizeof(player_t));
67 save_p += sizeof(player_t);
68 for (j=0; j<NUMPSPRITES; j++)
69 if (dest->psprites[j].state)
70 dest->psprites[j].state =
71 (state_t *)(dest->psprites[j].state-states);
72 }
73}
74
75//
76// P_UnArchivePlayers
77//
78void P_UnArchivePlayers (void)
79{
80 int i;
81
82 for (i=0 ; i<MAXPLAYERS ; i++)
83 if (playeringame[i])
84 {
85 int j;
86
87 PADSAVEP();
88
89 memcpy(&players[i], save_p, sizeof(player_t));
90 save_p += sizeof(player_t);
91
92 // will be set when unarc thinker
93 players[i].mo = NULL;
94 players[i].message = NULL;
95 players[i].attacker = NULL;
96
97 for (j=0 ; j<NUMPSPRITES ; j++)
98 if (players[i]. psprites[j].state)
99 players[i]. psprites[j].state =
100 &states[ (int)players[i].psprites[j].state ];
101 }
102}
103
104
105//
106// P_ArchiveWorld
107//
108void P_ArchiveWorld (void)
109{
110 int i;
111 const sector_t *sec;
112 const line_t *li;
113 const side_t *si;
114 short *put;
115
116 // killough 3/22/98: fix bug caused by hoisting save_p too early
117 // killough 10/98: adjust size for changes below
118 size_t size =
119 (sizeof(short)*5 + sizeof sec->floorheight + sizeof sec->ceilingheight)
120 * numsectors + sizeof(short)*3*numlines + 4;
121
122 for (i=0; i<numlines; i++)
123 {
124 if (lines[i].sidenum[0] != NO_INDEX)
125 size +=
126 sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
127 if (lines[i].sidenum[1] != NO_INDEX)
128 size +=
129 sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
130 }
131
132 CheckSaveGame(size); // killough
133
134 PADSAVEP(); // killough 3/22/98
135
136 put = (short *)save_p;
137
138 // do sectors
139 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
140 {
141 // killough 10/98: save full floor & ceiling heights, including fraction
142 memcpy(put, &sec->floorheight, sizeof sec->floorheight);
143 put = (void *)((char *) put + sizeof sec->floorheight);
144 memcpy(put, &sec->ceilingheight, sizeof sec->ceilingheight);
145 put = (void *)((char *) put + sizeof sec->ceilingheight);
146
147 *put++ = sec->floorpic;
148 *put++ = sec->ceilingpic;
149 *put++ = sec->lightlevel;
150 *put++ = sec->special; // needed? yes -- transfer types
151 *put++ = sec->tag; // needed? need them -- killough
152 }
153
154 // do lines
155 for (i=0, li = lines ; i<numlines ; i++,li++)
156 {
157 int j;
158
159 *put++ = li->flags;
160 *put++ = li->special;
161 *put++ = li->tag;
162
163 for (j=0; j<2; j++)
164 if (li->sidenum[j] != NO_INDEX)
165 {
166 si = &sides[li->sidenum[j]];
167
168 // killough 10/98: save full sidedef offsets,
169 // preserving fractional scroll offsets
170
171 memcpy(put, &si->textureoffset, sizeof si->textureoffset);
172 put = (void *)((char *) put + sizeof si->textureoffset);
173 memcpy(put, &si->rowoffset, sizeof si->rowoffset);
174 put = (void *)((char *) put + sizeof si->rowoffset);
175
176 *put++ = si->toptexture;
177 *put++ = si->bottomtexture;
178 *put++ = si->midtexture;
179 }
180 }
181 save_p = (byte *) put;
182}
183
184
185
186//
187// P_UnArchiveWorld
188//
189void P_UnArchiveWorld (void)
190{
191 int i;
192 sector_t *sec;
193 line_t *li;
194 const short *get;
195
196 PADSAVEP(); // killough 3/22/98
197
198 get = (short *) save_p;
199
200 // do sectors
201 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
202 {
203 // killough 10/98: load full floor & ceiling heights, including fractions
204
205 memcpy(&sec->floorheight, get, sizeof sec->floorheight);
206 get = (void *)((char *) get + sizeof sec->floorheight);
207 memcpy(&sec->ceilingheight, get, sizeof sec->ceilingheight);
208 get = (void *)((char *) get + sizeof sec->ceilingheight);
209
210 sec->floorpic = *get++;
211 sec->ceilingpic = *get++;
212 sec->lightlevel = *get++;
213 sec->special = *get++;
214 sec->tag = *get++;
215 sec->ceilingdata = 0; //jff 2/22/98 now three thinker fields, not two
216 sec->floordata = 0;
217 sec->lightingdata = 0;
218 sec->soundtarget = 0;
219 }
220
221 // do lines
222 for (i=0, li = lines ; i<numlines ; i++,li++)
223 {
224 int j;
225
226 li->flags = *get++;
227 li->special = *get++;
228 li->tag = *get++;
229 for (j=0 ; j<2 ; j++)
230 if (li->sidenum[j] != NO_INDEX)
231 {
232 side_t *si = &sides[li->sidenum[j]];
233
234 // killough 10/98: load full sidedef offsets, including fractions
235
236 memcpy(&si->textureoffset, get, sizeof si->textureoffset);
237 get = (void *)((char *) get + sizeof si->textureoffset);
238 memcpy(&si->rowoffset, get, sizeof si->rowoffset);
239 get = (void *)((char *) get + sizeof si->rowoffset);
240
241 si->toptexture = *get++;
242 si->bottomtexture = *get++;
243 si->midtexture = *get++;
244 }
245 }
246 save_p = (byte *) get;
247}
248
249//
250// Thinkers
251//
252
253typedef enum {
254 tc_end,
255 tc_mobj
256} thinkerclass_t;
257
258// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
259// thinker indices could be used by the code that saves sector info.
260
261static int number_of_thinkers;
262
263void P_ThinkerToIndex(void)
264 {
265 thinker_t *th;
266
267 // killough 2/14/98:
268 // count the number of thinkers, and mark each one with its index, using
269 // the prev field as a placeholder, since it can be restored later.
270
271 number_of_thinkers = 0;
272 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
273 if (th->function == P_MobjThinker)
274 th->prev = (thinker_t *) ++number_of_thinkers;
275 }
276
277// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
278// thinker indices could be used by the code that saves sector info.
279
280void P_IndexToThinker(void)
281 {
282 // killough 2/14/98: restore prev pointers
283 thinker_t *th;
284 thinker_t *prev = &thinkercap;
285
286 for (th = thinkercap.next ; th != &thinkercap ; prev=th, th=th->next)
287 th->prev = prev;
288 }
289
290//
291// P_ArchiveThinkers
292//
293// 2/14/98 killough: substantially modified to fix savegame bugs
294
295void P_ArchiveThinkers (void)
296{
297 thinker_t *th;
298
299 CheckSaveGame(sizeof brain); // killough 3/26/98: Save boss brain state
300 memcpy(save_p, &brain, sizeof brain);
301 save_p += sizeof brain;
302
303 /* check that enough room is available in savegame buffer
304 * - killough 2/14/98
305 * cph - use number_of_thinkers saved by P_ThinkerToIndex above
306 * size per object is sizeof(mobj_t) - 2*sizeof(void*) - 4*sizeof(fixed_t) plus
307 * padded type (4) plus 5*sizeof(void*), i.e. sizeof(mobj_t) + 4 +
308 * 3*sizeof(void*)
309 * cph - +1 for the tc_end
310 */
311 CheckSaveGame(number_of_thinkers*(sizeof(mobj_t)-3*sizeof(fixed_t)+4+3*sizeof(void*)) +1);
312
313 // save off the current thinkers
314 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
315 if (th->function == P_MobjThinker)
316 {
317 mobj_t *mobj;
318
319 *save_p++ = tc_mobj;
320 PADSAVEP();
321 mobj = (mobj_t *)save_p;
322 /* cph 2006/07/30 -
323 * The end of mobj_t changed from
324 * boolean invisible;
325 * mobj_t* lastenemy;
326 * mobj_t* above_monster;
327 * mobj_t* below_monster;
328 * void* touching_sectorlist;
329 * to
330 * mobj_t* lastenemy;
331 * void* touching_sectorlist;
332 * fixed_t PrevX, PrevY, PrevZ, padding;
333 * at prboom 2.4.4. There is code here to preserve the savegame format.
334 *
335 * touching_sectorlist is reconstructed anyway, so we now leave off the
336 * last 2 words of mobj_t, write 5 words of 0 and then write lastenemy
337 * into the second of these.
338 */
339 memcpy (mobj, th, sizeof(*mobj) - 2*sizeof(void*));
340 save_p += sizeof(*mobj) - 2*sizeof(void*) - 4*sizeof(fixed_t);
341 memset (save_p, 0, 5*sizeof(void*));
342 mobj->state = (state_t *)(mobj->state - states);
343
344 // killough 2/14/98: convert pointers into indices.
345 // Fixes many savegame problems, by properly saving
346 // target and tracer fields. Note: we store NULL if
347 // the thinker pointed to by these fields is not a
348 // mobj thinker.
349
350 if (mobj->target)
351 mobj->target = mobj->target->thinker.function ==
352 P_MobjThinker ?
353 (mobj_t *) mobj->target->thinker.prev : NULL;
354
355 if (mobj->tracer)
356 mobj->tracer = mobj->tracer->thinker.function ==
357 P_MobjThinker ?
358 (mobj_t *) mobj->tracer->thinker.prev : NULL;
359
360 // killough 2/14/98: new field: save last known enemy. Prevents
361 // monsters from going to sleep after killing monsters and not
362 // seeing player anymore.
363
364 if (((mobj_t*)th)->lastenemy && ((mobj_t*)th)->lastenemy->thinker.function == P_MobjThinker) {
365 memcpy (save_p + sizeof(void*), &(((mobj_t*)th)->lastenemy->thinker.prev), sizeof(void*));
366 }
367
368 // killough 2/14/98: end changes
369
370 save_p += 5*sizeof(void*);
371
372 if (mobj->player)
373 mobj->player = (player_t *)((mobj->player-players) + 1);
374 }
375
376 // add a terminating marker
377 *save_p++ = tc_end;
378
379 // killough 9/14/98: save soundtargets
380 {
381 int i;
382 CheckSaveGame(numsectors * sizeof(mobj_t *)); // killough 9/14/98
383 for (i = 0; i < numsectors; i++)
384 {
385 mobj_t *target = sectors[i].soundtarget;
386 // Fix crash on reload when a soundtarget points to a removed corpse
387 // (prboom bug #1590350)
388 if (target && target->thinker.function == P_MobjThinker)
389 target = (mobj_t *) target->thinker.prev;
390 else
391 target = NULL;
392 memcpy(save_p, &target, sizeof target);
393 save_p += sizeof target;
394 }
395 }
396}
397
398/*
399 * killough 11/98
400 *
401 * Same as P_SetTarget() in p_tick.c, except that the target is nullified
402 * first, so that no old target's reference count is decreased (when loading
403 * savegames, old targets are indices, not really pointers to targets).
404 */
405
406static void P_SetNewTarget(mobj_t **mop, mobj_t *targ)
407{
408 *mop = NULL;
409 P_SetTarget(mop, targ);
410}
411
412//
413// P_UnArchiveThinkers
414//
415// 2/14/98 killough: substantially modified to fix savegame bugs
416//
417
418// savegame file stores ints in the corresponding * field; this function
419// safely casts them back to int.
420static int P_GetMobj(mobj_t* mi, size_t s)
421{
422 size_t i = (size_t)mi;
423 if (i >= s) I_Error("Corrupt savegame");
424 return i;
425}
426
427void P_UnArchiveThinkers (void)
428{
429 thinker_t *th;
430 mobj_t **mobj_p; // killough 2/14/98: Translation table
431 size_t size; // killough 2/14/98: size of or index into table
432
433 totallive = 0;
434 // killough 3/26/98: Load boss brain state
435 memcpy(&brain, save_p, sizeof brain);
436 save_p += sizeof brain;
437
438 // remove all the current thinkers
439 for (th = thinkercap.next; th != &thinkercap; )
440 {
441 thinker_t *next = th->next;
442 if (th->function == P_MobjThinker)
443 P_RemoveMobj ((mobj_t *) th);
444 else
445 Z_Free (th);
446 th = next;
447 }
448 P_InitThinkers ();
449
450 // killough 2/14/98: count number of thinkers by skipping through them
451 {
452 byte *sp = save_p; // save pointer and skip header
453 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
454 { // skip all entries, adding up count
455 PADSAVEP();
456 /* cph 2006/07/30 - see comment below for change in layout of mobj_t */
457 save_p += sizeof(mobj_t)+3*sizeof(void*)-4*sizeof(fixed_t);
458 }
459
460 if (*--save_p != tc_end)
461 I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);
462
463 // first table entry special: 0 maps to NULL
464 *(mobj_p = malloc(size * sizeof *mobj_p)) = 0; // table of pointers
465 save_p = sp; // restore save pointer
466 }
467
468 // read in saved thinkers
469 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
470 {
471 mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);
472
473 // killough 2/14/98 -- insert pointers to thinkers into table, in order:
474 mobj_p[size] = mobj;
475
476 PADSAVEP();
477 /* cph 2006/07/30 -
478 * The end of mobj_t changed from
479 * boolean invisible;
480 * mobj_t* lastenemy;
481 * mobj_t* above_monster;
482 * mobj_t* below_monster;
483 * void* touching_sectorlist;
484 * to
485 * mobj_t* lastenemy;
486 * void* touching_sectorlist;
487 * fixed_t PrevX, PrevY, PrevZ;
488 * at prboom 2.4.4. There is code here to preserve the savegame format.
489 *
490 * touching_sectorlist is reconstructed anyway, so we now read in all
491 * but the last 5 words from the savegame (filling all but the last 2
492 * fields of our current mobj_t. We then pull lastenemy from the 2nd of
493 * the 5 leftover words, and skip the others.
494 */
495 memcpy (mobj, save_p, sizeof(mobj_t)-2*sizeof(void*)-4*sizeof(fixed_t));
496 save_p += sizeof(mobj_t)-sizeof(void*)-4*sizeof(fixed_t);
497 memcpy (&(mobj->lastenemy), save_p, sizeof(void*));
498 save_p += 4*sizeof(void*);
499 mobj->state = states + (int) mobj->state;
500
501 if (mobj->player)
502 (mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj;
503
504 P_SetThingPosition (mobj);
505 mobj->info = &mobjinfo[mobj->type];
506
507 // killough 2/28/98:
508 // Fix for falling down into a wall after savegame loaded:
509 // mobj->floorz = mobj->subsector->sector->floorheight;
510 // mobj->ceilingz = mobj->subsector->sector->ceilingheight;
511
512 mobj->thinker.function = P_MobjThinker;
513 P_AddThinker (&mobj->thinker);
514
515 if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
516 totallive++;
517 }
518
519 // killough 2/14/98: adjust target and tracer fields, plus
520 // lastenemy field, to correctly point to mobj thinkers.
521 // NULL entries automatically handled by first table entry.
522 //
523 // killough 11/98: use P_SetNewTarget() to set fields
524
525 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
526 {
527 P_SetNewTarget(&((mobj_t *) th)->target,
528 mobj_p[P_GetMobj(((mobj_t *)th)->target,size)]);
529
530 P_SetNewTarget(&((mobj_t *) th)->tracer,
531 mobj_p[P_GetMobj(((mobj_t *)th)->tracer,size)]);
532
533 P_SetNewTarget(&((mobj_t *) th)->lastenemy,
534 mobj_p[P_GetMobj(((mobj_t *)th)->lastenemy,size)]);
535 }
536
537 { // killough 9/14/98: restore soundtargets
538 int i;
539 for (i = 0; i < numsectors; i++)
540 {
541 mobj_t *target;
542 memcpy(&target, save_p, sizeof target);
543 save_p += sizeof target;
544 // Must verify soundtarget. See P_ArchiveThinkers.
545 P_SetNewTarget(&sectors[i].soundtarget, mobj_p[P_GetMobj(target,size)]);
546 }
547 }
548
549 free(mobj_p); // free translation table
550
551 // killough 3/26/98: Spawn icon landings:
552 if (gamemode == commercial)
553 P_SpawnBrainTargets();
554}
555
556//
557// P_ArchiveSpecials
558//
559enum {
560 tc_ceiling,
561 tc_door,
562 tc_floor,
563 tc_plat,
564 tc_flash,
565 tc_strobe,
566 tc_glow,
567 tc_elevator, //jff 2/22/98 new elevator type thinker
568 tc_scroll, // killough 3/7/98: new scroll effect thinker
569 tc_pusher, // phares 3/22/98: new push/pull effect thinker
570 tc_flicker, // killough 10/4/98
571 tc_endspecials
572} specials_e;
573
574//
575// Things to handle:
576//
577// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
578// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
579// T_MoveFloor, (floormove_t: sector_t * swizzle),
580// T_LightFlash, (lightflash_t: sector_t * swizzle),
581// T_StrobeFlash, (strobe_t: sector_t *),
582// T_Glow, (glow_t: sector_t *),
583// T_PlatRaise, (plat_t: sector_t *), - active list
584// T_MoveElevator, (plat_t: sector_t *), - active list // jff 2/22/98
585// T_Scroll // killough 3/7/98
586// T_Pusher // phares 3/22/98
587// T_FireFlicker // killough 10/4/98
588//
589
590void P_ArchiveSpecials (void)
591{
592 thinker_t *th;
593 size_t size = 0; // killough
594
595 // save off the current thinkers (memory size calculation -- killough)
596
597 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
598 if (!th->function)
599 {
600 platlist_t *pl;
601 ceilinglist_t *cl; //jff 2/22/98 need this for ceilings too now
602 for (pl=activeplats; pl; pl=pl->next)
603 if (pl->plat == (plat_t *) th) // killough 2/14/98
604 {
605 size += 4+sizeof(plat_t);
606 goto end;
607 }
608 for (cl=activeceilings; cl; cl=cl->next) // search for activeceiling
609 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
610 {
611 size += 4+sizeof(ceiling_t);
612 goto end;
613 }
614 end:;
615 }
616 else
617 size +=
618 th->function==T_MoveCeiling ? 4+sizeof(ceiling_t) :
619 th->function==T_VerticalDoor ? 4+sizeof(vldoor_t) :
620 th->function==T_MoveFloor ? 4+sizeof(floormove_t):
621 th->function==T_PlatRaise ? 4+sizeof(plat_t) :
622 th->function==T_LightFlash ? 4+sizeof(lightflash_t):
623 th->function==T_StrobeFlash ? 4+sizeof(strobe_t) :
624 th->function==T_Glow ? 4+sizeof(glow_t) :
625 th->function==T_MoveElevator ? 4+sizeof(elevator_t):
626 th->function==T_Scroll ? 4+sizeof(scroll_t) :
627 th->function==T_Pusher ? 4+sizeof(pusher_t) :
628 th->function==T_FireFlicker? 4+sizeof(fireflicker_t) :
629 0;
630
631 CheckSaveGame(size + 1); // killough; cph: +1 for the tc_endspecials
632
633 // save off the current thinkers
634 for (th=thinkercap.next; th!=&thinkercap; th=th->next)
635 {
636 if (!th->function)
637 {
638 platlist_t *pl;
639 ceilinglist_t *cl; //jff 2/22/98 add iter variable for ceilings
640
641 // killough 2/8/98: fix plat original height bug.
642 // Since acv==NULL, this could be a plat in stasis.
643 // so check the active plats list, and save this
644 // plat (jff: or ceiling) even if it is in stasis.
645
646 for (pl=activeplats; pl; pl=pl->next)
647 if (pl->plat == (plat_t *) th) // killough 2/14/98
648 goto plat;
649
650 for (cl=activeceilings; cl; cl=cl->next)
651 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
652 goto ceiling;
653
654 continue;
655 }
656
657 if (th->function == T_MoveCeiling)
658 {
659 ceiling_t *ceiling;
660 ceiling: // killough 2/14/98
661 *save_p++ = tc_ceiling;
662 PADSAVEP();
663 ceiling = (ceiling_t *)save_p;
664 memcpy (ceiling, th, sizeof(*ceiling));
665 save_p += sizeof(*ceiling);
666 ceiling->sector = (sector_t *)(ceiling->sector - sectors);
667 continue;
668 }
669
670 if (th->function == T_VerticalDoor)
671 {
672 vldoor_t *door;
673 *save_p++ = tc_door;
674 PADSAVEP();
675 door = (vldoor_t *) save_p;
676 memcpy (door, th, sizeof *door);
677 save_p += sizeof(*door);
678 door->sector = (sector_t *)(door->sector - sectors);
679 //jff 1/31/98 archive line remembered by door as well
680 door->line = (line_t *) (door->line ? door->line-lines : -1);
681 continue;
682 }
683
684 if (th->function == T_MoveFloor)
685 {
686 floormove_t *floor;
687 *save_p++ = tc_floor;
688 PADSAVEP();
689 floor = (floormove_t *)save_p;
690 memcpy (floor, th, sizeof(*floor));
691 save_p += sizeof(*floor);
692 floor->sector = (sector_t *)(floor->sector - sectors);
693 continue;
694 }
695
696 if (th->function == T_PlatRaise)
697 {
698 plat_t *plat;
699 plat: // killough 2/14/98: added fix for original plat height above
700 *save_p++ = tc_plat;
701 PADSAVEP();
702 plat = (plat_t *)save_p;
703 memcpy (plat, th, sizeof(*plat));
704 save_p += sizeof(*plat);
705 plat->sector = (sector_t *)(plat->sector - sectors);
706 continue;
707 }
708
709 if (th->function == T_LightFlash)
710 {
711 lightflash_t *flash;
712 *save_p++ = tc_flash;
713 PADSAVEP();
714 flash = (lightflash_t *)save_p;
715 memcpy (flash, th, sizeof(*flash));
716 save_p += sizeof(*flash);
717 flash->sector = (sector_t *)(flash->sector - sectors);
718 continue;
719 }
720
721 if (th->function == T_StrobeFlash)
722 {
723 strobe_t *strobe;
724 *save_p++ = tc_strobe;
725 PADSAVEP();
726 strobe = (strobe_t *)save_p;
727 memcpy (strobe, th, sizeof(*strobe));
728 save_p += sizeof(*strobe);
729 strobe->sector = (sector_t *)(strobe->sector - sectors);
730 continue;
731 }
732
733 if (th->function == T_Glow)
734 {
735 glow_t *glow;
736 *save_p++ = tc_glow;
737 PADSAVEP();
738 glow = (glow_t *)save_p;
739 memcpy (glow, th, sizeof(*glow));
740 save_p += sizeof(*glow);
741 glow->sector = (sector_t *)(glow->sector - sectors);
742 continue;
743 }
744
745 // killough 10/4/98: save flickers
746 if (th->function == T_FireFlicker)
747 {
748 fireflicker_t *flicker;
749 *save_p++ = tc_flicker;
750 PADSAVEP();
751 flicker = (fireflicker_t *)save_p;
752 memcpy (flicker, th, sizeof(*flicker));
753 save_p += sizeof(*flicker);
754 flicker->sector = (sector_t *)(flicker->sector - sectors);
755 continue;
756 }
757
758 //jff 2/22/98 new case for elevators
759 if (th->function == T_MoveElevator)
760 {
761 elevator_t *elevator; //jff 2/22/98
762 *save_p++ = tc_elevator;
763 PADSAVEP();
764 elevator = (elevator_t *)save_p;
765 memcpy (elevator, th, sizeof(*elevator));
766 save_p += sizeof(*elevator);
767 elevator->sector = (sector_t *)(elevator->sector - sectors);
768 continue;
769 }
770
771 // killough 3/7/98: Scroll effect thinkers
772 if (th->function == T_Scroll)
773 {
774 *save_p++ = tc_scroll;
775 memcpy (save_p, th, sizeof(scroll_t));
776 save_p += sizeof(scroll_t);
777 continue;
778 }
779
780 // phares 3/22/98: Push/Pull effect thinkers
781
782 if (th->function == T_Pusher)
783 {
784 *save_p++ = tc_pusher;
785 memcpy (save_p, th, sizeof(pusher_t));
786 save_p += sizeof(pusher_t);
787 continue;
788 }
789 }
790
791 // add a terminating marker
792 *save_p++ = tc_endspecials;
793}
794
795
796//
797// P_UnArchiveSpecials
798//
799void P_UnArchiveSpecials (void)
800{
801 byte tclass;
802
803 // read in saved thinkers
804 while ((tclass = *save_p++) != tc_endspecials) // killough 2/14/98
805 switch (tclass)
806 {
807 case tc_ceiling:
808 PADSAVEP();
809 {
810 ceiling_t *ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
811 memcpy (ceiling, save_p, sizeof(*ceiling));
812 save_p += sizeof(*ceiling);
813 ceiling->sector = &sectors[(int)ceiling->sector];
814 ceiling->sector->ceilingdata = ceiling; //jff 2/22/98
815
816 if (ceiling->thinker.function)
817 ceiling->thinker.function = T_MoveCeiling;
818
819 P_AddThinker (&ceiling->thinker);
820 P_AddActiveCeiling(ceiling);
821 break;
822 }
823
824 case tc_door:
825 PADSAVEP();
826 {
827 vldoor_t *door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
828 memcpy (door, save_p, sizeof(*door));
829 save_p += sizeof(*door);
830 door->sector = &sectors[(int)door->sector];
831
832 //jff 1/31/98 unarchive line remembered by door as well
833 door->line = (int)door->line!=-1? &lines[(int)door->line] : NULL;
834
835 door->sector->ceilingdata = door; //jff 2/22/98
836 door->thinker.function = T_VerticalDoor;
837 P_AddThinker (&door->thinker);
838 break;
839 }
840
841 case tc_floor:
842 PADSAVEP();
843 {
844 floormove_t *floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
845 memcpy (floor, save_p, sizeof(*floor));
846 save_p += sizeof(*floor);
847 floor->sector = &sectors[(int)floor->sector];
848 floor->sector->floordata = floor; //jff 2/22/98
849 floor->thinker.function = T_MoveFloor;
850 P_AddThinker (&floor->thinker);
851 break;
852 }
853
854 case tc_plat:
855 PADSAVEP();
856 {
857 plat_t *plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
858 memcpy (plat, save_p, sizeof(*plat));
859 save_p += sizeof(*plat);
860 plat->sector = &sectors[(int)plat->sector];
861 plat->sector->floordata = plat; //jff 2/22/98
862
863 if (plat->thinker.function)
864 plat->thinker.function = T_PlatRaise;
865
866 P_AddThinker (&plat->thinker);
867 P_AddActivePlat(plat);
868 break;
869 }
870
871 case tc_flash:
872 PADSAVEP();
873 {
874 lightflash_t *flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
875 memcpy (flash, save_p, sizeof(*flash));
876 save_p += sizeof(*flash);
877 flash->sector = &sectors[(int)flash->sector];
878 flash->thinker.function = T_LightFlash;
879 P_AddThinker (&flash->thinker);
880 break;
881 }
882
883 case tc_strobe:
884 PADSAVEP();
885 {
886 strobe_t *strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
887 memcpy (strobe, save_p, sizeof(*strobe));
888 save_p += sizeof(*strobe);
889 strobe->sector = &sectors[(int)strobe->sector];
890 strobe->thinker.function = T_StrobeFlash;
891 P_AddThinker (&strobe->thinker);
892 break;
893 }
894
895 case tc_glow:
896 PADSAVEP();
897 {
898 glow_t *glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
899 memcpy (glow, save_p, sizeof(*glow));
900 save_p += sizeof(*glow);
901 glow->sector = &sectors[(int)glow->sector];
902 glow->thinker.function = T_Glow;
903 P_AddThinker (&glow->thinker);
904 break;
905 }
906
907 case tc_flicker: // killough 10/4/98
908 PADSAVEP();
909 {
910 fireflicker_t *flicker = Z_Malloc (sizeof(*flicker), PU_LEVEL, NULL);
911 memcpy (flicker, save_p, sizeof(*flicker));
912 save_p += sizeof(*flicker);
913 flicker->sector = &sectors[(int)flicker->sector];
914 flicker->thinker.function = T_FireFlicker;
915 P_AddThinker (&flicker->thinker);
916 break;
917 }
918
919 //jff 2/22/98 new case for elevators
920 case tc_elevator:
921 PADSAVEP();
922 {
923 elevator_t *elevator = Z_Malloc (sizeof(*elevator), PU_LEVEL, NULL);
924 memcpy (elevator, save_p, sizeof(*elevator));
925 save_p += sizeof(*elevator);
926 elevator->sector = &sectors[(int)elevator->sector];
927 elevator->sector->floordata = elevator; //jff 2/22/98
928 elevator->sector->ceilingdata = elevator; //jff 2/22/98
929 elevator->thinker.function = T_MoveElevator;
930 P_AddThinker (&elevator->thinker);
931 break;
932 }
933
934 case tc_scroll: // killough 3/7/98: scroll effect thinkers
935 {
936 scroll_t *scroll = Z_Malloc (sizeof(scroll_t), PU_LEVEL, NULL);
937 memcpy (scroll, save_p, sizeof(scroll_t));
938 save_p += sizeof(scroll_t);
939 scroll->thinker.function = T_Scroll;
940 P_AddThinker(&scroll->thinker);
941 break;
942 }
943
944 case tc_pusher: // phares 3/22/98: new Push/Pull effect thinkers
945 {
946 pusher_t *pusher = Z_Malloc (sizeof(pusher_t), PU_LEVEL, NULL);
947 memcpy (pusher, save_p, sizeof(pusher_t));
948 save_p += sizeof(pusher_t);
949 pusher->thinker.function = T_Pusher;
950 pusher->source = P_GetPushThing(pusher->affectee);
951 P_AddThinker(&pusher->thinker);
952 break;
953 }
954
955 default:
956 I_Error("P_UnarchiveSpecials: Unknown tclass %i in savegame", tclass);
957 }
958}
959
960// killough 2/16/98: save/restore random number generator state information
961
962void P_ArchiveRNG(void)
963{
964 CheckSaveGame(sizeof rng);
965 memcpy(save_p, &rng, sizeof rng);
966 save_p += sizeof rng;
967}
968
969void P_UnArchiveRNG(void)
970{
971 memcpy(&rng, save_p, sizeof rng);
972 save_p += sizeof rng;
973}
974
975// killough 2/22/98: Save/restore automap state
976// killough 2/22/98: Save/restore automap state
977void P_ArchiveMap(void)
978{
979 int zero = 0, one = 1;
980 CheckSaveGame(2 * sizeof zero + sizeof markpointnum +
981 markpointnum * sizeof *markpoints +
982 sizeof automapmode + sizeof one);
983
984 memcpy(save_p, &automapmode, sizeof automapmode);
985 save_p += sizeof automapmode;
986 memcpy(save_p, &one, sizeof one); // CPhipps - used to be viewactive, now
987 save_p += sizeof one; // that's worked out locally by D_Display
988 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be followplayer
989 save_p += sizeof zero; // that is now part of automapmode
990 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be automap_grid, ditto
991 save_p += sizeof zero;
992 memcpy(save_p, &markpointnum, sizeof markpointnum);
993 save_p += sizeof markpointnum;
994
995 if (markpointnum)
996 {
997 memcpy(save_p, markpoints, sizeof *markpoints * markpointnum);
998 save_p += markpointnum * sizeof *markpoints;
999 }
1000}
1001
1002void P_UnArchiveMap(void)
1003{
1004 int unused;
1005 memcpy(&automapmode, save_p, sizeof automapmode);
1006 save_p += sizeof automapmode;
1007 memcpy(&unused, save_p, sizeof unused);
1008 save_p += sizeof unused;
1009 memcpy(&unused, save_p, sizeof unused);
1010 save_p += sizeof unused;
1011 memcpy(&unused, save_p, sizeof unused);
1012 save_p += sizeof unused;
1013
1014 if (automapmode & am_active)
1015 AM_Start();
1016
1017 memcpy(&markpointnum, save_p, sizeof markpointnum);
1018 save_p += sizeof markpointnum;
1019
1020 if (markpointnum)
1021 {
1022 while (markpointnum >= markpointnum_max)
1023 markpoints = realloc(markpoints, sizeof *markpoints *
1024 (markpointnum_max = markpointnum_max ? markpointnum_max*2 : 16));
1025 memcpy(markpoints, save_p, markpointnum * sizeof *markpoints);
1026 save_p += markpointnum * sizeof *markpoints;
1027 }
1028}
1029