mirror of
https://github.com/ZDoom/raze-gles.git
synced 2025-01-16 12:40:38 +00:00
77a2bcb958
This fell victim to some fudging code that was needed to avoid crashes with the original game loop. All that fudging could easily be removed now because nothing of it is needed anymore.
1082 lines
32 KiB
C++
1082 lines
32 KiB
C++
//-------------------------------------------------------------------------
|
|
/*
|
|
Copyright (C) 1997, 2005 - 3D Realms Entertainment
|
|
|
|
This file is part of Shadow Warrior version 1.2
|
|
|
|
Shadow Warrior 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
Original Source: 1997 - Frank Maddin and Jim Norwood
|
|
Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
|
|
*/
|
|
//-------------------------------------------------------------------------
|
|
|
|
#include "ns.h"
|
|
|
|
#define MAIN
|
|
#define QUIET
|
|
#include "build.h"
|
|
|
|
#include "names2.h"
|
|
#include "panel.h"
|
|
#include "game.h"
|
|
#include "tags.h"
|
|
#include "lists.h"
|
|
#include "interp.h"
|
|
#include "interpso.h"
|
|
|
|
#include "network.h"
|
|
#include "jsector.h"
|
|
#include "parent.h"
|
|
|
|
//#define FILE_TYPE 1
|
|
|
|
#include "weapon.h"
|
|
#include "misc.h"
|
|
#include "player.h"
|
|
#include "i_specialpaths.h"
|
|
#include "savegamehelp.h"
|
|
#include "raze_music.h"
|
|
#include "mapinfo.h"
|
|
|
|
//void TimerFunc(task * Task);
|
|
BEGIN_SW_NS
|
|
|
|
// This cannot have a namespace declaration
|
|
#include "saveable.h"
|
|
|
|
/*
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
TO DO
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
void InitLevelGlobals(void);
|
|
|
|
extern int lastUpdate;
|
|
extern char SaveGameDescr[10][80];
|
|
extern int PlayClock;
|
|
extern short Bunny_Count;
|
|
extern bool NewGame;
|
|
extern int GodMode;
|
|
extern int FinishTimer;
|
|
extern int FinishAnim;
|
|
extern int GameVersion;
|
|
//extern short Zombies;
|
|
|
|
extern bool serpwasseen;
|
|
extern bool sumowasseen;
|
|
extern bool zillawasseen;
|
|
extern short BossSpriteNum[3];
|
|
|
|
#define PANEL_SAVE 1
|
|
#define ANIM_SAVE 1
|
|
|
|
extern STATE s_NotRestored[];
|
|
|
|
OrgTileListP otlist[] = {&orgwalllist, &orgwalloverlist, &orgsectorceilinglist, &orgsectorfloorlist};
|
|
|
|
int PanelSpriteToNdx(PLAYERp pp, PANEL_SPRITEp psprite)
|
|
{
|
|
short ndx = 0;
|
|
PANEL_SPRITEp psp=NULL, next=NULL;
|
|
|
|
TRAVERSE(&pp->PanelSpriteList, psp, next)
|
|
{
|
|
if (psp == psprite)
|
|
return ndx;
|
|
|
|
ndx++;
|
|
}
|
|
|
|
// special case for pointing to the list head
|
|
if ((LIST)psprite == (LIST)&pp->PanelSpriteList)
|
|
return 9999;
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
PANEL_SPRITEp PanelNdxToSprite(PLAYERp pp, int ndx)
|
|
{
|
|
short count = 0;
|
|
PANEL_SPRITEp psp, next;
|
|
|
|
if (ndx == -1)
|
|
return NULL;
|
|
|
|
if (ndx == 9999)
|
|
return (PANEL_SPRITEp)&pp->PanelSpriteList;
|
|
|
|
TRAVERSE(&pp->PanelSpriteList, psp, next)
|
|
{
|
|
if (count == ndx)
|
|
return psp;
|
|
|
|
count++;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
int SaveSymDataInfo(MFILE_WRITE fil, void *ptr)
|
|
{
|
|
saveddatasym sym;
|
|
|
|
if (Saveable_FindDataSym(ptr, &sym))
|
|
{
|
|
FILE *fp;
|
|
|
|
assert(false);
|
|
fp = fopen("savegame symbols missing.txt", "a");
|
|
if (fp)
|
|
{
|
|
fprintf(fp,"data %p - reference variable xdim at %p\n",ptr, &xdim);
|
|
fclose(fp);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
MWRITE(&sym, sizeof(sym), 1, fil);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int SaveSymCodeInfo_raw(MFILE_WRITE fil, void *ptr)
|
|
{
|
|
savedcodesym sym;
|
|
|
|
if (Saveable_FindCodeSym(ptr, &sym))
|
|
{
|
|
FILE *fp;
|
|
|
|
assert(false);
|
|
fp = fopen("savegame symbols missing.txt", "a");
|
|
if (fp)
|
|
{
|
|
fprintf(fp,"code %p - reference function SaveSymDataInfo at %p\n",ptr, SaveSymDataInfo);
|
|
fclose(fp);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
MWRITE(&sym, sizeof(sym), 1, fil);
|
|
|
|
return 0;
|
|
}
|
|
template <typename T>
|
|
static int SaveSymCodeInfo(MFILE_WRITE fil, T * ptr)
|
|
{
|
|
return SaveSymCodeInfo_raw(fil, (void *)ptr);
|
|
}
|
|
|
|
int LoadSymDataInfo(MFILE_READ fil, void **ptr)
|
|
{
|
|
saveddatasym sym;
|
|
|
|
MREAD(&sym, sizeof(sym), 1, fil);
|
|
|
|
return Saveable_RestoreDataSym(&sym, ptr);
|
|
}
|
|
int LoadSymCodeInfo(MFILE_READ fil, void **ptr)
|
|
{
|
|
savedcodesym sym;
|
|
|
|
MREAD(&sym, sizeof(sym), 1, fil);
|
|
|
|
return Saveable_RestoreCodeSym(&sym, ptr);
|
|
}
|
|
|
|
|
|
|
|
bool GameInterface::SaveGame(FSaveGameNode *sv)
|
|
{
|
|
MFILE_WRITE fil;
|
|
int i,j;
|
|
short ndx;
|
|
PLAYER tp;
|
|
PLAYERp pp;
|
|
SECT_USERp sectu;
|
|
USER tu;
|
|
USERp u;
|
|
ANIM tanim;
|
|
ANIMp a;
|
|
PANEL_SPRITE tpanel_sprite;
|
|
PANEL_SPRITEp psp,cur,next;
|
|
SECTOR_OBJECTp sop;
|
|
int saveisshot=0;
|
|
OrgTileP otp, next_otp;
|
|
|
|
Saveable_Init();
|
|
|
|
|
|
// workaround until the level info here has been transitioned.
|
|
fil = WriteSavegameChunk("snapshot.sw");
|
|
|
|
MWRITE(&Skill,sizeof(Skill),1,fil);
|
|
|
|
MWRITE(&numplayers,sizeof(numplayers),1,fil);
|
|
MWRITE(&myconnectindex,sizeof(myconnectindex),1,fil);
|
|
MWRITE(&connecthead,sizeof(connecthead),1,fil);
|
|
MWRITE(connectpoint2,sizeof(connectpoint2),1,fil);
|
|
|
|
//save players info
|
|
pp = &tp;
|
|
for (i = 0; i < numplayers; i++)
|
|
{
|
|
memcpy(&tp, &Player[i], sizeof(PLAYER));
|
|
|
|
// this does not point to global data - this is allocated link list based
|
|
// save this inside the structure
|
|
#if PANEL_SAVE
|
|
pp->CurWpn = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->CurWpn);
|
|
for (ndx = 0; ndx < MAX_WEAPONS; ndx++)
|
|
pp->Wpn[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->Wpn[ndx]);
|
|
pp->Chops = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->Chops);
|
|
#endif
|
|
|
|
MWRITE(&tp, sizeof(PLAYER),1,fil);
|
|
|
|
//////
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, pp->remote_sprite);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->remote.sop_control);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop_remote);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->hi_sectp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->lo_sectp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->hi_sp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->lo_sp);
|
|
assert(!saveisshot);
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, pp->last_camera_sp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->SpriteP);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->UnderSpriteP);
|
|
assert(!saveisshot);
|
|
|
|
saveisshot |= SaveSymCodeInfo(fil, pp->DoPlayerAction);
|
|
assert(!saveisshot);
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop_control);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop_riding);
|
|
assert(!saveisshot);
|
|
}
|
|
|
|
#if PANEL_SAVE
|
|
// local copy
|
|
psp = &tpanel_sprite;
|
|
for (i = 0; i < numplayers; i++)
|
|
{
|
|
unsigned j;
|
|
pp = &Player[i];
|
|
ndx = 0;
|
|
|
|
TRAVERSE(&pp->PanelSpriteList, cur, next)
|
|
{
|
|
// this is a HEADER
|
|
MWRITE(&ndx, sizeof(ndx),1,fil);
|
|
|
|
memcpy(psp, cur, sizeof(PANEL_SPRITE));
|
|
|
|
// Panel Sprite - save in structure
|
|
psp->sibling = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(pp, cur->sibling);
|
|
MWRITE(psp, sizeof(PANEL_SPRITE),1,fil);
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, psp->PlayerP);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->State);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->RetractState);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->PresentState);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->ActionState);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->RestState);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymCodeInfo(fil, psp->PanelSpriteFunc);
|
|
assert(!saveisshot);
|
|
|
|
for (j = 0; j < SIZ(psp->over); j++)
|
|
{
|
|
saveisshot |= SaveSymDataInfo(fil, psp->over[j].State);
|
|
assert(!saveisshot);
|
|
}
|
|
|
|
ndx++;
|
|
}
|
|
|
|
// store -1 when done for player
|
|
ndx = -1;
|
|
MWRITE(&ndx, sizeof(ndx),1,fil);
|
|
}
|
|
#endif
|
|
|
|
//Sector User information
|
|
for (i = 0; i < numsectors; i++)
|
|
{
|
|
sectu = SectUser[i];
|
|
ndx = i;
|
|
if (sectu)
|
|
{
|
|
// write header
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
|
|
MWRITE(sectu,sizeof(SECT_USER),1,fil);
|
|
}
|
|
else
|
|
{
|
|
// write trailer
|
|
ndx = -1;
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
}
|
|
}
|
|
|
|
//User information
|
|
for (i = 0; i < MAXSPRITES; i++)
|
|
{
|
|
ndx = i;
|
|
if (User[i])
|
|
{
|
|
// write header
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
|
|
memcpy(&tu, User[i], sizeof(USER));
|
|
u = &tu;
|
|
|
|
MWRITE(u,sizeof(USER),1,fil);
|
|
|
|
if (u->WallShade)
|
|
{
|
|
MWRITE(u->WallShade,sizeof(*u->WallShade)*u->WallCount,1,fil);
|
|
}
|
|
|
|
if (u->rotator)
|
|
{
|
|
MWRITE(u->rotator,sizeof(*u->rotator),1,fil);
|
|
if (u->rotator->origx)
|
|
MWRITE(u->rotator->origx,sizeof(*u->rotator->origx)*u->rotator->num_walls,1,fil);
|
|
if (u->rotator->origy)
|
|
MWRITE(u->rotator->origy,sizeof(*u->rotator->origy)*u->rotator->num_walls,1,fil);
|
|
}
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, u->WallP);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->State);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->Rot);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->StateStart);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->StateEnd);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->StateFallOverride);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymCodeInfo(fil, u->ActorActionFunc);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->ActorActionSet);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->Personality);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->Attrib);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->sop_parent);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->hi_sectp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->lo_sectp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->hi_sp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->lo_sp);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->SpriteP);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->PlayerP);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->tgt_sp);
|
|
assert(!saveisshot);
|
|
}
|
|
}
|
|
ndx = -1;
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
|
|
//
|
|
// Sector object
|
|
//
|
|
|
|
MWRITE(SectorObject, sizeof(SectorObject),1,fil);
|
|
|
|
for (ndx = 0; ndx < (short)SIZ(SectorObject); ndx++)
|
|
{
|
|
sop = &SectorObject[ndx];
|
|
|
|
saveisshot |= SaveSymCodeInfo(fil, sop->PreMoveAnimator);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymCodeInfo(fil, sop->PostMoveAnimator);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymCodeInfo(fil, sop->Animator);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, sop->controller);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, sop->sp_child);
|
|
assert(!saveisshot);
|
|
}
|
|
|
|
|
|
MWRITE(SineWaveFloor, sizeof(SineWaveFloor),1,fil);
|
|
MWRITE(SineWall, sizeof(SineWall),1,fil);
|
|
MWRITE(SpringBoard, sizeof(SpringBoard),1,fil);
|
|
|
|
|
|
MWRITE(Track, sizeof(Track),1,fil);
|
|
for (i = 0; i < MAX_TRACKS; i++)
|
|
{
|
|
ASSERT(Track[i].TrackPoint);
|
|
if (Track[i].NumPoints == 0)
|
|
MWRITE(Track[i].TrackPoint, sizeof(TRACK_POINT),1,fil);
|
|
else
|
|
MWRITE(Track[i].TrackPoint, Track[i].NumPoints * sizeof(TRACK_POINT),1,fil);
|
|
}
|
|
|
|
// MWRITE(&loc,sizeof(loc),1,fil);
|
|
MWRITE(&screenpeek,sizeof(screenpeek),1,fil);
|
|
MWRITE(&randomseed, sizeof(randomseed), 1, fil);
|
|
|
|
// do all sector manipulation structures
|
|
|
|
#if ANIM_SAVE
|
|
#if 1
|
|
MWRITE(&AnimCnt,sizeof(AnimCnt),1,fil);
|
|
|
|
for (i = 0, a = &tanim; i < AnimCnt; i++)
|
|
{
|
|
intptr_t offset;
|
|
memcpy(a,&Anim[i],sizeof(ANIM));
|
|
|
|
// maintain compatibility with sinking boat which points to user data
|
|
for (j=0; j<MAXSPRITES; j++)
|
|
{
|
|
if (User[j])
|
|
{
|
|
uint8_t* bp = (uint8_t*)User[j];
|
|
|
|
if ((uint8_t*)a->ptr >= bp && (uint8_t*)a->ptr < bp + sizeof(USER))
|
|
{
|
|
offset = (intptr_t)((uint8_t*)a->ptr - bp); // offset from user data
|
|
a->ptr = (int *)-2;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ((intptr_t)a->ptr != -2)
|
|
{
|
|
for (j=0; j<numsectors; j++)
|
|
{
|
|
if (SectUser[j])
|
|
{
|
|
uint8_t* bp = (uint8_t*)SectUser[j];
|
|
|
|
if ((uint8_t*)a->ptr >= bp && (uint8_t*)a->ptr < bp + sizeof(SECT_USER))
|
|
{
|
|
offset = (intptr_t)((uint8_t*)a->ptr - bp); // offset from user data
|
|
a->ptr = (int *)-3;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
MWRITE(a,sizeof(ANIM),1,fil);
|
|
|
|
if ((intptr_t)a->ptr == -2 || (intptr_t)a->ptr == -3)
|
|
{
|
|
MWRITE(&j, sizeof(j),1,fil);
|
|
MWRITE(&offset, sizeof(offset),1,fil);
|
|
}
|
|
else
|
|
{
|
|
saveisshot |= SaveSymDataInfo(fil, a->ptr);
|
|
assert(!saveisshot);
|
|
}
|
|
|
|
saveisshot |= SaveSymCodeInfo(fil, a->callback);
|
|
assert(!saveisshot);
|
|
saveisshot |= SaveSymDataInfo(fil, a->callbackdata);
|
|
assert(!saveisshot);
|
|
}
|
|
|
|
#else
|
|
ndx = 0;
|
|
for (i = AnimCnt - 1, a = &tanim; i >= 0; i--)
|
|
{
|
|
// write header
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
|
|
memcpy(a,&Anim[i],sizeof(ANIM));
|
|
MWRITE(a,sizeof(ANIM),1,fil);
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, a->ptr);
|
|
saveisshot |= SaveSymCodeInfo(fil, a->callback);
|
|
saveisshot |= SaveSymDataInfo(fil, a->callbackdata);
|
|
|
|
ndx++;
|
|
}
|
|
|
|
// write trailer
|
|
ndx = -1;
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
#endif
|
|
#endif
|
|
|
|
MWRITE(&NormalVisibility,sizeof(NormalVisibility),1,fil);
|
|
MWRITE(&MoveSkip2,sizeof(MoveSkip2),1,fil);
|
|
MWRITE(&MoveSkip4,sizeof(MoveSkip4),1,fil);
|
|
MWRITE(&MoveSkip8,sizeof(MoveSkip8),1,fil);
|
|
|
|
// long interpolations
|
|
MWRITE(&numinterpolations,sizeof(numinterpolations),1,fil);
|
|
MWRITE(oldipos,sizeof(oldipos),1,fil);
|
|
MWRITE(bakipos,sizeof(bakipos),1,fil);
|
|
for (i = numinterpolations - 1; i >= 0; i--)
|
|
{
|
|
saveisshot |= SaveSymDataInfo(fil, curipos[i]);
|
|
assert(!saveisshot);
|
|
}
|
|
|
|
// short interpolations
|
|
MWRITE(&short_numinterpolations,sizeof(short_numinterpolations),1,fil);
|
|
MWRITE(short_oldipos,sizeof(short_oldipos),1,fil);
|
|
MWRITE(short_bakipos,sizeof(short_bakipos),1,fil);
|
|
for (i = short_numinterpolations - 1; i >= 0; i--)
|
|
{
|
|
saveisshot |= SaveSymDataInfo(fil, short_curipos[i]);
|
|
assert(!saveisshot);
|
|
}
|
|
|
|
// SO interpolations
|
|
saveisshot |= so_writeinterpolations(fil);
|
|
assert(!saveisshot);
|
|
|
|
// parental lock
|
|
for (i = 0; i < (int)SIZ(otlist); i++)
|
|
{
|
|
ndx = 0;
|
|
TRAVERSE(otlist[i], otp, next_otp)
|
|
{
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
MWRITE(&otp,sizeof(*otp),1,fil);
|
|
ndx++;
|
|
}
|
|
ndx = -1;
|
|
MWRITE(&ndx, sizeof(ndx),1,fil);
|
|
}
|
|
|
|
// mirror
|
|
MWRITE(mirror,sizeof(mirror),1,fil);
|
|
MWRITE(&mirrorcnt,sizeof(mirrorcnt),1,fil);
|
|
MWRITE(&mirrorinview,sizeof(mirrorinview),1,fil);
|
|
|
|
// queue
|
|
MWRITE(&StarQueueHead,sizeof(StarQueueHead),1,fil);
|
|
MWRITE(StarQueue,sizeof(StarQueue),1,fil);
|
|
MWRITE(&HoleQueueHead,sizeof(HoleQueueHead),1,fil);
|
|
MWRITE(HoleQueue,sizeof(HoleQueue),1,fil);
|
|
MWRITE(&WallBloodQueueHead,sizeof(WallBloodQueueHead),1,fil);
|
|
MWRITE(WallBloodQueue,sizeof(WallBloodQueue),1,fil);
|
|
MWRITE(&FloorBloodQueueHead,sizeof(FloorBloodQueueHead),1,fil);
|
|
MWRITE(FloorBloodQueue,sizeof(FloorBloodQueue),1,fil);
|
|
MWRITE(&GenericQueueHead,sizeof(GenericQueueHead),1,fil);
|
|
MWRITE(GenericQueue,sizeof(GenericQueue),1,fil);
|
|
MWRITE(&LoWangsQueueHead,sizeof(LoWangsQueueHead),1,fil);
|
|
MWRITE(LoWangsQueue,sizeof(LoWangsQueue),1,fil);
|
|
|
|
MWRITE(&PlayClock,sizeof(PlayClock),1,fil);
|
|
MWRITE(&TotalKillable,sizeof(TotalKillable),1,fil);
|
|
|
|
// game settings
|
|
MWRITE(&gNet,sizeof(gNet),1,fil);
|
|
|
|
MWRITE(&gs,sizeof(gs),1,fil);
|
|
|
|
MWRITE(&LevelSecrets,sizeof(LevelSecrets),1,fil);
|
|
|
|
MWRITE(&Bunny_Count,sizeof(Bunny_Count),1,fil);
|
|
|
|
MWRITE(&GodMode,sizeof(GodMode),1,fil);
|
|
|
|
MWRITE(&FinishTimer,sizeof(FinishTimer),1,fil);
|
|
MWRITE(&FinishAnim,sizeof(FinishAnim),1,fil);
|
|
|
|
MWRITE(&serpwasseen, sizeof(serpwasseen), 1, fil);
|
|
MWRITE(&sumowasseen, sizeof(sumowasseen), 1, fil);
|
|
MWRITE(&zillawasseen, sizeof(zillawasseen), 1, fil);
|
|
MWRITE(BossSpriteNum, sizeof(BossSpriteNum), 1, fil);
|
|
//MWRITE(&Zombies, sizeof(Zombies), 1, fil);
|
|
|
|
return !saveisshot;
|
|
}
|
|
|
|
|
|
bool GameInterface::LoadGame(FSaveGameNode* sv)
|
|
{
|
|
MFILE_READ fil;
|
|
int i,j,saveisshot=0;
|
|
short ndx,SpriteNum,sectnum;
|
|
PLAYERp pp = NULL;
|
|
USERp u;
|
|
SECTOR_OBJECTp sop;
|
|
SECT_USERp sectu;
|
|
ANIMp a;
|
|
PANEL_SPRITEp psp,next;
|
|
OrgTileP otp;
|
|
|
|
|
|
Saveable_Init();
|
|
|
|
auto filr = ReadSavegameChunk("snapshot.sw");
|
|
if (!filr.isOpen()) return false;
|
|
fil = &filr;
|
|
|
|
MREAD(&Skill,sizeof(Skill),1,fil);
|
|
|
|
MREAD(&numplayers, sizeof(numplayers),1,fil);
|
|
MREAD(&myconnectindex,sizeof(myconnectindex),1,fil);
|
|
MREAD(&connecthead,sizeof(connecthead),1,fil);
|
|
MREAD(connectpoint2,sizeof(connectpoint2),1,fil);
|
|
|
|
//save players
|
|
//MREAD(Player,sizeof(PLAYER), numplayers,fil);
|
|
|
|
//save players info
|
|
|
|
for (auto& pp : Player)
|
|
{
|
|
pp.cookieTime = 0;
|
|
memset(pp.cookieQuote, 0, sizeof(pp.cookieQuote));
|
|
}
|
|
|
|
for (i = 0; i < numplayers; i++)
|
|
{
|
|
pp = &Player[i];
|
|
|
|
MREAD(pp, sizeof(*pp), 1, fil);
|
|
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->remote_sprite);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->remote.sop_control);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->sop_remote);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->sop);
|
|
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->hi_sectp);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->lo_sectp);
|
|
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->hi_sp);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->lo_sp);
|
|
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->last_camera_sp);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->SpriteP);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->UnderSpriteP);
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&pp->DoPlayerAction);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->sop_control);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&pp->sop_riding);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
}
|
|
|
|
|
|
#if PANEL_SAVE
|
|
for (i = 0; i < numplayers; i++)
|
|
{
|
|
int j;
|
|
pp = &Player[i];
|
|
|
|
INITLIST(&pp->PanelSpriteList);
|
|
|
|
while (true)
|
|
{
|
|
MREAD(&ndx, sizeof(ndx),1,fil);
|
|
|
|
if (ndx == -1)
|
|
break;
|
|
|
|
psp = (PANEL_SPRITEp)CallocMem(sizeof(PANEL_SPRITE), 1);
|
|
ASSERT(psp);
|
|
|
|
MREAD(psp, sizeof(PANEL_SPRITE),1,fil);
|
|
INSERT_TAIL(&pp->PanelSpriteList,psp);
|
|
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&psp->PlayerP);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&psp->State);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&psp->RetractState);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&psp->PresentState);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&psp->ActionState);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&psp->RestState);
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&psp->PanelSpriteFunc);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
|
|
for (j = 0; j < (int)SIZ(psp->over); j++)
|
|
{
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&psp->over[j].State);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
}
|
|
|
|
}
|
|
}
|
|
#endif
|
|
|
|
//Sector User information
|
|
for (i = 0; i < numsectors; i++)
|
|
{
|
|
MREAD(§num,sizeof(sectnum),1,fil);
|
|
if (sectnum != -1)
|
|
{
|
|
SectUser[sectnum] = sectu = (SECT_USERp)CallocMem(sizeof(SECT_USER), 1);
|
|
MREAD(sectu,sizeof(SECT_USER),1,fil);
|
|
}
|
|
}
|
|
|
|
//User information
|
|
memset(User, 0, sizeof(User));
|
|
|
|
MREAD(&SpriteNum, sizeof(SpriteNum),1,fil);
|
|
while (SpriteNum != -1)
|
|
{
|
|
User[SpriteNum] = u = (USERp)CallocMem(sizeof(USER), 1);
|
|
MREAD(u,sizeof(USER),1,fil);
|
|
|
|
if (u->WallShade)
|
|
{
|
|
u->WallShade = (int8_t*)CallocMem(u->WallCount * sizeof(*u->WallShade), 1);
|
|
MREAD(u->WallShade,sizeof(*u->WallShade)*u->WallCount,1,fil);
|
|
}
|
|
|
|
if (u->rotator)
|
|
{
|
|
u->rotator = (ROTATORp)CallocMem(sizeof(*u->rotator), 1);
|
|
MREAD(u->rotator,sizeof(*u->rotator),1,fil);
|
|
|
|
if (u->rotator->origx)
|
|
{
|
|
u->rotator->origx = (int*)CallocMem(u->rotator->num_walls * sizeof(*u->rotator->origx), 1);
|
|
MREAD(u->rotator->origx,sizeof(*u->rotator->origx)*u->rotator->num_walls,1,fil);
|
|
}
|
|
if (u->rotator->origy)
|
|
{
|
|
u->rotator->origy = (int*)CallocMem(u->rotator->num_walls * sizeof(*u->rotator->origy), 1);
|
|
MREAD(u->rotator->origy,sizeof(*u->rotator->origy)*u->rotator->num_walls,1,fil);
|
|
}
|
|
}
|
|
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->WallP);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->State);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->Rot);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->StateStart);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->StateEnd);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->StateFallOverride);
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&u->ActorActionFunc);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->ActorActionSet);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->Personality);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->Attrib);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->sop_parent);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->hi_sectp);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->lo_sectp);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->hi_sp);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->lo_sp);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->SpriteP);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->PlayerP);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&u->tgt_sp);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
|
|
MREAD(&SpriteNum,sizeof(SpriteNum),1,fil);
|
|
}
|
|
|
|
MREAD(SectorObject, sizeof(SectorObject),1,fil);
|
|
|
|
for (ndx = 0; ndx < (short)SIZ(SectorObject); ndx++)
|
|
{
|
|
sop = &SectorObject[ndx];
|
|
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&sop->PreMoveAnimator);
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&sop->PostMoveAnimator);
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&sop->Animator);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&sop->controller);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&sop->sp_child);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
}
|
|
|
|
MREAD(SineWaveFloor, sizeof(SineWaveFloor),1,fil);
|
|
MREAD(SineWall, sizeof(SineWall),1,fil);
|
|
MREAD(SpringBoard, sizeof(SpringBoard),1,fil);
|
|
|
|
MREAD(Track, sizeof(Track),1,fil);
|
|
for (i = 0; i < MAX_TRACKS; i++)
|
|
{
|
|
if (Track[i].NumPoints == 0)
|
|
{
|
|
Track[i].TrackPoint = (TRACK_POINTp)CallocMem(sizeof(TRACK_POINT), 1);
|
|
MREAD(Track[i].TrackPoint, sizeof(TRACK_POINT),1,fil);
|
|
}
|
|
else
|
|
{
|
|
Track[i].TrackPoint = (TRACK_POINTp)CallocMem(Track[i].NumPoints * sizeof(TRACK_POINT), 1);
|
|
MREAD(Track[i].TrackPoint, Track[i].NumPoints * sizeof(TRACK_POINT),1,fil);
|
|
}
|
|
}
|
|
|
|
// MREAD(&loc,sizeof(loc),1,fil);
|
|
|
|
MREAD(&screenpeek,sizeof(screenpeek),1,fil);
|
|
MREAD(&randomseed, sizeof(randomseed), 1, fil);
|
|
|
|
// do all sector manipulation structures
|
|
|
|
#if ANIM_SAVE
|
|
#if 1
|
|
MREAD(&AnimCnt,sizeof(AnimCnt),1,fil);
|
|
|
|
for (i = 0; i < AnimCnt; i++)
|
|
{
|
|
a = &Anim[i];
|
|
MREAD(a,sizeof(ANIM),1,fil);
|
|
|
|
if ((intptr_t)a->ptr == -2)
|
|
{
|
|
// maintain compatibility with sinking boat which points to user data
|
|
int offset;
|
|
MREAD(&j, sizeof(j),1,fil);
|
|
MREAD(&offset, sizeof(offset),1,fil);
|
|
a->ptr = (int *)(((char *)User[j]) + offset);
|
|
}
|
|
else if ((intptr_t)a->ptr == -3)
|
|
{
|
|
// maintain compatibility with sinking boat which points to user data
|
|
int offset;
|
|
MREAD(&j, sizeof(j),1,fil);
|
|
MREAD(&offset, sizeof(offset),1,fil);
|
|
a->ptr = (int *)(((char *)SectUser[j]) + offset);
|
|
}
|
|
else
|
|
{
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&a->ptr);
|
|
}
|
|
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&a->callback);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&a->callbackdata);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
}
|
|
#else
|
|
AnimCnt = 0;
|
|
for (i = MAXANIM - 1; i >= 0; i--)
|
|
{
|
|
a = &Anim[i];
|
|
|
|
MREAD(&ndx,sizeof(ndx),1,fil);
|
|
|
|
if (ndx == -1)
|
|
break;
|
|
|
|
AnimCnt++;
|
|
|
|
MREAD(a,sizeof(ANIM),1,fil);
|
|
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&a->ptr);
|
|
saveisshot |= LoadSymCodeInfo(fil, (void **)&a->callback);
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&a->callbackdata);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
MREAD(&NormalVisibility,sizeof(NormalVisibility),1,fil);
|
|
|
|
MREAD(&MoveSkip2,sizeof(MoveSkip2),1,fil);
|
|
MREAD(&MoveSkip4,sizeof(MoveSkip4),1,fil);
|
|
MREAD(&MoveSkip8,sizeof(MoveSkip8),1,fil);
|
|
|
|
// long interpolations
|
|
MREAD(&numinterpolations,sizeof(numinterpolations),1,fil);
|
|
MREAD(oldipos,sizeof(oldipos),1,fil);
|
|
MREAD(bakipos,sizeof(bakipos),1,fil);
|
|
for (i = numinterpolations - 1; i >= 0; i--)
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&curipos[i]);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
|
|
// short interpolations
|
|
MREAD(&short_numinterpolations,sizeof(short_numinterpolations),1,fil);
|
|
MREAD(short_oldipos,sizeof(short_oldipos),1,fil);
|
|
MREAD(short_bakipos,sizeof(short_bakipos),1,fil);
|
|
for (i = short_numinterpolations - 1; i >= 0; i--)
|
|
saveisshot |= LoadSymDataInfo(fil, (void **)&short_curipos[i]);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
|
|
// SO interpolations
|
|
saveisshot |= so_readinterpolations(fil);
|
|
if (saveisshot) { MCLOSE_READ(fil); return false; }
|
|
|
|
// parental lock
|
|
for (i = 0; i < (int)SIZ(otlist); i++)
|
|
{
|
|
INITLIST(otlist[i]);
|
|
|
|
while (true)
|
|
{
|
|
MREAD(&ndx, sizeof(ndx),1,fil);
|
|
|
|
if (ndx == -1)
|
|
break;
|
|
|
|
otp = (OrgTileP)CallocMem(sizeof(*otp), 1);
|
|
ASSERT(otp);
|
|
|
|
MREAD(otp, sizeof(*otp),1,fil);
|
|
INSERT_TAIL(otlist[i],otp);
|
|
}
|
|
}
|
|
|
|
// mirror
|
|
MREAD(mirror,sizeof(mirror),1,fil);
|
|
MREAD(&mirrorcnt,sizeof(mirrorcnt),1,fil);
|
|
MREAD(&mirrorinview,sizeof(mirrorinview),1,fil);
|
|
|
|
// queue
|
|
MREAD(&StarQueueHead,sizeof(StarQueueHead),1,fil);
|
|
MREAD(StarQueue,sizeof(StarQueue),1,fil);
|
|
MREAD(&HoleQueueHead,sizeof(HoleQueueHead),1,fil);
|
|
MREAD(HoleQueue,sizeof(HoleQueue),1,fil);
|
|
MREAD(&WallBloodQueueHead,sizeof(WallBloodQueueHead),1,fil);
|
|
MREAD(WallBloodQueue,sizeof(WallBloodQueue),1,fil);
|
|
MREAD(&FloorBloodQueueHead,sizeof(FloorBloodQueueHead),1,fil);
|
|
MREAD(FloorBloodQueue,sizeof(FloorBloodQueue),1,fil);
|
|
MREAD(&GenericQueueHead,sizeof(GenericQueueHead),1,fil);
|
|
MREAD(GenericQueue,sizeof(GenericQueue),1,fil);
|
|
MREAD(&LoWangsQueueHead,sizeof(LoWangsQueueHead),1,fil);
|
|
MREAD(LoWangsQueue,sizeof(LoWangsQueue),1,fil);
|
|
|
|
// init timing vars before PlayClock is read
|
|
MREAD(&PlayClock,sizeof(PlayClock),1,fil);
|
|
MREAD(&TotalKillable,sizeof(TotalKillable),1,fil);
|
|
|
|
// game settings
|
|
MREAD(&gNet,sizeof(gNet),1,fil);
|
|
|
|
MREAD(&gs,sizeof(gs),1,fil);
|
|
|
|
MREAD(&LevelSecrets,sizeof(LevelSecrets),1,fil);
|
|
|
|
MREAD(&Bunny_Count,sizeof(Bunny_Count),1,fil);
|
|
|
|
MREAD(&GodMode,sizeof(GodMode),1,fil);
|
|
|
|
MREAD(&FinishTimer,sizeof(FinishTimer),1,fil);
|
|
MREAD(&FinishAnim,sizeof(FinishAnim),1,fil);
|
|
|
|
MREAD(&serpwasseen, sizeof(serpwasseen), 1, fil);
|
|
MREAD(&sumowasseen, sizeof(sumowasseen), 1, fil);
|
|
MREAD(&zillawasseen, sizeof(zillawasseen), 1, fil);
|
|
MREAD(BossSpriteNum, sizeof(BossSpriteNum), 1, fil);
|
|
//MREAD(&Zombies, sizeof(Zombies), 1, fil);
|
|
|
|
MCLOSE_READ(fil);
|
|
|
|
|
|
//!!IMPORTANT - this POST stuff will not work here now becaus it does actual reads
|
|
|
|
|
|
//
|
|
// POST processing of info MREAD in
|
|
//
|
|
|
|
#if PANEL_SAVE
|
|
for (i = 0; i < numplayers; i++)
|
|
{
|
|
pp = &Player[i];
|
|
TRAVERSE(&pp->PanelSpriteList, psp, next)
|
|
{
|
|
// dont need to set Next and Prev this was done
|
|
// when sprites were inserted
|
|
|
|
// sibling is the only PanelSprite (malloced ptr) in the PanelSprite struct
|
|
psp->sibling = PanelNdxToSprite(pp, (int)(intptr_t)psp->sibling);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
SetupPreCache();
|
|
DoTheCache();
|
|
|
|
// this is ok - just duplicating sector list with pointers
|
|
for (sop = SectorObject; sop < &SectorObject[SIZ(SectorObject)]; sop++)
|
|
{
|
|
for (i = 0; i < sop->num_sectors; i++)
|
|
sop->sectp[i] = §or[sop->sector[i]];
|
|
}
|
|
|
|
//!!Again this will not work here
|
|
//restore players info
|
|
for (i = 0; i < numplayers; i++)
|
|
{
|
|
#if PANEL_SAVE
|
|
pp->CurWpn = PanelNdxToSprite(pp, (int)(intptr_t)pp->CurWpn);
|
|
|
|
for (ndx = 0; ndx < MAX_WEAPONS; ndx++)
|
|
pp->Wpn[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->Wpn[ndx]);
|
|
|
|
pp->Chops = PanelNdxToSprite(pp, (int)(intptr_t)pp->Chops);
|
|
|
|
#endif
|
|
}
|
|
|
|
{
|
|
int SavePlayClock = PlayClock;
|
|
InitTimingVars();
|
|
PlayClock = SavePlayClock;
|
|
}
|
|
InitNetVars();
|
|
|
|
screenpeek = myconnectindex;
|
|
|
|
Mus_ResumeSaved();
|
|
if (snd_ambience)
|
|
StartAmbientSound();
|
|
|
|
TRAVERSE_CONNECT(i)
|
|
{
|
|
Player[i].StartColor = 0;
|
|
}
|
|
|
|
// this is not a new game
|
|
ShadowWarrior::NewGame = false;
|
|
|
|
|
|
DoPlayerDivePalette(Player+myconnectindex);
|
|
DoPlayerNightVisionPalette(Player+myconnectindex);
|
|
|
|
InitLevelGlobals();
|
|
return true;
|
|
}
|
|
|
|
END_SW_NS
|