commit d7a54ff91636b507c115ba6bf48f57931b4d8407
Author: Simon Howard <fraggle@gmail.com>
AuthorDate: Sun Sep 1 21:58:11 2013 +0000
Commit: Simon Howard <fraggle@gmail.com>
CommitDate: Sun Sep 1 21:58:11 2013 +0000
Read/write thinker structures portably. Hexen savegames should now be
Vanilla compatible.
Subversion-branch: /branches/v2-branch
Subversion-revision: 2630
---
src/hexen/sv_save.c | 1429 +++++++++++++++++++++++++++++++++++++++------------
1 file changed, 1096 insertions(+), 333 deletions(-)
diff --git a/src/hexen/sv_save.c b/src/hexen/sv_save.c
index 855e793d..f81df46a 100644
--- a/src/hexen/sv_save.c
+++ b/src/hexen/sv_save.c
@@ -83,7 +83,8 @@ typedef struct
{
thinkClass_t tClass;
think_t thinkerFunc;
- void (*mangleFunc) ();
+ void (*writeFunc)();
+ void (*readFunc)();
void (*restoreFunc) ();
size_t size;
} thinkInfo_t;
@@ -122,11 +123,7 @@ static void SetMobjArchiveNums(void);
static void RemoveAllThinkers(void);
static int GetMobjNum(mobj_t * mobj);
static void SetMobjPtr(mobj_t **ptr, unsigned int archiveNum);
-static void MangleSSThinker(ssthinker_t * sst);
static void RestoreSSThinker(ssthinker_t * sst);
-static void RestoreSSThinkerNoSD(ssthinker_t * sst);
-static void MangleScript(acs_t * script);
-static void RestoreScript(acs_t * script);
static void RestorePlatRaise(plat_t * plat);
static void RestoreMoveCeiling(ceiling_t * ceiling);
static void AssertSegment(gameArchiveSegment_t segType);
@@ -166,96 +163,6 @@ static union
} SavePtr;
static FILE *SavingFP;
-// This list has been prioritized using frequency estimates
-static thinkInfo_t ThinkerInfo[] = {
- {
- TC_MOVE_FLOOR,
- T_MoveFloor,
- MangleSSThinker,
- RestoreSSThinker,
- sizeof(floormove_t)}
- ,
- {
- TC_PLAT_RAISE,
- T_PlatRaise,
- MangleSSThinker,
- RestorePlatRaise,
- sizeof(plat_t)}
- ,
- {
- TC_MOVE_CEILING,
- T_MoveCeiling,
- MangleSSThinker,
- RestoreMoveCeiling,
- sizeof(ceiling_t)}
- ,
- {
- TC_LIGHT,
- T_Light,
- MangleSSThinker,
- RestoreSSThinkerNoSD,
- sizeof(light_t)}
- ,
- {
- TC_VERTICAL_DOOR,
- T_VerticalDoor,
- MangleSSThinker,
- RestoreSSThinker,
- sizeof(vldoor_t)}
- ,
- {
- TC_PHASE,
- T_Phase,
- MangleSSThinker,
- RestoreSSThinkerNoSD,
- sizeof(phase_t)}
- ,
- {
- TC_INTERPRET_ACS,
- T_InterpretACS,
- MangleScript,
- RestoreScript,
- sizeof(acs_t)}
- ,
- {
- TC_ROTATE_POLY,
- T_RotatePoly,
- NULL,
- NULL,
- sizeof(polyevent_t)}
- ,
- {
- TC_BUILD_PILLAR,
- T_BuildPillar,
- MangleSSThinker,
- RestoreSSThinker,
- sizeof(pillar_t)}
- ,
- {
- TC_MOVE_POLY,
- T_MovePoly,
- NULL,
- NULL,
- sizeof(polyevent_t)}
- ,
- {
- TC_POLY_DOOR,
- T_PolyDoor,
- NULL,
- NULL,
- sizeof(polydoor_t)}
- ,
- {
- TC_FLOOR_WAGGLE,
- T_FloorWaggle,
- MangleSSThinker,
- RestoreSSThinker,
- sizeof(floorWaggle_t)}
- ,
- { // Terminator
- TC_NULL, NULL, NULL, NULL, 0}
-};
-
// CODE --------------------------------------------------------------------
// Autogenerated functions for reading/writing structs:
@@ -1208,236 +1115,1047 @@ static void StreamOut_mobj_t(mobj_t *str)
}
-
-//==========================================================================
//
-// SV_SaveGame
+// floormove_t
//
-//==========================================================================
-void SV_SaveGame(int slot, char *description)
+static void StreamIn_floormove_t(floormove_t *str)
{
- char fileName[100];
- char versionText[HXS_VERSION_TEXT_LENGTH];
- unsigned int i;
+ int i;
- // Open the output file
- sprintf(fileName, "%shex6.hxs", SavePath);
- OpenStreamOut(fileName);
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
- // Write game save description
- StreamOutBuffer(description, HXS_DESCRIPTION_LENGTH);
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = sectors + i;
- // Write version info
- memset(versionText, 0, HXS_VERSION_TEXT_LENGTH);
- strcpy(versionText, HXS_VERSION_TEXT);
- StreamOutBuffer(versionText, HXS_VERSION_TEXT_LENGTH);
+ // floor_e type;
+ str->type = GET_LONG;
- // Place a header marker
- StreamOutLong(ASEG_GAME_HEADER);
+ // int crush;
+ str->crush = GET_LONG;
- // Write current map and difficulty
- StreamOutByte(gamemap);
- StreamOutByte(gameskill);
+ // int direction;
+ str->direction = GET_LONG;
- // Write global script info
- for (i = 0; i < MAX_ACS_WORLD_VARS; ++i)
- {
- StreamOutLong(WorldVars[i]);
- }
+ // int newspecial;
+ str->newspecial = GET_LONG;
- for (i = 0; i < MAX_ACS_STORE + 1; ++i)
- {
- StreamOut_acsstore_t(&ACSStore[i]);
- }
+ // short texture;
+ str->texture = GET_WORD;
- ArchivePlayers();
+ // fixed_t floordestheight;
+ str->floordestheight = GET_LONG;
- // Place a termination marker
- StreamOutLong(ASEG_END);
+ // fixed_t speed;
+ str->speed = GET_LONG;
- // Close the output file
- CloseStreamOut();
+ // int delayCount;
+ str->delayCount = GET_LONG;
- // Save out the current map
- SV_SaveMap(true); // true = save player info
+ // int delayTotal;
+ str->delayTotal = GET_LONG;
- // Clear all save files at destination slot
- ClearSaveSlot(slot);
+ // fixed_t stairsDelayHeight;
+ str->stairsDelayHeight = GET_LONG;
- // Copy base slot to destination slot
- CopySaveSlot(BASE_SLOT, slot);
-}
+ // fixed_t stairsDelayHeightDelta;
+ str->stairsDelayHeightDelta = GET_LONG;
-//==========================================================================
-//
-// SV_SaveMap
-//
-//==========================================================================
+ // fixed_t resetHeight;
+ str->resetHeight = GET_LONG;
-void SV_SaveMap(boolean savePlayers)
+ // short resetDelay;
+ str->resetDelay = GET_WORD;
+
+ // short resetDelayCount;
+ str->resetDelayCount = GET_WORD;
+
+ // byte textureChange;
+ str->textureChange = GET_BYTE;
+}
+
+static void StreamOut_floormove_t(floormove_t *str)
{
- char fileName[100];
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
- SavingPlayers = savePlayers;
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
- // Open the output file
- sprintf(fileName, "%shex6%02d.hxs", SavePath, gamemap);
- OpenStreamOut(fileName);
+ // floor_e type;
+ StreamOutLong(str->type);
- // Place a header marker
- StreamOutLong(ASEG_MAP_HEADER);
+ // int crush;
+ StreamOutLong(str->crush);
- // Write the level timer
- StreamOutLong(leveltime);
+ // int direction;
+ StreamOutLong(str->direction);
- // Set the mobj archive numbers
- SetMobjArchiveNums();
+ // int newspecial;
+ StreamOutLong(str->newspecial);
- ArchiveWorld();
- ArchivePolyobjs();
- ArchiveMobjs();
- ArchiveThinkers();
- ArchiveScripts();
- ArchiveSounds();
- ArchiveMisc();
+ // short texture;
+ StreamOutWord(str->texture);
- // Place a termination marker
- StreamOutLong(ASEG_END);
+ // fixed_t floordestheight;
+ StreamOutLong(str->floordestheight);
- // Close the output file
- CloseStreamOut();
+ // fixed_t speed;
+ StreamOutLong(str->speed);
+
+ // int delayCount;
+ StreamOutLong(str->delayCount);
+
+ // int delayTotal;
+ StreamOutLong(str->delayTotal);
+
+ // fixed_t stairsDelayHeight;
+ StreamOutLong(str->stairsDelayHeight);
+
+ // fixed_t stairsDelayHeightDelta;
+ StreamOutLong(str->stairsDelayHeightDelta);
+
+ // fixed_t resetHeight;
+ StreamOutLong(str->resetHeight);
+
+ // short resetDelay;
+ StreamOutWord(str->resetDelay);
+
+ // short resetDelayCount;
+ StreamOutWord(str->resetDelayCount);
+
+ // byte textureChange;
+ StreamOutByte(str->textureChange);
}
-//==========================================================================
+
//
-// SV_LoadGame
+// plat_t
//
-//==========================================================================
-void SV_LoadGame(int slot)
+static void StreamIn_plat_t(plat_t *str)
{
int i;
- char fileName[100];
- player_t playerBackup[MAXPLAYERS];
- mobj_t *mobj;
- // Copy all needed save files to the base slot
- if (slot != BASE_SLOT)
- {
- ClearSaveSlot(BASE_SLOT);
- CopySaveSlot(slot, BASE_SLOT);
- }
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
- // Create the name
- sprintf(fileName, "%shex6.hxs", SavePath);
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = sectors + i;
- // Load the file
- M_ReadFile(fileName, &SaveBuffer);
+ // fixed_t speed;
+ str->speed = GET_LONG;
- // Set the save pointer and skip the description field
- SavePtr.b = SaveBuffer + HXS_DESCRIPTION_LENGTH;
+ // fixed_t low;
+ str->low = GET_LONG;
- // Check the version text
- if (strcmp((char *) SavePtr.b, HXS_VERSION_TEXT))
- { // Bad version
- return;
- }
- SavePtr.b += HXS_VERSION_TEXT_LENGTH;
+ // fixed_t high;
+ str->high = GET_LONG;
- AssertSegment(ASEG_GAME_HEADER);
+ // int wait;
+ str->wait = GET_LONG;
- gameepisode = 1;
- gamemap = GET_BYTE;
- gameskill = GET_BYTE;
+ // int count;
+ str->count = GET_LONG;
- // Read global script info
+ // plat_e status;
+ str->status = GET_LONG;
- for (i = 0; i < MAX_ACS_WORLD_VARS; ++i)
- {
- WorldVars[i] = GET_LONG;
- }
+ // plat_e oldstatus;
+ str->oldstatus = GET_LONG;
- for (i = 0; i < MAX_ACS_STORE + 1; ++i)
- {
- StreamIn_acsstore_t(&ACSStore[i]);
- }
+ // int crush;
+ str->crush = GET_LONG;
- // Read the player structures
- UnarchivePlayers();
+ // int tag;
+ str->tag = GET_LONG;
- AssertSegment(ASEG_END);
+ // plattype_e type;
+ str->type = GET_LONG;
+}
- Z_Free(SaveBuffer);
+static void StreamOut_plat_t(plat_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
- // Save player structs
- for (i = 0; i < MAXPLAYERS; i++)
- {
- playerBackup[i] = players[i];
- }
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
- // Load the current map
- SV_LoadMap();
+ // fixed_t speed;
+ StreamOutLong(str->speed);
- // Don't need the player mobj relocation info for load game
- Z_Free(TargetPlayerAddrs);
+ // fixed_t low;
+ StreamOutLong(str->low);
- // Restore player structs
- inv_ptr = 0;
- curpos = 0;
- for (i = 0; i < MAXPLAYERS; i++)
- {
- mobj = players[i].mo;
- players[i] = playerBackup[i];
- players[i].mo = mobj;
- if (i == consoleplayer)
- {
- players[i].readyArtifact = players[i].inventory[inv_ptr].type;
- }
- }
-}
+ // fixed_t high;
+ StreamOutLong(str->high);
-//==========================================================================
-//
-// SV_UpdateRebornSlot
-//
-// Copies the base slot to the reborn slot.
-//
-//==========================================================================
+ // int wait;
+ StreamOutLong(str->wait);
-void SV_UpdateRebornSlot(void)
-{
- ClearSaveSlot(REBORN_SLOT);
- CopySaveSlot(BASE_SLOT, REBORN_SLOT);
-}
+ // int count;
+ StreamOutLong(str->count);
-//==========================================================================
-//
-// SV_ClearRebornSlot
-//
-//==========================================================================
+ // plat_e status;
+ StreamOutLong(str->status);
-void SV_ClearRebornSlot(void)
-{
- ClearSaveSlot(REBORN_SLOT);
+ // plat_e oldstatus;
+ StreamOutLong(str->oldstatus);
+
+ // int crush;
+ StreamOutLong(str->crush);
+
+ // int tag;
+ StreamOutLong(str->tag);
+
+ // plattype_e type;
+ StreamOutLong(str->type);
}
-//==========================================================================
+
//
-// SV_MapTeleport
+// ceiling_t
//
-//==========================================================================
-void SV_MapTeleport(int map, int position)
+static void StreamIn_ceiling_t(ceiling_t *str)
{
int i;
- int j;
- char fileName[100];
- player_t playerBackup[MAXPLAYERS];
- mobj_t *targetPlayerMobj;
- mobj_t *mobj;
- int inventoryPtr;
- int currentInvPos;
+
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = sectors + i;
+
+ // ceiling_e type;
+ str->type = GET_LONG;
+
+ // fixed_t bottomheight, topheight;
+ str->bottomheight = GET_LONG;
+ str->topheight = GET_LONG;
+
+ // fixed_t speed;
+ str->speed = GET_LONG;
+
+ // int crush;
+ str->crush = GET_LONG;
+
+ // int direction;
+ str->direction = GET_LONG;
+
+ // int tag;
+ str->tag = GET_LONG;
+
+ // int olddirection;
+ str->olddirection = GET_LONG;
+}
+
+static void StreamOut_ceiling_t(ceiling_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
+
+ // ceiling_e type;
+ StreamOutLong(str->type);
+
+ // fixed_t bottomheight, topheight;
+ StreamOutLong(str->bottomheight);
+ StreamOutLong(str->topheight);
+
+ // fixed_t speed;
+ StreamOutLong(str->speed);
+
+ // int crush;
+ StreamOutLong(str->crush);
+
+ // int direction;
+ StreamOutLong(str->direction);
+
+ // int tag;
+ StreamOutLong(str->tag);
+
+ // int olddirection;
+ StreamOutLong(str->olddirection);
+}
+
+
+//
+// light_t
+//
+
+static void StreamIn_light_t(light_t *str)
+{
+ int i;
+
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = sectors + i;
+
+ // lighttype_t type;
+ str->type = GET_LONG;
+
+ // int value1;
+ str->value1 = GET_LONG;
+
+ // int value2;
+ str->value2 = GET_LONG;
+
+ // int tics1;
+ str->tics1 = GET_LONG;
+
+ // int tics2;
+ str->tics2 = GET_LONG;
+
+ // int count;
+ str->count = GET_LONG;
+}
+
+static void StreamOut_light_t(light_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
+
+ // lighttype_t type;
+ StreamOutLong(str->type);
+
+ // int value1;
+ StreamOutLong(str->value1);
+
+ // int value2;
+ StreamOutLong(str->value2);
+
+ // int tics1;
+ StreamOutLong(str->tics1);
+
+ // int tics2;
+ StreamOutLong(str->tics2);
+
+ // int count;
+ StreamOutLong(str->count);
+}
+
+
+//
+// vldoor_t
+//
+
+static void StreamIn_vldoor_t(vldoor_t *str)
+{
+ int i;
+
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = §ors[i];
+
+ // vldoor_e type;
+ str->type = GET_LONG;
+
+ // fixed_t topheight;
+ str->topheight = GET_LONG;
+
+ // fixed_t speed;
+ str->speed = GET_LONG;
+
+ // int direction;
+ str->direction = GET_LONG;
+
+ // int topwait;
+ str->topwait = GET_LONG;
+
+ // int topcountdown;
+ str->topcountdown = GET_LONG;
+}
+
+static void StreamOut_vldoor_t(vldoor_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
+
+ // vldoor_e type;
+ StreamOutLong(str->type);
+
+ // fixed_t topheight;
+ StreamOutLong(str->topheight);
+
+ // fixed_t speed;
+ StreamOutLong(str->speed);
+
+ // int direction;
+ StreamOutLong(str->direction);
+
+ // int topwait;
+ StreamOutLong(str->topwait);
+
+ // int topcountdown;
+ StreamOutLong(str->topcountdown);
+}
+
+
+//
+// phase_t
+//
+
+static void StreamIn_phase_t(phase_t *str)
+{
+ int i;
+
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = §ors[i];
+
+ // int index;
+ str->index = GET_LONG;
+
+ // int base;
+ str->base = GET_LONG;
+}
+
+static void StreamOut_phase_t(phase_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
+
+ // int index;
+ StreamOutLong(str->index);
+
+ // int base;
+ StreamOutLong(str->base);
+}
+
+
+//
+// acs_t
+//
+
+static void StreamIn_acs_t(acs_t *str)
+{
+ int i;
+
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // mobj_t *activator;
+ i = GET_LONG;
+ SetMobjPtr(&str->activator, i);
+
+ // line_t *line;
+ i = GET_LONG;
+ if (i != -1)
+ {
+ str->line = &lines[i];
+ }
+ else
+ {
+ str->line = NULL;
+ }
+
+ // int side;
+ str->side = GET_LONG;
+
+ // int number;
+ str->number = GET_LONG;
+
+ // int infoIndex;
+ str->infoIndex = GET_LONG;
+
+ // int delayCount;
+ str->delayCount = GET_LONG;
+
+ // int stack[ACS_STACK_DEPTH];
+ for (i=0; i<ACS_STACK_DEPTH; ++i)
+ {
+ str->stack[i] = GET_LONG;
+ }
+
+ // int stackPtr;
+ str->stackPtr = GET_LONG;
+
+ // int vars[MAX_ACS_SCRIPT_VARS];
+ for (i=0; i<MAX_ACS_SCRIPT_VARS; ++i)
+ {
+ str->vars[i] = GET_LONG;
+ }
+
+ // int *ip;
+ i = GET_LONG;
+ str->ip = (int *) (ActionCodeBase + i);
+}
+
+static void StreamOut_acs_t(acs_t *str)
+{
+ int i;
+
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // mobj_t *activator;
+ StreamOutLong(GetMobjNum(str->activator));
+
+ // line_t *line;
+ if (str->line != NULL)
+ {
+ StreamOutLong(str->line - lines);
+ }
+ else
+ {
+ StreamOutLong(-1);
+ }
+
+ // int side;
+ StreamOutLong(str->side);
+
+ // int number;
+ StreamOutLong(str->number);
+
+ // int infoIndex;
+ StreamOutLong(str->infoIndex);
+
+ // int delayCount;
+ StreamOutLong(str->delayCount);
+
+ // int stack[ACS_STACK_DEPTH];
+ for (i=0; i<ACS_STACK_DEPTH; ++i)
+ {
+ StreamOutLong(str->stack[i]);
+ }
+
+ // int stackPtr;
+ StreamOutLong(str->stackPtr);
+
+ // int vars[MAX_ACS_SCRIPT_VARS];
+ for (i=0; i<MAX_ACS_SCRIPT_VARS; ++i)
+ {
+ StreamOutLong(str->vars[i]);
+ }
+
+ // int *ip;
+ StreamOutLong((byte *) str->ip - ActionCodeBase);
+}
+
+
+//
+// polyevent_t
+//
+
+static void StreamIn_polyevent_t(polyevent_t *str)
+{
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // int polyobj;
+ str->polyobj = GET_LONG;
+
+ // int speed;
+ str->speed = GET_LONG;
+
+ // unsigned int dist;
+ str->dist = GET_LONG;
+
+ // int angle;
+ str->angle = GET_LONG;
+
+ // fixed_t xSpeed;
+ str->xSpeed = GET_LONG;
+
+ // fixed_t ySpeed;
+ str->ySpeed = GET_LONG;
+}
+
+static void StreamOut_polyevent_t(polyevent_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // int polyobj;
+ StreamOutLong(str->polyobj);
+
+ // int speed;
+ StreamOutLong(str->speed);
+
+ // unsigned int dist;
+ StreamOutLong(str->dist);
+
+ // int angle;
+ StreamOutLong(str->angle);
+
+ // fixed_t xSpeed;
+ StreamOutLong(str->xSpeed);
+
+ // fixed_t ySpeed;
+ StreamOutLong(str->ySpeed);
+}
+
+
+//
+// pillar_t
+//
+
+static void StreamIn_pillar_t(pillar_t *str)
+{
+ int i;
+
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = §ors[i];
+
+ // int ceilingSpeed;
+ str->ceilingSpeed = GET_LONG;
+
+ // int floorSpeed;
+ str->floorSpeed = GET_LONG;
+
+ // int floordest;
+ str->floordest = GET_LONG;
+
+ // int ceilingdest;
+ str->ceilingdest = GET_LONG;
+
+ // int direction;
+ str->direction = GET_LONG;
+
+ // int crush;
+ str->crush = GET_LONG;
+}
+
+static void StreamOut_pillar_t(pillar_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
+
+ // int ceilingSpeed;
+ StreamOutLong(str->ceilingSpeed);
+
+ // int floorSpeed;
+ StreamOutLong(str->floorSpeed);
+
+ // int floordest;
+ StreamOutLong(str->floordest);
+
+ // int ceilingdest;
+ StreamOutLong(str->ceilingdest);
+
+ // int direction;
+ StreamOutLong(str->direction);
+
+ // int crush;
+ StreamOutLong(str->crush);
+}
+
+
+//
+// polydoor_t
+//
+
+static void StreamIn_polydoor_t(polydoor_t *str)
+{
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // int polyobj;
+ str->polyobj = GET_LONG;
+
+ // int speed;
+ str->speed = GET_LONG;
+
+ // int dist;
+ str->dist = GET_LONG;
+
+ // int totalDist;
+ str->totalDist = GET_LONG;
+
+ // int direction;
+ str->direction = GET_LONG;
+
+ // fixed_t xSpeed, ySpeed;
+ str->xSpeed = GET_LONG;
+ str->ySpeed = GET_LONG;
+
+ // int tics;
+ str->tics = GET_LONG;
+
+ // int waitTics;
+ str->waitTics = GET_LONG;
+
+ // podoortype_t type;
+ str->type = GET_LONG;
+
+ // boolean close;
+ str->close = GET_LONG;
+}
+
+static void StreamOut_polydoor_t(polydoor_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // int polyobj;
+ StreamOutLong(str->polyobj);
+
+ // int speed;
+ StreamOutLong(str->speed);
+
+ // int dist;
+ StreamOutLong(str->dist);
+
+ // int totalDist;
+ StreamOutLong(str->totalDist);
+
+ // int direction;
+ StreamOutLong(str->direction);
+
+ // fixed_t xSpeed, ySpeed;
+ StreamOutLong(str->xSpeed);
+ StreamOutLong(str->ySpeed);
+
+ // int tics;
+ StreamOutLong(str->tics);
+
+ // int waitTics;
+ StreamOutLong(str->waitTics);
+
+ // podoortype_t type;
+ StreamOutLong(str->type);
+
+ // boolean close;
+ StreamOutLong(str->close);
+}
+
+
+//
+// floorWaggle_t
+//
+
+static void StreamIn_floorWaggle_t(floorWaggle_t *str)
+{
+ int i;
+
+ // thinker_t thinker;
+ StreamIn_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ i = GET_LONG;
+ str->sector = §ors[i];
+
+ // fixed_t originalHeight;
+ str->originalHeight = GET_LONG;
+
+ // fixed_t accumulator;
+ str->accumulator = GET_LONG;
+
+ // fixed_t accDelta;
+ str->accDelta = GET_LONG;
+
+ // fixed_t targetScale;
+ str->targetScale = GET_LONG;
+
+ // fixed_t scale;
+ str->scale = GET_LONG;
+
+ // fixed_t scaleDelta;
+ str->scaleDelta = GET_LONG;
+
+ // int ticker;
+ str->ticker = GET_LONG;
+
+ // int state;
+ str->state = GET_LONG;
+}
+
+static void StreamOut_floorWaggle_t(floorWaggle_t *str)
+{
+ // thinker_t thinker;
+ StreamOut_thinker_t(&str->thinker);
+
+ // sector_t *sector;
+ StreamOutLong(str->sector - sectors);
+
+ // fixed_t originalHeight;
+ StreamOutLong(str->originalHeight);
+
+ // fixed_t accumulator;
+ StreamOutLong(str->accumulator);
+
+ // fixed_t accDelta;
+ StreamOutLong(str->accDelta);
+
+ // fixed_t targetScale;
+ StreamOutLong(str->targetScale);
+
+ // fixed_t scale;
+ StreamOutLong(str->scale);
+
+ // fixed_t scaleDelta;
+ StreamOutLong(str->scaleDelta);
+
+ // int ticker;
+ StreamOutLong(str->ticker);
+
+ // int state;
+ StreamOutLong(str->state);
+}
+
+
+//==========================================================================
+//
+// SV_SaveGame
+//
+//==========================================================================
+
+void SV_SaveGame(int slot, char *description)
+{
+ char fileName[100];
+ char versionText[HXS_VERSION_TEXT_LENGTH];
+ unsigned int i;
+
+ // Open the output file
+ sprintf(fileName, "%shex6.hxs", SavePath);
+ OpenStreamOut(fileName);
+
+ // Write game save description
+ StreamOutBuffer(description, HXS_DESCRIPTION_LENGTH);
+
+ // Write version info
+ memset(versionText, 0, HXS_VERSION_TEXT_LENGTH);
+ strcpy(versionText, HXS_VERSION_TEXT);
+ StreamOutBuffer(versionText, HXS_VERSION_TEXT_LENGTH);
+
+ // Place a header marker
+ StreamOutLong(ASEG_GAME_HEADER);
+
+ // Write current map and difficulty
+ StreamOutByte(gamemap);
+ StreamOutByte(gameskill);
+
+ // Write global script info
+ for (i = 0; i < MAX_ACS_WORLD_VARS; ++i)
+ {
+ StreamOutLong(WorldVars[i]);
+ }
+
+ for (i = 0; i < MAX_ACS_STORE + 1; ++i)
+ {
+ StreamOut_acsstore_t(&ACSStore[i]);
+ }
+
+ ArchivePlayers();
+
+ // Place a termination marker
+ StreamOutLong(ASEG_END);
+
+ // Close the output file
+ CloseStreamOut();
+
+ // Save out the current map
+ SV_SaveMap(true); // true = save player info
+
+ // Clear all save files at destination slot
+ ClearSaveSlot(slot);
+
+ // Copy base slot to destination slot
+ CopySaveSlot(BASE_SLOT, slot);
+}
+
+//==========================================================================
+//
+// SV_SaveMap
+//
+//==========================================================================
+
+void SV_SaveMap(boolean savePlayers)
+{
+ char fileName[100];
+
+ SavingPlayers = savePlayers;
+
+ // Open the output file
+ sprintf(fileName, "%shex6%02d.hxs", SavePath, gamemap);
+ OpenStreamOut(fileName);
+
+ // Place a header marker
+ StreamOutLong(ASEG_MAP_HEADER);
+
+ // Write the level timer
+ StreamOutLong(leveltime);
+
+ // Set the mobj archive numbers
+ SetMobjArchiveNums();
+
+ ArchiveWorld();
+ ArchivePolyobjs();
+ ArchiveMobjs();
+ ArchiveThinkers();
+ ArchiveScripts();
+ ArchiveSounds();
+ ArchiveMisc();
+
+ // Place a termination marker
+ StreamOutLong(ASEG_END);
+
+ // Close the output file
+ CloseStreamOut();
+}
+
+//==========================================================================
+//
+// SV_LoadGame
+//
+//==========================================================================
+
+void SV_LoadGame(int slot)
+{
+ int i;
+ char fileName[100];
+ player_t playerBackup[MAXPLAYERS];
+ mobj_t *mobj;
+
+ // Copy all needed save files to the base slot
+ if (slot != BASE_SLOT)
+ {
+ ClearSaveSlot(BASE_SLOT);
+ CopySaveSlot(slot, BASE_SLOT);
+ }
+
+ // Create the name
+ sprintf(fileName, "%shex6.hxs", SavePath);
+
+ // Load the file
+ M_ReadFile(fileName, &SaveBuffer);
+
+ // Set the save pointer and skip the description field
+ SavePtr.b = SaveBuffer + HXS_DESCRIPTION_LENGTH;
+
+ // Check the version text
+ if (strcmp((char *) SavePtr.b, HXS_VERSION_TEXT))
+ { // Bad version
+ return;
+ }
+ SavePtr.b += HXS_VERSION_TEXT_LENGTH;
+
+ AssertSegment(ASEG_GAME_HEADER);
+
+ gameepisode = 1;
+ gamemap = GET_BYTE;
+ gameskill = GET_BYTE;
+
+ // Read global script info
+
+ for (i = 0; i < MAX_ACS_WORLD_VARS; ++i)
+ {
+ WorldVars[i] = GET_LONG;
+ }
+
+ for (i = 0; i < MAX_ACS_STORE + 1; ++i)
+ {
+ StreamIn_acsstore_t(&ACSStore[i]);
+ }
+
+ // Read the player structures
+ UnarchivePlayers();
+
+ AssertSegment(ASEG_END);
+
+ Z_Free(SaveBuffer);
+
+ // Save player structs
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ playerBackup[i] = players[i];
+ }
+
+ // Load the current map
+ SV_LoadMap();
+
+ // Don't need the player mobj relocation info for load game
+ Z_Free(TargetPlayerAddrs);
+
+ // Restore player structs
+ inv_ptr = 0;
+ curpos = 0;
+ for (i = 0; i < MAXPLAYERS; i++)
+ {
+ mobj = players[i].mo;
+ players[i] = playerBackup[i];
+ players[i].mo = mobj;
+ if (i == consoleplayer)
+ {
+ players[i].readyArtifact = players[i].inventory[inv_ptr].type;
+ }
+ }
+}
+
+//==========================================================================
+//
+// SV_UpdateRebornSlot
+//
+// Copies the base slot to the reborn slot.
+//
+//==========================================================================
+
+void SV_UpdateRebornSlot(void)
+{
+ ClearSaveSlot(REBORN_SLOT);
+ CopySaveSlot(BASE_SLOT, REBORN_SLOT);
+}
+
+//==========================================================================
+//
+// SV_ClearRebornSlot
+//
+//==========================================================================
+
+void SV_ClearRebornSlot(void)
+{
+ ClearSaveSlot(REBORN_SLOT);
+}
+
+//==========================================================================
+//
+// SV_MapTeleport
+//
+//==========================================================================
+
+void SV_MapTeleport(int map, int position)
+{
+ int i;
+ int j;
+ char fileName[100];
+ player_t playerBackup[MAXPLAYERS];
+ mobj_t *targetPlayerMobj;
+ mobj_t *mobj;
+ int inventoryPtr;
+ int currentInvPos;
boolean rClass;
boolean playerWasReborn;
boolean oldWeaponowned[NUMWEAPONS];
@@ -1988,6 +2706,117 @@ static void SetMobjPtr(mobj_t **ptr, unsigned int archiveNum)
}
}
+//==========================================================================
+//
+// Thinker types list.
+//
+// This is used by ArchiveThinkers and UnarchiveThinkers, below.
+//
+// Original comment:
+// "This list has been prioritized using frequency estimates"
+//
+//==========================================================================
+
+static thinkInfo_t ThinkerInfo[] = {
+ {
+ TC_MOVE_FLOOR,
+ T_MoveFloor,
+ StreamOut_floormove_t,
+ StreamIn_floormove_t,
+ RestoreSSThinker,
+ sizeof(floormove_t)
+ },
+ {
+ TC_PLAT_RAISE,
+ T_PlatRaise,
+ StreamOut_plat_t,
+ StreamIn_plat_t,
+ RestorePlatRaise,
+ sizeof(plat_t)
+ },
+ {
+ TC_MOVE_CEILING,
+ T_MoveCeiling,
+ StreamOut_ceiling_t,
+ StreamIn_ceiling_t,
+ RestoreMoveCeiling,
+ sizeof(ceiling_t)
+ },
+ {
+ TC_LIGHT,
+ T_Light,
+ StreamOut_light_t,
+ StreamIn_light_t,
+ NULL,
+ sizeof(light_t)
+ },
+ {
+ TC_VERTICAL_DOOR,
+ T_VerticalDoor,
+ StreamOut_vldoor_t,
+ StreamIn_vldoor_t,
+ RestoreSSThinker,
+ sizeof(vldoor_t)
+ },
+ {
+ TC_PHASE,
+ T_Phase,
+ StreamOut_phase_t,
+ StreamIn_phase_t,
+ NULL,
+ sizeof(phase_t)
+ },
+ {
+ TC_INTERPRET_ACS,
+ T_InterpretACS,
+ StreamOut_acs_t,
+ StreamIn_acs_t,
+ NULL,
+ sizeof(acs_t)
+ },
+ {
+ TC_ROTATE_POLY,
+ T_RotatePoly,
+ StreamOut_polyevent_t,
+ StreamIn_polyevent_t,
+ NULL,
+ sizeof(polyevent_t)
+ },
+ {
+ TC_BUILD_PILLAR,
+ T_BuildPillar,
+ StreamOut_pillar_t,
+ StreamIn_pillar_t,
+ RestoreSSThinker,
+ sizeof(pillar_t)
+ },
+ {
+ TC_MOVE_POLY,
+ T_MovePoly,
+ StreamOut_polyevent_t,
+ StreamIn_polyevent_t,
+ NULL,
+ sizeof(polyevent_t)
+ },
+ {
+ TC_POLY_DOOR,
+ T_PolyDoor,
+ StreamOut_polydoor_t,
+ StreamIn_polydoor_t,
+ NULL,
+ sizeof(polydoor_t)
+ },
+ {
+ TC_FLOOR_WAGGLE,
+ T_FloorWaggle,
+ StreamOut_floorWaggle_t,
+ StreamIn_floorWaggle_t,
+ RestoreSSThinker,
+ sizeof(floorWaggle_t)
+ },
+ { TC_NULL, NULL, NULL, NULL, NULL, 0},
+};
+
//==========================================================================
//
// ArchiveThinkers
@@ -1998,7 +2827,6 @@ static void ArchiveThinkers(void)
{
thinker_t *thinker;
thinkInfo_t *info;
- byte buffer[MAX_THINKER_SIZE];
StreamOutLong(ASEG_THINKERS);
for (thinker = thinkercap.next; thinker != &thinkercap;
@@ -2009,12 +2837,7 @@ static void ArchiveThinkers(void)
if (thinker->function == info->thinkerFunc)
{
StreamOutByte(info->tClass);
- memcpy(buffer, thinker, info->size);
- if (info->mangleFunc)
- {
- info->mangleFunc(buffer);
- }
- StreamOutBuffer(buffer, info->size);
+ info->writeFunc(thinker);
break;
}
}
@@ -2043,8 +2866,7 @@ static void UnarchiveThinkers(void)
if (tClass == info->tClass)
{
thinker = Z_Malloc(info->size, PU_LEVEL, NULL);
- memcpy(thinker, SavePtr.b, info->size);
- SavePtr.b += info->size;
+ info->readFunc(thinker);
thinker->function = info->thinkerFunc;
if (info->restoreFunc)
{
@@ -2062,83 +2884,25 @@ static void UnarchiveThinkers(void)
}
}
-//==========================================================================
-//
-// MangleSSThinker
-//
-//==========================================================================
-
-static void MangleSSThinker(ssthinker_t * sst)
-{
- sst->sector = (sector_t *) (sst->sector - sectors);
-}
-
//==========================================================================
//
// RestoreSSThinker
//
//==========================================================================
-static void RestoreSSThinker(ssthinker_t * sst)
+static void RestoreSSThinker(ssthinker_t *sst)
{
- sst->sector = §ors[(int) sst->sector];
sst->sector->specialdata = sst->thinker.function;
}
-//==========================================================================
-//
-// RestoreSSThinkerNoSD
-//
-//==========================================================================
-
-static void RestoreSSThinkerNoSD(ssthinker_t * sst)
-{
- sst->sector = §ors[(int) sst->sector];
-}
-
-//==========================================================================
-//
-// MangleScript
-//
-//==========================================================================
-
-static void MangleScript(acs_t * script)
-{
- script->ip = (int *) ((int) (script->ip) - (int) ActionCodeBase);
- script->line = script->line ?
- (line_t *) (script->line - lines) : (line_t *) - 1;
- script->activator = (mobj_t *) GetMobjNum(script->activator);
-}
-
-//==========================================================================
-//
-// RestoreScript
-//
-//==========================================================================
-
-static void RestoreScript(acs_t * script)
-{
- script->ip = (int *) (ActionCodeBase + (int) script->ip);
- if ((int) script->line == -1)
- {
- script->line = NULL;
- }
- else
- {
- script->line = &lines[(int) script->line];
- }
- SetMobjPtr(&script->activator, (int) script->activator);
-}
-
//==========================================================================
//
// RestorePlatRaise
//
//==========================================================================
-static void RestorePlatRaise(plat_t * plat)
+static void RestorePlatRaise(plat_t *plat)
{
- plat->sector = §ors[(int) plat->sector];
plat->sector->specialdata = T_PlatRaise;
P_AddActivePlat(plat);
}
@@ -2149,9 +2913,8 @@ static void RestorePlatRaise(plat_t * plat)
//
//==========================================================================
-static void RestoreMoveCeiling(ceiling_t * ceiling)
+static void RestoreMoveCeiling(ceiling_t *ceiling)
{
- ceiling->sector = §ors[(int) ceiling->sector];
ceiling->sector->specialdata = T_MoveCeiling;
P_AddActiveCeiling(ceiling);
}