// Emacs style mode select -*- C++ -*- //----------------------------------------------------------------------------- // // $Id: p_saveg.c 300 2006-01-19 18:46:24Z fraggle $ // // Copyright(C) 1993-1996 Id Software, Inc. // Copyright(C) 2005 Simon Howard // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // 02111-1307, USA. // // $Log$ // Revision 1.7 2006/01/19 18:46:24 fraggle // Move savegame header read/write code into p_saveg.c // // Revision 1.6 2006/01/19 00:17:01 fraggle // Remove now-redundant note about structure packing. // // Revision 1.5 2006/01/19 00:09:20 fraggle // Add functions to r/w structures to the savegame buffer, rather than // copying the raw structures. This way, we read and write to the DOS // savegame format always, regardless of the compiler and processor // architecture, to ensure Vanilla compatibility. // // Revision 1.4 2006/01/16 21:40:38 fraggle // Vanilla savegame load/save // // Revision 1.3 2005/10/16 01:18:10 fraggle // Global "configdir" variable with directory to store config files in. // Create a function to find the filename for a savegame slot. Store // savegames in the config dir. // // Revision 1.2 2005/07/23 16:44:56 fraggle // Update copyright to GNU GPL // // Revision 1.1.1.1 2005/07/23 16:20:39 fraggle // Initial import // // // DESCRIPTION: // Archiving: SaveGame I/O. // //----------------------------------------------------------------------------- static const char rcsid[] = "$Id: p_saveg.c 300 2006-01-19 18:46:24Z fraggle $"; #include "dstrings.h" #include "deh_main.h" #include "i_system.h" #include "z_zone.h" #include "p_local.h" #include "p_saveg.h" // State. #include "doomstat.h" #include "r_state.h" #define SAVEGAME_EOF 0x1d #define VERSIONSIZE 16 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 char *P_SaveGameFile(int slot) { static char filename[256]; char basename[32]; sprintf(basename, DEH_String(SAVEGAMENAME "%d.dsg"), slot); sprintf(filename, "%s%s", configdir, basename); return filename; } // Endian-safe integer read/write functions static byte saveg_read8(void) { int result; result = *save_p; save_p += 1; return result; } static void saveg_write8(byte value) { *save_p = value; save_p += 1; } static short saveg_read16(void) { int result; result = save_p[0] | (save_p[1] << 8); save_p += 2; return result; } static void saveg_write16(short value) { save_p[0] = value & 0xff; save_p[1] = (value >> 8) & 0xff; save_p += 2; } static int saveg_read32(void) { int result; result = save_p[0] | (save_p[1] << 8) | (save_p[2] << 16) | (save_p[3] << 24); save_p += 4; return result; } static void saveg_write32(int value) { save_p[0] = value & 0xff; save_p[1] = (value >> 8) & 0xff; save_p[2] = (value >> 16) & 0xff; save_p[3] = (value >> 24) & 0xff; save_p += 4; } // Pointers static void *saveg_readp(void) { return (void *) saveg_read32(); } static void saveg_writep(void *p) { saveg_write32((int) p); } // Enum values are 32-bit integers. #define saveg_read_enum saveg_read32 #define saveg_write_enum saveg_write32 // // Structure read/write functions // // // mapthing_t // static void saveg_read_mapthing_t(mapthing_t *str) { // short x; str->x = saveg_read16(); // short y; str->y = saveg_read16(); // short angle; str->angle = saveg_read16(); // short type; str->type = saveg_read16(); // short options; str->options = saveg_read16(); } static void saveg_write_mapthing_t(mapthing_t *str) { // short x; saveg_write16(str->x); // short y; saveg_write16(str->y); // short angle; saveg_write16(str->angle); // short type; saveg_write16(str->type); // short options; saveg_write16(str->options); } // // actionf_t // static void saveg_read_actionf_t(actionf_t *str) { // actionf_p1 acp1; str->acp1 = saveg_readp(); } static void saveg_write_actionf_t(actionf_t *str) { // actionf_p1 acp1; saveg_writep(str->acp1); } // // think_t // // This is just an actionf_t. // #define saveg_read_think_t saveg_read_actionf_t #define saveg_write_think_t saveg_write_actionf_t // // thinker_t // static void saveg_read_thinker_t(thinker_t *str) { // struct thinker_s* prev; str->prev = saveg_readp(); // struct thinker_s* next; str->next = saveg_readp(); // think_t function; saveg_read_think_t(&str->function); } static void saveg_write_thinker_t(thinker_t *str) { // struct thinker_s* prev; saveg_writep(str->prev); // struct thinker_s* next; saveg_writep(str->next); // think_t function; saveg_write_think_t(&str->function); } // // mobj_t // static void saveg_read_mobj_t(mobj_t *str) { int pl; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // fixed_t x; str->x = saveg_read32(); // fixed_t y; str->y = saveg_read32(); // fixed_t z; str->z = saveg_read32(); // struct mobj_s* snext; str->snext = saveg_readp(); // struct mobj_s* sprev; str->sprev = saveg_readp(); // angle_t angle; str->angle = saveg_read32(); // spritenum_t sprite; str->sprite = saveg_read_enum(); // int frame; str->frame = saveg_read32(); // struct mobj_s* bnext; str->bnext = saveg_readp(); // struct mobj_s* bprev; str->bprev = saveg_readp(); // struct subsector_s* subsector; str->subsector = saveg_readp(); // fixed_t floorz; str->floorz = saveg_read32(); // fixed_t ceilingz; str->ceilingz = saveg_read32(); // fixed_t radius; str->radius = saveg_read32(); // fixed_t height; str->height = saveg_read32(); // fixed_t momx; str->momx = saveg_read32(); // fixed_t momy; str->momy = saveg_read32(); // fixed_t momz; str->momz = saveg_read32(); // int validcount; str->validcount = saveg_read32(); // mobjtype_t type; str->type = saveg_read_enum(); // mobjinfo_t* info; str->info = saveg_readp(); // int tics; str->tics = saveg_read32(); // state_t* state; str->state = &states[saveg_read32()]; // int flags; str->flags = saveg_read32(); // int health; str->health = saveg_read32(); // int movedir; str->movedir = saveg_read32(); // int movecount; str->movecount = saveg_read32(); // struct mobj_s* target; str->target = saveg_readp(); // int reactiontime; str->reactiontime = saveg_read32(); // int threshold; str->threshold = saveg_read32(); // struct player_s* player; pl = saveg_read32(); if (pl > 0) { str->player = &players[pl - 1]; str->player->mo = str; } else { str->player = NULL; } // int lastlook; str->lastlook = saveg_read32(); // mapthing_t spawnpoint; saveg_read_mapthing_t(&str->spawnpoint); // struct mobj_s* tracer; str->tracer = saveg_readp(); } static void saveg_write_mobj_t(mobj_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // fixed_t x; saveg_write32(str->x); // fixed_t y; saveg_write32(str->y); // fixed_t z; saveg_write32(str->z); // struct mobj_s* snext; saveg_writep(str->snext); // struct mobj_s* sprev; saveg_writep(str->sprev); // angle_t angle; saveg_write32(str->angle); // spritenum_t sprite; saveg_write_enum(str->sprite); // int frame; saveg_write32(str->frame); // struct mobj_s* bnext; saveg_writep(str->bnext); // struct mobj_s* bprev; saveg_writep(str->bprev); // struct subsector_s* subsector; saveg_writep(str->subsector); // fixed_t floorz; saveg_write32(str->floorz); // fixed_t ceilingz; saveg_write32(str->ceilingz); // fixed_t radius; saveg_write32(str->radius); // fixed_t height; saveg_write32(str->height); // fixed_t momx; saveg_write32(str->momx); // fixed_t momy; saveg_write32(str->momy); // fixed_t momz; saveg_write32(str->momz); // int validcount; saveg_write32(str->validcount); // mobjtype_t type; saveg_write_enum(str->type); // mobjinfo_t* info; saveg_writep(str->info); // int tics; saveg_write32(str->tics); // state_t* state; saveg_write32(str->state - states); // int flags; saveg_write32(str->flags); // int health; saveg_write32(str->health); // int movedir; saveg_write32(str->movedir); // int movecount; saveg_write32(str->movecount); // struct mobj_s* target; saveg_writep(str->target); // int reactiontime; saveg_write32(str->reactiontime); // int threshold; saveg_write32(str->threshold); // struct player_s* player; if (str->player) { saveg_write32(str->player - players + 1); } else { saveg_write32(0); } // int lastlook; saveg_write32(str->lastlook); // mapthing_t spawnpoint; saveg_write_mapthing_t(&str->spawnpoint); // struct mobj_s* tracer; saveg_writep(str->tracer); } // // ticcmd_t // static void saveg_read_ticcmd_t(ticcmd_t *str) { // signed char forwardmove; str->forwardmove = saveg_read8(); // signed char sidemove; str->sidemove = saveg_read8(); // short angleturn; str->angleturn = saveg_read16(); // short consistancy; str->consistancy = saveg_read16(); // byte chatchar; str->chatchar = saveg_read8(); // byte buttons; str->buttons = saveg_read8(); } static void saveg_write_ticcmd_t(ticcmd_t *str) { // signed char forwardmove; saveg_write8(str->forwardmove); // signed char sidemove; saveg_write8(str->sidemove); // short angleturn; saveg_write16(str->angleturn); // short consistancy; saveg_write16(str->consistancy); // byte chatchar; saveg_write8(str->chatchar); // byte buttons; saveg_write8(str->buttons); } // // pspdef_t // static void saveg_read_pspdef_t(pspdef_t *str) { int state; // state_t* state; state = saveg_read32(); if (state > 0) { str->state = &states[state]; } else { str->state = NULL; } // int tics; str->tics = saveg_read32(); // fixed_t sx; str->sx = saveg_read32(); // fixed_t sy; str->sy = saveg_read32(); } static void saveg_write_pspdef_t(pspdef_t *str) { // state_t* state; if (str->state) { saveg_write32(str->state - states); } else { saveg_write32(0); } // int tics; saveg_write32(str->tics); // fixed_t sx; saveg_write32(str->sx); // fixed_t sy; saveg_write32(str->sy); } // // player_t // static void saveg_read_player_t(player_t *str) { int i; // mobj_t* mo; str->mo = saveg_readp(); // playerstate_t playerstate; str->playerstate = saveg_read_enum(); // ticcmd_t cmd; saveg_read_ticcmd_t(&str->cmd); // fixed_t viewz; str->viewz = saveg_read32(); // fixed_t viewheight; str->viewheight = saveg_read32(); // fixed_t deltaviewheight; str->deltaviewheight = saveg_read32(); // fixed_t bob; str->bob = saveg_read32(); // int health; str->health = saveg_read32(); // int armorpoints; str->armorpoints = saveg_read32(); // int armortype; str->armortype = saveg_read32(); // int powers[NUMPOWERS]; for (i=0; ipowers[i] = saveg_read32(); } // boolean cards[NUMCARDS]; for (i=0; icards[i] = saveg_read32(); } // boolean backpack; str->backpack = saveg_read32(); // int frags[MAXPLAYERS]; for (i=0; ifrags[i] = saveg_read32(); } // weapontype_t readyweapon; str->readyweapon = saveg_read_enum(); // weapontype_t pendingweapon; str->pendingweapon = saveg_read_enum(); // boolean weaponowned[NUMWEAPONS]; for (i=0; iweaponowned[i] = saveg_read32(); } // int ammo[NUMAMMO]; for (i=0; iammo[i] = saveg_read32(); } // int maxammo[NUMAMMO]; for (i=0; imaxammo[i] = saveg_read32(); } // int attackdown; str->attackdown = saveg_read32(); // int usedown; str->usedown = saveg_read32(); // int cheats; str->cheats = saveg_read32(); // int refire; str->refire = saveg_read32(); // int killcount; str->killcount = saveg_read32(); // int itemcount; str->itemcount = saveg_read32(); // int secretcount; str->secretcount = saveg_read32(); // char* message; str->message = saveg_readp(); // int damagecount; str->damagecount = saveg_read32(); // int bonuscount; str->bonuscount = saveg_read32(); // mobj_t* attacker; str->attacker = saveg_readp(); // int extralight; str->extralight = saveg_read32(); // int fixedcolormap; str->fixedcolormap = saveg_read32(); // int colormap; str->colormap = saveg_read32(); // pspdef_t psprites[NUMPSPRITES]; for (i=0; ipsprites[i]); } // boolean didsecret; str->didsecret = saveg_read32(); } static void saveg_write_player_t(player_t *str) { int i; // mobj_t* mo; saveg_writep(str->mo); // playerstate_t playerstate; saveg_write_enum(str->playerstate); // ticcmd_t cmd; saveg_write_ticcmd_t(&str->cmd); // fixed_t viewz; saveg_write32(str->viewz); // fixed_t viewheight; saveg_write32(str->viewheight); // fixed_t deltaviewheight; saveg_write32(str->deltaviewheight); // fixed_t bob; saveg_write32(str->bob); // int health; saveg_write32(str->health); // int armorpoints; saveg_write32(str->armorpoints); // int armortype; saveg_write32(str->armortype); // int powers[NUMPOWERS]; for (i=0; ipowers[i]); } // boolean cards[NUMCARDS]; for (i=0; icards[i]); } // boolean backpack; saveg_write32(str->backpack); // int frags[MAXPLAYERS]; for (i=0; ifrags[i]); } // weapontype_t readyweapon; saveg_write_enum(str->readyweapon); // weapontype_t pendingweapon; saveg_write_enum(str->pendingweapon); // boolean weaponowned[NUMWEAPONS]; for (i=0; iweaponowned[i]); } // int ammo[NUMAMMO]; for (i=0; iammo[i]); } // int maxammo[NUMAMMO]; for (i=0; imaxammo[i]); } // int attackdown; saveg_write32(str->attackdown); // int usedown; saveg_write32(str->usedown); // int cheats; saveg_write32(str->cheats); // int refire; saveg_write32(str->refire); // int killcount; saveg_write32(str->killcount); // int itemcount; saveg_write32(str->itemcount); // int secretcount; saveg_write32(str->secretcount); // char* message; saveg_writep(str->message); // int damagecount; saveg_write32(str->damagecount); // int bonuscount; saveg_write32(str->bonuscount); // mobj_t* attacker; saveg_writep(str->attacker); // int extralight; saveg_write32(str->extralight); // int fixedcolormap; saveg_write32(str->fixedcolormap); // int colormap; saveg_write32(str->colormap); // pspdef_t psprites[NUMPSPRITES]; for (i=0; ipsprites[i]); } // boolean didsecret; saveg_write32(str->didsecret); } // // ceiling_t // static void saveg_read_ceiling_t(ceiling_t *str) { int sector; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // ceiling_e type; str->type = saveg_read_enum(); // sector_t* sector; sector = saveg_read32(); str->sector = §ors[sector]; // fixed_t bottomheight; str->bottomheight = saveg_read32(); // fixed_t topheight; str->topheight = saveg_read32(); // fixed_t speed; str->speed = saveg_read32(); // boolean crush; str->crush = saveg_read32(); // int direction; str->direction = saveg_read32(); // int tag; str->tag = saveg_read32(); // int olddirection; str->olddirection = saveg_read32(); } static void saveg_write_ceiling_t(ceiling_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // ceiling_e type; saveg_write_enum(str->type); // sector_t* sector; saveg_write32(str->sector - sectors); // fixed_t bottomheight; saveg_write32(str->bottomheight); // fixed_t topheight; saveg_write32(str->topheight); // fixed_t speed; saveg_write32(str->speed); // boolean crush; saveg_write32(str->crush); // int direction; saveg_write32(str->direction); // int tag; saveg_write32(str->tag); // int olddirection; saveg_write32(str->olddirection); } // // vldoor_t // static void saveg_read_vldoor_t(vldoor_t *str) { int sector; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // vldoor_e type; str->type = saveg_read_enum(); // sector_t* sector; sector = saveg_read32(); str->sector = §ors[sector]; // fixed_t topheight; str->topheight = saveg_read32(); // fixed_t speed; str->speed = saveg_read32(); // int direction; str->direction = saveg_read32(); // int topwait; str->topwait = saveg_read32(); // int topcountdown; str->topcountdown = saveg_read32(); } static void saveg_write_vldoor_t(vldoor_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // vldoor_e type; saveg_write_enum(str->type); // sector_t* sector; saveg_write32(str->sector - sectors); // fixed_t topheight; saveg_write32(str->topheight); // fixed_t speed; saveg_write32(str->speed); // int direction; saveg_write32(str->direction); // int topwait; saveg_write32(str->topwait); // int topcountdown; saveg_write32(str->topcountdown); } // // floormove_t // static void saveg_read_floormove_t(floormove_t *str) { int sector; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // floor_e type; str->type = saveg_read_enum(); // boolean crush; str->crush = saveg_read32(); // sector_t* sector; sector = saveg_read32(); str->sector = §ors[sector]; // int direction; str->direction = saveg_read32(); // int newspecial; str->newspecial = saveg_read32(); // short texture; str->texture = saveg_read16(); // fixed_t floordestheight; str->floordestheight = saveg_read32(); // fixed_t speed; str->speed = saveg_read32(); } static void saveg_write_floormove_t(floormove_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // floor_e type; saveg_write_enum(str->type); // boolean crush; saveg_write32(str->crush); // sector_t* sector; saveg_write32(str->sector - sectors); // int direction; saveg_write32(str->direction); // int newspecial; saveg_write32(str->newspecial); // short texture; saveg_write16(str->texture); // fixed_t floordestheight; saveg_write32(str->floordestheight); // fixed_t speed; saveg_write32(str->speed); } // // plat_t // static void saveg_read_plat_t(plat_t *str) { int sector; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // sector_t* sector; sector = saveg_read32(); str->sector = §ors[sector]; // fixed_t speed; str->speed = saveg_read32(); // fixed_t low; str->low = saveg_read32(); // fixed_t high; str->high = saveg_read32(); // int wait; str->wait = saveg_read32(); // int count; str->count = saveg_read32(); // plat_e status; str->status = saveg_read_enum(); // plat_e oldstatus; str->oldstatus = saveg_read_enum(); // boolean crush; str->crush = saveg_read32(); // int tag; str->tag = saveg_read32(); // plattype_e type; str->type = saveg_read_enum(); } static void saveg_write_plat_t(plat_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // sector_t* sector; saveg_write32(str->sector - sectors); // fixed_t speed; saveg_write32(str->speed); // fixed_t low; saveg_write32(str->low); // fixed_t high; saveg_write32(str->high); // int wait; saveg_write32(str->wait); // int count; saveg_write32(str->count); // plat_e status; saveg_write_enum(str->status); // plat_e oldstatus; saveg_write_enum(str->oldstatus); // boolean crush; saveg_write32(str->crush); // int tag; saveg_write32(str->tag); // plattype_e type; saveg_write_enum(str->type); } // // lightflash_t // static void saveg_read_lightflash_t(lightflash_t *str) { int sector; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // sector_t* sector; sector = saveg_read32(); str->sector = §ors[sector]; // int count; str->count = saveg_read32(); // int maxlight; str->maxlight = saveg_read32(); // int minlight; str->minlight = saveg_read32(); // int maxtime; str->maxtime = saveg_read32(); // int mintime; str->mintime = saveg_read32(); } static void saveg_write_lightflash_t(lightflash_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // sector_t* sector; saveg_write32(str->sector - sectors); // int count; saveg_write32(str->count); // int maxlight; saveg_write32(str->maxlight); // int minlight; saveg_write32(str->minlight); // int maxtime; saveg_write32(str->maxtime); // int mintime; saveg_write32(str->mintime); } // // strobe_t // static void saveg_read_strobe_t(strobe_t *str) { int sector; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // sector_t* sector; sector = saveg_read32(); str->sector = §ors[sector]; // int count; str->count = saveg_read32(); // int minlight; str->minlight = saveg_read32(); // int maxlight; str->maxlight = saveg_read32(); // int darktime; str->darktime = saveg_read32(); // int brighttime; str->brighttime = saveg_read32(); } static void saveg_write_strobe_t(strobe_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // sector_t* sector; saveg_write32(str->sector - sectors); // int count; saveg_write32(str->count); // int minlight; saveg_write32(str->minlight); // int maxlight; saveg_write32(str->maxlight); // int darktime; saveg_write32(str->darktime); // int brighttime; saveg_write32(str->brighttime); } // // glow_t // static void saveg_read_glow_t(glow_t *str) { int sector; // thinker_t thinker; saveg_read_thinker_t(&str->thinker); // sector_t* sector; sector = saveg_read32(); str->sector = §ors[sector]; // int minlight; str->minlight = saveg_read32(); // int maxlight; str->maxlight = saveg_read32(); // int direction; str->direction = saveg_read32(); } static void saveg_write_glow_t(glow_t *str) { // thinker_t thinker; saveg_write_thinker_t(&str->thinker); // sector_t* sector; saveg_write32(str->sector - sectors); // int minlight; saveg_write32(str->minlight); // int maxlight; saveg_write32(str->maxlight); // int direction; saveg_write32(str->direction); } // // Write the header for a savegame // void P_WriteSaveGameHeader(char *description) { char name[VERSIONSIZE]; int i; memcpy (save_p, description, SAVESTRINGSIZE); save_p += SAVESTRINGSIZE; memset (name,0,sizeof(name)); sprintf (name,"version %i",DOOM_VERSION); memcpy (save_p, name, VERSIONSIZE); save_p += VERSIONSIZE; saveg_write8(gameskill); saveg_write8(gameepisode); saveg_write8(gamemap); for (i=0 ; i> 16) & 0xff); saveg_write8((leveltime >> 8) & 0xff); saveg_write8(leveltime & 0xff); } // // Read the header for a savegame // boolean P_ReadSaveGameHeader(void) { int i; byte a, b, c; char vcheck[VERSIONSIZE]; save_p += SAVESTRINGSIZE; // skip the description field memset (vcheck,0,sizeof(vcheck)); sprintf (vcheck,"version %i",DOOM_VERSION); if (strcmp ((char *) save_p, vcheck)) return false; // bad version save_p += VERSIONSIZE; gameskill = saveg_read8(); gameepisode = saveg_read8(); gamemap = saveg_read8(); for (i=0 ; ifloorheight >> FRACBITS); saveg_write16(sec->ceilingheight >> FRACBITS); saveg_write16(sec->floorpic); saveg_write16(sec->ceilingpic); saveg_write16(sec->lightlevel); saveg_write16(sec->special); // needed? saveg_write16(sec->tag); // needed? } // do lines for (i=0, li = lines ; iflags); saveg_write16(li->special); saveg_write16(li->tag); for (j=0 ; j<2 ; j++) { if (li->sidenum[j] == -1) continue; si = &sides[li->sidenum[j]]; saveg_write16(si->textureoffset >> FRACBITS); saveg_write16(si->rowoffset >> FRACBITS); saveg_write16(si->toptexture); saveg_write16(si->bottomtexture); saveg_write16(si->midtexture); } } } // // P_UnArchiveWorld // void P_UnArchiveWorld (void) { int i; int j; sector_t* sec; line_t* li; side_t* si; // do sectors for (i=0, sec = sectors ; ifloorheight = saveg_read16() << FRACBITS; sec->ceilingheight = saveg_read16() << FRACBITS; sec->floorpic = saveg_read16(); sec->ceilingpic = saveg_read16(); sec->lightlevel = saveg_read16(); sec->special = saveg_read16(); // needed? sec->tag = saveg_read16(); // needed? sec->specialdata = 0; sec->soundtarget = 0; } // do lines for (i=0, li = lines ; iflags = saveg_read16(); li->special = saveg_read16(); li->tag = saveg_read16(); for (j=0 ; j<2 ; j++) { if (li->sidenum[j] == -1) continue; si = &sides[li->sidenum[j]]; si->textureoffset = saveg_read16() << FRACBITS; si->rowoffset = saveg_read16() << FRACBITS; si->toptexture = saveg_read16(); si->bottomtexture = saveg_read16(); si->midtexture = saveg_read16(); } } } // // Thinkers // typedef enum { tc_end, tc_mobj } thinkerclass_t; // // P_ArchiveThinkers // void P_ArchiveThinkers (void) { thinker_t* th; // save off the current thinkers for (th = thinkercap.next ; th != &thinkercap ; th=th->next) { if (th->function.acp1 == (actionf_p1)P_MobjThinker) { saveg_write8(tc_mobj); PADSAVEP(); saveg_write_mobj_t((mobj_t *) th); continue; } // I_Error ("P_ArchiveThinkers: Unknown thinker function"); } // add a terminating marker saveg_write8(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 = saveg_read8(); switch (tclass) { case tc_end: return; // end of list case tc_mobj: PADSAVEP(); mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); saveg_read_mobj_t(mobj); mobj->target = NULL; 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; 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 (ifunction.acp1 == (actionf_p1)T_MoveCeiling) { saveg_write8(tc_ceiling); PADSAVEP(); saveg_write_ceiling_t((ceiling_t *) th); continue; } if (th->function.acp1 == (actionf_p1)T_VerticalDoor) { saveg_write8(tc_door); PADSAVEP(); saveg_write_vldoor_t((vldoor_t *) th); continue; } if (th->function.acp1 == (actionf_p1)T_MoveFloor) { saveg_write8(tc_floor); PADSAVEP(); saveg_write_floormove_t((floormove_t *) th); continue; } if (th->function.acp1 == (actionf_p1)T_PlatRaise) { saveg_write8(tc_plat); PADSAVEP(); saveg_write_plat_t((plat_t *) th); continue; } if (th->function.acp1 == (actionf_p1)T_LightFlash) { saveg_write8(tc_flash); PADSAVEP(); saveg_write_lightflash_t((lightflash_t *) th); continue; } if (th->function.acp1 == (actionf_p1)T_StrobeFlash) { saveg_write8(tc_strobe); PADSAVEP(); saveg_write_strobe_t((strobe_t *) th); continue; } if (th->function.acp1 == (actionf_p1)T_Glow) { saveg_write8(tc_glow); PADSAVEP(); saveg_write_glow_t((glow_t *) th); continue; } } // add a terminating marker saveg_write8(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 = saveg_read8(); switch (tclass) { case tc_endspecials: return; // end of list case tc_ceiling: PADSAVEP(); ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVEL, NULL); saveg_read_ceiling_t(ceiling); 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); saveg_read_vldoor_t(door); 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); saveg_read_floormove_t(floor); 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); saveg_read_plat_t(plat); 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); saveg_read_lightflash_t(flash); 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); saveg_read_strobe_t(strobe); 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); saveg_read_glow_t(glow); glow->thinker.function.acp1 = (actionf_p1)T_Glow; P_AddThinker (&glow->thinker); break; default: I_Error ("P_UnarchiveSpecials:Unknown tclass %i " "in savegame",tclass); } } }