UFO: Alien Invasion
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
cp_save.cpp
Go to the documentation of this file.
1 
6 /*
7 Copyright (C) 2002-2020 UFO: Alien Invasion.
8 
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13 
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 
18 See the GNU General Public License for more details.
19 
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 */
24 
25 #include "../../cl_shared.h"
26 #include "../cl_game.h" /* GAME_ReloadMode */
27 #include "cp_campaign.h"
28 #include "cp_save.h"
29 #include "cp_time.h"
30 #include "cp_xvi.h" /* CP_UpdateXVIMapButton */
31 #include "save/save.h"
32 
36 
41 static bool SAV_GameActionsAfterLoad (void)
42 {
43  bool result = true;
44 
45  result = result && AIR_PostLoadInit();
46  result = result && B_PostLoadInit();
47  result = result && PR_PostLoadInit();
48 
49  /* Make sure the date&time is displayed when loading. */
50  CP_UpdateTime();
51 
52  /* Update number of UFO detected by radar */
54 
55  /* Update the XVI button -- needs to be done after research was loaded */
57 
58  return result;
59 }
60 
65 static bool SAV_VerifyHeader (saveFileHeader_t const * const header)
66 {
67  size_t len;
68  /*check the length of the string*/
69  len = strlen(header->name);
70  if (len > sizeof(header->name)) {
71  cgi->Com_Printf("Name is " UFO_SIZE_T " Bytes long, max is " UFO_SIZE_T "\n", len, sizeof(header->name));
72  return false;
73  }
74  len = strlen(header->gameVersion);
75  if (len > sizeof(header->gameVersion)) {
76  cgi->Com_Printf("gameVersion is " UFO_SIZE_T " Bytes long, max is " UFO_SIZE_T "\n", len, sizeof(header->gameVersion));
77  return false;
78  }
79  len = strlen(header->gameDate);
80  if (len > sizeof(header->gameDate)) {
81  cgi->Com_Printf("gameDate is " UFO_SIZE_T " Bytes long, max is " UFO_SIZE_T "\n", len, sizeof(header->gameDate));
82  return false;
83  }
84  len = strlen(header->realDate);
85  if (len > sizeof(header->realDate)) {
86  cgi->Com_Printf("realDate is " UFO_SIZE_T " Bytes long, max is " UFO_SIZE_T "\n", len, sizeof(header->realDate));
87  return false;
88  }
89  if (header->subsystems != 0 && header->subsystems != saveSubsystemsAmount) {
90  cgi->Com_DPrintf(DEBUG_CLIENT, "Savefile has incompatible amount of subsystems\n");
91  }
92 
93  /* saved games should not be bigger than 15MB */
94  if (header->xmlSize > 15 * 1024 * 1024) {
95  cgi->Com_Printf("Save size seems to be to large (over 15 MB) %i.\n", header->xmlSize);
96  return false;
97  }
98  if (header->version == 0) {
99  cgi->Com_Printf("Version is invalid - must be greater than zero\n");
100  return false;
101  }
102  if (header->version > SAVE_FILE_VERSION) {
103  cgi->Com_Printf("Savefile is newer than the game!\n");
104  }
105  return true;
106 }
107 
114 bool SAV_LoadHeader (const char* filename, saveFileHeader_t* header)
115 {
116  assert(filename);
117  assert(header);
118 
119  char path[MAX_OSPATH];
120  cgi->GetRelativeSavePath(path, sizeof(path));
121  Q_strcat(path, sizeof(path), "%s.%s", filename, SAVEGAME_EXTENSION);
122  ScopedFile f;
123  cgi->FS_OpenFile(path, &f, FILE_READ);
124  if (!f) {
125  cgi->Com_Printf("Couldn't open file '%s'\n", filename);
126  return false;
127  }
128 
129  if (cgi->FS_Read(header, sizeof(saveFileHeader_t), &f) != sizeof(saveFileHeader_t)) {
130  cgi->Com_Printf("Warning: Could not read %lu bytes from savefile %s.%s\n", sizeof(saveFileHeader_t), filename, SAVEGAME_EXTENSION);
131  return false;
132  }
133 
134  header->compressed = LittleLong(header->compressed);
135  header->version = LittleLong(header->version);
136  header->xmlSize = LittleLong(header->xmlSize);
137 
138  if (!SAV_VerifyHeader(header)) {
139  cgi->Com_Printf("The Header of the savegame '%s.%s' is corrupted.\n", filename, SAVEGAME_EXTENSION);
140  return false;
141  }
142 
143  return true;
144 }
145 
152 bool SAV_GameLoad (const char* file, const char** error)
153 {
154  char filename[MAX_OSPATH];
155 
156  cgi->GetRelativeSavePath(filename, sizeof(filename));
157  Q_strcat(filename, sizeof(filename), "%s.%s", file, SAVEGAME_EXTENSION);
158  ScopedFile f;
159  const int clen = cgi->FS_OpenFile(filename, &f, FILE_READ);
160  if (!f) {
161  cgi->Com_Printf("Couldn't open file '%s'\n", filename);
162  *error = "File not found";
163  return false;
164  }
165 
166  byte* const cbuf = Mem_PoolAllocTypeN(byte, clen + 1 /* for '\0' if not compressed */, cp_campaignPool);
167  if (cgi->FS_Read(cbuf, clen, &f) != clen)
168  cgi->Com_Printf("Warning: Could not read %i bytes from savefile\n", clen);
169  cgi->Com_Printf("Loading savegame xml (size %d)\n", clen);
170 
171  saveFileHeader_t header;
172  memcpy(&header, cbuf, sizeof(header));
173  /* swap all int values if needed */
174  header.compressed = LittleLong(header.compressed);
175  header.version = LittleLong(header.version);
176  header.xmlSize = LittleLong(header.xmlSize);
177  /* doing some header verification */
178  if (!SAV_VerifyHeader(&header)) {
179  /* our header is not valid, we MUST abort loading the game! */
180  cgi->Com_Printf("The Header of the savegame '%s.%s' is corrupted. Loading aborted\n", filename, SAVEGAME_EXTENSION);
181  cgi->Free(cbuf);
182  *error = "Corrupted header";
183  return false;
184  }
185 
186  cgi->Com_Printf("Loading savegame\n"
187  "...version: %i\n"
188  "...game version: %s\n"
189  "...xml Size: %i, compressed? %c\n",
190  header.version, header.gameVersion, header.xmlSize, header.compressed ? 'y' : 'n');
191 
192  xmlNode_t* topNode;
193  if (header.compressed) {
194  uLongf len = header.xmlSize + 1 /* for '\0' */;
195  byte* const buf = Mem_PoolAllocTypeN(byte, len /* sic, old savegames contain one (garbage) byte more than the header says. */, cp_campaignPool);
196  /* uncompress data, skipping comment header */
197  const int res = uncompress(buf, &len, cbuf + sizeof(header), clen - sizeof(header));
198  buf[header.xmlSize] = '\0'; /* Ensure '\0' termination. */
199  cgi->Free(cbuf);
200 
201  if (res != Z_OK) {
202  cgi->Free(buf);
203  *error = _("Error decompressing data");
204  cgi->Com_Printf("Error decompressing data in '%s'.\n", filename);
205  return false;
206  }
207  topNode = cgi->XML_Parse((const char*)buf);
208  if (!topNode) {
209  cgi->Free(buf);
210  cgi->Com_Printf("Error: Failure in loading the xml data!\n");
211  *error = "Corrupted xml data";
212  return false;
213  }
214  cgi->Free(buf);
215  } else {
216  topNode = cgi->XML_Parse((const char*)(cbuf + sizeof(header)));
217  cgi->Free(cbuf);
218  if (!topNode) {
219  cgi->Com_Printf("Error: Failure in loading the xml data!\n");
220  *error = "Corrupted xml data";
221  return false;
222  }
223  }
224 
225  /* doing a subsystem run */
226  cgi->GAME_ReloadMode();
227  xmlNode_t* node = cgi->XML_GetNode(topNode, SAVE_ROOTNODE);
228  if (!node) {
229  cgi->Com_Printf("Error: Failure in loading the xml data! (savegame node not found)\n");
230  mxmlDelete(topNode);
231  *error = "Invalid xml data";
232  return false;
233  }
234 
235  cgi->Com_Printf("Load '%s' %d subsystems\n", filename, saveSubsystemsAmount);
236  for (int i = 0; i < saveSubsystemsAmount; i++) {
237  if (!saveSubsystems[i].load)
238  continue;
239  cgi->Com_Printf("...Running subsystem '%s'\n", saveSubsystems[i].name);
240  if (!saveSubsystems[i].load(node)) {
241  cgi->Com_Printf("...subsystem '%s' returned false - savegame could not be loaded\n",
242  saveSubsystems[i].name);
243  *error = va("Could not load subsystem %s", saveSubsystems[i].name);
244  return false;
245  } else
246  cgi->Com_Printf("...subsystem '%s' - loaded.\n", saveSubsystems[i].name);
247  }
248  mxmlDelete(node);
249  mxmlDelete(topNode);
250 
251  if (!SAV_GameActionsAfterLoad()) {
252  cgi->Com_Printf("Savegame postprocessing returned false - savegame could not be loaded\n");
253  *error = "Postprocessing failed";
254  return false;
255  }
256 
257  cgi->Com_Printf("File '%s' successfully loaded from %s xml savegame.\n",
258  filename, header.compressed ? "compressed" : "");
259 
260  cgi->UI_InitStack("geoscape", "campaign_main");
261  return true;
262 }
263 
267 bool SAV_GameSaveAllowed (char** error = nullptr)
268 {
269  if (!CP_IsRunning()) {
270  if (error)
271  *error = _("Saving is not possible: Campaign is not active.");
272  return false;
273  }
274  if (cgi->CL_OnBattlescape()) {
275  if (error)
276  *error = _("Saving is not possible: Cannot save the Battlescape.");
277  return false;
278  }
279  if (!B_AtLeastOneExists()) {
280  if (error)
281  *error = _("Saving is not possible: No base is built.");
282  return false;
283  }
284  return true;
285 }
286 
293 bool SAV_GameSave (const char* filename, const char* comment, char** error)
294 {
295  if (!SAV_GameSaveAllowed(error)) {
296  cgi->Com_Printf(*error);
297  return false;
298  }
299 
300  char savegame[MAX_OSPATH];
301  dateLong_t date;
302  char message[30];
303  char timeStampBuffer[32];
304 
305  Com_MakeTimestamp(timeStampBuffer, sizeof(timeStampBuffer));
306  cgi->GetRelativeSavePath(savegame, sizeof(savegame));
307  Q_strcat(savegame, sizeof(savegame), "%s.%s", filename, SAVEGAME_EXTENSION);
308  xmlNode_t* topNode = mxmlNewXML("1.0");
309  xmlNode_t* node = cgi->XML_AddNode(topNode, SAVE_ROOTNODE);
310  /* writing Header */
311  cgi->XML_AddInt(node, SAVE_SAVEVERSION, SAVE_FILE_VERSION);
312  cgi->XML_AddString(node, SAVE_COMMENT, comment);
313  cgi->XML_AddString(node, SAVE_UFOVERSION, UFO_VERSION);
314  cgi->XML_AddString(node, SAVE_REALDATE, timeStampBuffer);
315  CP_DateConvertLong(&ccs.date, &date);
316  Com_sprintf(message, sizeof(message), _("%i %s %02i"),
317  date.year, Date_GetMonthName(date.month - 1), date.day);
318  cgi->XML_AddString(node, SAVE_GAMEDATE, message);
319  /* working through all subsystems. perhaps we should redesign it, order is not important anymore */
320  cgi->Com_Printf("Calling subsystems\n");
321  for (int i = 0; i < saveSubsystemsAmount; i++) {
322  if (!saveSubsystems[i].save)
323  continue;
324  if (!saveSubsystems[i].save(node))
325  cgi->Com_Printf("...subsystem '%s' failed to save the data\n", saveSubsystems[i].name);
326  else
327  cgi->Com_Printf("...subsystem '%s' - saved\n", saveSubsystems[i].name);
328  }
329 
330  /* calculate the needed buffer size */
331  saveFileHeader_t header;
332  OBJZERO(header);
333  header.compressed = LittleLong(save_compressed->integer);
335  header.subsystems = LittleLong(saveSubsystemsAmount);
336  Q_strncpyz(header.name, comment, sizeof(header.name));
337  Q_strncpyz(header.gameVersion, UFO_VERSION, sizeof(header.gameVersion));
338  CP_DateConvertLong(&ccs.date, &date);
339  Com_sprintf(header.gameDate, sizeof(header.gameDate), _("%i %s %02i"),
340  date.year, Date_GetMonthName(date.month - 1), date.day);
341  Q_strncpyz(header.realDate, timeStampBuffer, sizeof(header.realDate));
342 
343  char dummy[2];
344  int requiredBufferLength = mxmlSaveString(topNode, dummy, 2, MXML_NO_CALLBACK);
345 
346  header.xmlSize = LittleLong(requiredBufferLength);
347  byte* const buf = Mem_PoolAllocTypeN(byte, requiredBufferLength + 1, cp_campaignPool);
348  if (!buf) {
349  mxmlDelete(topNode);
350  *error = _("Could not allocate enough memory to save this game");
351  cgi->Com_Printf("Error: Could not allocate enough memory to save this game\n");
352  return false;
353  }
354  int res = mxmlSaveString(topNode, (char*)buf, requiredBufferLength + 1, MXML_NO_CALLBACK);
355  mxmlDelete(topNode);
356  cgi->Com_Printf("XML Written to buffer (%d Bytes)\n", res);
357 
358  uLongf bufLen;
359  if (header.compressed)
360  bufLen = compressBound(requiredBufferLength);
361  else
362  bufLen = requiredBufferLength;
363 
364  byte* const fbuf = Mem_PoolAllocTypeN(byte, bufLen + sizeof(header), cp_campaignPool);
365  memcpy(fbuf, &header, sizeof(header));
366 
367  if (header.compressed) {
368  res = compress(fbuf + sizeof(header), &bufLen, buf, requiredBufferLength);
369  cgi->Free(buf);
370 
371  if (res != Z_OK) {
372  cgi->Free(fbuf);
373  *error = _("Memory error compressing save-game data - set save_compressed cvar to 0");
374  cgi->Com_Printf("Memory error compressing save-game data (%s) (Error: %i)!\n", comment, res);
375  return false;
376  }
377  } else {
378  memcpy(fbuf + sizeof(header), buf, requiredBufferLength);
379  cgi->Free(buf);
380  }
381 
382  /* last step - write data */
383  cgi->FS_WriteFile(fbuf, bufLen + sizeof(header), savegame);
384  cgi->Free(fbuf);
385 
386  return true;
387 }
388 
395 {
397  return false;
398 
399  saveSubsystems[saveSubsystemsAmount].name = subsystem->name;
400  saveSubsystems[saveSubsystemsAmount].load = subsystem->load;
401  saveSubsystems[saveSubsystemsAmount].save = subsystem->save;
403 
404  cgi->Com_Printf("added %s subsystem\n", subsystem->name);
405  return true;
406 }
407 
413 void SAV_Init (void)
414 {
415  static saveSubsystems_t cp_subsystemXML = {"campaign", CP_SaveXML, CP_LoadXML};
416  static saveSubsystems_t rs_subsystemXML = {"research", RS_SaveXML, RS_LoadXML};
417  static saveSubsystems_t b_subsystemXML = {"base", B_SaveXML, B_LoadXML};
418  static saveSubsystems_t hos_subsystemXML = {"hospital", HOS_SaveXML, HOS_LoadXML};
419  static saveSubsystems_t bs_subsystemXML = {"market", BS_SaveXML, BS_LoadXML};
420  static saveSubsystems_t e_subsystemXML = {"employee", E_SaveXML, E_LoadXML};
421  static saveSubsystems_t ac_subsystemXML = {"aliencont", nullptr, AC_LoadXML};
422  static saveSubsystems_t pr_subsystemXML = {"production", PR_SaveXML, PR_LoadXML};
423  static saveSubsystems_t air_subsystemXML = {"aircraft", AIR_SaveXML, AIR_LoadXML};
424  static saveSubsystems_t ab_subsystemXML = {"alien base", AB_SaveXML, AB_LoadXML};
425  static saveSubsystems_t int_subsystemXML = {"interest", INT_SaveXML, INT_LoadXML};
426  static saveSubsystems_t mis_subsystemXML = {"mission", MIS_SaveXML, MIS_LoadXML};
427  static saveSubsystems_t ms_subsystemXML = {"messagesystem", MS_SaveXML, MS_LoadXML};
428  static saveSubsystems_t stats_subsystemXML = {"stats", STATS_SaveXML, STATS_LoadXML};
429  static saveSubsystems_t na_subsystemXML = {"nations", NAT_SaveXML, NAT_LoadXML};
430  static saveSubsystems_t trans_subsystemXML = {"transfer", TR_SaveXML, TR_LoadXML};
431  static saveSubsystems_t xvi_subsystemXML = {"xvirate", XVI_SaveXML, XVI_LoadXML};
432  static saveSubsystems_t ins_subsystemXML = {"installation", INS_SaveXML, INS_LoadXML};
433  static saveSubsystems_t mso_subsystemXML = {"messageoptions", MSO_SaveXML, MSO_LoadXML};
434  static saveSubsystems_t event_subsystemXML = {"triggerevents", CP_TriggerEventSaveXML, CP_TriggerEventLoadXML};
435  static saveSubsystems_t us_subsystemXML = {"ufostores", US_SaveXML, US_LoadXML};
436 
438  OBJZERO(saveSubsystems);
439 
440  cgi->Com_Printf("\n--- save subsystem initialization --\n");
441 
442  /* don't mess with the order */
443  SAV_AddSubsystem(&cp_subsystemXML);
444  SAV_AddSubsystem(&rs_subsystemXML);
445  SAV_AddSubsystem(&b_subsystemXML);
446  SAV_AddSubsystem(&hos_subsystemXML);
447  SAV_AddSubsystem(&bs_subsystemXML);
448  SAV_AddSubsystem(&e_subsystemXML);
449  SAV_AddSubsystem(&ac_subsystemXML);
450  SAV_AddSubsystem(&air_subsystemXML);
451  SAV_AddSubsystem(&ab_subsystemXML);
452  SAV_AddSubsystem(&int_subsystemXML);
453  SAV_AddSubsystem(&ins_subsystemXML);
454  SAV_AddSubsystem(&mis_subsystemXML);
455  SAV_AddSubsystem(&us_subsystemXML);
456  SAV_AddSubsystem(&pr_subsystemXML);
457  SAV_AddSubsystem(&ms_subsystemXML);
458  SAV_AddSubsystem(&stats_subsystemXML);
459  SAV_AddSubsystem(&na_subsystemXML);
460  SAV_AddSubsystem(&trans_subsystemXML);
461  SAV_AddSubsystem(&xvi_subsystemXML);
462  SAV_AddSubsystem(&mso_subsystemXML);
463  SAV_AddSubsystem(&event_subsystemXML);
464 
465  save_compressed = cgi->Cvar_Get("save_compressed", "1", CVAR_ARCHIVE, "Save the savefiles compressed if set to 1");
466 }
bool E_SaveXML(xmlNode_t *p)
Save callback for savegames in XML Format.
bool(* save)(xmlNode_t *parent)
Definition: cp_save.h:50
void SAV_Init(void)
Register all save-subsystems and init some cvars and commands.
Definition: cp_save.cpp:413
struct saveFileHeader_s saveFileHeader_t
bool B_SaveXML(xmlNode_t *parent)
Save callback for saving in xml format.
Definition: cp_base.cpp:2264
void RADAR_SetRadarAfterLoading(void)
Set radar to proper values after loading.
Definition: cp_radar.cpp:453
bool BS_SaveXML(xmlNode_t *parent)
Save callback for savegames.
Definition: cp_market.cpp:441
bool CP_IsRunning(void)
Checks whether a campaign mode game is running.
Definition: cp_campaign.cpp:79
static saveSubsystems_t saveSubsystems[MAX_SAVESUBSYSTEMS]
Definition: cp_save.cpp:33
char realDate[32]
Definition: cp_save.h:44
uint32_t compressed
Definition: cp_save.h:38
static bool SAV_GameActionsAfterLoad(void)
Perform actions after loading a game for single player campaign.
Definition: cp_save.cpp:41
const char * va(const char *format,...)
does a varargs printf into a temp buffer, so I don't need to have varargs versions of all text functi...
Definition: shared.cpp:410
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition: cvar.h:71
bool AIR_PostLoadInit(void)
Actions needs to be done after loading the savegame.
#define _(String)
Definition: cl_shared.h:43
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
static bool SAV_VerifyHeader(saveFileHeader_t const *const header)
Tries to verify the Header of the savegame.
Definition: cp_save.cpp:65
bool E_LoadXML(xmlNode_t *p)
Load callback for savegames in XML Format.
bool MS_LoadXML(xmlNode_t *p)
Load callback for messages.
const char * filename
Definition: ioapi.h:41
static cvar_t * save_compressed
Definition: cp_save.cpp:35
#define SAVEGAME_EXTENSION
Definition: cp_save.h:34
bool RS_LoadXML(xmlNode_t *parent)
Load callback for research and technologies.
date_t date
Definition: cp_campaign.h:245
#define B_AtLeastOneExists()
Definition: cp_base.h:55
bool XVI_SaveXML(xmlNode_t *parent)
XVI map saving callback.
Definition: cp_xvi.cpp:215
bool B_LoadXML(xmlNode_t *parent)
Loads base data.
Definition: cp_base.cpp:2407
bool INS_SaveXML(xmlNode_t *p)
Save callback for savegames in xml.
Defines some savefile structures.
bool BS_LoadXML(xmlNode_t *parent)
Load callback for savegames.
Definition: cp_market.cpp:482
bool STATS_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
#define MAX_OSPATH
Definition: filesys.h:44
byte day
Definition: cp_time.h:37
XML tag constants for savegame.
const char *IMPORT * GetRelativeSavePath(char *buf, size_t bufSize)
bool HOS_LoadXML(xmlNode_t *p)
Saving function for hospital related data.
xmlNode_t *IMPORT * XML_Parse(const char *buffer)
int integer
Definition: cvar.h:81
bool CP_TriggerEventSaveXML(xmlNode_t *p)
Definition: cp_event.cpp:402
bool TR_LoadXML(xmlNode_t *parent)
Load callback for xml savegames.
memPool_t * cp_campaignPool
Definition: cp_campaign.cpp:61
voidpf void * buf
Definition: ioapi.h:42
#define CVAR_ARCHIVE
Definition: cvar.h:40
bool TR_SaveXML(xmlNode_t *parent)
Save callback for xml savegames.
const char * name
Definition: cp_save.h:49
bool INT_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
const char * Date_GetMonthName(int month)
Returns the short monthame to the given month index.
Definition: cp_time.cpp:317
bool AB_LoadXML(xmlNode_t *p)
Load callback for alien base data.
bool CP_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
bool STATS_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
#define xmlNode_t
Definition: xml.h:24
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
Campaign XVI header.
#define SAVE_GAMEDATE
Definition: save.h:34
char name[32]
Definition: cp_save.h:42
bool NAT_LoadXML(xmlNode_t *p)
Nation loading xml callback.
Definition: cp_nation.cpp:323
#define UFO_VERSION
Definition: common.h:36
char gameDate[32]
Definition: cp_save.h:43
bool SAV_LoadHeader(const char *filename, saveFileHeader_t *header)
Loads and verifies a savegame header.
Definition: cp_save.cpp:114
#define DEBUG_CLIENT
Definition: defines.h:59
#define OBJZERO(obj)
Definition: shared.h:178
void CP_UpdateTime(void)
Updates date/time and timescale (=timelapse) on the geoscape menu.
Definition: cp_time.cpp:104
bool SAV_AddSubsystem(saveSubsystems_t *subsystem)
Adds a subsystem to the saveSubsystems array.
Definition: cp_save.cpp:394
bool US_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
uint32_t subsystems
Definition: cp_save.h:39
const cgame_import_t * cgi
short year
Definition: cp_time.h:35
bool MSO_SaveXML(xmlNode_t *p)
saves current notification and pause settings
bool HOS_SaveXML(xmlNode_t *p)
Saving function for hospital related data.
bool MS_SaveXML(xmlNode_t *p)
Save callback for messages.
ccs_t ccs
Definition: cp_campaign.cpp:62
uint32_t version
Definition: cp_save.h:37
byte month
Definition: cp_time.h:36
Campaign geoscape time header.
bool INS_LoadXML(xmlNode_t *p)
Load callback for savegames.
cvar_t *IMPORT * Cvar_Get(const char *varName, const char *value, int flags, const char *desc)
bool XVI_LoadXML(xmlNode_t *parent)
Load the XVI map from the savegame.
Definition: cp_xvi.cpp:247
bool MIS_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
#define MAX_SAVESUBSYSTEMS
Definition: cp_save.h:32
#define SAVE_FILE_VERSION
Definition: cp_save.h:33
#define SAVE_COMMENT
Definition: save.h:32
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
void Com_MakeTimestamp(char *ts, const size_t tslen)
Creates a timestamp with date and time at the specified location.
Definition: shared.cpp:352
#define SAVE_ROOTNODE
Definition: save.h:27
Human readable time information in the game.
Definition: cp_time.h:34
QGL_EXTERN GLint i
Definition: r_gl.h:113
bool US_LoadXML(xmlNode_t *parent)
Load callback for xml savegames.
QGL_EXTERN GLuint GLchar GLuint * len
Definition: r_gl.h:99
#define SAVE_REALDATE
Definition: save.h:33
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
bool PR_LoadXML(xmlNode_t *p)
Load callback for xml savegames.
Definition: cp_produce.cpp:712
bool B_PostLoadInit(void)
Set the capacity stuff for all the bases after loading a savegame.
Definition: cp_base.cpp:2378
uint32_t xmlSize
Definition: cp_save.h:45
bool NAT_SaveXML(xmlNode_t *p)
Nation saving callback.
Definition: cp_nation.cpp:228
void CP_DateConvertLong(const date_t *date, dateLong_t *dateLong)
Converts a date from the engine in a (longer) human-readable format.
Definition: cp_time.cpp:72
bool SAV_GameSave(const char *filename, const char *comment, char **error)
This is a savegame function which stores the game in xml-Format.
Definition: cp_save.cpp:293
bool MSO_LoadXML(xmlNode_t *p)
Restores the notification and pause settings from savegame.
#define SAVE_SAVEVERSION
Definition: save.h:30
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
#define UFO_SIZE_T
Definition: ufotypes.h:89
static int saveSubsystemsAmount
Definition: cp_save.cpp:34
bool SAV_GameSaveAllowed(char **error=nullptr)
Determines if saving is allowed.
Definition: cp_save.cpp:267
Header file for single player campaign control.
bool RS_SaveXML(xmlNode_t *parent)
Save callback for research and technologies.
bool INT_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
bool CP_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
char gameVersion[16]
Definition: cp_save.h:41
bool AIR_LoadXML(xmlNode_t *parent)
bool PR_SaveXML(xmlNode_t *p)
Save callback for savegames in XML Format.
Definition: cp_produce.cpp:678
bool CP_TriggerEventLoadXML(xmlNode_t *p)
Definition: cp_event.cpp:420
#define SAVE_UFOVERSION
Definition: save.h:31
uint8_t byte
Definition: ufotypes.h:34
void CP_UpdateXVIMapButton(void)
This will hide or show the geoscape button for handling the xvi overlay map.
Definition: cp_xvi.cpp:298
bool PR_PostLoadInit(void)
actions to do with productions after loading a savegame
Definition: cp_produce.cpp:802
bool AIR_SaveXML(xmlNode_t *parent)
Save callback for savegames in xml format.
bool AB_SaveXML(xmlNode_t *p)
Save callback for alien base data.
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
bool SAV_GameLoad(const char *file, const char **error)
Loads the given savegame from an xml File.
Definition: cp_save.cpp:152
bool(* load)(xmlNode_t *parent)
Definition: cp_save.h:51
#define LittleLong(X)
Definition: byte.h:37
bool MIS_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
bool AC_LoadXML(xmlNode_t *parent)
Load callback for savin in XML Format.