summaryrefslogtreecommitdiff
path: root/apps/plugins/doom/p_saveg.c
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2006-03-28 15:44:01 +0000
committerDave Chapman <dave@dchapman.com>2006-03-28 15:44:01 +0000
commit47f4a458d636a889e955e68f896708f1276febc0 (patch)
tree99f770c02ef606f0abbdcd332ac39e69830d8007 /apps/plugins/doom/p_saveg.c
parentfff7d6157d56f233cad5c2003475e47a5ff809a7 (diff)
downloadrockbox-47f4a458d636a889e955e68f896708f1276febc0.tar.gz
rockbox-47f4a458d636a889e955e68f896708f1276febc0.zip
Patch #2969 - Doom! Currently only working on the H300.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9312 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/doom/p_saveg.c')
-rw-r--r--apps/plugins/doom/p_saveg.c987
1 files changed, 987 insertions, 0 deletions
diff --git a/apps/plugins/doom/p_saveg.c b/apps/plugins/doom/p_saveg.c
new file mode 100644
index 0000000000..bf1a2edc45
--- /dev/null
+++ b/apps/plugins/doom/p_saveg.c
@@ -0,0 +1,987 @@
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 *
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.
16 *
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.
21 *
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.
26 *
27 * DESCRIPTION:
28 * Archiving: SaveGame I/O.
29 *
30 *-----------------------------------------------------------------------------*/
31
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"
43byte *save_p;
44
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 - ((int) save_p & 3)) & 3; } while (0)
48//
49// P_ArchivePlayers
50//
51void P_ArchivePlayers (void)
52{
53 int i;
54
55 CheckSaveGame(sizeof(player_t) * MAXPLAYERS); // killough
56 for (i=0 ; i<MAXPLAYERS ; i++)
57 if (playeringame[i])
58 {
59 int j;
60 player_t *dest;
61
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);
70 }
71}
72
73//
74// P_UnArchivePlayers
75//
76void P_UnArchivePlayers (void)
77{
78 int i;
79
80 for (i=0 ; i<MAXPLAYERS ; i++)
81 if (playeringame[i])
82 {
83 int j;
84
85 PADSAVEP();
86
87 memcpy(&players[i], save_p, sizeof(player_t));
88 save_p += sizeof(player_t);
89
90 // will be set when unarc thinker
91 players[i].mo = NULL;
92 players[i].message = NULL;
93 players[i].attacker = NULL;
94
95 for (j=0 ; j<NUMPSPRITES ; j++)
96 if (players[i]. psprites[j].state)
97 players[i]. psprites[j].state =
98 &states[ (int)players[i].psprites[j].state ];
99 }
100}
101
102
103//
104// P_ArchiveWorld
105//
106void P_ArchiveWorld (void)
107{
108 int i;
109 const sector_t *sec;
110 const line_t *li;
111 const side_t *si;
112 short *put;
113
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;
119
120 for (i=0; i<numlines; i++)
121 {
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;
128 }
129
130 CheckSaveGame(size); // killough
131
132 PADSAVEP(); // killough 3/22/98
133
134 put = (short *)save_p;
135
136 // do sectors
137 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
138 {
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);
144
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
150 }
151
152 // do lines
153 for (i=0, li = lines ; i<numlines ; i++,li++)
154 {
155 int j;
156
157 *put++ = li->flags;
158 *put++ = li->special;
159 *put++ = li->tag;
160
161 for (j=0; j<2; j++)
162 if (li->sidenum[j] != -1)
163 {
164 si = &sides[li->sidenum[j]];
165
166 // killough 10/98: save full sidedef offsets,
167 // preserving fractional scroll offsets
168
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);
173
174 *put++ = si->toptexture;
175 *put++ = si->bottomtexture;
176 *put++ = si->midtexture;
177 }
178 }
179 save_p = (byte *) put;
180}
181
182
183
184//
185// P_UnArchiveWorld
186//
187void P_UnArchiveWorld (void)
188{
189 int i;
190 sector_t *sec;
191 line_t *li;
192 const short *get;
193
194 PADSAVEP(); // killough 3/22/98
195
196 get = (short *) save_p;
197
198 // do sectors
199 for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
200 {
201 // killough 10/98: load full floor & ceiling heights, including fractions
202
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);
207
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;
217 }
218
219 // do lines
220 for (i=0, li = lines ; i<numlines ; i++,li++)
221 {
222 int j;
223
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)
229 {
230 side_t *si = &sides[li->sidenum[j]];
231
232 // killough 10/98: load full sidedef offsets, including fractions
233
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);
238
239 si->toptexture = *get++;
240 si->bottomtexture = *get++;
241 si->midtexture = *get++;
242 }
243 }
244 save_p = (byte *) get;
245}
246
247//
248// Thinkers
249//
250
251typedef enum {
252 tc_end,
253 tc_mobj
254} thinkerclass_t;
255
256// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
257// thinker indices could be used by the code that saves sector info.
258
259static int number_of_thinkers;
260
261void P_ThinkerToIndex(void)
262{
263 thinker_t *th;
264
265 // killough 2/14/98:
266 // count the number of thinkers, and mark each one with its index, using
267 // the prev field as a placeholder, since it can be restored later.
268
269 number_of_thinkers = 0;
270 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
271 if (th->function == P_MobjThinker)
272 th->prev = (thinker_t *) ++number_of_thinkers;
273}
274
275// phares 9/13/98: Moved this code outside of P_ArchiveThinkers so the
276// thinker indices could be used by the code that saves sector info.
277
278void P_IndexToThinker(void)
279{
280 // killough 2/14/98: restore prev pointers
281 thinker_t *th;
282 thinker_t *prev = &thinkercap;
283
284 for (th = thinkercap.next ; th != &thinkercap ; prev=th, th=th->next)
285 th->prev = prev;
286}
287
288//
289// P_ArchiveThinkers
290//
291// 2/14/98 killough: substantially modified to fix savegame bugs
292
293void P_ArchiveThinkers (void)
294{
295 thinker_t *th;
296
297 CheckSaveGame(sizeof brain); // killough 3/26/98: Save boss brain state
298 memcpy(save_p, &brain, sizeof brain);
299 save_p += sizeof brain;
300
301 /* check that enough room is available in savegame buffer
302 * - killough 2/14/98
303 * cph - use number_of_thinkers saved by P_ThinkerToIndex above
304 */
305 CheckSaveGame(number_of_thinkers*(sizeof(mobj_t)+4));
306
307 // save off the current thinkers
308 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
309 if (th->function == P_MobjThinker)
310 {
311 mobj_t *mobj;
312
313 *save_p++ = tc_mobj;
314 PADSAVEP();
315 mobj = (mobj_t *)save_p;
316 memcpy (mobj, th, sizeof(*mobj));
317 save_p += sizeof(*mobj);
318 mobj->state = (state_t *)(mobj->state - states);
319
320 // killough 2/14/98: convert pointers into indices.
321 // Fixes many savegame problems, by properly saving
322 // target and tracer fields. Note: we store NULL if
323 // the thinker pointed to by these fields is not a
324 // mobj thinker.
325
326 if (mobj->target)
327 mobj->target = mobj->target->thinker.function ==
328 P_MobjThinker ?
329 (mobj_t *) mobj->target->thinker.prev : NULL;
330
331 if (mobj->tracer)
332 mobj->tracer = mobj->tracer->thinker.function ==
333 P_MobjThinker ?
334 (mobj_t *) mobj->tracer->thinker.prev : NULL;
335
336 // killough 2/14/98: new field: save last known enemy. Prevents
337 // monsters from going to sleep after killing monsters and not
338 // seeing player anymore.
339
340 if (mobj->lastenemy)
341 mobj->lastenemy = mobj->lastenemy->thinker.function ==
342 P_MobjThinker ?
343 (mobj_t *) mobj->lastenemy->thinker.prev : NULL;
344
345 // killough 2/14/98: end changes
346
347 if (mobj->above_thing) // phares
348 mobj->above_thing = mobj->above_thing->thinker.function ==
349 P_MobjThinker ?
350 (mobj_t *) mobj->above_thing->thinker.prev : NULL;
351
352 if (mobj->below_thing)
353 mobj->below_thing = mobj->below_thing->thinker.function ==
354 P_MobjThinker ?
355 (mobj_t *) mobj->below_thing->thinker.prev : NULL; // phares
356
357 if (mobj->player)
358 mobj->player = (player_t *)((mobj->player-players) + 1);
359 }
360
361 // add a terminating marker
362 *save_p++ = tc_end;
363
364 // killough 9/14/98: save soundtargets
365 {
366 int i;
367 CheckSaveGame(numsectors * sizeof(mobj_t *)); // killough 9/14/98
368 for (i = 0; i < numsectors; i++)
369 {
370 mobj_t *target = sectors[i].soundtarget;
371 if (target)
372 target = (mobj_t *) target->thinker.prev;
373 memcpy(save_p, &target, sizeof target);
374 save_p += sizeof target;
375 }
376 }
377}
378
379/*
380 * killough 11/98
381 *
382 * Same as P_SetTarget() in p_tick.c, except that the target is nullified
383 * first, so that no old target's reference count is decreased (when loading
384 * savegames, old targets are indices, not really pointers to targets).
385 */
386
387static void P_SetNewTarget(mobj_t **mop, mobj_t *targ)
388{
389 *mop = NULL;
390 P_SetTarget(mop, targ);
391}
392
393//
394// P_UnArchiveThinkers
395//
396// 2/14/98 killough: substantially modified to fix savegame bugs
397//
398
399void P_UnArchiveThinkers (void)
400{
401 thinker_t *th;
402 mobj_t **mobj_p; // killough 2/14/98: Translation table
403 size_t size; // killough 2/14/98: size of or index into table
404
405 totallive = 0;
406 // killough 3/26/98: Load boss brain state
407 memcpy(&brain, save_p, sizeof brain);
408 save_p += sizeof brain;
409
410 // remove all the current thinkers
411 for (th = thinkercap.next; th != &thinkercap; )
412 {
413 thinker_t *next = th->next;
414 if (th->function == P_MobjThinker)
415 P_RemoveMobj ((mobj_t *) th);
416 else
417 Z_Free (th);
418 th = next;
419 }
420 P_InitThinkers ();
421
422 // killough 2/14/98: count number of thinkers by skipping through them
423 {
424 byte *sp = save_p; // save pointer and skip header
425 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
426 { // skip all entries, adding up count
427 PADSAVEP();
428 save_p += sizeof(mobj_t);
429 }
430
431 if (*--save_p != tc_end)
432 I_Error ("P_UnArchiveThinkers: Unknown tclass %i in savegame", *save_p);
433
434 // first table entry special: 0 maps to NULL
435 *(mobj_p = malloc(size * sizeof *mobj_p)) = 0; // table of pointers
436 save_p = sp; // restore save pointer
437 }
438
439 // read in saved thinkers
440 for (size = 1; *save_p++ == tc_mobj; size++) // killough 2/14/98
441 {
442 mobj_t *mobj = Z_Malloc(sizeof(mobj_t), PU_LEVEL, NULL);
443
444 // killough 2/14/98 -- insert pointers to thinkers into table, in order:
445 mobj_p[size] = mobj;
446
447 PADSAVEP();
448 memcpy (mobj, save_p, sizeof(mobj_t));
449 save_p += sizeof(mobj_t);
450 mobj->state = states + (int) mobj->state;
451
452 if (mobj->player)
453 (mobj->player = &players[(int) mobj->player - 1]) -> mo = mobj;
454
455 P_SetThingPosition (mobj);
456 mobj->info = &mobjinfo[mobj->type];
457
458 // killough 2/28/98:
459 // Fix for falling down into a wall after savegame loaded:
460 // mobj->floorz = mobj->subsector->sector->floorheight;
461 // mobj->ceilingz = mobj->subsector->sector->ceilingheight;
462
463 mobj->thinker.function = P_MobjThinker;
464 P_AddThinker (&mobj->thinker);
465
466 if (!((mobj->flags ^ MF_COUNTKILL) & (MF_FRIEND | MF_COUNTKILL | MF_CORPSE)))
467 totallive++;
468 }
469
470 // killough 2/14/98: adjust target and tracer fields, plus
471 // lastenemy field, to correctly point to mobj thinkers.
472 // NULL entries automatically handled by first table entry.
473 //
474 // killough 11/98: use P_SetNewTarget() to set fields
475
476 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
477 {
478 P_SetNewTarget(&((mobj_t *) th)->target,
479 mobj_p[(size_t)((mobj_t *)th)->target]);
480
481 P_SetNewTarget(&((mobj_t *) th)->tracer,
482 mobj_p[(size_t)((mobj_t *)th)->tracer]);
483
484 P_SetNewTarget(&((mobj_t *) th)->lastenemy,
485 mobj_p[(size_t)((mobj_t *)th)->lastenemy]);
486
487 // phares: added two new fields for Sprite Height problem
488
489 P_SetNewTarget(&((mobj_t *) th)->above_thing,
490 mobj_p[(size_t)((mobj_t *)th)->above_thing]);
491
492 P_SetNewTarget(&((mobj_t *) th)->below_thing,
493 mobj_p[(size_t)((mobj_t *)th)->below_thing]);
494 }
495
496 { // killough 9/14/98: restore soundtargets
497 int i;
498 for (i = 0; i < numsectors; i++)
499 {
500 mobj_t *target;
501 memcpy(&target, save_p, sizeof target);
502 save_p += sizeof target;
503 P_SetNewTarget(&sectors[i].soundtarget, mobj_p[(size_t) target]);
504 }
505 }
506
507 free(mobj_p); // free translation table
508
509 // killough 3/26/98: Spawn icon landings:
510 if (gamemode == commercial)
511 P_SpawnBrainTargets();
512}
513
514//
515// P_ArchiveSpecials
516//
517enum {
518 tc_ceiling,
519 tc_door,
520 tc_floor,
521 tc_plat,
522 tc_flash,
523 tc_strobe,
524 tc_glow,
525 tc_elevator, //jff 2/22/98 new elevator type thinker
526 tc_scroll, // killough 3/7/98: new scroll effect thinker
527 tc_pusher, // phares 3/22/98: new push/pull effect thinker
528 tc_flicker, // killough 10/4/98
529 tc_endspecials
530} specials_e;
531
532//
533// Things to handle:
534//
535// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
536// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
537// T_MoveFloor, (floormove_t: sector_t * swizzle),
538// T_LightFlash, (lightflash_t: sector_t * swizzle),
539// T_StrobeFlash, (strobe_t: sector_t *),
540// T_Glow, (glow_t: sector_t *),
541// T_PlatRaise, (plat_t: sector_t *), - active list
542// T_MoveElevator, (plat_t: sector_t *), - active list // jff 2/22/98
543// T_Scroll // killough 3/7/98
544// T_Pusher // phares 3/22/98
545// T_FireFlicker // killough 10/4/98
546//
547
548void P_ArchiveSpecials (void)
549{
550 thinker_t *th;
551 size_t size = 0; // killough
552
553 // save off the current thinkers (memory size calculation -- killough)
554
555 for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
556 if (!th->function)
557 {
558 platlist_t *pl;
559 ceilinglist_t *cl; //jff 2/22/98 need this for ceilings too now
560 for (pl=activeplats; pl; pl=pl->next)
561 if (pl->plat == (plat_t *) th) // killough 2/14/98
562 {
563 size += 4+sizeof(plat_t);
564 goto end;
565 }
566 for (cl=activeceilings; cl; cl=cl->next) // search for activeceiling
567 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
568 {
569 size += 4+sizeof(ceiling_t);
570 goto end;
571 }
572end:;
573 }
574 else
575 size +=
576 th->function==T_MoveCeiling ? 4+sizeof(ceiling_t) :
577 th->function==T_VerticalDoor ? 4+sizeof(vldoor_t) :
578 th->function==T_MoveFloor ? 4+sizeof(floormove_t):
579 th->function==T_PlatRaise ? 4+sizeof(plat_t) :
580 th->function==T_LightFlash ? 4+sizeof(lightflash_t):
581 th->function==T_StrobeFlash ? 4+sizeof(strobe_t) :
582 th->function==T_Glow ? 4+sizeof(glow_t) :
583 th->function==T_MoveElevator ? 4+sizeof(elevator_t):
584 th->function==T_Scroll ? 4+sizeof(scroll_t) :
585 th->function==T_Pusher ? 4+sizeof(pusher_t) :
586 th->function==T_FireFlicker? 4+sizeof(fireflicker_t) :
587 0;
588
589 CheckSaveGame(size); // killough
590
591 // save off the current thinkers
592 for (th=thinkercap.next; th!=&thinkercap; th=th->next)
593 {
594 if (!th->function)
595 {
596 platlist_t *pl;
597 ceilinglist_t *cl; //jff 2/22/98 add iter variable for ceilings
598
599 // killough 2/8/98: fix plat original height bug.
600 // Since acv==NULL, this could be a plat in stasis.
601 // so check the active plats list, and save this
602 // plat (jff: or ceiling) even if it is in stasis.
603
604 for (pl=activeplats; pl; pl=pl->next)
605 if (pl->plat == (plat_t *) th) // killough 2/14/98
606 goto plat;
607
608 for (cl=activeceilings; cl; cl=cl->next)
609 if (cl->ceiling == (ceiling_t *) th) //jff 2/22/98
610 goto ceiling;
611
612 continue;
613 }
614
615 if (th->function == T_MoveCeiling)
616 {
617 ceiling_t *ceiling;
618ceiling: // killough 2/14/98
619 *save_p++ = tc_ceiling;
620 PADSAVEP();
621 ceiling = (ceiling_t *)save_p;
622 memcpy (ceiling, th, sizeof(*ceiling));
623 save_p += sizeof(*ceiling);
624 ceiling->sector = (sector_t *)(ceiling->sector - sectors);
625 continue;
626 }
627
628 if (th->function == T_VerticalDoor)
629 {
630 vldoor_t *door;
631 *save_p++ = tc_door;
632 PADSAVEP();
633 door = (vldoor_t *) save_p;
634 memcpy (door, th, sizeof *door);
635 save_p += sizeof(*door);
636 door->sector = (sector_t *)(door->sector - sectors);
637 //jff 1/31/98 archive line remembered by door as well
638 door->line = (line_t *) (door->line ? door->line-lines : -1);
639 continue;
640 }
641
642 if (th->function == T_MoveFloor)
643 {
644 floormove_t *floor;
645 *save_p++ = tc_floor;
646 PADSAVEP();
647 floor = (floormove_t *)save_p;
648 memcpy (floor, th, sizeof(*floor));
649 save_p += sizeof(*floor);
650 floor->sector = (sector_t *)(floor->sector - sectors);
651 continue;
652 }
653
654 if (th->function == T_PlatRaise)
655 {
656 plat_t *plat;
657plat: // killough 2/14/98: added fix for original plat height above
658 *save_p++ = tc_plat;
659 PADSAVEP();
660 plat = (plat_t *)save_p;
661 memcpy (plat, th, sizeof(*plat));
662 save_p += sizeof(*plat);
663 plat->sector = (sector_t *)(plat->sector - sectors);
664 continue;
665 }
666
667 if (th->function == T_LightFlash)
668 {
669 lightflash_t *flash;
670 *save_p++ = tc_flash;
671 PADSAVEP();
672 flash = (lightflash_t *)save_p;
673 memcpy (flash, th, sizeof(*flash));
674 save_p += sizeof(*flash);
675 flash->sector = (sector_t *)(flash->sector - sectors);
676 continue;
677 }
678
679 if (th->function == T_StrobeFlash)
680 {
681 strobe_t *strobe;
682 *save_p++ = tc_strobe;
683 PADSAVEP();
684 strobe = (strobe_t *)save_p;
685 memcpy (strobe, th, sizeof(*strobe));
686 save_p += sizeof(*strobe);
687 strobe->sector = (sector_t *)(strobe->sector - sectors);
688 continue;
689 }
690
691 if (th->function == T_Glow)
692 {
693 glow_t *glow;
694 *save_p++ = tc_glow;
695 PADSAVEP();
696 glow = (glow_t *)save_p;
697 memcpy (glow, th, sizeof(*glow));
698 save_p += sizeof(*glow);
699 glow->sector = (sector_t *)(glow->sector - sectors);
700 continue;
701 }
702
703 // killough 10/4/98: save flickers
704 if (th->function == T_FireFlicker)
705 {
706 fireflicker_t *flicker;
707 *save_p++ = tc_flicker;
708 PADSAVEP();
709 flicker = (fireflicker_t *)save_p;
710 memcpy (flicker, th, sizeof(*flicker));
711 save_p += sizeof(*flicker);
712 flicker->sector = (sector_t *)(flicker->sector - sectors);
713 continue;
714 }
715
716 //jff 2/22/98 new case for elevators
717 if (th->function == T_MoveElevator)
718 {
719 elevator_t *elevator; //jff 2/22/98
720 *save_p++ = tc_elevator;
721 PADSAVEP();
722 elevator = (elevator_t *)save_p;
723 memcpy (elevator, th, sizeof(*elevator));
724 save_p += sizeof(*elevator);
725 elevator->sector = (sector_t *)(elevator->sector - sectors);
726 continue;
727 }
728
729 // killough 3/7/98: Scroll effect thinkers
730 if (th->function == T_Scroll)
731 {
732 *save_p++ = tc_scroll;
733 memcpy (save_p, th, sizeof(scroll_t));
734 save_p += sizeof(scroll_t);
735 continue;
736 }
737
738 // phares 3/22/98: Push/Pull effect thinkers
739
740 if (th->function == T_Pusher)
741 {
742 *save_p++ = tc_pusher;
743 memcpy (save_p, th, sizeof(pusher_t));
744 save_p += sizeof(pusher_t);
745 continue;
746 }
747 }
748
749 // add a terminating marker
750 *save_p++ = tc_endspecials;
751}
752
753
754//
755// P_UnArchiveSpecials
756//
757void P_UnArchiveSpecials (void)
758{
759 byte tclass;
760
761 // read in saved thinkers
762 while ((tclass = *save_p++) != tc_endspecials) // killough 2/14/98
763 switch (tclass)
764 {
765 case tc_ceiling:
766 PADSAVEP();
767 {
768 ceiling_t *ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
769 memcpy (ceiling, save_p, sizeof(*ceiling));
770 save_p += sizeof(*ceiling);
771 ceiling->sector = &sectors[(int)ceiling->sector];
772 ceiling->sector->ceilingdata = ceiling; //jff 2/22/98
773
774 if (ceiling->thinker.function)
775 ceiling->thinker.function = T_MoveCeiling;
776
777 P_AddThinker (&ceiling->thinker);
778 P_AddActiveCeiling(ceiling);
779 break;
780 }
781
782 case tc_door:
783 PADSAVEP();
784 {
785 vldoor_t *door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
786 memcpy (door, save_p, sizeof(*door));
787 save_p += sizeof(*door);
788 door->sector = &sectors[(int)door->sector];
789
790 //jff 1/31/98 unarchive line remembered by door as well
791 door->line = (int)door->line!=-1? &lines[(int)door->line] : NULL;
792
793 door->sector->ceilingdata = door; //jff 2/22/98
794 door->thinker.function = T_VerticalDoor;
795 P_AddThinker (&door->thinker);
796 break;
797 }
798
799 case tc_floor:
800 PADSAVEP();
801 {
802 floormove_t *floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
803 memcpy (floor, save_p, sizeof(*floor));
804 save_p += sizeof(*floor);
805 floor->sector = &sectors[(int)floor->sector];
806 floor->sector->floordata = floor; //jff 2/22/98
807 floor->thinker.function = T_MoveFloor;
808 P_AddThinker (&floor->thinker);
809 break;
810 }
811
812 case tc_plat:
813 PADSAVEP();
814 {
815 plat_t *plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
816 memcpy (plat, save_p, sizeof(*plat));
817 save_p += sizeof(*plat);
818 plat->sector = &sectors[(int)plat->sector];
819 plat->sector->floordata = plat; //jff 2/22/98
820
821 if (plat->thinker.function)
822 plat->thinker.function = T_PlatRaise;
823
824 P_AddThinker (&plat->thinker);
825 P_AddActivePlat(plat);
826 break;
827 }
828
829 case tc_flash:
830 PADSAVEP();
831 {
832 lightflash_t *flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
833 memcpy (flash, save_p, sizeof(*flash));
834 save_p += sizeof(*flash);
835 flash->sector = &sectors[(int)flash->sector];
836 flash->thinker.function = T_LightFlash;
837 P_AddThinker (&flash->thinker);
838 break;
839 }
840
841 case tc_strobe:
842 PADSAVEP();
843 {
844 strobe_t *strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
845 memcpy (strobe, save_p, sizeof(*strobe));
846 save_p += sizeof(*strobe);
847 strobe->sector = &sectors[(int)strobe->sector];
848 strobe->thinker.function = T_StrobeFlash;
849 P_AddThinker (&strobe->thinker);
850 break;
851 }
852
853 case tc_glow:
854 PADSAVEP();
855 {
856 glow_t *glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
857 memcpy (glow, save_p, sizeof(*glow));
858 save_p += sizeof(*glow);
859 glow->sector = &sectors[(int)glow->sector];
860 glow->thinker.function = T_Glow;
861 P_AddThinker (&glow->thinker);
862 break;
863 }
864
865 case tc_flicker: // killough 10/4/98
866 PADSAVEP();
867 {
868 fireflicker_t *flicker = Z_Malloc (sizeof(*flicker), PU_LEVEL, NULL);
869 memcpy (flicker, save_p, sizeof(*flicker));
870 save_p += sizeof(*flicker);
871 flicker->sector = &sectors[(int)flicker->sector];
872 flicker->thinker.function = T_FireFlicker;
873 P_AddThinker (&flicker->thinker);
874 break;
875 }
876
877 //jff 2/22/98 new case for elevators
878 case tc_elevator:
879 PADSAVEP();
880 {
881 elevator_t *elevator = Z_Malloc (sizeof(*elevator), PU_LEVEL, NULL);
882 memcpy (elevator, save_p, sizeof(*elevator));
883 save_p += sizeof(*elevator);
884 elevator->sector = &sectors[(int)elevator->sector];
885 elevator->sector->floordata = elevator; //jff 2/22/98
886 elevator->sector->ceilingdata = elevator; //jff 2/22/98
887 elevator->thinker.function = T_MoveElevator;
888 P_AddThinker (&elevator->thinker);
889 break;
890 }
891
892 case tc_scroll: // killough 3/7/98: scroll effect thinkers
893 {
894 scroll_t *scroll = Z_Malloc (sizeof(scroll_t), PU_LEVEL, NULL);
895 memcpy (scroll, save_p, sizeof(scroll_t));
896 save_p += sizeof(scroll_t);
897 scroll->thinker.function = T_Scroll;
898 P_AddThinker(&scroll->thinker);
899 break;
900 }
901
902 case tc_pusher: // phares 3/22/98: new Push/Pull effect thinkers
903 {
904 pusher_t *pusher = Z_Malloc (sizeof(pusher_t), PU_LEVEL, NULL);
905 memcpy (pusher, save_p, sizeof(pusher_t));
906 save_p += sizeof(pusher_t);
907 pusher->thinker.function = T_Pusher;
908 pusher->source = P_GetPushThing(pusher->affectee);
909 P_AddThinker(&pusher->thinker);
910 break;
911 }
912
913 default:
914 I_Error("P_UnarchiveSpecials: Unknown tclass %i in savegame", tclass);
915 }
916}
917
918// killough 2/16/98: save/restore random number generator state information
919
920void P_ArchiveRNG(void)
921{
922 CheckSaveGame(sizeof rng);
923 memcpy(save_p, &rng, sizeof rng);
924 save_p += sizeof rng;
925}
926
927void P_UnArchiveRNG(void)
928{
929 memcpy(&rng, save_p, sizeof rng);
930 save_p += sizeof rng;
931}
932
933// killough 2/22/98: Save/restore automap state
934// killough 2/22/98: Save/restore automap state
935void P_ArchiveMap(void)
936{
937 int zero = 0, one = 1;
938 CheckSaveGame(2 * sizeof zero + sizeof markpointnum +
939 markpointnum * sizeof *markpoints +
940 sizeof automapmode + sizeof one);
941
942 memcpy(save_p, &automapmode, sizeof automapmode);
943 save_p += sizeof automapmode;
944 memcpy(save_p, &one, sizeof one); // CPhipps - used to be viewactive, now
945 save_p += sizeof one; // that's worked out locally by D_Display
946 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be followplayer
947 save_p += sizeof zero; // that is now part of automapmode
948 memcpy(save_p, &zero, sizeof zero); // CPhipps - used to be automap_grid, ditto
949 save_p += sizeof zero;
950 memcpy(save_p, &markpointnum, sizeof markpointnum);
951 save_p += sizeof markpointnum;
952
953 if (markpointnum)
954 {
955 memcpy(save_p, markpoints, sizeof *markpoints * markpointnum);
956 save_p += markpointnum * sizeof *markpoints;
957 }
958}
959
960void P_UnArchiveMap(void)
961{
962 int unused;
963 memcpy(&automapmode, save_p, sizeof automapmode);
964 save_p += sizeof automapmode;
965 memcpy(&unused, save_p, sizeof unused);
966 save_p += sizeof unused;
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
972 if (automapmode & am_active)
973 AM_Start();
974
975 memcpy(&markpointnum, save_p, sizeof markpointnum);
976 save_p += sizeof markpointnum;
977
978 if (markpointnum)
979 {
980 while (markpointnum >= markpointnum_max)
981 markpoints = realloc(markpoints, sizeof *markpoints *
982 (markpointnum_max = markpointnum_max ? markpointnum_max*2 : 16));
983 memcpy(markpoints, save_p, markpointnum * sizeof *markpoints);
984 save_p += markpointnum * sizeof *markpoints;
985 }
986}
987