Prepare new maemo release
[maemo-rb.git] / apps / plugins / doom / p_saveg.c
bloba704bfa83ca2cffc6e392069bfb0a75cab899a8b
1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
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
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 * 02111-1307, USA.
27 * DESCRIPTION:
28 * Archiving: SaveGame I/O.
30 *-----------------------------------------------------------------------------*/
32 #include "doomstat.h"
33 #include "r_main.h"
34 #include "p_maputl.h"
35 #include "p_spec.h"
36 #include "p_tick.h"
37 #include "p_saveg.h"
38 #include "m_random.h"
39 #include "am_map.h"
40 #include "p_enemy.h"
41 #include "i_system.h"
42 #include "rockmacros.h"
43 byte *save_p;
45 // Pads save_p to a 4-byte boundary
46 // so that the load/save works on SGI&Gecko.
47 #define PADSAVEP() do { save_p += (4 - ((unsigned long) save_p & 3)) & 3; } while (0)
49 // P_ArchivePlayers
51 void P_ArchivePlayers (void)
53 int i;
55 CheckSaveGame(sizeof(player_t) * MAXPLAYERS); // killough
56 for (i=0 ; i<MAXPLAYERS ; i++)
57 if (playeringame[i])
59 int j;
60 player_t *dest;
62 PADSAVEP();
63 dest = (player_t *) save_p;
64 memcpy(dest, &players[i], sizeof(player_t));
65 save_p += sizeof(player_t);
66 for (j=0; j<NUMPSPRITES; j++)
67 if (dest->psprites[j].state)
68 dest->psprites[j].state =
69 (state_t *)(dest->psprites[j].state-states);
74 // P_UnArchivePlayers
76 void P_UnArchivePlayers (void)
78 int i;
80 for (i=0 ; i<MAXPLAYERS ; i++)
81 if (playeringame[i])
83 int j;
85 PADSAVEP();
87 memcpy(&players[i], save_p, sizeof(player_t));
88 save_p += sizeof(player_t);
90 // will be set when unarc thinker
91 players[i].mo = NULL;
92 players[i].message = NULL;
93 players[i].attacker = NULL;
95 for (j=0 ; j<NUMPSPRITES ; j++)
96 if (players[i]. psprites[j].state)
97 players[i]. psprites[j].state =
98 &states[ (unsigned long)players[i].psprites[j].state ];
104 // P_ArchiveWorld
106 void P_ArchiveWorld (void)
108 int i;
109 const sector_t *sec;
110 const line_t *li;
111 const side_t *si;
112 short *put;
114 // killough 3/22/98: fix bug caused by hoisting save_p too early
115 // killough 10/98: adjust size for changes below
116 size_t size =
117 (sizeof(short)*5 + sizeof sec->floorheight + sizeof sec->ceilingheight)
118 * numsectors + sizeof(short)*3*numlines + 4;
120 for (i=0; i<numlines; i++)
122 if (lines[i].sidenum[0] != -1)
123 size +=
124 sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
125 if (lines[i].sidenum[1] != -1)
126 size +=
127 sizeof(short)*3 + sizeof si->textureoffset + sizeof si->rowoffset;
130 CheckSaveGame(size); // killough
132 PADSAVEP(); // killough 3/22/98
134 put = (short *)save_p;
136 // do sectors
137 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
139 // killough 10/98: save full floor & ceiling heights, including fraction
140 memcpy(put, &sec->floorheight, sizeof sec->floorheight);
141 put = (void *)((char *) put + sizeof sec->floorheight);
142 memcpy(put, &sec->ceilingheight, sizeof sec->ceilingheight);
143 put = (void *)((char *) put + sizeof sec->ceilingheight);
145 *put++ = sec->floorpic;
146 *put++ = sec->ceilingpic;
147 *put++ = sec->lightlevel;
148 *put++ = sec->special; // needed? yes -- transfer types
149 *put++ = sec->tag; // needed? need them -- killough
152 // do lines
153 for (i=0, li = lines ; i<numlines ; i++,li++)
155 int j;
157 *put++ = li->flags;
158 *put++ = li->special;
159 *put++ = li->tag;
161 for (j=0; j<2; j++)
162 if (li->sidenum[j] != -1)
164 si = &sides[li->sidenum[j]];
166 // killough 10/98: save full sidedef offsets,
167 // preserving fractional scroll offsets
169 memcpy(put, &si->textureoffset, sizeof si->textureoffset);
170 put = (void *)((char *) put + sizeof si->textureoffset);
171 memcpy(put, &si->rowoffset, sizeof si->rowoffset);
172 put = (void *)((char *) put + sizeof si->rowoffset);
174 *put++ = si->toptexture;
175 *put++ = si->bottomtexture;
176 *put++ = si->midtexture;
179 save_p = (byte *) put;
185 // P_UnArchiveWorld
187 void P_UnArchiveWorld (void)
189 int i;
190 sector_t *sec;
191 line_t *li;
192 const short *get;
194 PADSAVEP(); // killough 3/22/98
196 get = (short *) save_p;
198 // do sectors
199 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
201 // killough 10/98: load full floor & ceiling heights, including fractions
203 memcpy(&sec->floorheight, get, sizeof sec->floorheight);
204 get = (void *)((char *) get + sizeof sec->floorheight);
205 memcpy(&sec->ceilingheight, get, sizeof sec->ceilingheight);
206 get = (void *)((char *) get + sizeof sec->ceilingheight);
208 sec->floorpic = *get++;
209 sec->ceilingpic = *get++;
210 sec->lightlevel = *get++;
211 sec->special = *get++;
212 sec->tag = *get++;
213 sec->ceilingdata = 0; //jff 2/22/98 now three thinker fields, not two
214 sec->floordata = 0;
215 sec->lightingdata = 0;
216 sec->soundtarget = 0;
219 // do lines
220 for (i=0, li = lines ; i<numlines ; i++,li++)
222 int j;
224 li->flags = *get++;
225 li->special = *get++;
226 li->tag = *get++;
227 for (j=0 ; j<2 ; j++)
228 if (li->sidenum[j] != -1)
230 side_t *si = &sides[li->sidenum[j]];
232 // killough 10/98: load full sidedef offsets, including fractions
234 memcpy(&si->textureoffset, get, sizeof si->textureoffset);
235 get = (void *)((char *) get + sizeof si->textureoffset);
236 memcpy(&si->rowoffset, get, sizeof si->rowoffset);
237 get = (void *)((char *) get + sizeof si->rowoffset);
239 si->toptexture = *get++;
240 si->bottomtexture = *get++;
241 si->midtexture = *get++;
244 save_p = (byte *) get;
248 // Thinkers
251 enum {
252 tc_end,
253 tc_mobj
255 typedef unsigned thinkerclass_t;
257 // phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
258 // thinker indices could be used by the code that saves sector info.
260 static int number_of_thinkers;
262 void P_ThinkerToIndex(void)
264 thinker_t *th;
266 // killough 2/14/98:
267 // count the number of thinkers, and mark each one with its index, using
268 // the prev field as a placeholder, since it can be restored later.
270 number_of_thinkers = 0;
271 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
272 if (th->function == P_MobjThinker)
273 th->prev = (thinker_t *)(long)(++number_of_thinkers);
276 // phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
277 // thinker indices could be used by the code that saves sector info.
279 void P_IndexToThinker(void)
281 // killough 2/14/98: restore prev pointers
282 thinker_t *th;
283 thinker_t *prev = &thinkercap;
285 for (th = thinkercap.next ; th != &thinkercap ; prev=th, th=th->next)
286 th->prev = prev;
290 // P_ArchiveThinkers
292 // 2/14/98 killough: substantially modified to fix savegame bugs
294 void P_ArchiveThinkers (void)
296 thinker_t *th;
298 CheckSaveGame(sizeof brain); // killough 3/26/98: Save boss brain state
299 memcpy(save_p, &brain, sizeof brain);
300 save_p += sizeof brain;
302 /* check that enough room is available in savegame buffer
303 * - killough 2/14/98
304 * cph - use number_of_thinkers saved by P_ThinkerToIndex above
306 CheckSaveGame(number_of_thinkers*(sizeof(mobj_t)+4));
308 // save off the current thinkers
309 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
310 if (th->function == P_MobjThinker)
312 mobj_t *mobj;
314 *save_p++ = tc_mobj;
315 PADSAVEP();
316 mobj = (mobj_t *)save_p;
317 memcpy (mobj, th, sizeof(*mobj));
318 save_p += sizeof(*mobj);
319 mobj->state = (state_t *)(mobj->state - states);
321 // killough 2/14/98: convert pointers into indices.
322 // Fixes many savegame problems, by properly saving
323 // target and tracer fields. Note: we store NULL if
324 // the thinker pointed to by these fields is not a
325 // mobj thinker.
327 if (mobj->target)
328 mobj->target = mobj->target->thinker.function ==
329 P_MobjThinker ?
330 (mobj_t *) mobj->target->thinker.prev : NULL;
332 if (mobj->tracer)
333 mobj->tracer = mobj->tracer->thinker.function ==
334 P_MobjThinker ?
335 (mobj_t *) mobj->tracer->thinker.prev : NULL;
337 // killough 2/14/98: new field: save last known enemy. Prevents
338 // monsters from going to sleep after killing monsters and not
339 // seeing player anymore.
341 if (mobj->lastenemy)
342 mobj->lastenemy = mobj->lastenemy->thinker.function ==
343 P_MobjThinker ?
344 (mobj_t *) mobj->lastenemy->thinker.prev : NULL;
346 // killough 2/14/98: end changes
348 if (mobj->above_thing) // phares
349 mobj->above_thing = mobj->above_thing->thinker.function ==
350 P_MobjThinker ?
351 (mobj_t *) mobj->above_thing->thinker.prev : NULL;
353 if (mobj->below_thing)
354 mobj->below_thing = mobj->below_thing->thinker.function ==
355 P_MobjThinker ?
356 (mobj_t *) mobj->below_thing->thinker.prev : NULL; // phares
358 if (mobj->player)
359 mobj->player = (player_t *)((mobj->player-players) + 1);
362 // add a terminating marker
363 *save_p++ = tc_end;
365 // killough 9/14/98: save soundtargets
367 int i;
368 CheckSaveGame(numsectors * sizeof(mobj_t *)); // killough 9/14/98
369 for (i = 0; i < numsectors; i++)
371 mobj_t *target = sectors[i].soundtarget;
372 if (target)
373 target = (mobj_t *) target->thinker.prev;
374 memcpy(save_p, &target, sizeof target);
375 save_p += sizeof target;
381 * killough 11/98
383 * Same as P_SetTarget() in p_tick.c, except that the target is nullified
384 * first, so that no old target's reference count is decreased (when loading
385 * savegames, old targets are indices, not really pointers to targets).
388 static void P_SetNewTarget(mobj_t **mop, mobj_t *targ)
390 *mop = NULL;
391 P_SetTarget(mop, targ);
395 // P_UnArchiveThinkers
397 // 2/14/98 killough: substantially modified to fix savegame bugs
400 void P_UnArchiveThinkers (void)
402 thinker_t *th;
403 mobj_t **mobj_p; // killough 2/14/98: Translation table
404 size_t size; // killough 2/14/98: size of or index into table
406 totallive = 0;
407 // killough 3/26/98: Load boss brain state
408 memcpy(&brain, save_p, sizeof brain);
409 save_p += sizeof brain;
411 // remove all the current thinkers
412 for (th = thinkercap.next; th != &thinkercap; )
414 thinker_t *next = th->next;
415 if (th->function == P_MobjThinker)
416 P_RemoveMobj ((mobj_t *) th);
417 else
418 Z_Free (th);
419 th = next;
421 P_InitThinkers ();
423 // killough 2/14/98: count number of thinkers by skipping through them
425 byte *sp = save_p; // save pointer and skip header
426 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
427 { // skip all entries, adding up count
428 PADSAVEP();
429 save_p += sizeof(mobj_t);
432 if (*--save_p != tc_end)
433 I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);
435 // first table entry special: 0 maps to NULL
436 *(mobj_p = malloc(size * sizeof *mobj_p)) = 0; // table of pointers
437 save_p = sp; // restore save pointer
440 // read in saved thinkers
441 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
443 mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);
445 // killough 2/14/98 -- insert pointers to thinkers into table, in order:
446 mobj_p[size] = mobj;
448 PADSAVEP();
449 memcpy (mobj, save_p, sizeof(mobj_t));
450 save_p += sizeof(mobj_t);
451 mobj->state = states + (unsigned long) mobj->state;
453 if (mobj->player)
454 (mobj->player = &players[(unsigned long) mobj->player - 1]) -> mo = mobj;
456 P_SetThingPosition (mobj);
457 mobj->info = &mobjinfo[mobj->type];
459 // killough 2/28/98:
460 // Fix for falling down into a wall after savegame loaded:
461 // mobj->floorz = mobj->subsector->sector->floorheight;
462 // mobj->ceilingz = mobj->subsector->sector->ceilingheight;
464 mobj->thinker.function = P_MobjThinker;
465 P_AddThinker (&mobj->thinker);
467 if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
468 totallive++;
471 // killough 2/14/98: adjust target and tracer fields, plus
472 // lastenemy field, to correctly point to mobj thinkers.
473 // NULL entries automatically handled by first table entry.
475 // killough 11/98: use P_SetNewTarget() to set fields
477 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
479 P_SetNewTarget(&((mobj_t *) th)->target,
480 mobj_p[(size_t)((mobj_t *)th)->target]);
482 P_SetNewTarget(&((mobj_t *) th)->tracer,
483 mobj_p[(size_t)((mobj_t *)th)->tracer]);
485 P_SetNewTarget(&((mobj_t *) th)->lastenemy,
486 mobj_p[(size_t)((mobj_t *)th)->lastenemy]);
488 // phares: added two new fields for Sprite Height problem
490 P_SetNewTarget(&((mobj_t *) th)->above_thing,
491 mobj_p[(size_t)((mobj_t *)th)->above_thing]);
493 P_SetNewTarget(&((mobj_t *) th)->below_thing,
494 mobj_p[(size_t)((mobj_t *)th)->below_thing]);
497 { // killough 9/14/98: restore soundtargets
498 int i;
499 for (i = 0; i < numsectors; i++)
501 mobj_t *target;
502 memcpy(&target, save_p, sizeof target);
503 save_p += sizeof target;
504 P_SetNewTarget(&sectors[i].soundtarget, mobj_p[(size_t) target]);
508 free(mobj_p); // free translation table
510 // killough 3/26/98: Spawn icon landings:
511 if (gamemode == commercial)
512 P_SpawnBrainTargets();
516 // P_ArchiveSpecials
518 enum {
519 tc_ceiling,
520 tc_door,
521 tc_floor,
522 tc_plat,
523 tc_flash,
524 tc_strobe,
525 tc_glow,
526 tc_elevator, //jff 2/22/98 new elevator type thinker
527 tc_scroll, // killough 3/7/98: new scroll effect thinker
528 tc_pusher, // phares 3/22/98: new push/pull effect thinker
529 tc_flicker, // killough 10/4/98
530 tc_endspecials
532 unsigned specials_e;
535 // Things to handle:
537 // T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
538 // T_VerticalDoor, (vldoor_t: sector_t * swizzle),
539 // T_MoveFloor, (floormove_t: sector_t * swizzle),
540 // T_LightFlash, (lightflash_t: sector_t * swizzle),
541 // T_StrobeFlash, (strobe_t: sector_t *),
542 // T_Glow, (glow_t: sector_t *),
543 // T_PlatRaise, (plat_t: sector_t *), - active list
544 // T_MoveElevator, (plat_t: sector_t *), - active list // jff 2/22/98
545 // T_Scroll // killough 3/7/98
546 // T_Pusher // phares 3/22/98
547 // T_FireFlicker // killough 10/4/98
550 void P_ArchiveSpecials (void)
552 thinker_t *th;
553 size_t size = 0; // killough
555 // save off the current thinkers (memory size calculation -- killough)
557 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
558 if (!th->function)
560 platlist_t *pl;
561 ceilinglist_t *cl; //jff 2/22/98 need this for ceilings too now
562 for (pl=activeplats; pl; pl=pl->next)
563 if (pl->plat == (plat_t *) th) // killough 2/14/98
565 size += 4+sizeof(plat_t);
566 goto end;
568 for (cl=activeceilings; cl; cl=cl->next) // search for activeceiling
569 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
571 size += 4+sizeof(ceiling_t);
572 goto end;
574 end:;
576 else
577 size +=
578 th->function==T_MoveCeiling ? 4+sizeof(ceiling_t) :
579 th->function==T_VerticalDoor ? 4+sizeof(vldoor_t) :
580 th->function==T_MoveFloor ? 4+sizeof(floormove_t):
581 th->function==T_PlatRaise ? 4+sizeof(plat_t) :
582 th->function==T_LightFlash ? 4+sizeof(lightflash_t):
583 th->function==T_StrobeFlash ? 4+sizeof(strobe_t) :
584 th->function==T_Glow ? 4+sizeof(glow_t) :
585 th->function==T_MoveElevator ? 4+sizeof(elevator_t):
586 th->function==T_Scroll ? 4+sizeof(scroll_t) :
587 th->function==T_Pusher ? 4+sizeof(pusher_t) :
588 th->function==T_FireFlicker? 4+sizeof(fireflicker_t) :
591 CheckSaveGame(size); // killough
593 // save off the current thinkers
594 for (th=thinkercap.next; th!=&thinkercap; th=th->next)
596 if (!th->function)
598 platlist_t *pl;
599 ceilinglist_t *cl; //jff 2/22/98 add iter variable for ceilings
601 // killough 2/8/98: fix plat original height bug.
602 // Since acv==NULL, this could be a plat in stasis.
603 // so check the active plats list, and save this
604 // plat (jff: or ceiling) even if it is in stasis.
606 for (pl=activeplats; pl; pl=pl->next)
607 if (pl->plat == (plat_t *) th) // killough 2/14/98
608 goto plat;
610 for (cl=activeceilings; cl; cl=cl->next)
611 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
612 goto ceiling;
614 continue;
617 if (th->function == T_MoveCeiling)
619 ceiling_t *ceiling;
620 ceiling: // killough 2/14/98
621 *save_p++ = tc_ceiling;
622 PADSAVEP();
623 ceiling = (ceiling_t *)save_p;
624 memcpy (ceiling, th, sizeof(*ceiling));
625 save_p += sizeof(*ceiling);
626 ceiling->sector = (sector_t *)(ceiling->sector - sectors);
627 continue;
630 if (th->function == T_VerticalDoor)
632 vldoor_t *door;
633 *save_p++ = tc_door;
634 PADSAVEP();
635 door = (vldoor_t *) save_p;
636 memcpy (door, th, sizeof *door);
637 save_p += sizeof(*door);
638 door->sector = (sector_t *)(door->sector - sectors);
639 //jff 1/31/98 archive line remembered by door as well
640 door->line = (line_t *) (door->line ? door->line-lines : -1);
641 continue;
644 if (th->function == T_MoveFloor)
646 floormove_t *floor;
647 *save_p++ = tc_floor;
648 PADSAVEP();
649 floor = (floormove_t *)save_p;
650 memcpy (floor, th, sizeof(*floor));
651 save_p += sizeof(*floor);
652 floor->sector = (sector_t *)(floor->sector - sectors);
653 continue;
656 if (th->function == T_PlatRaise)
658 plat_t *plat;
659 plat: // killough 2/14/98: added fix for original plat height above
660 *save_p++ = tc_plat;
661 PADSAVEP();
662 plat = (plat_t *)save_p;
663 memcpy (plat, th, sizeof(*plat));
664 save_p += sizeof(*plat);
665 plat->sector = (sector_t *)(plat->sector - sectors);
666 continue;
669 if (th->function == T_LightFlash)
671 lightflash_t *flash;
672 *save_p++ = tc_flash;
673 PADSAVEP();
674 flash = (lightflash_t *)save_p;
675 memcpy (flash, th, sizeof(*flash));
676 save_p += sizeof(*flash);
677 flash->sector = (sector_t *)(flash->sector - sectors);
678 continue;
681 if (th->function == T_StrobeFlash)
683 strobe_t *strobe;
684 *save_p++ = tc_strobe;
685 PADSAVEP();
686 strobe = (strobe_t *)save_p;
687 memcpy (strobe, th, sizeof(*strobe));
688 save_p += sizeof(*strobe);
689 strobe->sector = (sector_t *)(strobe->sector - sectors);
690 continue;
693 if (th->function == T_Glow)
695 glow_t *glow;
696 *save_p++ = tc_glow;
697 PADSAVEP();
698 glow = (glow_t *)save_p;
699 memcpy (glow, th, sizeof(*glow));
700 save_p += sizeof(*glow);
701 glow->sector = (sector_t *)(glow->sector - sectors);
702 continue;
705 // killough 10/4/98: save flickers
706 if (th->function == T_FireFlicker)
708 fireflicker_t *flicker;
709 *save_p++ = tc_flicker;
710 PADSAVEP();
711 flicker = (fireflicker_t *)save_p;
712 memcpy (flicker, th, sizeof(*flicker));
713 save_p += sizeof(*flicker);
714 flicker->sector = (sector_t *)(flicker->sector - sectors);
715 continue;
718 //jff 2/22/98 new case for elevators
719 if (th->function == T_MoveElevator)
721 elevator_t *elevator; //jff 2/22/98
722 *save_p++ = tc_elevator;
723 PADSAVEP();
724 elevator = (elevator_t *)save_p;
725 memcpy (elevator, th, sizeof(*elevator));
726 save_p += sizeof(*elevator);
727 elevator->sector = (sector_t *)(elevator->sector - sectors);
728 continue;
731 // killough 3/7/98: Scroll effect thinkers
732 if (th->function == T_Scroll)
734 *save_p++ = tc_scroll;
735 memcpy (save_p, th, sizeof(scroll_t));
736 save_p += sizeof(scroll_t);
737 continue;
740 // phares 3/22/98: Push/Pull effect thinkers
742 if (th->function == T_Pusher)
744 *save_p++ = tc_pusher;
745 memcpy (save_p, th, sizeof(pusher_t));
746 save_p += sizeof(pusher_t);
747 continue;
751 // add a terminating marker
752 *save_p++ = tc_endspecials;
757 // P_UnArchiveSpecials
759 void P_UnArchiveSpecials (void)
761 byte tclass;
763 // read in saved thinkers
764 while ((tclass = *save_p++) != tc_endspecials) // killough 2/14/98
765 switch (tclass)
767 case tc_ceiling:
768 PADSAVEP();
770 ceiling_t *ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
771 memcpy (ceiling, save_p, sizeof(*ceiling));
772 save_p += sizeof(*ceiling);
773 ceiling->sector = &sectors[(unsigned long)ceiling->sector];
774 ceiling->sector->ceilingdata = ceiling; //jff 2/22/98
776 if (ceiling->thinker.function)
777 ceiling->thinker.function = T_MoveCeiling;
779 P_AddThinker (&ceiling->thinker);
780 P_AddActiveCeiling(ceiling);
781 break;
784 case tc_door:
785 PADSAVEP();
787 vldoor_t *door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
788 memcpy (door, save_p, sizeof(*door));
789 save_p += sizeof(*door);
790 door->sector = &sectors[(unsigned long)door->sector];
792 //jff 1/31/98 unarchive line remembered by door as well
793 door->line = (long)door->line!=-1? &lines[(unsigned long)door->line] : NULL;
795 door->sector->ceilingdata = door; //jff 2/22/98
796 door->thinker.function = T_VerticalDoor;
797 P_AddThinker (&door->thinker);
798 break;
801 case tc_floor:
802 PADSAVEP();
804 floormove_t *floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
805 memcpy (floor, save_p, sizeof(*floor));
806 save_p += sizeof(*floor);
807 floor->sector = &sectors[(unsigned long)floor->sector];
808 floor->sector->floordata = floor; //jff 2/22/98
809 floor->thinker.function = T_MoveFloor;
810 P_AddThinker (&floor->thinker);
811 break;
814 case tc_plat:
815 PADSAVEP();
817 plat_t *plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
818 memcpy (plat, save_p, sizeof(*plat));
819 save_p += sizeof(*plat);
820 plat->sector = &sectors[(unsigned long)plat->sector];
821 plat->sector->floordata = plat; //jff 2/22/98
823 if (plat->thinker.function)
824 plat->thinker.function = T_PlatRaise;
826 P_AddThinker (&plat->thinker);
827 P_AddActivePlat(plat);
828 break;
831 case tc_flash:
832 PADSAVEP();
834 lightflash_t *flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
835 memcpy (flash, save_p, sizeof(*flash));
836 save_p += sizeof(*flash);
837 flash->sector = &sectors[(unsigned long)flash->sector];
838 flash->thinker.function = T_LightFlash;
839 P_AddThinker (&flash->thinker);
840 break;
843 case tc_strobe:
844 PADSAVEP();
846 strobe_t *strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
847 memcpy (strobe, save_p, sizeof(*strobe));
848 save_p += sizeof(*strobe);
849 strobe->sector = &sectors[(unsigned long)strobe->sector];
850 strobe->thinker.function = T_StrobeFlash;
851 P_AddThinker (&strobe->thinker);
852 break;
855 case tc_glow:
856 PADSAVEP();
858 glow_t *glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
859 memcpy (glow, save_p, sizeof(*glow));
860 save_p += sizeof(*glow);
861 glow->sector = &sectors[(unsigned long)glow->sector];
862 glow->thinker.function = T_Glow;
863 P_AddThinker (&glow->thinker);
864 break;
867 case tc_flicker: // killough 10/4/98
868 PADSAVEP();
870 fireflicker_t *flicker = Z_Malloc (sizeof(*flicker), PU_LEVEL, NULL);
871 memcpy (flicker, save_p, sizeof(*flicker));
872 save_p += sizeof(*flicker);
873 flicker->sector = &sectors[(unsigned long)flicker->sector];
874 flicker->thinker.function = T_FireFlicker;
875 P_AddThinker (&flicker->thinker);
876 break;
879 //jff 2/22/98 new case for elevators
880 case tc_elevator:
881 PADSAVEP();
883 elevator_t *elevator = Z_Malloc (sizeof(*elevator), PU_LEVEL, NULL);
884 memcpy (elevator, save_p, sizeof(*elevator));
885 save_p += sizeof(*elevator);
886 elevator->sector = &sectors[(unsigned long)elevator->sector];
887 elevator->sector->floordata = elevator; //jff 2/22/98
888 elevator->sector->ceilingdata = elevator; //jff 2/22/98
889 elevator->thinker.function = T_MoveElevator;
890 P_AddThinker (&elevator->thinker);
891 break;
894 case tc_scroll: // killough 3/7/98: scroll effect thinkers
896 scroll_t *scroll = Z_Malloc (sizeof(scroll_t), PU_LEVEL, NULL);
897 memcpy (scroll, save_p, sizeof(scroll_t));
898 save_p += sizeof(scroll_t);
899 scroll->thinker.function = T_Scroll;
900 P_AddThinker(&scroll->thinker);
901 break;
904 case tc_pusher: // phares 3/22/98: new Push/Pull effect thinkers
906 pusher_t *pusher = Z_Malloc (sizeof(pusher_t), PU_LEVEL, NULL);
907 memcpy (pusher, save_p, sizeof(pusher_t));
908 save_p += sizeof(pusher_t);
909 pusher->thinker.function = T_Pusher;
910 pusher->source = P_GetPushThing(pusher->affectee);
911 P_AddThinker(&pusher->thinker);
912 break;
915 default:
916 I_Error("P_UnarchiveSpecials: Unknown tclass %i in savegame", tclass);
920 // killough 2/16/98: save/restore random number generator state information
922 void P_ArchiveRNG(void)
924 CheckSaveGame(sizeof rng);
925 memcpy(save_p, &rng, sizeof rng);
926 save_p += sizeof rng;
929 void P_UnArchiveRNG(void)
931 memcpy(&rng, save_p, sizeof rng);
932 save_p += sizeof rng;
935 // killough 2/22/98: Save/restore automap state
936 // killough 2/22/98: Save/restore automap state
937 void P_ArchiveMap(void)
939 int zero = 0, one = 1;
940 CheckSaveGame(2 * sizeof zero + sizeof markpointnum +
941 markpointnum * sizeof *markpoints +
942 sizeof automapmode + sizeof one);
944 memcpy(save_p, &automapmode, sizeof automapmode);
945 save_p += sizeof automapmode;
946 memcpy(save_p, &one, sizeof one); // CPhipps - used to be viewactive, now
947 save_p += sizeof one; // that's worked out locally by D_Display
948 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be followplayer
949 save_p += sizeof zero; // that is now part of automapmode
950 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be automap_grid, ditto
951 save_p += sizeof zero;
952 memcpy(save_p, &markpointnum, sizeof markpointnum);
953 save_p += sizeof markpointnum;
955 if (markpointnum)
957 memcpy(save_p, markpoints, sizeof *markpoints * markpointnum);
958 save_p += markpointnum * sizeof *markpoints;
962 void P_UnArchiveMap(void)
964 int unused;
965 memcpy(&automapmode, save_p, sizeof automapmode);
966 save_p += sizeof automapmode;
967 memcpy(&unused, save_p, sizeof unused);
968 save_p += sizeof unused;
969 memcpy(&unused, save_p, sizeof unused);
970 save_p += sizeof unused;
971 memcpy(&unused, save_p, sizeof unused);
972 save_p += sizeof unused;
974 if (automapmode & am_active)
975 AM_Start();
977 memcpy(&markpointnum, save_p, sizeof markpointnum);
978 save_p += sizeof markpointnum;
980 if (markpointnum)
982 while (markpointnum >= markpointnum_max)
983 markpoints = realloc(markpoints, sizeof *markpoints *
984 (markpointnum_max = markpointnum_max ? markpointnum_max*2 : 16));
985 memcpy(markpoints, save_p, markpointnum * sizeof *markpoints);
986 save_p += markpointnum * sizeof *markpoints;