UFO: Alien Invasion
Loading...
Searching...
No Matches
cp_save.cpp
Go to the documentation of this file.
1
5
6/*
7Copyright (C) 2002-2025 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
156 cgi->GetRelativeSavePath(filename, sizeof(filename));
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 char* buf;
302 dateLong_t date;
303 char message[30];
304 char timeStampBuffer[32];
305
306 Com_MakeTimestamp(timeStampBuffer, sizeof(timeStampBuffer));
307 cgi->GetRelativeSavePath(savegame, sizeof(savegame));
308 Q_strcat(savegame, sizeof(savegame), "%s.%s", filename, SAVEGAME_EXTENSION);
309 xmlNode_t* topNode = mxmlNewXML("1.0");
310 xmlNode_t* node = cgi->XML_AddNode(topNode, SAVE_ROOTNODE);
311 /* writing Header */
312 cgi->XML_AddInt(node, SAVE_SAVEVERSION, SAVE_FILE_VERSION);
313 cgi->XML_AddString(node, SAVE_COMMENT, comment);
314 cgi->XML_AddString(node, SAVE_UFOVERSION, UFO_VERSION);
315 cgi->XML_AddString(node, SAVE_REALDATE, timeStampBuffer);
316 CP_DateConvertLong(ccs.date, &date);
317 Com_sprintf(message, sizeof(message), _("%i %s %02i"),
318 date.year, Date_GetMonthName(date.month - 1), date.day);
319 cgi->XML_AddString(node, SAVE_GAMEDATE, message);
320 /* working through all subsystems. perhaps we should redesign it, order is not important anymore */
321 cgi->Com_Printf("Calling subsystems\n");
322 for (int i = 0; i < saveSubsystemsAmount; i++) {
323 if (!saveSubsystems[i].save)
324 continue;
325 if (!saveSubsystems[i].save(node))
326 cgi->Com_Printf("...subsystem '%s' failed to save the data\n", saveSubsystems[i].name);
327 else
328 cgi->Com_Printf("...subsystem '%s' - saved\n", saveSubsystems[i].name);
329 }
330
331 /* calculate the needed buffer size */
332 saveFileHeader_t header;
333 OBJZERO(header);
334 header.compressed = LittleLong(save_compressed->integer);
337 Q_strncpyz(header.name, comment, sizeof(header.name));
338 Q_strncpyz(header.gameVersion, UFO_VERSION, sizeof(header.gameVersion));
339 CP_DateConvertLong(ccs.date, &date);
340 Com_sprintf(header.gameDate, sizeof(header.gameDate), _("%i %s %02i"),
341 date.year, Date_GetMonthName(date.month - 1), date.day);
342 Q_strncpyz(header.realDate, timeStampBuffer, sizeof(header.realDate));
343
344 buf = mxmlSaveAllocString(topNode, nullptr);
345 mxmlDelete(topNode);
346 if (!buf) {
347 *error = _("Could not allocate enough memory to save this game");
348 cgi->Com_Printf("Error: Could not allocate enough memory to save this game\n");
349 return false;
350 }
351 int requiredBufferLength = strlen(buf) + 1;
352 header.xmlSize = LittleLong(requiredBufferLength);
353 cgi->Com_Printf("XML Written to buffer (%d Bytes)\n", requiredBufferLength);
354
355 uLongf bufLen;
356 if (header.compressed)
357 bufLen = compressBound(requiredBufferLength);
358 else
359 bufLen = requiredBufferLength;
360
361 byte* const fbuf = Mem_PoolAllocTypeN(byte, bufLen + sizeof(header), cp_campaignPool);
362 memcpy(fbuf, &header, sizeof(header));
363
364 if (header.compressed) {
365 int res = compress(fbuf + sizeof(header), &bufLen, (byte*) buf, requiredBufferLength);
366 free(buf);
367
368 if (res != Z_OK) {
369 cgi->Free(fbuf);
370 *error = _("Memory error compressing save-game data - set save_compressed cvar to 0");
371 cgi->Com_Printf("Memory error compressing save-game data (%s) (Error: %i)!\n", comment, res);
372 return false;
373 }
374 } else {
375 memcpy(fbuf + sizeof(header), buf, requiredBufferLength);
376 free(buf);
377 }
378
379 /* last step - write data */
380 cgi->FS_WriteFile(fbuf, bufLen + sizeof(header), savegame);
381 cgi->Free(fbuf);
382
383 return true;
384}
385
392{
394 return false;
395
396 saveSubsystems[saveSubsystemsAmount].name = subsystem->name;
397 saveSubsystems[saveSubsystemsAmount].load = subsystem->load;
398 saveSubsystems[saveSubsystemsAmount].save = subsystem->save;
400
401 cgi->Com_Printf("added %s subsystem\n", subsystem->name);
402 return true;
403}
404
410void SAV_Init (void)
411{
412 static saveSubsystems_t cp_subsystemXML = {"campaign", CP_SaveXML, CP_LoadXML};
413 static saveSubsystems_t rs_subsystemXML = {"research", RS_SaveXML, RS_LoadXML};
414 static saveSubsystems_t b_subsystemXML = {"base", B_SaveXML, B_LoadXML};
415 static saveSubsystems_t hos_subsystemXML = {"hospital", HOS_SaveXML, HOS_LoadXML};
416 static saveSubsystems_t bs_subsystemXML = {"market", BS_SaveXML, BS_LoadXML};
417 static saveSubsystems_t e_subsystemXML = {"employee", E_SaveXML, E_LoadXML};
418 static saveSubsystems_t ac_subsystemXML = {"aliencont", nullptr, AC_LoadXML};
419 static saveSubsystems_t pr_subsystemXML = {"production", PR_SaveXML, PR_LoadXML};
420 static saveSubsystems_t air_subsystemXML = {"aircraft", AIR_SaveXML, AIR_LoadXML};
421 static saveSubsystems_t ab_subsystemXML = {"alien base", AB_SaveXML, AB_LoadXML};
422 static saveSubsystems_t int_subsystemXML = {"interest", INT_SaveXML, INT_LoadXML};
423 static saveSubsystems_t mis_subsystemXML = {"mission", MIS_SaveXML, MIS_LoadXML};
424 static saveSubsystems_t ms_subsystemXML = {"messagesystem", MS_SaveXML, MS_LoadXML};
425 static saveSubsystems_t stats_subsystemXML = {"stats", STATS_SaveXML, STATS_LoadXML};
426 static saveSubsystems_t na_subsystemXML = {"nations", NAT_SaveXML, NAT_LoadXML};
427 static saveSubsystems_t trans_subsystemXML = {"transfer", TR_SaveXML, TR_LoadXML};
428 static saveSubsystems_t xvi_subsystemXML = {"xvirate", XVI_SaveXML, XVI_LoadXML};
429 static saveSubsystems_t ins_subsystemXML = {"installation", INS_SaveXML, INS_LoadXML};
430 static saveSubsystems_t mso_subsystemXML = {"messageoptions", MSO_SaveXML, MSO_LoadXML};
431 static saveSubsystems_t event_subsystemXML = {"triggerevents", CP_TriggerEventSaveXML, CP_TriggerEventLoadXML};
432 static saveSubsystems_t us_subsystemXML = {"ufostores", US_SaveXML, US_LoadXML};
433
436
437 cgi->Com_Printf("\n--- save subsystem initialization --\n");
438
439 /* don't mess with the order */
440 SAV_AddSubsystem(&cp_subsystemXML);
441 SAV_AddSubsystem(&rs_subsystemXML);
442 SAV_AddSubsystem(&b_subsystemXML);
443 SAV_AddSubsystem(&hos_subsystemXML);
444 SAV_AddSubsystem(&bs_subsystemXML);
445 SAV_AddSubsystem(&e_subsystemXML);
446 SAV_AddSubsystem(&ac_subsystemXML);
447 SAV_AddSubsystem(&air_subsystemXML);
448 SAV_AddSubsystem(&ab_subsystemXML);
449 SAV_AddSubsystem(&int_subsystemXML);
450 SAV_AddSubsystem(&ins_subsystemXML);
451 SAV_AddSubsystem(&mis_subsystemXML);
452 SAV_AddSubsystem(&us_subsystemXML);
453 SAV_AddSubsystem(&pr_subsystemXML);
454 SAV_AddSubsystem(&ms_subsystemXML);
455 SAV_AddSubsystem(&stats_subsystemXML);
456 SAV_AddSubsystem(&na_subsystemXML);
457 SAV_AddSubsystem(&trans_subsystemXML);
458 SAV_AddSubsystem(&xvi_subsystemXML);
459 SAV_AddSubsystem(&mso_subsystemXML);
460 SAV_AddSubsystem(&event_subsystemXML);
461
462 save_compressed = cgi->Cvar_Get("save_compressed", "1", CVAR_ARCHIVE, "Save the savefiles compressed if set to 1");
463}
#define LittleLong(X)
Definition byte.h:37
Shared game type headers.
Share stuff between the different cgame implementations.
#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
bool CP_IsRunning(void)
Checks whether a campaign mode game is running.
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
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.
bool BS_SaveXML(xmlNode_t *parent)
Save callback for savegames.
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.
bool NAT_LoadXML(xmlNode_t *p)
Nation loading xml callback.
bool PR_LoadXML(xmlNode_t *p)
Load callback for xml savegames.
bool PR_SaveXML(xmlNode_t *p)
Save callback for savegames in XML Format.
bool PR_PostLoadInit(void)
actions to do with productions after loading a savegame
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:391
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:410
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
This is a cvar definition. Cvars can be user modified and used in our menus e.g.
Definition cvar.h:71
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