First draft of namable savegames.
This code is loosely adapted from JMS's code in UQM-HD, but very little remains beyond the text input loop internals. Fully backwards compatible, but this format shouldn't survive to the final merge.
This commit is contained in:
+196
-12
@@ -34,6 +34,7 @@
|
|||||||
#include "sounds.h"
|
#include "sounds.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "libs/graphics/gfx_common.h"
|
#include "libs/graphics/gfx_common.h"
|
||||||
|
#include "libs/log.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
@@ -352,10 +353,178 @@ NameCaptainOrShip (bool nameCaptain)
|
|||||||
|
|
||||||
DrawNameString (nameCaptain, buf, 0, DDSHS_NORMAL);
|
DrawNameString (nameCaptain, buf, 0, DDSHS_NORMAL);
|
||||||
|
|
||||||
|
if (namingCB)
|
||||||
|
namingCB ();
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
DrawSaveNameString (UNICODE *Str, COUNT CursorPos, COUNT state, COUNT gameIndex)
|
||||||
|
{
|
||||||
|
RECT r;
|
||||||
|
TEXT lf;
|
||||||
|
Color BackGround, ForeGround;
|
||||||
|
FONT Font;
|
||||||
|
|
||||||
|
SetContextForeGroundColor (BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33));
|
||||||
|
r.extent.width = 15;
|
||||||
|
if (MAX_SAVED_GAMES > 99)
|
||||||
|
r.extent.width += 5;
|
||||||
|
r.extent.height = 11;
|
||||||
|
r.corner.x = 8;
|
||||||
|
r.corner.y = (160 + ((gameIndex % SAVES_PER_PAGE) * 13));
|
||||||
|
DrawRectangle (&r);
|
||||||
|
|
||||||
|
r.extent.width = (204 - SAFE_X);
|
||||||
|
r.corner.x = (30 + SAFE_X);
|
||||||
|
DrawRectangle (&r);
|
||||||
|
|
||||||
|
Font = TinyFont;
|
||||||
|
lf.baseline.x = r.corner.x + 3;
|
||||||
|
lf.baseline.y = r.corner.y + 8;
|
||||||
|
|
||||||
|
BackGround = BUILD_COLOR (MAKE_RGB15 (0x1B, 0x00, 0x1B), 0x33);
|
||||||
|
ForeGround = BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x14), 0x01);
|
||||||
|
|
||||||
|
lf.align = ALIGN_LEFT;
|
||||||
|
|
||||||
|
SetContextFont (Font);
|
||||||
|
lf.pStr = Str;
|
||||||
|
lf.CharCount = (COUNT)~0;
|
||||||
|
|
||||||
|
if (!(state & DDSHS_EDIT))
|
||||||
|
{
|
||||||
|
//RECT r;
|
||||||
|
TEXT t;
|
||||||
|
|
||||||
|
SetContextForeGroundColor (BLACK_COLOR);
|
||||||
|
DrawFilledRectangle (&r);
|
||||||
|
|
||||||
|
t.baseline.x = r.corner.x + 3;
|
||||||
|
t.baseline.y = r.corner.y + 8;
|
||||||
|
t.align = ALIGN_LEFT;
|
||||||
|
t.pStr = Str;
|
||||||
|
t.CharCount = (COUNT)~0;
|
||||||
|
SetContextForeGroundColor (CAPTAIN_NAME_TEXT_COLOR);
|
||||||
|
font_DrawText (&t);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // editing state
|
||||||
|
COUNT i;
|
||||||
|
RECT text_r;
|
||||||
|
BYTE char_deltas[SAVE_NAME_SIZE];
|
||||||
|
BYTE *pchar_deltas;
|
||||||
|
|
||||||
|
TextRect (&lf, &text_r, char_deltas);
|
||||||
|
if ((text_r.extent.width + 2) >= r.extent.width)
|
||||||
|
{ // the text does not fit the input box size and so
|
||||||
|
// will not fit when displayed later
|
||||||
|
// disallow the change
|
||||||
|
return (FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreUpdateFlashRect ();
|
||||||
|
|
||||||
|
SetContextForeGroundColor (BackGround);
|
||||||
|
DrawFilledRectangle (&r);
|
||||||
|
|
||||||
|
pchar_deltas = char_deltas;
|
||||||
|
|
||||||
|
for (i = CursorPos; i > 0; --i)
|
||||||
|
text_r.corner.x += *pchar_deltas++;
|
||||||
|
if (CursorPos < lf.CharCount) /* end of line */
|
||||||
|
--text_r.corner.x;
|
||||||
|
|
||||||
|
if (state & DDSHS_BLOCKCUR)
|
||||||
|
{ // Use block cursor for keyboardless systems
|
||||||
|
if (CursorPos == lf.CharCount)
|
||||||
|
{ // cursor at end-line -- use insertion point
|
||||||
|
text_r.extent.width = 1;
|
||||||
|
}
|
||||||
|
else if (CursorPos + 1 == lf.CharCount)
|
||||||
|
{ // extra pixel for last char margin
|
||||||
|
text_r.extent.width = (SIZE)*pchar_deltas + 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // normal mid-line char
|
||||||
|
text_r.extent.width = (SIZE)*pchar_deltas + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // Insertion point cursor
|
||||||
|
text_r.extent.width = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
text_r.corner.y = r.corner.y;
|
||||||
|
text_r.extent.height = r.extent.height;
|
||||||
|
SetContextForeGroundColor (BLACK_COLOR);
|
||||||
|
DrawFilledRectangle (&text_r);
|
||||||
|
|
||||||
|
SetContextForeGroundColor (ForeGround);
|
||||||
|
font_DrawText (&lf);
|
||||||
|
PostUpdateFlashRect ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
OnSaveNameChange (TEXTENTRY_STATE *pTES)
|
||||||
|
{
|
||||||
|
COUNT hl = DDSHS_EDIT;
|
||||||
|
COUNT *gameIndex = pTES->CbParam;
|
||||||
|
|
||||||
|
if (pTES->JoystickMode)
|
||||||
|
hl |= DDSHS_BLOCKCUR;
|
||||||
|
|
||||||
|
return DrawSaveNameString (pTES->BaseStr, pTES->CursorPos, hl, *gameIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOLEAN
|
||||||
|
NameSaveGame (COUNT gameIndex, UNICODE *buf)
|
||||||
|
{
|
||||||
|
TEXTENTRY_STATE tes;
|
||||||
|
COUNT CursPos = 0;
|
||||||
|
COUNT *gIndex = HMalloc (sizeof (COUNT));
|
||||||
|
RECT r;
|
||||||
|
*gIndex = gameIndex;
|
||||||
|
|
||||||
|
DrawSaveNameString (buf, CursPos, DDSHS_EDIT, gameIndex);
|
||||||
|
|
||||||
|
tes.MaxSize = SAVE_NAME_SIZE;
|
||||||
|
|
||||||
|
// text entry setup
|
||||||
|
tes.Initialized = FALSE;
|
||||||
|
tes.BaseStr = buf;
|
||||||
|
tes.CursorPos = CursPos;
|
||||||
|
tes.CbParam = gIndex;
|
||||||
|
tes.ChangeCallback = OnSaveNameChange;
|
||||||
|
tes.FrameCallback = 0;
|
||||||
|
r.extent.width = (204 - SAFE_X);
|
||||||
|
r.extent.height = 11;
|
||||||
|
r.corner.x = (30 + SAFE_X);
|
||||||
|
r.corner.y = (160 + ((gameIndex % SAVES_PER_PAGE) * 13));
|
||||||
|
SetFlashRect (&r);
|
||||||
|
|
||||||
|
if (!DoTextEntry (&tes))
|
||||||
|
buf[0] = 0;
|
||||||
|
|
||||||
|
SetFlashRect(NULL);
|
||||||
|
|
||||||
|
DrawSaveNameString (buf, CursPos, DDSHS_NORMAL, gameIndex);
|
||||||
|
|
||||||
if (namingCB)
|
if (namingCB)
|
||||||
namingCB ();
|
namingCB ();
|
||||||
|
|
||||||
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
|
SetMenuSounds (MENU_SOUND_ARROWS, MENU_SOUND_SELECT);
|
||||||
|
|
||||||
|
HFree (gIndex);
|
||||||
|
|
||||||
|
SetFlashRect (NULL);
|
||||||
|
|
||||||
|
if (tes.Success)
|
||||||
|
return (TRUE);
|
||||||
|
else
|
||||||
|
return (FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -825,9 +994,10 @@ DrawGameSelection (PICK_GAME_STATE *pickState, COUNT selSlot)
|
|||||||
{
|
{
|
||||||
DateToString (buf2, sizeof buf2, desc->month_index,
|
DateToString (buf2, sizeof buf2, desc->month_index,
|
||||||
desc->day_index, desc->year_index);
|
desc->day_index, desc->year_index);
|
||||||
snprintf (buf, sizeof buf, "%s %s",
|
if (desc->SaveName[0])
|
||||||
GAME_STRING (SAVEGAME_STRING_BASE + 4), buf2);
|
snprintf (buf, sizeof buf, "%s: %s", buf2, desc->SaveName);
|
||||||
// "Saved Game - Date:"
|
else
|
||||||
|
snprintf (buf, sizeof buf, "%s", buf2);
|
||||||
}
|
}
|
||||||
font_DrawText (&t);
|
font_DrawText (&t);
|
||||||
}
|
}
|
||||||
@@ -936,22 +1106,35 @@ DoPickGame (MENU_STATE *pMS)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
SaveLoadGame (PICK_GAME_STATE *pickState, COUNT gameIndex)
|
SaveLoadGame (PICK_GAME_STATE *pickState, COUNT gameIndex, BOOLEAN *canceled_by_user)
|
||||||
{
|
{
|
||||||
SUMMARY_DESC *desc = pickState->summary + gameIndex;
|
SUMMARY_DESC *desc = pickState->summary + gameIndex;
|
||||||
|
UNICODE nameBuf[SAVE_NAME_SIZE];
|
||||||
STAMP saveStamp;
|
STAMP saveStamp;
|
||||||
BOOLEAN success;
|
BOOLEAN success;
|
||||||
|
|
||||||
saveStamp.frame = NULL;
|
saveStamp.frame = NULL;
|
||||||
|
|
||||||
// TODO: fix ConfirmSaveLoad() interface so it does not rely on
|
|
||||||
// MsgStamp != NULL parameter.
|
|
||||||
ConfirmSaveLoad (pickState->saving ? &saveStamp : NULL);
|
|
||||||
|
|
||||||
if (pickState->saving)
|
if (pickState->saving)
|
||||||
success = SaveGame (gameIndex, desc);
|
{
|
||||||
|
nameBuf[0] = 0;
|
||||||
|
if (NameSaveGame (gameIndex, nameBuf))
|
||||||
|
{
|
||||||
|
PlayMenuSound (MENU_SOUND_SUCCESS);
|
||||||
|
ConfirmSaveLoad (pickState->saving ? &saveStamp : NULL);
|
||||||
|
success = SaveGame (gameIndex, desc, nameBuf);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
success = FALSE;
|
||||||
|
*canceled_by_user = TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConfirmSaveLoad (pickState->saving ? &saveStamp : NULL);
|
||||||
success = LoadGame (gameIndex, NULL);
|
success = LoadGame (gameIndex, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: the same should be done for both save and load if we also
|
// TODO: the same should be done for both save and load if we also
|
||||||
// display a load problem message
|
// display a load problem message
|
||||||
@@ -1032,6 +1215,8 @@ PickGame (BOOLEAN saving, BOOLEAN fromMainMenu)
|
|||||||
// Save/load retry loop
|
// Save/load retry loop
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
|
BOOLEAN canceled_by_user = FALSE;
|
||||||
|
|
||||||
pickState.success = FALSE;
|
pickState.success = FALSE;
|
||||||
DoInput (&MenuState, TRUE);
|
DoInput (&MenuState, TRUE);
|
||||||
if (!pickState.success)
|
if (!pickState.success)
|
||||||
@@ -1039,11 +1224,11 @@ PickGame (BOOLEAN saving, BOOLEAN fromMainMenu)
|
|||||||
|
|
||||||
lastUsedSlot = MenuState.CurState;
|
lastUsedSlot = MenuState.CurState;
|
||||||
|
|
||||||
if (SaveLoadGame (&pickState, MenuState.CurState))
|
if (SaveLoadGame (&pickState, MenuState.CurState, &canceled_by_user))
|
||||||
break; // all good
|
break; // all good
|
||||||
|
|
||||||
// something broke
|
// something broke
|
||||||
if (saving)
|
if (saving && !canceled_by_user)
|
||||||
SaveProblem ();
|
SaveProblem ();
|
||||||
// TODO: Shouldn't we have a Problem() equivalent for Load too?
|
// TODO: Shouldn't we have a Problem() equivalent for Load too?
|
||||||
|
|
||||||
@@ -1154,4 +1339,3 @@ GameOptions (void)
|
|||||||
|
|
||||||
return !(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD));
|
return !(GLOBAL (CurrentActivity) & (CHECK_ABORT | CHECK_LOAD));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+29
-8
@@ -480,10 +480,10 @@ LoadGameState (GAME_STATE *GSPtr, DECODE_REF fh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
LoadSisState (SIS_STATE *SSPtr, void *fp)
|
LoadSisState (SIS_STATE *SSPtr, void *fp, SDWORD first)
|
||||||
{
|
{
|
||||||
|
SSPtr->log_x = first;
|
||||||
if (
|
if (
|
||||||
read_32s (fp, &SSPtr->log_x) != 1 ||
|
|
||||||
read_32s (fp, &SSPtr->log_y) != 1 ||
|
read_32s (fp, &SSPtr->log_y) != 1 ||
|
||||||
read_32 (fp, &SSPtr->ResUnits) != 1 ||
|
read_32 (fp, &SSPtr->ResUnits) != 1 ||
|
||||||
read_32 (fp, &SSPtr->FuelOnBoard) != 1 ||
|
read_32 (fp, &SSPtr->FuelOnBoard) != 1 ||
|
||||||
@@ -510,7 +510,26 @@ LoadSisState (SIS_STATE *SSPtr, void *fp)
|
|||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
LoadSummary (SUMMARY_DESC *SummPtr, void *fp)
|
LoadSummary (SUMMARY_DESC *SummPtr, void *fp)
|
||||||
{
|
{
|
||||||
if (!LoadSisState (&SummPtr->SS, fp))
|
SDWORD magic;
|
||||||
|
BOOLEAN legacy;
|
||||||
|
SummPtr->SaveName[0] = 0;
|
||||||
|
if (!read_32s (fp, &magic))
|
||||||
|
return FALSE;
|
||||||
|
if (magic == SAVE_MAGIC)
|
||||||
|
{
|
||||||
|
legacy = FALSE;
|
||||||
|
// Read in the real first value for LoadSisState
|
||||||
|
if (read_32 (fp, &magic) != 1)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Otherwise, we're legacy and the "magic" number was
|
||||||
|
// really LoadSisState's first value
|
||||||
|
legacy = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!LoadSisState (&SummPtr->SS, fp, magic))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@@ -524,11 +543,15 @@ LoadSummary (SUMMARY_DESC *SummPtr, void *fp)
|
|||||||
read_8 (fp, &SummPtr->NumShips) != 1 ||
|
read_8 (fp, &SummPtr->NumShips) != 1 ||
|
||||||
read_8 (fp, &SummPtr->NumDevices) != 1 ||
|
read_8 (fp, &SummPtr->NumDevices) != 1 ||
|
||||||
read_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 ||
|
read_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 ||
|
||||||
read_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1 ||
|
read_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1
|
||||||
|
|
||||||
read_16 (fp, NULL) != 1 /* padding */
|
|
||||||
)
|
)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
if (!legacy && (read_a8 (fp, SummPtr->SaveName, SAVE_NAME_SIZE) != 1))
|
||||||
|
return FALSE;
|
||||||
|
// Don't trust the savefile to properly null-terminate!
|
||||||
|
SummPtr->SaveName[SAVE_NAME_SIZE-1] = 0;
|
||||||
|
if (read_16 (fp, NULL) != 1) /* padding */
|
||||||
|
return FALSE;
|
||||||
else
|
else
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -760,5 +783,3 @@ LoadGame (COUNT which_game, SUMMARY_DESC *SummPtr)
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+9
-4
@@ -443,6 +443,8 @@ SaveSisState (const SIS_STATE *SSPtr, void *fp)
|
|||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
SaveSummary (const SUMMARY_DESC *SummPtr, void *fp)
|
SaveSummary (const SUMMARY_DESC *SummPtr, void *fp)
|
||||||
{
|
{
|
||||||
|
if (write_32 (fp, SAVE_MAGIC) != 1)
|
||||||
|
return FALSE;
|
||||||
if (!SaveSisState (&SummPtr->SS, fp))
|
if (!SaveSisState (&SummPtr->SS, fp))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@@ -458,6 +460,7 @@ SaveSummary (const SUMMARY_DESC *SummPtr, void *fp)
|
|||||||
write_8 (fp, SummPtr->NumDevices) != 1 ||
|
write_8 (fp, SummPtr->NumDevices) != 1 ||
|
||||||
write_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 ||
|
write_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 ||
|
||||||
write_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1 ||
|
write_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1 ||
|
||||||
|
write_a8 (fp, SummPtr->SaveName, SAVE_NAME_SIZE) != 1 ||
|
||||||
|
|
||||||
write_16 (fp, 0) != 1 /* padding */
|
write_16 (fp, 0) != 1 /* padding */
|
||||||
)
|
)
|
||||||
@@ -478,8 +481,9 @@ SaveStarDesc (const STAR_DESC *SDPtr, DECODE_REF fh)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
PrepareSummary (SUMMARY_DESC *SummPtr)
|
PrepareSummary (SUMMARY_DESC *SummPtr, const char *name)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
SummPtr->SS = GlobData.SIS_state;
|
SummPtr->SS = GlobData.SIS_state;
|
||||||
|
|
||||||
SummPtr->Activity = LOBYTE (GLOBAL (CurrentActivity));
|
SummPtr->Activity = LOBYTE (GLOBAL (CurrentActivity));
|
||||||
@@ -535,6 +539,8 @@ PrepareSummary (SUMMARY_DESC *SummPtr)
|
|||||||
SummPtr->day_index = GLOBAL (GameClock.day_index);
|
SummPtr->day_index = GLOBAL (GameClock.day_index);
|
||||||
SummPtr->month_index = GLOBAL (GameClock.month_index);
|
SummPtr->month_index = GLOBAL (GameClock.month_index);
|
||||||
SummPtr->year_index = GLOBAL (GameClock.year_index);
|
SummPtr->year_index = GLOBAL (GameClock.year_index);
|
||||||
|
SummPtr->SaveName[SAVE_NAME_SIZE-1] = 0;
|
||||||
|
strncpy (SummPtr->SaveName, name, SAVE_NAME_SIZE-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -635,7 +641,7 @@ SaveFlagshipState (void)
|
|||||||
// This function first writes to a memory file, and then writes the whole
|
// This function first writes to a memory file, and then writes the whole
|
||||||
// lot to the actual save file at once.
|
// lot to the actual save file at once.
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
SaveGame (COUNT which_game, SUMMARY_DESC *SummPtr)
|
SaveGame (COUNT which_game, SUMMARY_DESC *SummPtr, const char *name)
|
||||||
{
|
{
|
||||||
BOOLEAN success, made_room;
|
BOOLEAN success, made_room;
|
||||||
void *out_fp, *h;
|
void *out_fp, *h;
|
||||||
@@ -833,7 +839,7 @@ RetrySave:
|
|||||||
flen + sizeof (*SummPtr));
|
flen + sizeof (*SummPtr));
|
||||||
if (flen && (out_fp = res_OpenResFile (saveDir, file, "wb")))
|
if (flen && (out_fp = res_OpenResFile (saveDir, file, "wb")))
|
||||||
{
|
{
|
||||||
PrepareSummary (SummPtr);
|
PrepareSummary (SummPtr, name);
|
||||||
|
|
||||||
success = SaveSummary (SummPtr, out_fp);
|
success = SaveSummary (SummPtr, out_fp);
|
||||||
// Then write the rest of the data.
|
// Then write the rest of the data.
|
||||||
@@ -858,4 +864,3 @@ RetrySave:
|
|||||||
|
|
||||||
return (success);
|
return (success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -26,7 +26,7 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern void SaveProblem (void);
|
extern void SaveProblem (void);
|
||||||
extern BOOLEAN SaveGame (COUNT which_game, SUMMARY_DESC *summary_desc);
|
extern BOOLEAN SaveGame (COUNT which_game, SUMMARY_DESC *summary_desc, const char *name);
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,8 @@ typedef struct
|
|||||||
// is only used for displaying savegame summaries. There is also
|
// is only used for displaying savegame summaries. There is also
|
||||||
// room for only 16 devices on screen.
|
// room for only 16 devices on screen.
|
||||||
#define MAX_EXCLUSIVE_DEVICES 16
|
#define MAX_EXCLUSIVE_DEVICES 16
|
||||||
|
#define SAVE_MAGIC 0x01534d55
|
||||||
|
#define SAVE_NAME_SIZE 24
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -172,6 +174,7 @@ typedef struct
|
|||||||
BYTE NumShips, NumDevices;
|
BYTE NumShips, NumDevices;
|
||||||
BYTE ShipList[MAX_BUILT_SHIPS];
|
BYTE ShipList[MAX_BUILT_SHIPS];
|
||||||
BYTE DeviceList[MAX_EXCLUSIVE_DEVICES];
|
BYTE DeviceList[MAX_EXCLUSIVE_DEVICES];
|
||||||
|
UNICODE SaveName[SAVE_NAME_SIZE];
|
||||||
} SUMMARY_DESC;
|
} SUMMARY_DESC;
|
||||||
|
|
||||||
#define OVERRIDE_LANDER_FLAGS (1 << 7)
|
#define OVERRIDE_LANDER_FLAGS (1 << 7)
|
||||||
|
|||||||
Reference in New Issue
Block a user