v4k-git-backup/demos/ports/doom/src/p_saveg.c

585 lines
16 KiB
C

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// 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:$
//
// DESCRIPTION:
// Archiving: SaveGame I/O.
//
//-----------------------------------------------------------------------------
#include "doom_config.h"
#include "i_system.h"
#include "z_zone.h"
#include "p_local.h"
#include "doomstat.h" // State.
#include "r_state.h" // State.
// Pads save_p to a 4-byte boundary
// so that the load/save works on SGI&Gecko.
#define PADSAVEP() save_p += (4 - ((long long)save_p & 3)) & 3
byte* save_p;
// TODO: [pd] We are loading/saving raw pointers. It will not work with saves from 32bits system. We need to rewrite those functions.
//
// 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;
doom_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();
doom_memcpy(&players[i], save_p, sizeof(player_t));
save_p += sizeof(player_t);
// will be set when unarc thinker
players[i].mo = 0;
players[i].message = 0;
players[i].attacker = 0;
for (j = 0; j < NUMPSPRITES; j++)
{
if (players[i].psprites[j].state)
{
players[i].psprites[j].state
= &states[(long long)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;
doom_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, 0);
doom_memcpy(mobj, save_p, sizeof(*mobj));
save_p += sizeof(*mobj);
mobj->state = &states[(long long)mobj->state];
mobj->target = 0;
if (mobj->player)
{
mobj->player = &players[(long long)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("Error: Unknown tclass %i in savegame", tclass);
doom_strcpy(error_buf, "Error: Unknown tclass ");
doom_concat(error_buf, doom_itoa(tclass, 10));
doom_concat(error_buf, " in savegame");
I_Error(error_buf);
}
}
}
}
//
// 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)0)
{
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;
doom_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;
doom_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;
doom_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;
doom_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;
doom_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;
doom_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;
doom_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;
doom_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, 0);
doom_memcpy(ceiling, save_p, sizeof(*ceiling));
save_p += sizeof(*ceiling);
ceiling->sector = &sectors[(long long)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, 0);
doom_memcpy(door, save_p, sizeof(*door));
save_p += sizeof(*door);
door->sector = &sectors[(long long)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, 0);
doom_memcpy(floor, save_p, sizeof(*floor));
save_p += sizeof(*floor);
floor->sector = &sectors[(long long)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, 0);
doom_memcpy(plat, save_p, sizeof(*plat));
save_p += sizeof(*plat);
plat->sector = &sectors[(long long)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, 0);
doom_memcpy(flash, save_p, sizeof(*flash));
save_p += sizeof(*flash);
flash->sector = &sectors[(long long)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, 0);
doom_memcpy(strobe, save_p, sizeof(*strobe));
save_p += sizeof(*strobe);
strobe->sector = &sectors[(long long)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, 0);
doom_memcpy(glow, save_p, sizeof(*glow));
save_p += sizeof(*glow);
glow->sector = &sectors[(long long)glow->sector];
glow->thinker.function.acp1 = (actionf_p1)T_Glow;
P_AddThinker(&glow->thinker);
break;
default:
{
//I_Error("Error: P_UnarchiveSpecials:Unknown tclass %i "
// "in savegame", tclass);
doom_strcpy(error_buf, "Error: P_UnarchiveSpecials:Unknown tclass ");
doom_concat(error_buf, doom_itoa(tclass, 10));
doom_concat(error_buf, " in savegame");
I_Error(error_buf);
}
}
}
}