mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-18 02:01:39 +00:00
0157446ad1
This was one huge mess where nothing fit together. Also added an enhancement that the CD Audio boss theme tracks are also played when CD music is generally off, because these have no equivalent in MIDI. This needs to be checked if it's stylistically ok, though.
1272 lines
39 KiB
C++
1272 lines
39 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 "keys.h"
|
|
#include "names2.h"
|
|
#include "panel.h"
|
|
#include "game.h"
|
|
#include "tags.h"
|
|
#include "lists.h"
|
|
#include "interp.h"
|
|
|
|
#include "network.h"
|
|
//#include "save.h"
|
|
#include "savedef.h"
|
|
#include "jsector.h"
|
|
#include "parent.h"
|
|
#include "reserve.h"
|
|
|
|
//#define FILE_TYPE 1
|
|
#include "mfile.h"
|
|
|
|
#include "fx_man.h"
|
|
#include "music.h"
|
|
|
|
#include "weapon.h"
|
|
#include "cache.h"
|
|
#include "colormap.h"
|
|
#include "player.h"
|
|
#include "i_specialpaths.h"
|
|
#include "savegamehelp.h"
|
|
#include "z_music.h"
|
|
|
|
//void TimerFunc(task * Task);
|
|
BEGIN_SW_NS
|
|
|
|
// This cannot have a namespace declaration
|
|
#include "saveable.h"
|
|
|
|
/*
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
TO DO
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
*/
|
|
|
|
extern int lastUpdate;
|
|
extern uint8_t RedBookSong[40];
|
|
extern char UserMapName[80];
|
|
extern char SaveGameDescr[10][80];
|
|
extern int PlayClock;
|
|
extern short TotalKillable;
|
|
extern short LevelSecrets;
|
|
extern short Bunny_Count;
|
|
extern SWBOOL NewGame;
|
|
extern char CacheLastLevel[];
|
|
extern short PlayingLevel;
|
|
extern int GodMode;
|
|
extern int GameVersion;
|
|
//extern short Zombies;
|
|
|
|
extern SWBOOL serpwasseen;
|
|
extern SWBOOL sumowasseen;
|
|
extern SWBOOL zillawasseen;
|
|
extern short BossSpriteNum[3];
|
|
|
|
void ScreenTileLock(void);
|
|
void ScreenTileUnLock(void);
|
|
|
|
int ScreenSaveSetup(PLAYERp pp);
|
|
void ScreenSave(MFILE_WRITE fout);
|
|
|
|
int ScreenLoadSaveSetup(PLAYERp pp);
|
|
void ScreenLoad(MFILE_READ fin);
|
|
|
|
#define PANEL_SAVE 1
|
|
#define ANIM_SAVE 1
|
|
|
|
extern SW_PACKET loc;
|
|
extern char LevelName[20];
|
|
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;
|
|
|
|
fp = fopen("savegame symbols missing.txt", "a");
|
|
if (fp)
|
|
{
|
|
fprintf(fp,"data %p\n",ptr);
|
|
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;
|
|
|
|
fp = fopen("savegame symbols missing.txt", "a");
|
|
if (fp)
|
|
{
|
|
fprintf(fp,"code %p\n",ptr);
|
|
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;
|
|
SPRITE tsp;
|
|
SPRITEp sp;
|
|
PLAYER tp;
|
|
PLAYERp pp;
|
|
SECT_USERp sectu;
|
|
USER tu;
|
|
USERp u;
|
|
ANIM tanim;
|
|
ANIMp a;
|
|
int8_t code;
|
|
uint8_t data_code;
|
|
int16_t data_ndx;
|
|
PANEL_SPRITE tpanel_sprite;
|
|
PANEL_SPRITEp psp,cur,next;
|
|
SECTOR_OBJECTp sop;
|
|
int cnt = 0, saveisshot=0;
|
|
OrgTileP otp, next_otp;
|
|
|
|
Saveable_Init();
|
|
|
|
|
|
auto game_name = G_BuildSaveName(sv->Filename);
|
|
OpenSaveGameForWrite(game_name);
|
|
G_WriteSaveHeader(sv->SaveTitle, LevelInfo[Level].LevelName, LevelInfo[Level].Description);
|
|
fil = WriteSavegameChunk("snapshot.sw");
|
|
|
|
MWRITE(&GameVersion,sizeof(GameVersion),1,fil);
|
|
|
|
MWRITE(&Level,sizeof(Level),1,fil);
|
|
MWRITE(&Skill,sizeof(Skill),1,fil);
|
|
|
|
ScreenSaveSetup(&Player[myconnectindex]);
|
|
|
|
ScreenSave(fil);
|
|
|
|
ScreenTileUnLock();
|
|
|
|
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);
|
|
for (ndx = 0; ndx < MAX_INVENTORY; ndx++)
|
|
pp->InventorySprite[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->InventorySprite[ndx]);
|
|
pp->InventorySelectionBox = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->InventorySelectionBox);
|
|
pp->MiniBarHealthBox = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarHealthBox);
|
|
pp->MiniBarAmmo = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarAmmo);
|
|
for (ndx = 0; ndx < (short)SIZ(pp->MiniBarHealthBoxDigit); ndx++)
|
|
pp->MiniBarHealthBoxDigit[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarHealthBoxDigit[ndx]);
|
|
for (ndx = 0; ndx < (short)SIZ(pp->MiniBarAmmoDigit); ndx++)
|
|
pp->MiniBarAmmoDigit[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarAmmoDigit[ndx]);
|
|
#endif
|
|
|
|
MWRITE(&tp, sizeof(PLAYER),1,fil);
|
|
|
|
//////
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, pp->remote_sprite);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->remote.sop_control);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop_remote);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->hi_sectp);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->lo_sectp);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->hi_sp);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->lo_sp);
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, pp->last_camera_sp);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->SpriteP);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->UnderSpriteP);
|
|
|
|
saveisshot |= SaveSymCodeInfo(fil, pp->DoPlayerAction);
|
|
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop_control);
|
|
saveisshot |= SaveSymDataInfo(fil, pp->sop_riding);
|
|
}
|
|
|
|
#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);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->State);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->RetractState);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->PresentState);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->ActionState);
|
|
saveisshot |= SaveSymDataInfo(fil, psp->RestState);
|
|
saveisshot |= SaveSymCodeInfo(fil, psp->PanelSpriteFunc);
|
|
|
|
for (j = 0; j < SIZ(psp->over); j++)
|
|
{
|
|
saveisshot |= SaveSymDataInfo(fil, psp->over[j].State);
|
|
}
|
|
|
|
ndx++;
|
|
}
|
|
|
|
// store -1 when done for player
|
|
ndx = -1;
|
|
MWRITE(&ndx, sizeof(ndx),1,fil);
|
|
}
|
|
#endif
|
|
|
|
MWRITE(&numsectors,sizeof(numsectors),1,fil);
|
|
MWRITE(sector,sizeof(SECTOR), numsectors, fil);
|
|
|
|
//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);
|
|
}
|
|
}
|
|
|
|
MWRITE(&numwalls,sizeof(numwalls),1,fil);
|
|
MWRITE(wall,sizeof(WALL),numwalls,fil);
|
|
|
|
for (i = 0; i < MAXSPRITES; i++)
|
|
{
|
|
if (sprite[i].statnum != MAXSTATUS)
|
|
{
|
|
MWRITE(&i,sizeof(i),1,fil);
|
|
|
|
MWRITE(&sprite[i],sizeof(SPRITE),1,fil);
|
|
}
|
|
}
|
|
i = -1;
|
|
MWRITE(&i,sizeof(i),1,fil);
|
|
|
|
MWRITE(headspritesect,sizeof(headspritesect),1,fil);
|
|
MWRITE(prevspritesect,sizeof(prevspritesect),1,fil);
|
|
MWRITE(nextspritesect,sizeof(nextspritesect),1,fil);
|
|
MWRITE(headspritestat,sizeof(headspritestat),1,fil);
|
|
MWRITE(prevspritestat,sizeof(prevspritestat),1,fil);
|
|
MWRITE(nextspritestat,sizeof(nextspritestat),1,fil);
|
|
|
|
//User information
|
|
for (i = 0; i < MAXSPRITES; i++)
|
|
{
|
|
ndx = i;
|
|
if (User[i])
|
|
{
|
|
// write header
|
|
MWRITE(&ndx,sizeof(ndx),1,fil);
|
|
|
|
sp = &sprite[i];
|
|
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);
|
|
saveisshot |= SaveSymDataInfo(fil, u->State);
|
|
saveisshot |= SaveSymDataInfo(fil, u->Rot);
|
|
saveisshot |= SaveSymDataInfo(fil, u->StateStart);
|
|
saveisshot |= SaveSymDataInfo(fil, u->StateEnd);
|
|
saveisshot |= SaveSymDataInfo(fil, u->StateFallOverride);
|
|
saveisshot |= SaveSymCodeInfo(fil, u->ActorActionFunc);
|
|
saveisshot |= SaveSymDataInfo(fil, u->ActorActionSet);
|
|
saveisshot |= SaveSymDataInfo(fil, u->Personality);
|
|
saveisshot |= SaveSymDataInfo(fil, u->Attrib);
|
|
saveisshot |= SaveSymDataInfo(fil, u->sop_parent);
|
|
saveisshot |= SaveSymDataInfo(fil, u->hi_sectp);
|
|
saveisshot |= SaveSymDataInfo(fil, u->lo_sectp);
|
|
saveisshot |= SaveSymDataInfo(fil, u->hi_sp);
|
|
saveisshot |= SaveSymDataInfo(fil, u->lo_sp);
|
|
saveisshot |= SaveSymDataInfo(fil, u->SpriteP);
|
|
saveisshot |= SaveSymDataInfo(fil, u->PlayerP);
|
|
saveisshot |= SaveSymDataInfo(fil, u->tgt_sp);
|
|
}
|
|
}
|
|
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);
|
|
saveisshot |= SaveSymCodeInfo(fil, sop->PostMoveAnimator);
|
|
saveisshot |= SaveSymCodeInfo(fil, sop->Animator);
|
|
saveisshot |= SaveSymDataInfo(fil, sop->controller);
|
|
saveisshot |= SaveSymDataInfo(fil, sop->sp_child);
|
|
}
|
|
|
|
|
|
MWRITE(SineWaveFloor, sizeof(SineWaveFloor),1,fil);
|
|
MWRITE(SineWall, sizeof(SineWall),1,fil);
|
|
MWRITE(SpringBoard, sizeof(SpringBoard),1,fil);
|
|
//MWRITE(Rotate, sizeof(Rotate),1,fil);
|
|
//MWRITE(DoorAutoClose, sizeof(DoorAutoClose),1,fil);
|
|
MWRITE(&x_min_bound, sizeof(x_min_bound),1,fil);
|
|
MWRITE(&y_min_bound, sizeof(y_min_bound),1,fil);
|
|
MWRITE(&x_max_bound, sizeof(x_max_bound),1,fil);
|
|
MWRITE(&y_max_bound, sizeof(y_max_bound),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);
|
|
}
|
|
|
|
int32_t svel = 0, vel = 0, angvel = 0;
|
|
MWRITE(&vel,sizeof(vel),1,fil);
|
|
MWRITE(&svel,sizeof(svel),1,fil);
|
|
MWRITE(&angvel,sizeof(angvel),1,fil);
|
|
|
|
MWRITE(&loc,sizeof(loc),1,fil);
|
|
//MWRITE(&oloc,sizeof(oloc),1,fil);
|
|
//MWRITE(&fsync,sizeof(fsync),1,fil);
|
|
|
|
MWRITE(LevelName,sizeof(LevelName),1,fil);
|
|
MWRITE(&screenpeek,sizeof(screenpeek),1,fil);
|
|
MWRITE(&totalsynctics,sizeof(totalsynctics),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);
|
|
}
|
|
|
|
saveisshot |= SaveSymCodeInfo(fil, a->callback);
|
|
saveisshot |= SaveSymDataInfo(fil, a->callbackdata);
|
|
}
|
|
|
|
#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(&totalclock,sizeof(totalclock),1,fil);
|
|
MWRITE(&numframes,sizeof(numframes),1,fil);
|
|
MWRITE(&randomseed,sizeof(randomseed),1,fil);
|
|
MWRITE(&numshades,sizeof(numshades),1,fil);
|
|
|
|
MWRITE(&NormalVisibility,sizeof(NormalVisibility),1,fil);
|
|
MWRITE(&g_visibility,sizeof(g_visibility),1,fil);
|
|
MWRITE(¶llaxtype,sizeof(parallaxtype),1,fil);
|
|
MWRITE(¶llaxyoffs_override,sizeof(parallaxyoffs_override),1,fil);
|
|
MWRITE(¶llaxyscale_override,sizeof(parallaxyscale_override),1,fil);
|
|
MWRITE(&pskybits_override,sizeof(pskybits_override),1,fil);
|
|
|
|
MWRITE(&BorderInfo,sizeof(BorderInfo),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(&startofdynamicinterpolations,sizeof(startofdynamicinterpolations),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]);
|
|
|
|
// short interpolations
|
|
MWRITE(&short_numinterpolations,sizeof(short_numinterpolations),1,fil);
|
|
MWRITE(&short_startofdynamicinterpolations,sizeof(short_startofdynamicinterpolations),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]);
|
|
|
|
|
|
// 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(palette,sizeof(palette),1,fil);
|
|
MWRITE(palette_data,sizeof(palette_data),1,fil);
|
|
MWRITE(&gs,sizeof(gs),1,fil);
|
|
for (int i = 0; i < MAXTILES; i++)
|
|
{
|
|
MWRITE(&picanm[i], sizeof(picanm[i]), 1, fil);
|
|
}
|
|
|
|
MWRITE(&LevelSecrets,sizeof(LevelSecrets),1,fil);
|
|
|
|
MWRITE(show2dwall,sizeof(show2dwall),1,fil);
|
|
MWRITE(show2dsprite,sizeof(show2dsprite),1,fil);
|
|
MWRITE(show2dsector,sizeof(show2dsector),1,fil);
|
|
|
|
MWRITE(&Bunny_Count,sizeof(Bunny_Count),1,fil);
|
|
|
|
MWRITE(UserMapName,sizeof(UserMapName),1,fil);
|
|
MWRITE(&GodMode,sizeof(GodMode),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);
|
|
|
|
MCLOSE_WRITE(fil);
|
|
if (!saveisshot)
|
|
return FinishSavegameWrite();
|
|
|
|
return false;
|
|
}
|
|
|
|
|
|
extern SWBOOL LoadGameOutsideMoveLoop;
|
|
extern SWBOOL InMenuLevel;
|
|
|
|
bool GameInterface::LoadGame(FSaveGameNode* sv)
|
|
{
|
|
MFILE_READ fil;
|
|
int i,j,saveisshot=0;
|
|
short ndx,SpriteNum,sectnum;
|
|
PLAYERp pp = NULL;
|
|
SPRITEp sp;
|
|
USERp u;
|
|
SECTOR_OBJECTp sop;
|
|
SECT_USERp sectu;
|
|
int8_t code;
|
|
ANIMp a;
|
|
uint8_t data_code;
|
|
int16_t data_ndx;
|
|
PANEL_SPRITEp psp,next,cur;
|
|
PANEL_SPRITE tpanel_sprite;
|
|
OrgTileP otp, next_otp;
|
|
|
|
int RotNdx;
|
|
int StateStartNdx;
|
|
int StateNdx;
|
|
int StateEndNdx;
|
|
|
|
if (!InMenuLevel) PauseAction();
|
|
|
|
Saveable_Init();
|
|
|
|
auto game_name = G_BuildSaveName(sv->Filename);
|
|
OpenSaveGameForRead(game_name);
|
|
|
|
auto filr = ReadSavegameChunk("snapshot.sw");
|
|
if (!filr.isOpen()) return false;
|
|
fil = &filr;
|
|
|
|
MREAD(&i,sizeof(i),1,fil);
|
|
if (i != GameVersion)
|
|
{
|
|
MCLOSE_READ(fil);
|
|
return false;
|
|
}
|
|
|
|
// Don't terminate until you've made sure conditions are valid for loading.
|
|
if (InMenuLevel)
|
|
Mus_Stop();
|
|
else
|
|
TerminateLevel();
|
|
Terminate3DSounds();
|
|
|
|
Terminate3DSounds();
|
|
|
|
MREAD(&Level,sizeof(Level),1,fil);
|
|
MREAD(&Skill,sizeof(Skill),1,fil);
|
|
|
|
ScreenLoadSaveSetup(Player + myconnectindex);
|
|
ScreenLoad(fil);
|
|
ScreenTileUnLock();
|
|
|
|
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 (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
|
|
|
|
MREAD(&numsectors,sizeof(numsectors),1,fil);
|
|
MREAD(sector,sizeof(SECTOR),numsectors,fil);
|
|
|
|
//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);
|
|
}
|
|
}
|
|
|
|
MREAD(&numwalls,sizeof(numwalls),1,fil);
|
|
MREAD(wall,sizeof(WALL),numwalls,fil);
|
|
|
|
//Store all sprites to preserve indeces
|
|
MREAD(&i, sizeof(i),1,fil);
|
|
while (i != -1)
|
|
{
|
|
MREAD(&sprite[i], sizeof(SPRITE),1,fil);
|
|
MREAD(&i, sizeof(i),1,fil);
|
|
}
|
|
|
|
MREAD(headspritesect,sizeof(headspritesect),1,fil);
|
|
MREAD(prevspritesect,sizeof(prevspritesect),1,fil);
|
|
MREAD(nextspritesect,sizeof(nextspritesect),1,fil);
|
|
MREAD(headspritestat,sizeof(headspritestat),1,fil);
|
|
MREAD(prevspritestat,sizeof(prevspritestat),1,fil);
|
|
MREAD(nextspritestat,sizeof(nextspritestat),1,fil);
|
|
|
|
//User information
|
|
memset(User, 0, sizeof(User));
|
|
|
|
MREAD(&SpriteNum, sizeof(SpriteNum),1,fil);
|
|
while (SpriteNum != -1)
|
|
{
|
|
sp = &sprite[SpriteNum];
|
|
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(Rotate, sizeof(Rotate),1,fil);
|
|
//MREAD(DoorAutoClose, sizeof(DoorAutoClose),1,fil);
|
|
MREAD(&x_min_bound, sizeof(x_min_bound),1,fil);
|
|
MREAD(&y_min_bound, sizeof(y_min_bound),1,fil);
|
|
MREAD(&x_max_bound, sizeof(x_max_bound),1,fil);
|
|
MREAD(&y_max_bound, sizeof(y_max_bound),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);
|
|
}
|
|
}
|
|
|
|
int32_t svel, vel, angvel;
|
|
MREAD(&vel,sizeof(vel),1,fil);
|
|
MREAD(&svel,sizeof(svel),1,fil);
|
|
MREAD(&angvel,sizeof(angvel),1,fil);
|
|
|
|
MREAD(&loc,sizeof(loc),1,fil);
|
|
|
|
MREAD(LevelName,sizeof(LevelName),1,fil);
|
|
MREAD(&screenpeek,sizeof(screenpeek),1,fil);
|
|
MREAD(&totalsynctics,sizeof(totalsynctics),1,fil); // same as kens lockclock
|
|
|
|
// 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(&totalclock,sizeof(totalclock),1,fil);
|
|
MREAD(&numframes,sizeof(numframes),1,fil);
|
|
MREAD(&randomseed,sizeof(randomseed),1,fil);
|
|
MREAD(&numshades,sizeof(numshades),1,fil);
|
|
|
|
MREAD(&NormalVisibility,sizeof(NormalVisibility),1,fil);
|
|
MREAD(&g_visibility,sizeof(g_visibility),1,fil);
|
|
MREAD(¶llaxtype,sizeof(parallaxtype),1,fil);
|
|
MREAD(¶llaxyoffs_override,sizeof(parallaxyoffs_override),1,fil);
|
|
MREAD(¶llaxyscale_override,sizeof(parallaxyscale_override),1,fil);
|
|
MREAD(&pskybits_override,sizeof(pskybits_override),1,fil);
|
|
|
|
MREAD(&BorderInfo,sizeof(BorderInfo),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(&startofdynamicinterpolations,sizeof(startofdynamicinterpolations),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_startofdynamicinterpolations,sizeof(short_startofdynamicinterpolations),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; }
|
|
|
|
// 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(palette,sizeof(palette),1,fil);
|
|
MREAD(palette_data,sizeof(palette_data),1,fil);
|
|
|
|
MREAD(&gs,sizeof(gs),1,fil);
|
|
|
|
for (int i = 0; i < MAXTILES; i++)
|
|
{
|
|
MREAD(&picanm[i], sizeof(picanm[i]), 1, fil);
|
|
}
|
|
|
|
MREAD(&LevelSecrets,sizeof(LevelSecrets),1,fil);
|
|
|
|
MREAD(show2dwall,sizeof(show2dwall),1,fil);
|
|
MREAD(show2dsprite,sizeof(show2dsprite),1,fil);
|
|
MREAD(show2dsector,sizeof(show2dsector),1,fil);
|
|
|
|
MREAD(&Bunny_Count,sizeof(Bunny_Count),1,fil);
|
|
|
|
MREAD(UserMapName,sizeof(UserMapName),1,fil);
|
|
MREAD(&GodMode,sizeof(GodMode),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
|
|
|
|
if (Bstrcasecmp(CacheLastLevel, LevelName) != 0)
|
|
{
|
|
SetupPreCache();
|
|
DoTheCache();
|
|
}
|
|
|
|
// what is this for? don't remember
|
|
totalclock = totalsynctics;
|
|
ototalclock = totalsynctics;
|
|
|
|
// 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]);
|
|
|
|
for (ndx = 0; ndx < MAX_INVENTORY; ndx++)
|
|
pp->InventorySprite[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->InventorySprite[ndx]);
|
|
|
|
pp->Chops = PanelNdxToSprite(pp, (int)(intptr_t)pp->Chops);
|
|
pp->InventorySelectionBox = PanelNdxToSprite(pp, (int)(intptr_t)pp->InventorySelectionBox);
|
|
pp->MiniBarHealthBox = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarHealthBox);
|
|
pp->MiniBarAmmo = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarAmmo);
|
|
|
|
for (ndx = 0; ndx < (short)SIZ(pp->MiniBarHealthBoxDigit); ndx++)
|
|
pp->MiniBarHealthBoxDigit[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarHealthBoxDigit[ndx]);
|
|
|
|
for (ndx = 0; ndx < (short)SIZ(pp->MiniBarAmmoDigit); ndx++)
|
|
pp->MiniBarAmmoDigit[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarAmmoDigit[ndx]);
|
|
|
|
#endif
|
|
}
|
|
|
|
{
|
|
int SavePlayClock = PlayClock;
|
|
InitTimingVars();
|
|
PlayClock = SavePlayClock;
|
|
}
|
|
InitNetVars();
|
|
|
|
SetupAspectRatio();
|
|
SetRedrawScreen(Player + myconnectindex);
|
|
|
|
COVERsetbrightness(0,&palette_data[0][0]);
|
|
|
|
screenpeek = myconnectindex;
|
|
PlayingLevel = Level;
|
|
|
|
MUS_ResumeSaved();
|
|
if (snd_ambience)
|
|
StartAmbientSound();
|
|
FX_SetVolume(snd_fxvolume);
|
|
|
|
TRAVERSE_CONNECT(i)
|
|
{
|
|
Player[i].PlayerTalking = FALSE;
|
|
Player[i].TalkVocnum = -1;
|
|
Player[i].TalkVocHandle = -1;
|
|
Player[i].StartColor = 0;
|
|
}
|
|
|
|
// this is not a new game
|
|
NewGame = FALSE;
|
|
|
|
|
|
DoPlayerDivePalette(Player+myconnectindex);
|
|
DoPlayerNightVisionPalette(Player+myconnectindex);
|
|
|
|
|
|
ExitLevel = TRUE;
|
|
LoadGameOutsideMoveLoop = TRUE;
|
|
|
|
if (!InMenuLevel) ready2send = 1;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
ScreenSave(MFILE_WRITE fout)
|
|
{
|
|
// int num;
|
|
MWRITE((void *)tileData(SAVE_SCREEN_TILE), SAVE_SCREEN_XSIZE * SAVE_SCREEN_YSIZE, 1, fout);
|
|
// ASSERT(num == 1);
|
|
}
|
|
|
|
void
|
|
ScreenLoad(MFILE_READ fin)
|
|
{
|
|
int num;
|
|
|
|
renderSetTarget(SAVE_SCREEN_TILE, SAVE_SCREEN_YSIZE, SAVE_SCREEN_XSIZE);
|
|
|
|
num = MREAD(tileData(SAVE_SCREEN_TILE), SAVE_SCREEN_XSIZE * SAVE_SCREEN_YSIZE, 1, fin);
|
|
|
|
renderRestoreTarget();
|
|
}
|
|
|
|
END_SW_NS
|