summaryrefslogtreecommitdiff
path: root/src/p_saveg.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/p_saveg.c')
-rw-r--r--src/p_saveg.c589
1 files changed, 589 insertions, 0 deletions
diff --git a/src/p_saveg.c b/src/p_saveg.c
new file mode 100644
index 00000000..bb550b5e
--- /dev/null
+++ b/src/p_saveg.c
@@ -0,0 +1,589 @@
+// Emacs style mode select -*- C++ -*-
+//-----------------------------------------------------------------------------
+//
+// $Id: p_saveg.c 4 2005-07-23 16:19:41Z fraggle $
+//
+// Copyright (C) 1993-1996 by id Software, Inc.
+//
+// This source is available for distribution and/or modification
+// only under the terms of the DOOM Source Code License as
+// published by id Software. All rights reserved.
+//
+// The source is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License
+// for more details.
+//
+// $Log$
+// Revision 1.1 2005/07/23 16:20:39 fraggle
+// Initial revision
+//
+//
+// DESCRIPTION:
+// Archiving: SaveGame I/O.
+//
+//-----------------------------------------------------------------------------
+
+static const char
+rcsid[] = "$Id: p_saveg.c 4 2005-07-23 16:19:41Z fraggle $";
+
+#include "i_system.h"
+#include "z_zone.h"
+#include "p_local.h"
+
+// State.
+#include "doomstat.h"
+#include "r_state.h"
+
+byte* save_p;
+
+
+// Pads save_p to a 4-byte boundary
+// so that the load/save works on SGI&Gecko.
+#define PADSAVEP() save_p += (4 - ((int) save_p & 3)) & 3
+
+
+
+//
+// P_ArchivePlayers
+//
+void P_ArchivePlayers (void)
+{
+ int i;
+ int j;
+ player_t* dest;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ PADSAVEP();
+
+ dest = (player_t *)save_p;
+ memcpy (dest,&players[i],sizeof(player_t));
+ save_p += sizeof(player_t);
+ for (j=0 ; j<NUMPSPRITES ; j++)
+ {
+ if (dest->psprites[j].state)
+ {
+ dest->psprites[j].state
+ = (state_t *)(dest->psprites[j].state-states);
+ }
+ }
+ }
+}
+
+
+
+//
+// P_UnArchivePlayers
+//
+void P_UnArchivePlayers (void)
+{
+ int i;
+ int j;
+
+ for (i=0 ; i<MAXPLAYERS ; i++)
+ {
+ if (!playeringame[i])
+ continue;
+
+ PADSAVEP();
+
+ memcpy (&players[i],save_p, sizeof(player_t));
+ save_p += sizeof(player_t);
+
+ // will be set when unarc thinker
+ players[i].mo = NULL;
+ players[i].message = NULL;
+ players[i].attacker = NULL;
+
+ for (j=0 ; j<NUMPSPRITES ; j++)
+ {
+ if (players[i]. psprites[j].state)
+ {
+ players[i]. psprites[j].state
+ = &states[ (int)players[i].psprites[j].state ];
+ }
+ }
+ }
+}
+
+
+//
+// P_ArchiveWorld
+//
+void P_ArchiveWorld (void)
+{
+ int i;
+ int j;
+ sector_t* sec;
+ line_t* li;
+ side_t* si;
+ short* put;
+
+ put = (short *)save_p;
+
+ // do sectors
+ for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
+ {
+ *put++ = sec->floorheight >> FRACBITS;
+ *put++ = sec->ceilingheight >> FRACBITS;
+ *put++ = sec->floorpic;
+ *put++ = sec->ceilingpic;
+ *put++ = sec->lightlevel;
+ *put++ = sec->special; // needed?
+ *put++ = sec->tag; // needed?
+ }
+
+
+ // do lines
+ for (i=0, li = lines ; i<numlines ; i++,li++)
+ {
+ *put++ = li->flags;
+ *put++ = li->special;
+ *put++ = li->tag;
+ for (j=0 ; j<2 ; j++)
+ {
+ if (li->sidenum[j] == -1)
+ continue;
+
+ si = &sides[li->sidenum[j]];
+
+ *put++ = si->textureoffset >> FRACBITS;
+ *put++ = si->rowoffset >> FRACBITS;
+ *put++ = si->toptexture;
+ *put++ = si->bottomtexture;
+ *put++ = si->midtexture;
+ }
+ }
+
+ save_p = (byte *)put;
+}
+
+
+
+//
+// P_UnArchiveWorld
+//
+void P_UnArchiveWorld (void)
+{
+ int i;
+ int j;
+ sector_t* sec;
+ line_t* li;
+ side_t* si;
+ short* get;
+
+ get = (short *)save_p;
+
+ // do sectors
+ for (i=0, sec = sectors ; i<numsectors ; i++,sec++)
+ {
+ sec->floorheight = *get++ << FRACBITS;
+ sec->ceilingheight = *get++ << FRACBITS;
+ sec->floorpic = *get++;
+ sec->ceilingpic = *get++;
+ sec->lightlevel = *get++;
+ sec->special = *get++; // needed?
+ sec->tag = *get++; // needed?
+ sec->specialdata = 0;
+ sec->soundtarget = 0;
+ }
+
+ // do lines
+ for (i=0, li = lines ; i<numlines ; i++,li++)
+ {
+ li->flags = *get++;
+ li->special = *get++;
+ li->tag = *get++;
+ for (j=0 ; j<2 ; j++)
+ {
+ if (li->sidenum[j] == -1)
+ continue;
+ si = &sides[li->sidenum[j]];
+ si->textureoffset = *get++ << FRACBITS;
+ si->rowoffset = *get++ << FRACBITS;
+ si->toptexture = *get++;
+ si->bottomtexture = *get++;
+ si->midtexture = *get++;
+ }
+ }
+ save_p = (byte *)get;
+}
+
+
+
+
+
+//
+// Thinkers
+//
+typedef enum
+{
+ tc_end,
+ tc_mobj
+
+} thinkerclass_t;
+
+
+
+//
+// P_ArchiveThinkers
+//
+void P_ArchiveThinkers (void)
+{
+ thinker_t* th;
+ mobj_t* mobj;
+
+ // save off the current thinkers
+ for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
+ {
+ if (th->function.acp1 == (actionf_p1)P_MobjThinker)
+ {
+ *save_p++ = tc_mobj;
+ PADSAVEP();
+ mobj = (mobj_t *)save_p;
+ memcpy (mobj, th, sizeof(*mobj));
+ save_p += sizeof(*mobj);
+ mobj->state = (state_t *)(mobj->state - states);
+
+ if (mobj->player)
+ mobj->player = (player_t *)((mobj->player-players) + 1);
+ continue;
+ }
+
+ // I_Error ("P_ArchiveThinkers: Unknown thinker function");
+ }
+
+ // add a terminating marker
+ *save_p++ = tc_end;
+}
+
+
+
+//
+// P_UnArchiveThinkers
+//
+void P_UnArchiveThinkers (void)
+{
+ byte tclass;
+ thinker_t* currentthinker;
+ thinker_t* next;
+ mobj_t* mobj;
+
+ // remove all the current thinkers
+ currentthinker = thinkercap.next;
+ while (currentthinker != &thinkercap)
+ {
+ next = currentthinker->next;
+
+ if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
+ P_RemoveMobj ((mobj_t *)currentthinker);
+ else
+ Z_Free (currentthinker);
+
+ currentthinker = next;
+ }
+ P_InitThinkers ();
+
+ // read in saved thinkers
+ while (1)
+ {
+ tclass = *save_p++;
+ switch (tclass)
+ {
+ case tc_end:
+ return; // end of list
+
+ case tc_mobj:
+ PADSAVEP();
+ mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL);
+ memcpy (mobj, save_p, sizeof(*mobj));
+ save_p += sizeof(*mobj);
+ mobj->state = &states[(int)mobj->state];
+ mobj->target = NULL;
+ if (mobj->player)
+ {
+ mobj->player = &players[(int)mobj->player-1];
+ mobj->player->mo = mobj;
+ }
+ P_SetThingPosition (mobj);
+ mobj->info = &mobjinfo[mobj->type];
+ mobj->floorz = mobj->subsector->sector->floorheight;
+ mobj->ceilingz = mobj->subsector->sector->ceilingheight;
+ mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
+ P_AddThinker (&mobj->thinker);
+ break;
+
+ default:
+ I_Error ("Unknown tclass %i in savegame",tclass);
+ }
+
+ }
+
+}
+
+
+//
+// P_ArchiveSpecials
+//
+enum
+{
+ tc_ceiling,
+ tc_door,
+ tc_floor,
+ tc_plat,
+ tc_flash,
+ tc_strobe,
+ tc_glow,
+ tc_endspecials
+
+} specials_e;
+
+
+
+//
+// Things to handle:
+//
+// T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
+// T_VerticalDoor, (vldoor_t: sector_t * swizzle),
+// T_MoveFloor, (floormove_t: sector_t * swizzle),
+// T_LightFlash, (lightflash_t: sector_t * swizzle),
+// T_StrobeFlash, (strobe_t: sector_t *),
+// T_Glow, (glow_t: sector_t *),
+// T_PlatRaise, (plat_t: sector_t *), - active list
+//
+void P_ArchiveSpecials (void)
+{
+ thinker_t* th;
+ ceiling_t* ceiling;
+ vldoor_t* door;
+ floormove_t* floor;
+ plat_t* plat;
+ lightflash_t* flash;
+ strobe_t* strobe;
+ glow_t* glow;
+ int i;
+
+ // save off the current thinkers
+ for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
+ {
+ if (th->function.acv == (actionf_v)NULL)
+ {
+ for (i = 0; i < MAXCEILINGS;i++)
+ if (activeceilings[i] == (ceiling_t *)th)
+ break;
+
+ if (i<MAXCEILINGS)
+ {
+ *save_p++ = tc_ceiling;
+ PADSAVEP();
+ ceiling = (ceiling_t *)save_p;
+ memcpy (ceiling, th, sizeof(*ceiling));
+ save_p += sizeof(*ceiling);
+ ceiling->sector = (sector_t *)(ceiling->sector - sectors);
+ }
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
+ {
+ *save_p++ = tc_ceiling;
+ PADSAVEP();
+ ceiling = (ceiling_t *)save_p;
+ memcpy (ceiling, th, sizeof(*ceiling));
+ save_p += sizeof(*ceiling);
+ ceiling->sector = (sector_t *)(ceiling->sector - sectors);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_VerticalDoor)
+ {
+ *save_p++ = tc_door;
+ PADSAVEP();
+ door = (vldoor_t *)save_p;
+ memcpy (door, th, sizeof(*door));
+ save_p += sizeof(*door);
+ door->sector = (sector_t *)(door->sector - sectors);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_MoveFloor)
+ {
+ *save_p++ = tc_floor;
+ PADSAVEP();
+ floor = (floormove_t *)save_p;
+ memcpy (floor, th, sizeof(*floor));
+ save_p += sizeof(*floor);
+ floor->sector = (sector_t *)(floor->sector - sectors);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_PlatRaise)
+ {
+ *save_p++ = tc_plat;
+ PADSAVEP();
+ plat = (plat_t *)save_p;
+ memcpy (plat, th, sizeof(*plat));
+ save_p += sizeof(*plat);
+ plat->sector = (sector_t *)(plat->sector - sectors);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_LightFlash)
+ {
+ *save_p++ = tc_flash;
+ PADSAVEP();
+ flash = (lightflash_t *)save_p;
+ memcpy (flash, th, sizeof(*flash));
+ save_p += sizeof(*flash);
+ flash->sector = (sector_t *)(flash->sector - sectors);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
+ {
+ *save_p++ = tc_strobe;
+ PADSAVEP();
+ strobe = (strobe_t *)save_p;
+ memcpy (strobe, th, sizeof(*strobe));
+ save_p += sizeof(*strobe);
+ strobe->sector = (sector_t *)(strobe->sector - sectors);
+ continue;
+ }
+
+ if (th->function.acp1 == (actionf_p1)T_Glow)
+ {
+ *save_p++ = tc_glow;
+ PADSAVEP();
+ glow = (glow_t *)save_p;
+ memcpy (glow, th, sizeof(*glow));
+ save_p += sizeof(*glow);
+ glow->sector = (sector_t *)(glow->sector - sectors);
+ continue;
+ }
+ }
+
+ // add a terminating marker
+ *save_p++ = tc_endspecials;
+
+}
+
+
+//
+// P_UnArchiveSpecials
+//
+void P_UnArchiveSpecials (void)
+{
+ byte tclass;
+ ceiling_t* ceiling;
+ vldoor_t* door;
+ floormove_t* floor;
+ plat_t* plat;
+ lightflash_t* flash;
+ strobe_t* strobe;
+ glow_t* glow;
+
+
+ // read in saved thinkers
+ while (1)
+ {
+ tclass = *save_p++;
+ switch (tclass)
+ {
+ case tc_endspecials:
+ return; // end of list
+
+ case tc_ceiling:
+ PADSAVEP();
+ ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL);
+ memcpy (ceiling, save_p, sizeof(*ceiling));
+ save_p += sizeof(*ceiling);
+ ceiling->sector = &sectors[(int)ceiling->sector];
+ ceiling->sector->specialdata = ceiling;
+
+ if (ceiling->thinker.function.acp1)
+ ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
+
+ P_AddThinker (&ceiling->thinker);
+ P_AddActiveCeiling(ceiling);
+ break;
+
+ case tc_door:
+ PADSAVEP();
+ door = Z_Malloc (sizeof(*door), PU_LEVEL, NULL);
+ memcpy (door, save_p, sizeof(*door));
+ save_p += sizeof(*door);
+ door->sector = &sectors[(int)door->sector];
+ door->sector->specialdata = door;
+ door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
+ P_AddThinker (&door->thinker);
+ break;
+
+ case tc_floor:
+ PADSAVEP();
+ floor = Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
+ memcpy (floor, save_p, sizeof(*floor));
+ save_p += sizeof(*floor);
+ floor->sector = &sectors[(int)floor->sector];
+ floor->sector->specialdata = floor;
+ floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
+ P_AddThinker (&floor->thinker);
+ break;
+
+ case tc_plat:
+ PADSAVEP();
+ plat = Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
+ memcpy (plat, save_p, sizeof(*plat));
+ save_p += sizeof(*plat);
+ plat->sector = &sectors[(int)plat->sector];
+ plat->sector->specialdata = plat;
+
+ if (plat->thinker.function.acp1)
+ plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
+
+ P_AddThinker (&plat->thinker);
+ P_AddActivePlat(plat);
+ break;
+
+ case tc_flash:
+ PADSAVEP();
+ flash = Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
+ memcpy (flash, save_p, sizeof(*flash));
+ save_p += sizeof(*flash);
+ flash->sector = &sectors[(int)flash->sector];
+ flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
+ P_AddThinker (&flash->thinker);
+ break;
+
+ case tc_strobe:
+ PADSAVEP();
+ strobe = Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
+ memcpy (strobe, save_p, sizeof(*strobe));
+ save_p += sizeof(*strobe);
+ strobe->sector = &sectors[(int)strobe->sector];
+ strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
+ P_AddThinker (&strobe->thinker);
+ break;
+
+ case tc_glow:
+ PADSAVEP();
+ glow = Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
+ memcpy (glow, save_p, sizeof(*glow));
+ save_p += sizeof(*glow);
+ glow->sector = &sectors[(int)glow->sector];
+ glow->thinker.function.acp1 = (actionf_p1)T_Glow;
+ P_AddThinker (&glow->thinker);
+ break;
+
+ default:
+ I_Error ("P_UnarchiveSpecials:Unknown tclass %i "
+ "in savegame",tclass);
+ }
+
+ }
+
+}
+