UFO: Alien Invasion
cp_save.cpp
Go to the documentation of this file.
1
6/*
7Copyright (C) 2002-2022 UFO: Alien Invasion.
8
9This program is free software; you can redistribute it and/or
10modify it under the terms of the GNU General Public License
11as published by the Free Software Foundation; either version 2
12of the License, or (at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18See the GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, 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
41static 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. */
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
65static 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
114bool 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);
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
152bool SAV_GameLoad (const char* file, const char** error)
153{
154 char filename[MAX_OSPATH];
155
157 Q_strcat(filename, sizeof(filename), "%s.%s", file, SAVEGAME_EXTENSION);
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",
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
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
267bool 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
293bool SAV_GameSave (const char* filename, const char* comment, char** error)
294{
295 if (!SAV_GameSaveAllowed(error)) {
296 cgi->Com_Printf("%s", *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);
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);
336 Q_strncpyz(header.name, comment, sizeof(header.name));
337 Q_strncpyz(header.gameVersion, UFO_VERSION, sizeof(header.gameVersion));
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
403
404 cgi->Com_Printf("added %s subsystem\n", subsystem->name);
405 return true;
406}
407
413void 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
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}
#define LittleLong(X)
Definition: byte.h:37
#define _(String)
Definition: cl_shared.h:44
#define UFO_VERSION
Definition: common.h:36
bool AIR_LoadXML(xmlNode_t *parent)
bool AIR_SaveXML(xmlNode_t *parent)
Save callback for savegames in xml format.
bool AIR_PostLoadInit(void)
Actions needs to be done after loading the savegame.
bool INT_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
bool INT_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
bool AB_SaveXML(xmlNode_t *p)
Save callback for alien base data.
bool AB_LoadXML(xmlNode_t *p)
Load callback for alien base data.
bool AC_LoadXML(xmlNode_t *parent)
Load callback for savin in XML Format.
bool B_LoadXML(xmlNode_t *parent)
Loads base data.
Definition: cp_base.cpp:2406
bool B_PostLoadInit(void)
Set the capacity stuff for all the bases after loading a savegame.
Definition: cp_base.cpp:2377
bool B_SaveXML(xmlNode_t *parent)
Save callback for saving in xml format.
Definition: cp_base.cpp:2263
#define B_AtLeastOneExists()
Definition: cp_base.h:55
memPool_t * cp_campaignPool
Definition: cp_campaign.cpp:62
bool CP_IsRunning(void)
Checks whether a campaign mode game is running.
Definition: cp_campaign.cpp:80
bool CP_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
bool CP_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
ccs_t ccs
Definition: cp_campaign.cpp:63
Header file for single player campaign control.
const cgame_import_t * cgi
bool E_LoadXML(xmlNode_t *p)
Load callback for savegames in XML Format.
bool E_SaveXML(xmlNode_t *p)
Save callback for savegames in XML Format.
bool CP_TriggerEventLoadXML(xmlNode_t *p)
Definition: cp_event.cpp:419
bool CP_TriggerEventSaveXML(xmlNode_t *p)
Definition: cp_event.cpp:401
bool HOS_SaveXML(xmlNode_t *p)
Saving function for hospital related data.
bool HOS_LoadXML(xmlNode_t *p)
Saving function for hospital related data.
bool INS_SaveXML(xmlNode_t *p)
Save callback for savegames in xml.
bool INS_LoadXML(xmlNode_t *p)
Load callback for savegames.
bool BS_LoadXML(xmlNode_t *parent)
Load callback for savegames.
Definition: cp_market.cpp:483
bool BS_SaveXML(xmlNode_t *parent)
Save callback for savegames.
Definition: cp_market.cpp:442
bool MSO_SaveXML(xmlNode_t *p)
saves current notification and pause settings
bool MSO_LoadXML(xmlNode_t *p)
Restores the notification and pause settings from savegame.
bool MS_LoadXML(xmlNode_t *p)
Load callback for messages.
bool MS_SaveXML(xmlNode_t *p)
Save callback for messages.
bool MIS_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
bool MIS_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
bool NAT_SaveXML(xmlNode_t *p)
Nation saving callback.
Definition: cp_nation.cpp:229
bool NAT_LoadXML(xmlNode_t *p)
Nation loading xml callback.
Definition: cp_nation.cpp:324
bool PR_LoadXML(xmlNode_t *p)
Load callback for xml savegames.
Definition: cp_produce.cpp:713
bool PR_SaveXML(xmlNode_t *p)
Save callback for savegames in XML Format.
Definition: cp_produce.cpp:679
bool PR_PostLoadInit(void)
actions to do with productions after loading a savegame
Definition: cp_produce.cpp:803
void RADAR_SetRadarAfterLoading(void)
Set radar to proper values after loading.
Definition: cp_radar.cpp:453
bool RS_SaveXML(xmlNode_t *parent)
Save callback for research and technologies.
bool RS_LoadXML(xmlNode_t *parent)
Load callback for research and technologies.
static cvar_t * save_compressed
Definition: cp_save.cpp:35
bool SAV_AddSubsystem(saveSubsystems_t *subsystem)
Adds a subsystem to the saveSubsystems array.
Definition: cp_save.cpp:394
static saveSubsystems_t saveSubsystems[MAX_SAVESUBSYSTEMS]
Definition: cp_save.cpp:33
bool SAV_GameLoad(const char *file, const char **error)
Loads the given savegame from an xml File.
Definition: cp_save.cpp:152
static int saveSubsystemsAmount
Definition: cp_save.cpp:34
bool SAV_LoadHeader(const char *filename, saveFileHeader_t *header)
Loads and verifies a savegame header.
Definition: cp_save.cpp:114
static bool SAV_VerifyHeader(saveFileHeader_t const *const header)
Tries to verify the Header of the savegame.
Definition: cp_save.cpp:65
void SAV_Init(void)
Register all save-subsystems and init some cvars and commands.
Definition: cp_save.cpp:413
bool SAV_GameSaveAllowed(char **error=nullptr)
Determines if saving is allowed.
Definition: cp_save.cpp:267
static bool SAV_GameActionsAfterLoad(void)
Perform actions after loading a game for single player campaign.
Definition: cp_save.cpp:41
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
Defines some savefile structures.
bool US_LoadXML(xmlNode_t *parent)
Load callback for xml savegames.
bool STATS_LoadXML(xmlNode_t *parent)
Load callback for savegames in XML Format.
bool US_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
bool XVI_LoadXML(xmlNode_t *parent)
Load the XVI map from the savegame.
Definition: cp_xvi.cpp:247
bool TR_SaveXML(xmlNode_t *parent)
Save callback for xml savegames.
bool TR_LoadXML(xmlNode_t *parent)
Load callback for xml savegames.
bool STATS_SaveXML(xmlNode_t *parent)
Save callback for savegames in XML Format.
#define SAVE_FILE_VERSION
Definition: cp_save.h:33
#define MAX_SAVESUBSYSTEMS
Definition: cp_save.h:32
bool XVI_SaveXML(xmlNode_t *parent)
XVI map saving callback.
Definition: cp_xvi.cpp:215
#define SAVEGAME_EXTENSION
Definition: cp_save.h:34
void CP_UpdateTime(void)
Updates date/time and timescale (=timelapse) on the geoscape menu.
Definition: cp_time.cpp:104
void CP_DateConvertLong(const DateTime &date, dateLong_t *dateLong)
Converts a date from the engine in a (longer) human-readable format.
Definition: cp_time.cpp:73
const char * Date_GetMonthName(int month)
Returns the short monthame to the given month index.
Definition: cp_time.cpp:250
Campaign geoscape time header.
void CP_UpdateXVIMapButton(void)
This will hide or show the geoscape button for handling the xvi overlay map.
Definition: cp_xvi.cpp:298
Campaign XVI header.
#define CVAR_ARCHIVE
Definition: cvar.h:40
#define DEBUG_CLIENT
Definition: defines.h:59
#define MAX_OSPATH
Definition: filesys.h:44
@ FILE_READ
Definition: filesys.h:111
const char * filename
Definition: ioapi.h:41
voidpf void * buf
Definition: ioapi.h:42
#define Mem_PoolAllocTypeN(type, n, pool)
Definition: mem.h:42
QGL_EXTERN GLuint GLchar GLuint * len
Definition: r_gl.h:99
QGL_EXTERN GLfloat f
Definition: r_gl.h:114
QGL_EXTERN GLint i
Definition: r_gl.h:113
QGL_EXTERN GLuint GLsizei GLsizei GLint GLenum GLchar * name
Definition: r_gl.h:110
XML tag constants for savegame.
#define SAVE_COMMENT
Definition: save.h:32
#define SAVE_UFOVERSION
Definition: save.h:31
#define SAVE_ROOTNODE
Definition: save.h:27
#define SAVE_SAVEVERSION
Definition: save.h:30
#define SAVE_REALDATE
Definition: save.h:33
#define SAVE_GAMEDATE
Definition: save.h:34
#define OBJZERO(obj)
Definition: shared.h:178
void Q_strncpyz(char *dest, const char *src, size_t destsize)
Safe strncpy that ensures a trailing zero.
Definition: shared.cpp:457
void Q_strcat(char *dest, size_t destsize, const char *format,...)
Safely (without overflowing the destination buffer) concatenates two strings.
Definition: shared.cpp:475
void Com_MakeTimestamp(char *ts, const size_t tslen)
Creates a timestamp with date and time at the specified location.
Definition: shared.cpp:352
bool Com_sprintf(char *dest, size_t size, const char *fmt,...)
copies formatted string with buffer-size checking
Definition: shared.cpp:494
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
class DateTime date
Definition: cp_campaign.h:246
xmlNode_t *IMPORT * XML_GetNode(xmlNode_t *parent, const char *name)
xmlNode_t *IMPORT * XML_AddNode(xmlNode_t *parent, const char *name)
const char *IMPORT * GetRelativeSavePath(char *buf, size_t bufSize)
cvar_t *IMPORT * Cvar_Get(const char *varName, const char *value, int flags, const char *desc)
xmlNode_t *IMPORT * XML_Parse(const char *buffer)
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition: cvar.h:71
int integer
Definition: cvar.h:81
Human readable time information in the game.
Definition: cp_time.h:36
byte month
Definition: cp_time.h:38
byte day
Definition: cp_time.h:39
short year
Definition: cp_time.h:37
char realDate[32]
Definition: cp_save.h:44
char gameDate[32]
Definition: cp_save.h:43
char name[32]
Definition: cp_save.h:42
uint32_t subsystems
Definition: cp_save.h:39
char gameVersion[16]
Definition: cp_save.h:41
uint32_t compressed
Definition: cp_save.h:38
uint32_t version
Definition: cp_save.h:37
uint32_t xmlSize
Definition: cp_save.h:45
bool(* load)(xmlNode_t *parent)
Definition: cp_save.h:51
const char * name
Definition: cp_save.h:49
bool(* save)(xmlNode_t *parent)
Definition: cp_save.h:50
#define UFO_SIZE_T
Definition: ufotypes.h:89
#define xmlNode_t
Definition: xml.h:24