From 21bc4c4ab90df0455eaeba6a4c959005493f0a76 Mon Sep 17 00:00:00 2001 From: Simon Howard Date: Sun, 25 Aug 2013 05:44:45 +0000 Subject: First step towards portable Hexen savegames. Perform endianness conversions for ACS vars and add functions to read/write player_t structures. Subversion-branch: /branches/v2-branch Subversion-revision: 2625 --- src/hexen/sv_save.c | 616 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 579 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/hexen/sv_save.c b/src/hexen/sv_save.c index 9dc8fc5d..bb9bd797 100644 --- a/src/hexen/sv_save.c +++ b/src/hexen/sv_save.c @@ -37,8 +37,8 @@ #define MOBJ_NULL -1 #define MOBJ_XX_PLAYER -2 #define GET_BYTE (*SavePtr.b++) -#define GET_WORD (*SavePtr.w++) -#define GET_LONG (*SavePtr.l++) +#define GET_WORD SHORT(*SavePtr.w++) +#define GET_LONG LONG(*SavePtr.l++) #define MAX_MAPS 99 #define BASE_SLOT 6 #define REBORN_SLOT 7 @@ -142,6 +142,7 @@ static void StreamOutBuffer(void *buffer, int size); static void StreamOutByte(byte val); static void StreamOutWord(unsigned short val); static void StreamOutLong(unsigned int val); +static void StreamOutPtr(void *ptr); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- @@ -259,6 +260,527 @@ static thinkInfo_t ThinkerInfo[] = { // CODE -------------------------------------------------------------------- +// Autogenerated functions for reading/writing structs: + +// +// acsstore_t +// + +static void StreamIn_acsstore_t(acsstore_t *str) +{ + int i; + + // int map; + str->map = GET_LONG; + + // int script; + str->script = GET_LONG; + + // byte args[4]; + for (i=0; i<4; ++i) + { + str->args[i] = GET_BYTE; + } +} + +static void StreamOut_acsstore_t(acsstore_t *str) +{ + int i; + + // int map; + StreamOutLong(str->map); + + // int script; + StreamOutLong(str->script); + + // byte args[4]; + for (i=0; i<4; ++i) + { + StreamOutByte(str->args[i]); + } +} + + +// +// ticcmd_t +// (this is based on the Vanilla definition of the struct) +// + +static void StreamIn_ticcmd_t(ticcmd_t *str) +{ + // char forwardmove; + str->forwardmove = GET_BYTE; + + // char sidemove; + str->sidemove = GET_BYTE; + + // short angleturn; + str->angleturn = GET_WORD; + + // short consistancy; + str->consistancy = GET_WORD; + + // byte chatchar; + str->chatchar = GET_BYTE; + + // byte buttons; + str->buttons = GET_BYTE; + + // byte lookfly; + str->lookfly = GET_BYTE; + + // byte arti; + str->arti = GET_BYTE; +} + +static void StreamOut_ticcmd_t(ticcmd_t *str) +{ + // char forwardmove; + StreamOutByte(str->forwardmove); + + // char sidemove; + StreamOutByte(str->sidemove); + + // short angleturn; + StreamOutWord(str->angleturn); + + // short consistancy; + StreamOutWord(str->consistancy); + + // byte chatchar; + StreamOutByte(str->chatchar); + + // byte buttons; + StreamOutByte(str->buttons); + + // byte lookfly; + StreamOutByte(str->lookfly); + + // byte arti; + StreamOutByte(str->arti); +} + + + +// +// inventory_t +// + +static void StreamIn_inventory_t(inventory_t *str) +{ + // int type; + str->type = GET_LONG; + + // int count; + str->count = GET_LONG; +} + +static void StreamOut_inventory_t(inventory_t *str) +{ + // int type; + StreamOutLong(str->type); + + // int count; + StreamOutLong(str->count); +} + + +// +// pspdef_t +// + +static void StreamIn_pspdef_t(pspdef_t *str) +{ + int state_num; + + // state_t *state; + + // This is a pointer; it is stored as an index into the states table. + + state_num = GET_LONG; + + if (state_num != 0) + { + str->state = states + state_num; + } + else + { + str->state = NULL; + } + + // int tics; + str->tics = GET_LONG; + + // fixed_t sx, sy; + str->sx = GET_LONG; + str->sy = GET_LONG; +} + +static void StreamOut_pspdef_t(pspdef_t *str) +{ + // state_t *state; + // This is a pointer; store the index in the states table, + // rather than the pointer itself. + if (str->state != NULL) + { + StreamOutLong(str->state - states); + } + else + { + StreamOutLong(0); + } + + // int tics; + StreamOutLong(str->tics); + + // fixed_t sx, sy; + StreamOutLong(str->sx); + StreamOutLong(str->sy); +} + + +// +// player_t +// + +static void StreamIn_player_t(player_t *str) +{ + int i; + + // mobj_t *mo; + // Pointer value is reset on load. + GET_LONG; + str->mo = NULL; + + // playerstate_t playerstate; + str->playerstate = GET_LONG; + + // ticcmd_t cmd; + StreamIn_ticcmd_t(&str->cmd); + + // pclass_t class; + str->class = GET_LONG; + + // fixed_t viewz; + str->viewz = GET_LONG; + + // fixed_t viewheight; + str->viewheight = GET_LONG; + + // fixed_t deltaviewheight; + str->deltaviewheight = GET_LONG; + + // fixed_t bob; + str->bob = GET_LONG; + + // int flyheight; + str->flyheight = GET_LONG; + + // int lookdir; + str->lookdir = GET_LONG; + + // boolean centering; + str->centering = GET_LONG; + + // int health; + str->health = GET_LONG; + + // int armorpoints[NUMARMOR]; + for (i=0; iarmorpoints[i] = GET_LONG; + } + + // inventory_t inventory[NUMINVENTORYSLOTS]; + for (i=0; iinventory[i]); + } + + // artitype_t readyArtifact; + str->readyArtifact = GET_LONG; + + // int artifactCount; + str->artifactCount = GET_LONG; + + // int inventorySlotNum; + str->inventorySlotNum = GET_LONG; + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i] = GET_LONG; + } + + // int keys; + str->keys = GET_LONG; + + // int pieces; + str->pieces = GET_LONG; + + // signed int frags[MAXPLAYERS]; + for (i=0; ifrags[i] = GET_LONG; + } + + // weapontype_t readyweapon; + str->readyweapon = GET_LONG; + + // weapontype_t pendingweapon; + str->pendingweapon = GET_LONG; + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i] = GET_LONG; + } + + // int mana[NUMMANA]; + for (i=0; imana[i] = GET_LONG; + } + + // int attackdown, usedown; + str->attackdown = GET_LONG; + str->usedown = GET_LONG; + + // int cheats; + str->cheats = GET_LONG; + + // int refire; + str->refire = GET_LONG; + + // int killcount, itemcount, secretcount; + str->killcount = GET_LONG; + str->itemcount = GET_LONG; + str->secretcount = GET_LONG; + + // char message[80]; + for (i=0; i<80; ++i) + { + str->message[i] = GET_BYTE; + } + + // int messageTics; + str->messageTics = GET_LONG; + + // short ultimateMessage; + str->ultimateMessage = GET_WORD; + + // short yellowMessage; + str->yellowMessage = GET_WORD; + + // int damagecount, bonuscount; + str->damagecount = GET_LONG; + str->bonuscount = GET_LONG; + + // int poisoncount; + str->poisoncount = GET_LONG; + + // mobj_t *poisoner; + // Pointer value is reset. + GET_LONG; + str->poisoner = NULL; + + // mobj_t *attacker; + // Pointer value is reset. + GET_LONG; + str->attacker = NULL; + + // int extralight; + str->extralight = GET_LONG; + + // int fixedcolormap; + str->fixedcolormap = GET_LONG; + + // int colormap; + str->colormap = GET_LONG; + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // int morphTics; + str->morphTics = GET_LONG; + + // unsigned int jumpTics; + str->jumpTics = GET_LONG; + + // unsigned int worldTimer; + str->worldTimer = GET_LONG; +} + +static void StreamOut_player_t(player_t *str) +{ + int i; + + // mobj_t *mo; + StreamOutPtr(str->mo); + + // playerstate_t playerstate; + StreamOutLong(str->playerstate); + + // ticcmd_t cmd; + StreamOut_ticcmd_t(&str->cmd); + + // pclass_t class; + StreamOutLong(str->class); + + // fixed_t viewz; + StreamOutLong(str->viewz); + + // fixed_t viewheight; + StreamOutLong(str->viewheight); + + // fixed_t deltaviewheight; + StreamOutLong(str->deltaviewheight); + + // fixed_t bob; + StreamOutLong(str->bob); + + // int flyheight; + StreamOutLong(str->flyheight); + + // int lookdir; + StreamOutLong(str->lookdir); + + // boolean centering; + StreamOutLong(str->centering); + + // int health; + StreamOutLong(str->health); + + // int armorpoints[NUMARMOR]; + for (i=0; iarmorpoints[i]); + } + + // inventory_t inventory[NUMINVENTORYSLOTS]; + for (i=0; iinventory[i]); + } + + // artitype_t readyArtifact; + StreamOutLong(str->readyArtifact); + + // int artifactCount; + StreamOutLong(str->artifactCount); + + // int inventorySlotNum; + StreamOutLong(str->inventorySlotNum); + + // int powers[NUMPOWERS]; + for (i=0; ipowers[i]); + } + + // int keys; + StreamOutLong(str->keys); + + // int pieces; + StreamOutLong(str->pieces); + + // signed int frags[MAXPLAYERS]; + for (i=0; ifrags[i]); + } + + // weapontype_t readyweapon; + StreamOutLong(str->readyweapon); + + // weapontype_t pendingweapon; + StreamOutLong(str->pendingweapon); + + // boolean weaponowned[NUMWEAPONS]; + for (i=0; iweaponowned[i]); + } + + // int mana[NUMMANA]; + for (i=0; imana[i]); + } + + // int attackdown, usedown; + StreamOutLong(str->attackdown); + StreamOutLong(str->usedown); + + // int cheats; + StreamOutLong(str->cheats); + + // int refire; + StreamOutLong(str->refire); + + // int killcount, itemcount, secretcount; + StreamOutLong(str->killcount); + StreamOutLong(str->itemcount); + StreamOutLong(str->secretcount); + + // char message[80]; + for (i=0; i<80; ++i) + { + StreamOutByte(str->message[i]); + } + + // int messageTics; + StreamOutLong(str->messageTics); + + // short ultimateMessage; + StreamOutWord(str->ultimateMessage); + + // short yellowMessage; + StreamOutWord(str->yellowMessage); + + // int damagecount, bonuscount; + StreamOutLong(str->damagecount); + StreamOutLong(str->bonuscount); + + // int poisoncount; + StreamOutLong(str->poisoncount); + + // mobj_t *poisoner; + StreamOutPtr(str->poisoner); + + // mobj_t *attacker; + StreamOutPtr(str->attacker); + + // int extralight; + StreamOutLong(str->extralight); + + // int fixedcolormap; + StreamOutLong(str->fixedcolormap); + + // int colormap; + StreamOutLong(str->colormap); + + // pspdef_t psprites[NUMPSPRITES]; + for (i=0; ipsprites[i]); + } + + // int morphTics; + StreamOutLong(str->morphTics); + + // unsigned int jumpTics; + StreamOutLong(str->jumpTics); + + // unsigned int worldTimer; + StreamOutLong(str->worldTimer); +} + + + //========================================================================== // // SV_SaveGame @@ -269,6 +791,7 @@ 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); @@ -290,8 +813,15 @@ void SV_SaveGame(int slot, char *description) StreamOutByte(gameskill); // Write global script info - StreamOutBuffer(WorldVars, sizeof(WorldVars)); - StreamOutBuffer(ACSStore, sizeof(ACSStore)); + 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(); @@ -394,10 +924,16 @@ void SV_LoadGame(int slot) gameskill = GET_BYTE; // Read global script info - memcpy(WorldVars, SavePtr.b, sizeof(WorldVars)); - SavePtr.b += sizeof(WorldVars); - memcpy(ACSStore, SavePtr.b, sizeof(ACSStore)); - SavePtr.b += sizeof(ACSStore); + + 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(); @@ -727,8 +1263,6 @@ void SV_InitBaseSlot(void) static void ArchivePlayers(void) { int i; - int j; - player_t tempPlayer; StreamOutLong(ASEG_PLAYERS); for (i = 0; i < MAXPLAYERS; i++) @@ -742,16 +1276,7 @@ static void ArchivePlayers(void) continue; } StreamOutByte(PlayerClass[i]); - tempPlayer = players[i]; - for (j = 0; j < NUMPSPRITES; j++) - { - if (tempPlayer.psprites[j].state) - { - tempPlayer.psprites[j].state = - (state_t *) (tempPlayer.psprites[j].state - states); - } - } - StreamOutBuffer(&tempPlayer, sizeof(player_t)); + StreamOut_player_t(&players[i]); } } @@ -763,7 +1288,7 @@ static void ArchivePlayers(void) static void UnarchivePlayers(void) { - int i, j; + int i; AssertSegment(ASEG_PLAYERS); for (i = 0; i < MAXPLAYERS; i++) @@ -777,20 +1302,8 @@ static void UnarchivePlayers(void) continue; } PlayerClass[i] = GET_BYTE; - memcpy(&players[i], SavePtr.b, sizeof(player_t)); - SavePtr.b += sizeof(player_t); - players[i].mo = NULL; // Will be set when unarc thinker + StreamIn_player_t(&players[i]); P_ClearMessage(&players[i]); - players[i].attacker = NULL; - players[i].poisoner = 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]; - } - } } } @@ -1361,7 +1874,11 @@ static void ArchiveScripts(void) StreamOutWord(ACSInfo[i].state); StreamOutWord(ACSInfo[i].waitValue); } - StreamOutBuffer(MapVars, sizeof(MapVars)); + + for (i = 0; i< MAX_ACS_MAP_VARS; ++i) + { + StreamOutLong(MapVars[i]); + } } //========================================================================== @@ -1380,8 +1897,11 @@ static void UnarchiveScripts(void) ACSInfo[i].state = GET_WORD; ACSInfo[i].waitValue = GET_WORD; } - memcpy(MapVars, SavePtr.b, sizeof(MapVars)); - SavePtr.b += sizeof(MapVars); + + for (i = 0; i < MAX_ACS_MAP_VARS; ++i) + { + MapVars[i] = GET_LONG; + } } //========================================================================== @@ -1753,6 +2273,7 @@ static void StreamOutByte(byte val) static void StreamOutWord(unsigned short val) { + val = SHORT(val); fwrite(&val, sizeof(unsigned short), 1, SavingFP); } @@ -1764,5 +2285,26 @@ static void StreamOutWord(unsigned short val) static void StreamOutLong(unsigned int val) { + val = LONG(val); fwrite(&val, sizeof(int), 1, SavingFP); } + +//========================================================================== +// +// StreamOutPtr +// +//========================================================================== + +static void StreamOutPtr(void *val) +{ + long ptr; + + // Write a pointer value. In Vanilla Hexen pointers are 32-bit but + // nowadays they might be larger. Whatever value we write here isn't + // going to be much use when we reload the game. + + ptr = (long) val; + StreamOutLong((unsigned int) (ptr & 0xffffffff)); +} + + -- cgit v1.2.3