Restructed and normalized savegame and game-state reading/writing code; not reading/writing pointers and useless values anymore

git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2390 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
avolkov
2006-07-07 19:25:51 +00:00
parent 2d6763b0d1
commit a031b75c2d
36 changed files with 1171 additions and 543 deletions
+5 -1
View File
@@ -924,13 +924,17 @@ typedef struct
VELOCITY_DESC velocity; VELOCITY_DESC velocity;
DWORD BattleGroupRef; DWORD BattleGroupRef;
QUEUE avail_race_q, npc_built_ship_q; QUEUE avail_race_q;
QUEUE npc_built_ship_q;
// Non-player-character list of ships (during encounter)
// or list of groups present in solarsys (during IP)
QUEUE encounter_q; QUEUE encounter_q;
QUEUE built_ship_q; QUEUE built_ship_q;
/* Queue of SIS escort ships */ /* Queue of SIS escort ships */
BYTE GameState[(NUM_GAME_STATE_BITS + 7) >> 3]; BYTE GameState[(NUM_GAME_STATE_BITS + 7) >> 3];
} GAME_STATE; } GAME_STATE;
typedef GAME_STATE *PGAME_STATE;
typedef struct typedef struct
{ {
+115 -36
View File
@@ -38,11 +38,95 @@ static BYTE LastEncGroup;
typedef struct typedef struct
{ {
BYTE NumGroups, day_index, month_index; BYTE NumGroups;
BYTE day_index, month_index;
COUNT star_index, year_index; COUNT star_index, year_index;
// day_index, month_index, year_index specify when
// random groups expire (if you were to leave the system
// by going to HSpace and stay there till such time)
// star_index is the index of a star this group header
// applies to; ~0 means uninited
DWORD GroupOffset[MAX_BATTLE_GROUPS + 1]; DWORD GroupOffset[MAX_BATTLE_GROUPS + 1];
// Absolute offsets of group definitions in a state file
// Group 0 is actually a list of groups present in solarsys
// Groups 1..max are definitions of actual battle groups
// containing ships composition and status
// Each group has the following format:
// 1 byte, RaceType (LastEncGroup in Group 0)
// 1 byte, NumShips
// Ships follow:
// 1 byte, RaceType
// 16 bytes, part of SHIP_FRAGMENT struct
} GROUP_HEADER; } GROUP_HEADER;
static void
ReadGroupHeader (PVOID fp, GROUP_HEADER* pGH)
{
sread_8 (fp, &pGH->NumGroups);
sread_8 (fp, &pGH->day_index);
sread_8 (fp, &pGH->month_index);
sread_8 (fp, NULL); /* padding */
sread_16 (fp, &pGH->star_index);
sread_16 (fp, &pGH->year_index);
sread_a32 (fp, pGH->GroupOffset, MAX_BATTLE_GROUPS + 1);
}
static void
WriteGroupHeader (PVOID fp, GROUP_HEADER* pGH)
{
swrite_8 (fp, pGH->NumGroups);
swrite_8 (fp, pGH->day_index);
swrite_8 (fp, pGH->month_index);
swrite_8 (fp, 0); /* padding */
swrite_16 (fp, pGH->star_index);
swrite_16 (fp, pGH->year_index);
swrite_a32 (fp, pGH->GroupOffset, MAX_BATTLE_GROUPS + 1);
}
static void
ReadShipFragment (PVOID fp, SHIP_FRAGMENTPTR FragPtr)
{
BYTE tmpb;
// Read SHIP_FRAGMENT elements
sread_16 (fp, &FragPtr->s.Player);
sread_8 (fp, &FragPtr->s.Captain);
sread_8 (fp, NULL); /* padding */
// Read SHIP_INFO elements
sread_16 (fp, &FragPtr->ShipInfo.ship_flags);
sread_8 (fp, &FragPtr->ShipInfo.var1);
sread_8 (fp, &FragPtr->ShipInfo.var2);
sread_8 (fp, &tmpb);
FragPtr->ShipInfo.crew_level = tmpb;
sread_8 (fp, &tmpb);
FragPtr->ShipInfo.max_crew = tmpb;
sread_8 (fp, &FragPtr->ShipInfo.energy_level);
sread_8 (fp, &FragPtr->ShipInfo.max_energy);
sread_16 (fp, &FragPtr->ShipInfo.loc.x);
sread_16 (fp, &FragPtr->ShipInfo.loc.y);
}
static void
WriteShipFragment (PVOID fp, SHIP_FRAGMENTPTR FragPtr)
{
// Write SHIP_FRAGMENT elements
swrite_16 (fp, FragPtr->s.Player);
swrite_8 (fp, FragPtr->s.Captain);
swrite_8 (fp, 0); /* padding */
// Write SHIP_INFO elements
swrite_16 (fp, FragPtr->ShipInfo.ship_flags);
swrite_8 (fp, FragPtr->ShipInfo.var1);
swrite_8 (fp, FragPtr->ShipInfo.var2);
swrite_8 (fp, FragPtr->ShipInfo.crew_level);
swrite_8 (fp, FragPtr->ShipInfo.max_crew);
swrite_8 (fp, FragPtr->ShipInfo.energy_level);
swrite_8 (fp, FragPtr->ShipInfo.max_energy);
swrite_16 (fp, FragPtr->ShipInfo.loc.x);
swrite_16 (fp, FragPtr->ShipInfo.loc.y);
}
void void
InitGroupInfo (BOOLEAN FirstTime) InitGroupInfo (BOOLEAN FirstTime)
{ {
@@ -56,14 +140,16 @@ InitGroupInfo (BOOLEAN FirstTime)
GH.NumGroups = 0; GH.NumGroups = 0;
GH.star_index = (COUNT)~0; GH.star_index = (COUNT)~0;
GH.GroupOffset[0] = 0; GH.GroupOffset[0] = 0;
WriteStateFile (&GH, sizeof (GH), 1, fp); WriteGroupHeader (fp, &GH);
CloseStateFile (fp); CloseStateFile (fp);
} }
if (FirstTime && (fp = OpenStateFile (DEFGRPINFO_FILE, "wb"))) if (FirstTime && (fp = OpenStateFile (DEFGRPINFO_FILE, "wb")))
{ {
PutStateFileChar (0, fp); // Group headers cannot start with offset 0 in
// defined group info file, so bump it
swrite_8 (fp, 0);
CloseStateFile (fp); CloseStateFile (fp);
} }
@@ -297,11 +383,11 @@ FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID fp)
&GLOBAL (npc_built_ship_q), hStarShip); &GLOBAL (npc_built_ship_q), hStarShip);
RaceType = GET_RACE_ID (FragPtr); RaceType = GET_RACE_ID (FragPtr);
SeekStateFile (fp, pGH->GroupOffset[which_group], SEEK_SET); SeekStateFile (fp, pGH->GroupOffset[which_group], SEEK_SET);
WriteStateFile (&RaceType, sizeof (RaceType), 1, fp); swrite_8 (fp, RaceType);
UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip);
} }
SeekStateFile (fp, offset, SEEK_SET); SeekStateFile (fp, offset, SEEK_SET);
WriteStateFile (pGH, sizeof (*pGH), 1, fp); WriteGroupHeader (fp, pGH);
#ifdef DEBUG_GROUPS #ifdef DEBUG_GROUPS
log_add (log_Debug, "1)FlushGroupInfo(%lu): WG = %u(%lu), NG = %u, " log_add (log_Debug, "1)FlushGroupInfo(%lu): WG = %u(%lu), NG = %u, "
"SI = %u", offset, which_group, pGH->GroupOffset[which_group], "SI = %u", offset, which_group, pGH->GroupOffset[which_group],
@@ -311,22 +397,20 @@ FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID fp)
NumShips = (BYTE)CountLinks (&GLOBAL (npc_built_ship_q)); NumShips = (BYTE)CountLinks (&GLOBAL (npc_built_ship_q));
if (which_group != GROUP_LIST) if (which_group != GROUP_LIST)
{ { // skip RaceType
SeekStateFile (fp, pGH->GroupOffset[which_group] SeekStateFile (fp, pGH->GroupOffset[which_group] + 1, SEEK_SET);
+ sizeof (LastEncGroup), SEEK_SET);
} }
else else
{ {
SeekStateFile (fp, pGH->GroupOffset[0], SEEK_SET); SeekStateFile (fp, pGH->GroupOffset[0], SEEK_SET);
WriteStateFile (&LastEncGroup, sizeof (LastEncGroup), 1, fp); swrite_8 (fp, LastEncGroup);
} }
WriteStateFile (&NumShips, sizeof (NumShips), 1, fp); swrite_8 (fp, NumShips);
hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q)); hStarShip = GetHeadLink (&GLOBAL (npc_built_ship_q));
while (NumShips--) while (NumShips--)
{ {
HSTARSHIP hNextShip; HSTARSHIP hNextShip;
PBYTE Ptr;
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (
&GLOBAL (npc_built_ship_q), hStarShip &GLOBAL (npc_built_ship_q), hStarShip
@@ -334,7 +418,7 @@ FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID fp)
hNextShip = _GetSuccLink (FragPtr); hNextShip = _GetSuccLink (FragPtr);
RaceType = GET_RACE_ID (FragPtr); RaceType = GET_RACE_ID (FragPtr);
WriteStateFile (&RaceType, sizeof (RaceType), 1, fp); swrite_8 (fp, RaceType);
#ifdef DEBUG_GROUPS #ifdef DEBUG_GROUPS
if (which_group == GROUP_LIST) if (which_group == GROUP_LIST)
@@ -346,9 +430,7 @@ FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID fp)
GET_GROUP_MISSION (FragPtr), GET_GROUP_MISSION (FragPtr),
GET_GROUP_DEST (FragPtr)); GET_GROUP_DEST (FragPtr));
#endif /* DEBUG_GROUPS */ #endif /* DEBUG_GROUPS */
Ptr = (PBYTE)&FragPtr->RaceDescPtr; WriteShipFragment (fp, FragPtr);
WriteStateFile (Ptr,
((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, 1, fp);
UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip); UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip);
hStarShip = hNextShip; hStarShip = hNextShip;
} }
@@ -372,7 +454,7 @@ GetGroupInfo (DWORD offset, BYTE which_group)
SHIP_FRAGMENTPTR FragPtr; SHIP_FRAGMENTPTR FragPtr;
SeekStateFile (fp, offset, SEEK_SET); SeekStateFile (fp, offset, SEEK_SET);
ReadStateFile (&GH, sizeof (GH), 1, fp); ReadGroupHeader (fp, &GH);
#ifdef DEBUG_GROUPS #ifdef DEBUG_GROUPS
log_add (log_Debug, "GetGroupInfo(%lu): %u(%lu) out of %u", offset, log_add (log_Debug, "GetGroupInfo(%lu): %u(%lu) out of %u", offset,
which_group, GH.GroupOffset[which_group], GH.NumGroups); which_group, GH.GroupOffset[which_group], GH.NumGroups);
@@ -402,11 +484,12 @@ GetGroupInfo (DWORD offset, BYTE which_group)
"date %u/%u/%u!", month_index, day_index, "date %u/%u/%u!", month_index, day_index,
year_index); year_index);
#endif /* DEBUG_GROUPS */ #endif /* DEBUG_GROUPS */
// Erase random groups (out of date)
fp = OpenStateFile (RANDGRPINFO_FILE, "wb"); fp = OpenStateFile (RANDGRPINFO_FILE, "wb");
GH.NumGroups = 0; GH.NumGroups = 0;
GH.star_index = (COUNT)~0; GH.star_index = (COUNT)~0;
GH.GroupOffset[0] = 0; GH.GroupOffset[0] = 0;
WriteStateFile (&GH, sizeof (GH), 1, fp); WriteGroupHeader (fp, &GH);
} }
else else
{ {
@@ -417,8 +500,8 @@ GetGroupInfo (DWORD offset, BYTE which_group)
continue; continue;
SeekStateFile (fp, GH.GroupOffset[which_group], SEEK_SET); SeekStateFile (fp, GH.GroupOffset[which_group], SEEK_SET);
ReadStateFile (&RaceType, sizeof (RaceType), 1, fp); sread_8 (fp, &RaceType);
ReadStateFile (&NumShips, sizeof (NumShips), 1, fp); sread_8 (fp, &NumShips);
if (NumShips) if (NumShips)
{ {
@@ -516,7 +599,7 @@ GetGroupInfo (DWORD offset, BYTE which_group)
if (which_group == GROUP_LIST) if (which_group == GROUP_LIST)
{ {
SeekStateFile (fp, GH.GroupOffset[0], SEEK_SET); SeekStateFile (fp, GH.GroupOffset[0], SEEK_SET);
ReadStateFile (&LastEncGroup, sizeof (LastEncGroup), 1, fp); sread_8 (fp, &LastEncGroup);
if (LastEncGroup) if (LastEncGroup)
{ {
@@ -536,25 +619,20 @@ GetGroupInfo (DWORD offset, BYTE which_group)
} }
ReinitQueue (&GLOBAL (npc_built_ship_q)); ReinitQueue (&GLOBAL (npc_built_ship_q));
SeekStateFile (fp, GH.GroupOffset[which_group] // skip RaceType
+ sizeof (LastEncGroup), SEEK_SET); SeekStateFile (fp, GH.GroupOffset[which_group] + 1, SEEK_SET);
ReadStateFile (&NumShips, sizeof (NumShips), 1, fp); sread_8 (fp, &NumShips);
while (NumShips--) while (NumShips--)
{ {
PBYTE Ptr; sread_8 (fp, &RaceType);
ReadStateFile (&RaceType, sizeof (RaceType), 1, fp);
hStarShip = CloneShipFragment (RaceType, hStarShip = CloneShipFragment (RaceType,
&GLOBAL (npc_built_ship_q), 0); &GLOBAL (npc_built_ship_q), 0);
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip ( FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (
&GLOBAL (npc_built_ship_q), hStarShip); &GLOBAL (npc_built_ship_q), hStarShip);
Ptr = (PBYTE)&FragPtr->RaceDescPtr; ReadShipFragment (fp, FragPtr);
ReadStateFile (Ptr,
((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, 1,
fp);
#ifdef DEBUG_GROUPS #ifdef DEBUG_GROUPS
if (which_group == GROUP_LIST) if (which_group == GROUP_LIST)
@@ -625,12 +703,13 @@ PutGroupInfo (DWORD offset, BYTE which_group)
if (offset == GROUPS_ADD_NEW) if (offset == GROUPS_ADD_NEW)
{ {
offset = LengthStateFile (fp); offset = LengthStateFile (fp);
GH.NumGroups = 0;
GH.GroupOffset[0] = 0;
SeekStateFile (fp, offset, SEEK_SET); SeekStateFile (fp, offset, SEEK_SET);
WriteStateFile (&GH, sizeof (GH), 1, fp); // XXX: All important fields are inited here, and the
// XXX: It seems that GH is not completely initialised. // rest are inited below
// Some garbage is saved. -- SvdB GH.NumGroups = 0;
GH.star_index = (COUNT)~0;
GH.GroupOffset[0] = 0;
WriteGroupHeader (fp, &GH);
} }
if (which_group != GROUP_LIST) if (which_group != GROUP_LIST)
@@ -642,7 +721,7 @@ PutGroupInfo (DWORD offset, BYTE which_group)
which_group = GROUP_LIST; which_group = GROUP_LIST;
} }
} }
ReadStateFile (&GH, sizeof (GH), 1, fp); ReadGroupHeader (fp, &GH);
#ifdef NEVER #ifdef NEVER
if (GetHeadLink (&GLOBAL (npc_built_ship_q)) if (GetHeadLink (&GLOBAL (npc_built_ship_q))
+566 -290
View File
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <assert.h>
#include "load.h" #include "load.h"
#include "build.h" #include "build.h"
@@ -35,62 +37,166 @@
ACTIVITY NextActivity; ACTIVITY NextActivity;
static BOOLEAN LoadSummary (uio_Stream *in_fp); // XXX: these should handle endian conversions later
static inline COUNT
cread_8 (DECODE_REF fh, PBYTE v)
{
BYTE t;
if (!v) /* read value ignored */
v = &t;
return cread (v, 1, 1, fh);
}
static inline COUNT
cread_16 (DECODE_REF fh, PUWORD v)
{
UWORD t;
if (!v) /* read value ignored */
v = &t;
return cread (v, 2, 1, fh);
}
static inline COUNT
cread_32 (DECODE_REF fh, PDWORD v)
{
DWORD t;
if (!v) /* read value ignored */
v = &t;
return cread (v, 4, 1, fh);
}
static inline COUNT
cread_ptr (DECODE_REF fh)
{
DWORD t;
return cread_32 (fh, &t); /* ptrs are useless in saves */
}
static inline COUNT
cread_a8 (DECODE_REF fh, PBYTE ar, COUNT count)
{
assert (ar != NULL);
return cread (ar, 1, count, fh) == count;
}
static inline COUNT
read_8 (PVOID fp, PBYTE v)
{
BYTE t;
if (!v) /* read value ignored */
v = &t;
return ReadResFile (v, 1, 1, fp);
}
static inline COUNT
read_16 (PVOID fp, PUWORD v)
{
UWORD t;
if (!v) /* read value ignored */
v = &t;
return ReadResFile (v, 2, 1, fp);
}
static inline COUNT
read_32 (PVOID fp, PDWORD v)
{
DWORD t;
if (!v) /* read value ignored */
v = &t;
return ReadResFile (v, 4, 1, fp);
}
static inline COUNT
read_ptr (PVOID fp)
{
DWORD t;
return read_32 (fp, &t); /* ptrs are useless in saves */
}
static inline COUNT
read_a8 (PVOID fp, PBYTE ar, COUNT count)
{
assert (ar != NULL);
return ReadResFile (ar, 1, count, fp) == count;
}
static inline COUNT
read_a16 (PVOID fp, PUWORD ar, COUNT count)
{
assert (ar != NULL);
for ( ; count > 0; --count, ++ar)
{
if (read_16 (fp, ar) != 1)
return 0;
}
return 1;
}
static void static void
LoadShipQueue (DECODE_REF fh, PQUEUE pQueue, BOOLEAN MakeQ) LoadShipQueue (DECODE_REF fh, PQUEUE pQueue, BOOLEAN MakeQ)
{ {
COUNT num_links; COUNT num_links;
cread ((PBYTE)&num_links, sizeof (num_links), 1, fh); cread_16 (fh, &num_links);
if (num_links) if (num_links && MakeQ)
InitQueue (pQueue, num_links, sizeof (SHIP_FRAGMENT));
while (num_links--)
{ {
if (MakeQ) HSTARSHIP hStarShip;
InitQueue (pQueue, num_links, sizeof (SHIP_FRAGMENT)); SHIP_FRAGMENTPTR FragPtr;
COUNT Index;
BYTE tmpb;
do cread_16 (fh, &Index);
if (pQueue == &GLOBAL (avail_race_q))
hStarShip = GetStarShipFromIndex (pQueue, Index);
else
hStarShip = CloneShipFragment (Index, pQueue, 0);
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip);
if (pQueue != &GLOBAL (avail_race_q))
{ // queues other than avail_race_q save SHIP_FRAGMENT elements
// Read SHIP_FRAGMENT elements
cread_16 (fh, &FragPtr->s.Player);
cread_8 (fh, &FragPtr->s.Captain);
cread_8 (fh, NULL); /* padding */
}
// Read SHIP_INFO elements
cread_16 (fh, &FragPtr->ShipInfo.ship_flags);
cread_8 (fh, &FragPtr->ShipInfo.var1);
cread_8 (fh, &FragPtr->ShipInfo.var2);
cread_8 (fh, &tmpb);
FragPtr->ShipInfo.crew_level = tmpb;
cread_8 (fh, &tmpb);
FragPtr->ShipInfo.max_crew = tmpb;
cread_8 (fh, &FragPtr->ShipInfo.energy_level);
cread_8 (fh, &FragPtr->ShipInfo.max_energy);
cread_16 (fh, &FragPtr->ShipInfo.loc.x);
cread_16 (fh, &FragPtr->ShipInfo.loc.y);
if (pQueue == &GLOBAL (avail_race_q))
{ {
HSTARSHIP hStarShip; // avail_race_q contains information not about specific ships,
SHIP_FRAGMENTPTR FragPtr; // but about a race.
COUNT Index, Offset; EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr =
PBYTE Ptr; (EXTENDED_SHIP_FRAGMENTPTR) FragPtr;
cread ((PBYTE)&Index, sizeof (Index), 1, fh); cread_16 (fh, &ExtFragPtr->ShipInfo.actual_strength);
cread_16 (fh, &ExtFragPtr->ShipInfo.known_strength);
cread_16 (fh, &ExtFragPtr->ShipInfo.known_loc.x);
cread_16 (fh, &ExtFragPtr->ShipInfo.known_loc.y);
cread_8 (fh, &ExtFragPtr->ShipInfo.growth_err_term);
cread_8 (fh, &ExtFragPtr->ShipInfo.func_index);
cread_16 (fh, &ExtFragPtr->ShipInfo.dest_loc.x);
cread_16 (fh, &ExtFragPtr->ShipInfo.dest_loc.y);
cread_16 (fh, NULL); /* alignment padding */
}
if (pQueue == &GLOBAL (avail_race_q)) UnlockStarShip (pQueue, hStarShip);
{
hStarShip = GetStarShipFromIndex (pQueue, Index);
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip);
Offset = 0;
}
else
{
hStarShip = CloneShipFragment (Index, pQueue, 0);
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip);
Offset = (PBYTE)&FragPtr->ShipInfo
- (PBYTE)&FragPtr->RaceDescPtr;
}
Ptr = ((PBYTE)&FragPtr->ShipInfo) - Offset;
cread ((PBYTE)Ptr,
((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, 1, fh);
// Hack to retain savegame backwards compatibility, after
// increasing crew_level and max_crew from BYTE to COUNT.
// For the queues that are saved here, a BYTE is large enough.
FragPtr->ShipInfo.max_crew = FragPtr->ShipInfo.dummy_max_crew;
FragPtr->ShipInfo.crew_level = FragPtr->ShipInfo.dummy_crew_level;
if (Offset == 0)
{
EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr;
ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR)FragPtr;
Ptr = (PBYTE)&ExtFragPtr->ShipInfo.actual_strength;
cread ((PBYTE)Ptr, ((PBYTE)&ExtFragPtr[1]) - Ptr, 1, fh);
}
UnlockStarShip (pQueue, hStarShip);
} while (--num_links);
} }
} }
@@ -98,278 +204,448 @@ static void
LoadEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh) LoadEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh)
{ {
COUNT i; COUNT i;
#define LOAD_BLOCK(file, start, end) \
cread((PBYTE) (start), (PBYTE) (end) - (PBYTE) start, \
1, (file))
// An ENCOUNTER structure (indirectly) contains an array of
// SHIP_INFO structure, which is bigger now because of the
// larger type for crew.
// This hack makes sure the savegames format is unchanged.
// The original code consisted of just one line:
// cread ((PBYTE)EncounterPtr, sizeof (*EncounterPtr), 1, fh);
// Load the stuff before the SHIP_INFO array: cread_ptr (fh); /* useless ptr; HENCOUNTER pred */
LOAD_BLOCK(fh, EncounterPtr, EncounterPtr->SD.ShipList); EncounterPtr->pred = 0;
cread_ptr (fh); /* useless ptr; HENCOUNTER succ */
EncounterPtr->succ = 0;
cread_ptr (fh); /* useless ptr; HELEMENT hElement */
EncounterPtr->hElement = 0;
cread_16 (fh, &EncounterPtr->transition_state);
cread_16 (fh, &EncounterPtr->origin.x);
cread_16 (fh, &EncounterPtr->origin.y);
cread_16 (fh, &EncounterPtr->radius);
// EXTENDED_STAR_DESC fields
cread_16 (fh, &EncounterPtr->SD.star_pt.x);
cread_16 (fh, &EncounterPtr->SD.star_pt.y);
cread_8 (fh, &EncounterPtr->SD.Type);
cread_8 (fh, &EncounterPtr->SD.Index);
cread_16 (fh, NULL); /* alignment padding */
// Load each entry in the SHIP_INFO array: // Load each entry in the SHIP_INFO array:
for (i = 0; i < MAX_HYPER_SHIPS; i++) for (i = 0; i < MAX_HYPER_SHIPS; i++)
{ {
SHIP_INFO *ShipInfo = &EncounterPtr->SD.ShipList[i]; SHIP_INFOPTR ShipInfo = &EncounterPtr->SD.ShipList[i];
LOAD_BLOCK(fh, ShipInfo, &ShipInfo->crew_level); BYTE tmpb;
ShipInfo->crew_level = ShipInfo->dummy_crew_level;
ShipInfo->max_crew = ShipInfo->dummy_max_crew; cread_16 (fh, &ShipInfo->ship_flags);
cread_8 (fh, &ShipInfo->var1);
cread_8 (fh, &ShipInfo->var2);
cread_8 (fh, &tmpb);
ShipInfo->crew_level = tmpb;
cread_8 (fh, &tmpb);
ShipInfo->max_crew = tmpb;
cread_8 (fh, &ShipInfo->energy_level);
cread_8 (fh, &ShipInfo->max_energy);
cread_16 (fh, &ShipInfo->loc.x);
cread_16 (fh, &ShipInfo->loc.y);
cread_32 (fh, NULL); /* useless val; STRING race_strings */
ShipInfo->race_strings = 0;
cread_ptr (fh); /* useless ptr; FRAME icons */
ShipInfo->icons = 0;
cread_ptr (fh); /* useless ptr; FRAME melee_icon */
ShipInfo->melee_icon = 0;
} }
// Load the stuff after the SHIP_INFO array: // Load the stuff after the SHIP_INFO array:
LOAD_BLOCK(fh, &EncounterPtr->log_x, &EncounterPtr[1]); cread_32 (fh, &EncounterPtr->log_x);
cread_32 (fh, &EncounterPtr->log_y);
}
static void
LoadEvent (EVENTPTR EventPtr, DECODE_REF fh)
{
cread_ptr (fh); /* useless ptr; HEVENT pred */
EventPtr->pred = 0;
cread_ptr (fh); /* useless ptr; HEVENT succ */
EventPtr->succ = 0;
cread_8 (fh, &EventPtr->day_index);
cread_8 (fh, &EventPtr->month_index);
cread_16 (fh, &EventPtr->year_index);
cread_8 (fh, &EventPtr->func_index);
cread_8 (fh, NULL); /* padding */
cread_16 (fh, NULL); /* padding */
}
static void
DummyLoadQueue (PQUEUE QueuePtr, DECODE_REF fh)
{
/* QUEUE should never actually be loaded since it contains
* purely internal representation and the lists
* involved are actually loaded separately */
(void)QueuePtr; /* silence compiler */
/* QUEUE format with QUEUE_TABLE defined -- UQM default */
cread_ptr (fh); /* HLINK head */
cread_ptr (fh); /* HLINK tail */
cread_ptr (fh); /* PBYTE pq_tab */
cread_ptr (fh); /* HLINK free_list */
cread_16 (fh, NULL); /* MEM_HANDLE hq_tab */
cread_16 (fh, NULL); /* COUNT object_size */
cread_8 (fh, NULL); /* BYTE num_objects */
cread_8 (fh, NULL); /* padding */
cread_16 (fh, NULL); /* padding */
}
static void
LoadClockState (PCLOCK_STATE ClockPtr, DECODE_REF fh)
{
cread_8 (fh, &ClockPtr->day_index);
cread_8 (fh, &ClockPtr->month_index);
cread_16 (fh, &ClockPtr->year_index);
cread_16 (fh, &ClockPtr->tick_count);
cread_16 (fh, &ClockPtr->day_in_ticks);
cread_ptr (fh); /* not loading ptr; Semaphore clock_sem */
cread_ptr (fh); /* not loading ptr; Task clock_task */
cread_32 (fh, &ClockPtr->TimeCounter); /* theoretically useless */
DummyLoadQueue (&ClockPtr->event_q, fh);
}
static void
LoadGameState (PGAME_STATE GSPtr, DECODE_REF fh)
{
DWORD tmpd;
cread_8 (fh, &GSPtr->cur_state); /* obsolete */
cread_8 (fh, &GSPtr->glob_flags);
cread_8 (fh, &GSPtr->CrewCost);
cread_8 (fh, &GSPtr->FuelCost);
cread_a8 (fh, GSPtr->ModuleCost, NUM_MODULES);
cread_a8 (fh, GSPtr->ElementWorth, NUM_ELEMENT_CATEGORIES);
cread_ptr (fh); /* not loading ptr; PPRIMITIVE DisplayArray */
cread_16 (fh, &GSPtr->CurrentActivity);
cread_16 (fh, NULL); /* CLOCK_STATE alignment padding */
LoadClockState (&GSPtr->GameClock, fh);
cread_16 (fh, &GSPtr->autopilot.x);
cread_16 (fh, &GSPtr->autopilot.y);
cread_16 (fh, &GSPtr->ip_location.x);
cread_16 (fh, &GSPtr->ip_location.y);
/* STAMP ShipStamp */
cread_16 (fh, &GSPtr->ShipStamp.origin.x);
cread_16 (fh, &GSPtr->ShipStamp.origin.y);
cread_32 (fh, &tmpd); /* abused ptr to store DWORD */
GSPtr->ShipStamp.frame = (FRAME)tmpd;
/* VELOCITY_DESC velocity */
cread_16 (fh, &GSPtr->velocity.TravelAngle);
cread_16 (fh, &GSPtr->velocity.vector.width);
cread_16 (fh, &GSPtr->velocity.vector.height);
cread_16 (fh, &GSPtr->velocity.fract.width);
cread_16 (fh, &GSPtr->velocity.fract.height);
cread_16 (fh, &GSPtr->velocity.error.width);
cread_16 (fh, &GSPtr->velocity.error.height);
cread_16 (fh, &GSPtr->velocity.incr.width);
cread_16 (fh, &GSPtr->velocity.incr.height);
cread_16 (fh, NULL); /* VELOCITY_DESC padding */
cread_32 (fh, &GSPtr->BattleGroupRef);
DummyLoadQueue (&GSPtr->avail_race_q, fh);
DummyLoadQueue (&GSPtr->npc_built_ship_q, fh);
DummyLoadQueue (&GSPtr->encounter_q, fh);
DummyLoadQueue (&GSPtr->built_ship_q, fh);
cread_a8 (fh, GSPtr->GameState, sizeof (GSPtr->GameState));
assert (sizeof (GSPtr->GameState) % 4 == 3);
cread_8 (fh, NULL); /* GAME_STATE alignment padding */
} }
static BOOLEAN static BOOLEAN
LoadSummary (uio_Stream *in_fp) LoadSisState (PSIS_STATE SSPtr, PVOID fp)
{ {
// XXX: This function seems to be unused. if (
SUMMARY_DESC S; read_32 (fp, &SSPtr->log_x) != 1 ||
read_32 (fp, &SSPtr->log_y) != 1 ||
read_32 (fp, &SSPtr->ResUnits) != 1 ||
read_32 (fp, &SSPtr->FuelOnBoard) != 1 ||
read_16 (fp, &SSPtr->CrewEnlisted) != 1 ||
read_16 (fp, &SSPtr->TotalElementMass) != 1 ||
read_16 (fp, &SSPtr->TotalBioMass) != 1 ||
read_a8 (fp, SSPtr->ModuleSlots, NUM_MODULE_SLOTS) != 1 ||
read_a8 (fp, SSPtr->DriveSlots, NUM_DRIVE_SLOTS) != 1 ||
read_a8 (fp, SSPtr->JetSlots, NUM_JET_SLOTS) != 1 ||
read_8 (fp, &SSPtr->NumLanders) != 1 ||
read_a16 (fp, SSPtr->ElementAmounts, NUM_ELEMENT_CATEGORIES) != 1 ||
return (ReadResFile (&S, sizeof (S), 1, in_fp) == sizeof (S)); read_a8 (fp, SSPtr->ShipName, SIS_NAME_SIZE) != 1 ||
read_a8 (fp, SSPtr->CommanderName, SIS_NAME_SIZE) != 1 ||
read_a8 (fp, SSPtr->PlanetName, SIS_NAME_SIZE) != 1 ||
read_16 (fp, NULL) != 1 /* padding */
)
return FALSE;
else
return TRUE;
}
static BOOLEAN
LoadSummary (SUMMARY_DESC *SummPtr, PVOID fp)
{
if (!LoadSisState (&SummPtr->SS, fp))
return FALSE;
if (
read_8 (fp, &SummPtr->Activity) != 1 ||
read_8 (fp, &SummPtr->Flags) != 1 ||
read_8 (fp, &SummPtr->day_index) != 1 ||
read_8 (fp, &SummPtr->month_index) != 1 ||
read_16 (fp, &SummPtr->year_index) != 1 ||
read_8 (fp, &SummPtr->MCreditLo) != 1 ||
read_8 (fp, &SummPtr->MCreditHi) != 1 ||
read_8 (fp, &SummPtr->NumShips) != 1 ||
read_8 (fp, &SummPtr->NumDevices) != 1 ||
read_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 ||
read_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1 ||
read_16 (fp, NULL) != 1 /* padding */
)
return FALSE;
else
return TRUE;
}
static void
LoadStarDesc (STAR_DESCPTR SDPtr, DECODE_REF fh)
{
cread_16 (fh, &SDPtr->star_pt.x);
cread_16 (fh, &SDPtr->star_pt.y);
cread_8 (fh, &SDPtr->Type);
cread_8 (fh, &SDPtr->Index);
cread_8 (fh, &SDPtr->Prefix);
cread_8 (fh, &SDPtr->Postfix);
} }
BOOLEAN BOOLEAN
LoadGame (COUNT which_game, SUMMARY_DESC *summary_desc) LoadGame (COUNT which_game, SUMMARY_DESC *SummPtr)
{ {
uio_Stream *in_fp; uio_Stream *in_fp;
char buf[256], file[PATH_MAX]; char file[PATH_MAX];
char buf[256];
SUMMARY_DESC loc_sd;
GAME_STATE_FILE *fp;
DECODE_REF fh;
COUNT num_links;
STAR_DESC SD;
ACTIVITY Activity;
sprintf (file, "starcon2.%02u", which_game); sprintf (file, "starcon2.%02u", which_game);
in_fp = res_OpenResFile (saveDir, file, "rb"); in_fp = res_OpenResFile (saveDir, file, "rb");
if (in_fp) if (!in_fp)
return FALSE;
if (!LoadSummary (&loc_sd, in_fp))
{ {
GAME_STATE_FILE *fp; log_add (log_Always, "Warning: Savegame is corrupt");
DECODE_REF fh;
COUNT num_links;
Semaphore clock_sem;
Task clock_task;
QUEUE event_q, encounter_q, avail_q, npc_q, player_q;
STAR_DESC SD;
ACTIVITY Activity;
ReadResFile (buf, sizeof (*summary_desc), 1, in_fp);
if (summary_desc == 0)
summary_desc = (SUMMARY_DESC *)buf;
else
{
memcpy (summary_desc, buf, sizeof (*summary_desc));
res_CloseResFile (in_fp);
return TRUE;
}
// Crude check for big-endian/little-endian incompatibilities.
// year_index is suitable as it's a multi-byte value within
// a specific recognisable range.
if (summary_desc->year_index < START_YEAR ||
summary_desc->year_index >= START_YEAR +
YEARS_TO_KOHRAH_VICTORY + 1 /* Utwig intervention */ +
1 /* time to destroy all races, plenty */ +
25 /* for cheaters */)
{
log_add (log_Always, "Warning: Savegame corrupt or from an "
"an incompatible platform.");
res_CloseResFile (in_fp);
return FALSE;
}
GlobData.SIS_state = summary_desc->SS;
if ((fh = copen (in_fp, FILE_STREAM, STREAM_READ)) == 0)
{
res_CloseResFile (in_fp);
return FALSE;
}
ReinitQueue (&GLOBAL (GameClock.event_q));
ReinitQueue (&GLOBAL (encounter_q));
ReinitQueue (&GLOBAL (npc_built_ship_q));
ReinitQueue (&GLOBAL (built_ship_q));
clock_sem = GLOBAL (GameClock.clock_sem);
clock_task = GLOBAL (GameClock.clock_task);
event_q = GLOBAL (GameClock.event_q);
encounter_q = GLOBAL (encounter_q);
avail_q = GLOBAL (avail_race_q);
npc_q = GLOBAL (npc_built_ship_q);
player_q = GLOBAL (built_ship_q);
memset ((PBYTE)&GLOBAL (GameState[0]),
0, sizeof (GLOBAL (GameState)));
Activity = GLOBAL (CurrentActivity);
cread ((PBYTE)&GlobData.Game_state, sizeof (GlobData.Game_state), 1,
fh);
NextActivity = GLOBAL (CurrentActivity);
GLOBAL (CurrentActivity) = Activity;
GLOBAL (GameClock.clock_sem) = clock_sem;
GLOBAL (GameClock.clock_task) = clock_task;
GLOBAL (GameClock.event_q) = event_q;
GLOBAL (encounter_q) = encounter_q;
GLOBAL (avail_race_q) = avail_q;
GLOBAL (npc_built_ship_q) = npc_q;
GLOBAL (built_ship_q) = player_q;
// It shouldn't be possible to ever save with TimeCounter != 0
// But if it does happen, it needs to be reset to 0, since on load
// the clock semaphore is gauranteed to be 0
if (GLOBAL (GameClock.TimeCounter) != 0)
log_add (log_Always, "Warning: Game clock wasn't stopped during "
"save, Savegame may be corrupt!\n");
GLOBAL (GameClock.TimeCounter) = 0;
LoadShipQueue (fh, &GLOBAL (avail_race_q), FALSE);
if (!(NextActivity & START_INTERPLANETARY))
LoadShipQueue (fh, &GLOBAL (npc_built_ship_q), FALSE);
LoadShipQueue (fh, &GLOBAL (built_ship_q), FALSE);
cread ((PBYTE)&num_links, sizeof (num_links), 1, fh);
{
#ifdef DEBUG_LOAD
log_add (log_Debug, "EVENTS:");
#endif /* DEBUG_LOAD */
while (num_links--)
{
HEVENT hEvent;
EVENTPTR EventPtr;
hEvent = AllocEvent ();
LockEvent (hEvent, &EventPtr);
cread ((PBYTE)EventPtr, sizeof (*EventPtr), 1, fh);
#ifdef DEBUG_LOAD
log_add (log_Debug, "\t%u/%u/%u -- %u",
EventPtr->month_index,
EventPtr->day_index,
EventPtr->year_index,
EventPtr->func_index);
#endif /* DEBUG_LOAD */
UnlockEvent (hEvent);
PutEvent (hEvent);
}
}
cread ((PBYTE)&num_links, sizeof (num_links), 1, fh);
{
while (num_links--)
{
BYTE i, NumShips;
HENCOUNTER hEncounter;
ENCOUNTERPTR EncounterPtr;
hEncounter = AllocEncounter ();
LockEncounter (hEncounter, &EncounterPtr);
LoadEncounter(EncounterPtr, fh);
EncounterPtr->hElement = 0;
NumShips = LONIBBLE (EncounterPtr->SD.Index);
for (i = 0; i < NumShips; ++i)
{
HSTARSHIP hStarShip;
SHIP_FRAGMENTPTR TemplatePtr;
hStarShip = GetStarShipFromIndex (
&GLOBAL (avail_race_q),
EncounterPtr->SD.ShipList[i].var1);
TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip (
&GLOBAL (avail_race_q), hStarShip);
EncounterPtr->SD.ShipList[i].race_strings =
TemplatePtr->ShipInfo.race_strings;
EncounterPtr->SD.ShipList[i].icons =
TemplatePtr->ShipInfo.icons;
EncounterPtr->SD.ShipList[i].melee_icon =
TemplatePtr->ShipInfo.melee_icon;
UnlockStarShip (&GLOBAL (avail_race_q), hStarShip);
}
UnlockEncounter (hEncounter);
PutEncounter (hEncounter);
}
}
fp = OpenStateFile (STARINFO_FILE, "wb");
if (fp)
{
DWORD flen;
cread ((PBYTE)&flen, sizeof (flen), 1, fh);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
cread ((PBYTE)buf, num_bytes, 1, fh);
WriteStateFile (buf, num_bytes, 1, fp);
flen -= num_bytes;
}
CloseStateFile (fp);
}
fp = OpenStateFile (DEFGRPINFO_FILE, "wb");
if (fp)
{
DWORD flen;
cread ((PBYTE)&flen, sizeof (flen), 1, fh);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
cread ((PBYTE)buf, num_bytes, 1, fh);
WriteStateFile (buf, num_bytes, 1, fp);
flen -= num_bytes;
}
CloseStateFile (fp);
}
fp = OpenStateFile (RANDGRPINFO_FILE, "wb");
if (fp)
{
DWORD flen;
cread ((PBYTE)&flen, sizeof (flen), 1, fh);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
cread ((PBYTE)buf, num_bytes, 1, fh);
WriteStateFile (buf, num_bytes, 1, fp);
flen -= num_bytes;
}
CloseStateFile (fp);
}
cread ((PBYTE)&SD, sizeof (SD), 1, fh);
cclose (fh);
res_CloseResFile (in_fp); res_CloseResFile (in_fp);
return FALSE;
}
EncounterGroup = 0; if (!SummPtr)
EncounterRace = -1; {
SummPtr = &loc_sd;
ReinitQueue (&race_q[0]); }
ReinitQueue (&race_q[1]); else
CurStarDescPtr = FindStar (NULL_PTR, &SD.star_pt, 0, 0); { // only need summary for displaying to user
if (!(NextActivity & START_ENCOUNTER) memcpy (SummPtr, &loc_sd, sizeof (*SummPtr));
&& LOBYTE (NextActivity) == IN_INTERPLANETARY) res_CloseResFile (in_fp);
NextActivity |= START_INTERPLANETARY;
GLOBAL (DisplayArray) = DisplayArray;
return TRUE; return TRUE;
} }
return FALSE; // Crude check for big-endian/little-endian incompatibilities.
// year_index is suitable as it's a multi-byte value within
// a specific recognisable range.
if (SummPtr->year_index < START_YEAR ||
SummPtr->year_index >= START_YEAR +
YEARS_TO_KOHRAH_VICTORY + 1 /* Utwig intervention */ +
1 /* time to destroy all races, plenty */ +
25 /* for cheaters */)
{
log_add (log_Always, "Warning: Savegame corrupt or from an "
"an incompatible platform.");
res_CloseResFile (in_fp);
return FALSE;
}
GlobData.SIS_state = SummPtr->SS;
if ((fh = copen (in_fp, FILE_STREAM, STREAM_READ)) == 0)
{
res_CloseResFile (in_fp);
return FALSE;
}
ReinitQueue (&GLOBAL (GameClock.event_q));
ReinitQueue (&GLOBAL (encounter_q));
ReinitQueue (&GLOBAL (npc_built_ship_q));
ReinitQueue (&GLOBAL (built_ship_q));
memset (&GLOBAL (GameState[0]), 0, sizeof (GLOBAL (GameState)));
Activity = GLOBAL (CurrentActivity);
LoadGameState (&GlobData.Game_state, fh);
NextActivity = GLOBAL (CurrentActivity);
GLOBAL (CurrentActivity) = Activity;
// It shouldn't be possible to ever save with TimeCounter != 0
// But if it does happen, it needs to be reset to 0, since on load
// the clock semaphore is gauranteed to be 0
if (GLOBAL (GameClock.TimeCounter) != 0)
log_add (log_Always, "Warning: Game clock wasn't stopped during "
"save, Savegame may be corrupt!\n");
GLOBAL (GameClock.TimeCounter) = 0;
LoadShipQueue (fh, &GLOBAL (avail_race_q), FALSE);
if (!(NextActivity & START_INTERPLANETARY))
LoadShipQueue (fh, &GLOBAL (npc_built_ship_q), FALSE);
LoadShipQueue (fh, &GLOBAL (built_ship_q), FALSE);
// Load the game events (compressed)
cread_16 (fh, &num_links);
{
#ifdef DEBUG_LOAD
log_add (log_Debug, "EVENTS:");
#endif /* DEBUG_LOAD */
while (num_links--)
{
HEVENT hEvent;
EVENTPTR EventPtr;
hEvent = AllocEvent ();
LockEvent (hEvent, &EventPtr);
LoadEvent (EventPtr, fh);
#ifdef DEBUG_LOAD
log_add (log_Debug, "\t%u/%u/%u -- %u",
EventPtr->month_index,
EventPtr->day_index,
EventPtr->year_index,
EventPtr->func_index);
#endif /* DEBUG_LOAD */
UnlockEvent (hEvent);
PutEvent (hEvent);
}
}
// Load the encounters (black globes in HS/QS (compressed))
cread_16 (fh, &num_links);
{
while (num_links--)
{
BYTE i, NumShips;
HENCOUNTER hEncounter;
ENCOUNTERPTR EncounterPtr;
hEncounter = AllocEncounter ();
LockEncounter (hEncounter, &EncounterPtr);
LoadEncounter (EncounterPtr, fh);
NumShips = LONIBBLE (EncounterPtr->SD.Index);
for (i = 0; i < NumShips; ++i)
{
HSTARSHIP hStarShip;
SHIP_FRAGMENTPTR TemplatePtr;
hStarShip = GetStarShipFromIndex (
&GLOBAL (avail_race_q),
EncounterPtr->SD.ShipList[i].var1);
TemplatePtr = (SHIP_FRAGMENTPTR)LockStarShip (
&GLOBAL (avail_race_q), hStarShip);
EncounterPtr->SD.ShipList[i].race_strings =
TemplatePtr->ShipInfo.race_strings;
EncounterPtr->SD.ShipList[i].icons =
TemplatePtr->ShipInfo.icons;
EncounterPtr->SD.ShipList[i].melee_icon =
TemplatePtr->ShipInfo.melee_icon;
UnlockStarShip (&GLOBAL (avail_race_q), hStarShip);
}
UnlockEncounter (hEncounter);
PutEncounter (hEncounter);
}
}
// Copy the star info file from the compressed stream
fp = OpenStateFile (STARINFO_FILE, "wb");
if (fp)
{
DWORD flen;
cread_32 (fh, &flen);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
cread (buf, num_bytes, 1, fh);
WriteStateFile (buf, num_bytes, 1, fp);
flen -= num_bytes;
}
CloseStateFile (fp);
}
// Copy the defined groupinfo file from the compressed stream
fp = OpenStateFile (DEFGRPINFO_FILE, "wb");
if (fp)
{
DWORD flen;
cread_32 (fh, &flen);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
cread (buf, num_bytes, 1, fh);
WriteStateFile (buf, num_bytes, 1, fp);
flen -= num_bytes;
}
CloseStateFile (fp);
}
// Copy the random groupinfo file from the compressed stream
fp = OpenStateFile (RANDGRPINFO_FILE, "wb");
if (fp)
{
DWORD flen;
cread_32 (fh, &flen);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
cread (buf, num_bytes, 1, fh);
WriteStateFile (buf, num_bytes, 1, fp);
flen -= num_bytes;
}
CloseStateFile (fp);
}
LoadStarDesc (&SD, fh);
cclose (fh);
res_CloseResFile (in_fp);
EncounterGroup = 0;
EncounterRace = -1;
ReinitQueue (&race_q[0]);
ReinitQueue (&race_q[1]);
CurStarDescPtr = FindStar (NULL, &SD.star_pt, 0, 0);
if (!(NextActivity & START_ENCOUNTER)
&& LOBYTE (NextActivity) == IN_INTERPLANETARY)
NextActivity |= START_INTERPLANETARY;
return TRUE;
} }
+6 -14
View File
@@ -101,10 +101,9 @@ typedef struct
{ {
UWORD ship_flags; UWORD ship_flags;
BYTE var1, var2; BYTE var1, var2;
BYTE dummy_crew_level, dummy_max_crew; COUNT crew_level, max_crew;
/* Necessary for savegame backwards compatibility. /* For ships in npc_built_ship_q, the value INFINITE_FLEET for
* Unused during the game, only used during save/load. * crew_level indicates an infinite number of ships. */
*/
BYTE energy_level, max_energy; BYTE energy_level, max_energy;
POINT loc; POINT loc;
@@ -115,9 +114,6 @@ typedef struct
STRING race_strings; STRING race_strings;
FRAME icons, melee_icon; FRAME icons, melee_icon;
COUNT crew_level, max_crew;
/* For ships in npc_built_ship_q, the value INFINITE_FLEET for
* crew_level indicates an infinite number of ships. */
#define INFINITE_FLEET ((COUNT) ~0) #define INFINITE_FLEET ((COUNT) ~0)
} SHIP_INFO; } SHIP_INFO;
typedef SHIP_INFO *PSHIP_INFO; typedef SHIP_INFO *PSHIP_INFO;
@@ -164,10 +160,9 @@ typedef struct
BYTE days_left; BYTE days_left;
/* Days left before the fleet reachers 'dest_loc'. */ /* Days left before the fleet reachers 'dest_loc'. */
BYTE growth_fract; BYTE growth_fract;
BYTE dummy_crew_level, dummy_max_crew; COUNT crew_level, max_crew;
/* Necessary for savegame backwards compatibility. /* For ships in npc_built_ship_q, the value INFINITE_FLEET for
* Unused during the game, only used during save/load. * crew_level indicates an infinite number of ships. */
*/
BYTE energy_level, max_energy; BYTE energy_level, max_energy;
POINT loc; POINT loc;
/* Location of the fleet (center) */ /* Location of the fleet (center) */
@@ -175,9 +170,6 @@ typedef struct
STRING race_strings; STRING race_strings;
/* Race specific strings, see doc/devel/racestrings. */ /* Race specific strings, see doc/devel/racestrings. */
FRAME icons, melee_icon; FRAME icons, melee_icon;
COUNT crew_level, max_crew;
/* For ships in npc_built_ship_q, the value INFINITE_FLEET for
* crew_level indicates an infinite number of ships. */
/* -== The fields below this line are included in savegames. ==- */ /* -== The fields below this line are included in savegames. ==- */
+341 -98
View File
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/ */
#include <assert.h>
#include "save.h" #include "save.h"
#include "build.h" #include "build.h"
@@ -35,6 +37,78 @@
#include "libs/log.h" #include "libs/log.h"
// XXX: these should handle endian conversions later
static inline COUNT
cwrite_8 (DECODE_REF fh, BYTE v)
{
return cwrite (&v, 1, 1, fh);
}
static inline COUNT
cwrite_16 (DECODE_REF fh, UWORD v)
{
return cwrite (&v, 2, 1, fh);
}
static inline COUNT
cwrite_32 (DECODE_REF fh, DWORD v)
{
return cwrite (&v, 4, 1, fh);
}
static inline COUNT
cwrite_ptr (DECODE_REF fh)
{
return cwrite_32 (fh, 0); /* ptrs are useless in saves */
}
static inline COUNT
cwrite_a8 (DECODE_REF fh, PBYTE ar, COUNT count)
{
return cwrite (ar, 1, count, fh) == count;
}
static inline COUNT
write_8 (PVOID fp, BYTE v)
{
return WriteResFile (&v, 1, 1, fp);
}
static inline COUNT
write_16 (PVOID fp, UWORD v)
{
return WriteResFile (&v, 2, 1, fp);
}
static inline COUNT
write_32 (PVOID fp, DWORD v)
{
return WriteResFile (&v, 4, 1, fp);
}
static inline COUNT
write_ptr (PVOID fp)
{
return write_32 (fp, 0); /* ptrs are useless in saves */
}
static inline COUNT
write_a8 (PVOID fp, PBYTE ar, COUNT count)
{
return WriteResFile (ar, 1, count, fp) == count;
}
static inline COUNT
write_a16 (PVOID fp, PUWORD ar, COUNT count)
{
for ( ; count > 0; --count, ++ar)
{
if (write_16 (fp, *ar) != 1)
return 0;
}
return 1;
}
static void static void
SaveShipQueue (DECODE_REF fh, PQUEUE pQueue) SaveShipQueue (DECODE_REF fh, PQUEUE pQueue)
{ {
@@ -43,67 +117,62 @@ SaveShipQueue (DECODE_REF fh, PQUEUE pQueue)
// Write the number of entries in the queue. // Write the number of entries in the queue.
num_links = CountLinks (pQueue); num_links = CountLinks (pQueue);
cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh); cwrite_16 (fh, num_links);
hStarShip = GetHeadLink (pQueue); hStarShip = GetHeadLink (pQueue);
while (num_links--) while (num_links--)
{ {
HSTARSHIP hNextShip; HSTARSHIP hNextShip;
SHIP_FRAGMENTPTR FragPtr; SHIP_FRAGMENTPTR FragPtr;
COUNT Index, Offset; COUNT Index;
PBYTE Ptr;
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip); FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip);
hNextShip = _GetSuccLink (FragPtr); hNextShip = _GetSuccLink (FragPtr);
if (pQueue == &GLOBAL (avail_race_q)) if (pQueue == &GLOBAL (avail_race_q))
{
Index = GetIndexFromStarShip (pQueue, hStarShip); Index = GetIndexFromStarShip (pQueue, hStarShip);
// The index is the position in the queue. // The index is the position in the queue.
Offset = 0;
}
else else
{
Index = GET_RACE_ID (FragPtr); Index = GET_RACE_ID (FragPtr);
Offset = (PBYTE)&FragPtr->ShipInfo
- (PBYTE)&FragPtr->RaceDescPtr;
}
// Write the number identifying this ship type. // Write the number identifying this ship type.
// See races.h; look for the enum containing NUM_AVAILABLE_RACES. // See races.h; look for the enum containing NUM_AVAILABLE_RACES.
cwrite ((PBYTE)&Index, sizeof (Index), 1, fh); cwrite_16 (fh, Index);
// Hack to retain savegame backwards compatibility, after if (pQueue != &GLOBAL (avail_race_q))
// increasing crew_level and max_crew from BYTE to COUNT. { // queues other than avail_race_q save SHIP_FRAGMENT elements
// For the queues that are saved here, a BYTE is large enough. // Write SHIP_FRAGMENT elements
FragPtr->ShipInfo.dummy_max_crew = FragPtr->ShipInfo.max_crew; cwrite_16 (fh, FragPtr->s.Player);
FragPtr->ShipInfo.dummy_crew_level = FragPtr->ShipInfo.crew_level; cwrite_8 (fh, FragPtr->s.Captain);
cwrite_8 (fh, 0); /* padding */
}
// Write SHIP_INFO elements
cwrite_16 (fh, FragPtr->ShipInfo.ship_flags);
cwrite_8 (fh, FragPtr->ShipInfo.var1);
cwrite_8 (fh, FragPtr->ShipInfo.var2);
cwrite_8 (fh, FragPtr->ShipInfo.crew_level);
cwrite_8 (fh, FragPtr->ShipInfo.max_crew);
cwrite_8 (fh, FragPtr->ShipInfo.energy_level);
cwrite_8 (fh, FragPtr->ShipInfo.max_energy);
cwrite_16 (fh, FragPtr->ShipInfo.loc.x);
cwrite_16 (fh, FragPtr->ShipInfo.loc.y);
// Write part of FragPtr, starting with FragPtr->ShipInfo for if (pQueue == &GLOBAL (avail_race_q))
// GLOBAL(avail_race_q), and FragPtr->RaceDescPtr for other queues.
// When FragPtr->RaceDescPtr is saved, it does not actually
// contain a pointer (see the definition of SHIP_FRAGMENT).
// This is only so because SaveShipQueue() is only ever called with
// GLOBAL_avail_race_q), GLOBAL(built_ship_q) and
// GLOBAL(npc_built_ship_q).
Ptr = ((PBYTE)&FragPtr->ShipInfo) - Offset;
cwrite ((PBYTE)Ptr, ((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr,
1, fh);
if (Offset == 0)
{ {
// The queue being saved is avail_race_q. // avail_race_q contains information not about specific ships,
// It contains information not about specific ships, but about // but about a race.
// a race. What is saved is everything in the EXTENDED_SHIP_INFO EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr =
// structure from the field 'actual_strength' onwards, (EXTENDED_SHIP_FRAGMENTPTR) FragPtr;
// for each of the races.
EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr;
ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR)FragPtr; cwrite_16 (fh, ExtFragPtr->ShipInfo.actual_strength);
Ptr = (PBYTE)&ExtFragPtr->ShipInfo.actual_strength; cwrite_16 (fh, ExtFragPtr->ShipInfo.known_strength);
cwrite ((PBYTE)Ptr, ((PBYTE)&ExtFragPtr[1]) - Ptr, 1, fh); cwrite_16 (fh, ExtFragPtr->ShipInfo.known_loc.x);
// XXX: This saves padding too, which may contain cwrite_16 (fh, ExtFragPtr->ShipInfo.known_loc.y);
// garbage. cwrite_8 (fh, ExtFragPtr->ShipInfo.growth_err_term);
cwrite_8 (fh, ExtFragPtr->ShipInfo.func_index);
cwrite_16 (fh, ExtFragPtr->ShipInfo.dest_loc.x);
cwrite_16 (fh, ExtFragPtr->ShipInfo.dest_loc.y);
cwrite_16 (fh, 0); /* alignment padding */
} }
UnlockStarShip (pQueue, hStarShip); UnlockStarShip (pQueue, hStarShip);
@@ -115,59 +184,234 @@ static void
SaveEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh) SaveEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh)
{ {
COUNT i; COUNT i;
#define SAVE_BLOCK(file, start, end) \
cwrite((PBYTE) (start), (PBYTE) (end) - (PBYTE) start, \
1, (file))
// An ENCOUNTER structure (indirectly) contains an array of
// SHIP_INFO structure, which is bigger now because of the
// larger type for crew.
// This hack makes sure the savegames format is unchanged.
// The original code consisted of jsut one line:
// cwrite ((PBYTE)EncounterPtr, sizeof (*EncounterPtr), 1, fh);
// Save the stuff before the SHIP_INFO array: cwrite_ptr (fh); /* useless ptr; HENCOUNTER pred */
SAVE_BLOCK(fh, EncounterPtr, EncounterPtr->SD.ShipList); cwrite_ptr (fh); /* useless ptr; HENCOUNTER succ */
cwrite_ptr (fh); /* useless ptr; HELEMENT hElement */
cwrite_16 (fh, EncounterPtr->transition_state);
cwrite_16 (fh, EncounterPtr->origin.x);
cwrite_16 (fh, EncounterPtr->origin.y);
cwrite_16 (fh, EncounterPtr->radius);
// EXTENDED_STAR_DESC fields
cwrite_16 (fh, EncounterPtr->SD.star_pt.x);
cwrite_16 (fh, EncounterPtr->SD.star_pt.y);
cwrite_8 (fh, EncounterPtr->SD.Type);
cwrite_8 (fh, EncounterPtr->SD.Index);
cwrite_16 (fh, 0); /* alignment padding */
// Save each entry in the SHIP_INFO array: // Save each entry in the SHIP_INFO array:
for (i = 0; i < MAX_HYPER_SHIPS; i++) for (i = 0; i < MAX_HYPER_SHIPS; i++)
{ {
SHIP_INFO *ShipInfo = &EncounterPtr->SD.ShipList[i]; SHIP_INFOPTR ShipInfo = &EncounterPtr->SD.ShipList[i];
ShipInfo->dummy_crew_level = (BYTE) ShipInfo->crew_level;
ShipInfo->dummy_max_crew = (BYTE) ShipInfo->max_crew; cwrite_16 (fh, ShipInfo->ship_flags);
SAVE_BLOCK(fh, ShipInfo, &ShipInfo->crew_level); cwrite_8 (fh, ShipInfo->var1);
cwrite_8 (fh, ShipInfo->var2);
cwrite_8 (fh, ShipInfo->crew_level);
cwrite_8 (fh, ShipInfo->max_crew);
cwrite_8 (fh, ShipInfo->energy_level);
cwrite_8 (fh, ShipInfo->max_energy);
cwrite_16 (fh, ShipInfo->loc.x);
cwrite_16 (fh, ShipInfo->loc.y);
cwrite_32 (fh, 0); /* useless val; STRING race_strings */
cwrite_ptr (fh); /* useless ptr; FRAME icons */
cwrite_ptr (fh); /* useless ptr; FRAME melee_icon */
} }
// Save the stuff after the SHIP_INFO array: // Save the stuff after the SHIP_INFO array:
SAVE_BLOCK(fh, &EncounterPtr->log_x, &EncounterPtr[1]); cwrite_32 (fh, EncounterPtr->log_x);
cwrite_32 (fh, EncounterPtr->log_y);
} }
static void static void
PrepareSummary (SUMMARY_DESC *summary_desc) SaveEvent (EVENTPTR EventPtr, DECODE_REF fh)
{ {
summary_desc->SS = GlobData.SIS_state; cwrite_ptr (fh); /* useless ptr; HEVENT pred */
cwrite_ptr (fh); /* useless ptr; HEVENT succ */
cwrite_8 (fh, EventPtr->day_index);
cwrite_8 (fh, EventPtr->month_index);
cwrite_16 (fh, EventPtr->year_index);
cwrite_8 (fh, EventPtr->func_index);
cwrite_8 (fh, 0); /* padding */
cwrite_16 (fh, 0); /* padding */
}
switch (summary_desc->Activity = LOBYTE (GLOBAL (CurrentActivity))) static void
DummySaveQueue (PQUEUE QueuePtr, DECODE_REF fh)
{
/* QUEUE should never actually be saved since it contains
* purely internal representation and the lists
* involved are actually saved separately */
(void)QueuePtr; /* silence compiler */
/* QUEUE format with QUEUE_TABLE defined -- UQM default */
cwrite_ptr (fh); /* HLINK head */
cwrite_ptr (fh); /* HLINK tail */
cwrite_ptr (fh); /* PBYTE pq_tab */
cwrite_ptr (fh); /* HLINK free_list */
cwrite_16 (fh, 0); /* MEM_HANDLE hq_tab */
cwrite_16 (fh, 0); /* COUNT object_size */
cwrite_8 (fh, 0); /* BYTE num_objects */
cwrite_8 (fh, 0); /* padding */
cwrite_16 (fh, 0); /* padding */
}
static void
SaveClockState (PCLOCK_STATE ClockPtr, DECODE_REF fh)
{
cwrite_8 (fh, ClockPtr->day_index);
cwrite_8 (fh, ClockPtr->month_index);
cwrite_16 (fh, ClockPtr->year_index);
cwrite_16 (fh, ClockPtr->tick_count);
cwrite_16 (fh, ClockPtr->day_in_ticks);
cwrite_ptr (fh); /* useless ptr; Semaphore clock_sem */
cwrite_ptr (fh); /* useless ptr; Task clock_task */
cwrite_32 (fh, ClockPtr->TimeCounter); /* theoretically useless */
DummySaveQueue (&ClockPtr->event_q, fh);
}
static void
SaveGameState (PGAME_STATE GSPtr, DECODE_REF fh)
{
cwrite_8 (fh, 0); /* obsolete; BYTE cur_state */
cwrite_8 (fh, GSPtr->glob_flags);
cwrite_8 (fh, GSPtr->CrewCost);
cwrite_8 (fh, GSPtr->FuelCost);
cwrite_a8 (fh, GSPtr->ModuleCost, NUM_MODULES);
cwrite_a8 (fh, GSPtr->ElementWorth, NUM_ELEMENT_CATEGORIES);
cwrite_ptr (fh); /* useless ptr; PPRIMITIVE DisplayArray */
cwrite_16 (fh, GSPtr->CurrentActivity);
cwrite_16 (fh, 0); /* CLOCK_STATE alignment padding */
SaveClockState (&GSPtr->GameClock, fh);
cwrite_16 (fh, GSPtr->autopilot.x);
cwrite_16 (fh, GSPtr->autopilot.y);
cwrite_16 (fh, GSPtr->ip_location.x);
cwrite_16 (fh, GSPtr->ip_location.y);
/* STAMP ShipStamp */
cwrite_16 (fh, GSPtr->ShipStamp.origin.x);
cwrite_16 (fh, GSPtr->ShipStamp.origin.y);
cwrite_32 (fh, (DWORD)GSPtr->ShipStamp.frame); /* abused ptr to store DWORD */
/* VELOCITY_DESC velocity */
cwrite_16 (fh, GSPtr->velocity.TravelAngle);
cwrite_16 (fh, GSPtr->velocity.vector.width);
cwrite_16 (fh, GSPtr->velocity.vector.height);
cwrite_16 (fh, GSPtr->velocity.fract.width);
cwrite_16 (fh, GSPtr->velocity.fract.height);
cwrite_16 (fh, GSPtr->velocity.error.width);
cwrite_16 (fh, GSPtr->velocity.error.height);
cwrite_16 (fh, GSPtr->velocity.incr.width);
cwrite_16 (fh, GSPtr->velocity.incr.height);
cwrite_16 (fh, 0); /* VELOCITY_DESC padding */
cwrite_32 (fh, GSPtr->BattleGroupRef);
DummySaveQueue (&GSPtr->avail_race_q, fh);
DummySaveQueue (&GSPtr->npc_built_ship_q, fh);
DummySaveQueue (&GSPtr->encounter_q, fh);
DummySaveQueue (&GSPtr->built_ship_q, fh);
cwrite_a8 (fh, GSPtr->GameState, sizeof (GSPtr->GameState));
assert (sizeof (GSPtr->GameState) % 4 == 3);
cwrite_8 (fh, 0); /* GAME_STATE alignment padding */
}
static BOOLEAN
SaveSisState (PSIS_STATE SSPtr, PVOID fp)
{
if (
write_32 (fp, SSPtr->log_x) != 1 ||
write_32 (fp, SSPtr->log_y) != 1 ||
write_32 (fp, SSPtr->ResUnits) != 1 ||
write_32 (fp, SSPtr->FuelOnBoard) != 1 ||
write_16 (fp, SSPtr->CrewEnlisted) != 1 ||
write_16 (fp, SSPtr->TotalElementMass) != 1 ||
write_16 (fp, SSPtr->TotalBioMass) != 1 ||
write_a8 (fp, SSPtr->ModuleSlots, NUM_MODULE_SLOTS) != 1 ||
write_a8 (fp, SSPtr->DriveSlots, NUM_DRIVE_SLOTS) != 1 ||
write_a8 (fp, SSPtr->JetSlots, NUM_JET_SLOTS) != 1 ||
write_8 (fp, SSPtr->NumLanders) != 1 ||
write_a16 (fp, SSPtr->ElementAmounts, NUM_ELEMENT_CATEGORIES) != 1 ||
write_a8 (fp, SSPtr->ShipName, SIS_NAME_SIZE) != 1 ||
write_a8 (fp, SSPtr->CommanderName, SIS_NAME_SIZE) != 1 ||
write_a8 (fp, SSPtr->PlanetName, SIS_NAME_SIZE) != 1 ||
write_16 (fp, 0) != 1 /* padding */
)
return FALSE;
else
return TRUE;
}
static BOOLEAN
SaveSummary (SUMMARY_DESC *SummPtr, PVOID fp)
{
if (!SaveSisState (&SummPtr->SS, fp))
return FALSE;
if (
write_8 (fp, SummPtr->Activity) != 1 ||
write_8 (fp, SummPtr->Flags) != 1 ||
write_8 (fp, SummPtr->day_index) != 1 ||
write_8 (fp, SummPtr->month_index) != 1 ||
write_16 (fp, SummPtr->year_index) != 1 ||
write_8 (fp, SummPtr->MCreditLo) != 1 ||
write_8 (fp, SummPtr->MCreditHi) != 1 ||
write_8 (fp, SummPtr->NumShips) != 1 ||
write_8 (fp, SummPtr->NumDevices) != 1 ||
write_a8 (fp, SummPtr->ShipList, MAX_BUILT_SHIPS) != 1 ||
write_a8 (fp, SummPtr->DeviceList, MAX_EXCLUSIVE_DEVICES) != 1 ||
write_16 (fp, 0) != 1 /* padding */
)
return FALSE;
else
return TRUE;
}
static void
SaveStarDesc (STAR_DESCPTR SDPtr, DECODE_REF fh)
{
cwrite_16 (fh, SDPtr->star_pt.x);
cwrite_16 (fh, SDPtr->star_pt.y);
cwrite_8 (fh, SDPtr->Type);
cwrite_8 (fh, SDPtr->Index);
cwrite_8 (fh, SDPtr->Prefix);
cwrite_8 (fh, SDPtr->Postfix);
}
static void
PrepareSummary (SUMMARY_DESC *SummPtr)
{
SummPtr->SS = GlobData.SIS_state;
switch (SummPtr->Activity = LOBYTE (GLOBAL (CurrentActivity)))
{ {
case IN_HYPERSPACE: case IN_HYPERSPACE:
if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1) if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1)
summary_desc->Activity = IN_QUASISPACE; SummPtr->Activity = IN_QUASISPACE;
break; break;
case IN_INTERPLANETARY: case IN_INTERPLANETARY:
if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == (BYTE)~0) if (GET_GAME_STATE (GLOBAL_FLAGS_AND_DATA) == (BYTE)~0)
summary_desc->Activity = IN_STARBASE; SummPtr->Activity = IN_STARBASE;
else if (pSolarSysState && pSolarSysState->MenuState.Initialized >= 3) else if (pSolarSysState && pSolarSysState->MenuState.Initialized >= 3)
summary_desc->Activity = IN_PLANET_ORBIT; SummPtr->Activity = IN_PLANET_ORBIT;
break; break;
} }
summary_desc->MCreditLo = GET_GAME_STATE (MELNORME_CREDIT0); SummPtr->MCreditLo = GET_GAME_STATE (MELNORME_CREDIT0);
summary_desc->MCreditHi = GET_GAME_STATE (MELNORME_CREDIT1); SummPtr->MCreditHi = GET_GAME_STATE (MELNORME_CREDIT1);
{ {
HSTARSHIP hStarShip, hNextShip; HSTARSHIP hStarShip, hNextShip;
for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), summary_desc->NumShips = 0; for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), SummPtr->NumShips = 0;
hStarShip; hStarShip = hNextShip, ++summary_desc->NumShips) hStarShip; hStarShip = hNextShip, ++SummPtr->NumShips)
{ {
SHIP_FRAGMENTPTR StarShipPtr; SHIP_FRAGMENTPTR StarShipPtr;
@@ -175,26 +419,26 @@ PrepareSummary (SUMMARY_DESC *summary_desc)
&GLOBAL (built_ship_q), hStarShip &GLOBAL (built_ship_q), hStarShip
); );
hNextShip = _GetSuccLink (StarShipPtr); hNextShip = _GetSuccLink (StarShipPtr);
summary_desc->ShipList[summary_desc->NumShips] = GET_RACE_ID (StarShipPtr); SummPtr->ShipList[SummPtr->NumShips] = GET_RACE_ID (StarShipPtr);
UnlockStarShip (&GLOBAL (built_ship_q), hStarShip); UnlockStarShip (&GLOBAL (built_ship_q), hStarShip);
} }
} }
summary_desc->NumDevices = InventoryDevices (summary_desc->DeviceList); SummPtr->NumDevices = InventoryDevices (SummPtr->DeviceList);
summary_desc->Flags = GET_GAME_STATE (LANDER_SHIELDS) SummPtr->Flags = GET_GAME_STATE (LANDER_SHIELDS)
| (GET_GAME_STATE (IMPROVED_LANDER_SPEED) << (4 + 0)) | (GET_GAME_STATE (IMPROVED_LANDER_SPEED) << (4 + 0))
| (GET_GAME_STATE (IMPROVED_LANDER_CARGO) << (4 + 1)) | (GET_GAME_STATE (IMPROVED_LANDER_CARGO) << (4 + 1))
| (GET_GAME_STATE (IMPROVED_LANDER_SHOT) << (4 + 2)) | (GET_GAME_STATE (IMPROVED_LANDER_SHOT) << (4 + 2))
| ((GET_GAME_STATE (CHMMR_BOMB_STATE) < 2 ? 0 : 1) << (4 + 3)); | ((GET_GAME_STATE (CHMMR_BOMB_STATE) < 2 ? 0 : 1) << (4 + 3));
summary_desc->day_index = GLOBAL (GameClock.day_index); SummPtr->day_index = GLOBAL (GameClock.day_index);
summary_desc->month_index = GLOBAL (GameClock.month_index); SummPtr->month_index = GLOBAL (GameClock.month_index);
summary_desc->year_index = GLOBAL (GameClock.year_index); SummPtr->year_index = GLOBAL (GameClock.year_index);
} }
static void static void
SaveProblemMessage (STAMP *MsgStamp) SaveProblemMessage (PSTAMP MsgStamp)
{ {
#define MAX_MSG_LINES 1 #define MAX_MSG_LINES 1
RECT r; RECT r;
@@ -299,7 +543,7 @@ SaveProblem (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 *summary_desc) SaveGame (COUNT which_game, SUMMARY_DESC *SummPtr)
{ {
BOOLEAN success, made_room; BOOLEAN success, made_room;
PVOID out_fp; PVOID out_fp;
@@ -346,6 +590,8 @@ RetrySave:
else else
memset (&SD, 0, sizeof (SD)); memset (&SD, 0, sizeof (SD));
// XXX: Backup: ShipStamp.frame is abused to store DWORD info
// SaveFlagshipState() overwrites it with a DWORD value
frame = GLOBAL (ShipStamp.frame); frame = GLOBAL (ShipStamp.frame);
pt = GLOBAL (ip_location); pt = GLOBAL (ip_location);
SaveFlagshipState (); SaveFlagshipState ();
@@ -354,10 +600,10 @@ RetrySave:
& (START_ENCOUNTER | START_INTERPLANETARY))) & (START_ENCOUNTER | START_INTERPLANETARY)))
PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP); PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP);
cwrite ((PBYTE)&GlobData.Game_state, sizeof (GlobData.Game_state), SaveGameState (&GlobData.Game_state, fh);
1, fh);
GLOBAL (ip_location) = pt; GLOBAL (ip_location) = pt;
// XXX: Restore: ShipStamp.frame is abused to store DWORD info
GLOBAL (ShipStamp.frame) = frame; GLOBAL (ShipStamp.frame) = frame;
SaveShipQueue (fh, &GLOBAL (avail_race_q)); SaveShipQueue (fh, &GLOBAL (avail_race_q));
@@ -367,7 +613,7 @@ RetrySave:
// Save the number of game events (compressed). // Save the number of game events (compressed).
num_links = CountLinks (&GLOBAL (GameClock.event_q)); num_links = CountLinks (&GLOBAL (GameClock.event_q));
cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh); cwrite_16 (fh, num_links);
// Save the game events themselves (compressed): // Save the game events themselves (compressed):
{ {
HEVENT hEvent; HEVENT hEvent;
@@ -381,7 +627,7 @@ RetrySave:
LockEvent (hEvent, &EventPtr); LockEvent (hEvent, &EventPtr);
hNextEvent = GetSuccEvent (EventPtr); hNextEvent = GetSuccEvent (EventPtr);
cwrite ((PBYTE)EventPtr, sizeof (*EventPtr), 1, fh); SaveEvent (EventPtr, fh);
UnlockEvent (hEvent); UnlockEvent (hEvent);
hEvent = hNextEvent; hEvent = hNextEvent;
@@ -391,7 +637,7 @@ RetrySave:
// Save the number of encounters (black globes in HS/QS (compressed)) // Save the number of encounters (black globes in HS/QS (compressed))
num_links = CountLinks (&GLOBAL (encounter_q)); num_links = CountLinks (&GLOBAL (encounter_q));
// Save the encounters themselves (compressed): // Save the encounters themselves (compressed):
cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh); cwrite_16 (fh, num_links);
{ {
HENCOUNTER hEncounter; HENCOUNTER hEncounter;
@@ -404,7 +650,7 @@ RetrySave:
LockEncounter (hEncounter, &EncounterPtr); LockEncounter (hEncounter, &EncounterPtr);
hNextEncounter = GetSuccEncounter (EncounterPtr); hNextEncounter = GetSuccEncounter (EncounterPtr);
SaveEncounter(EncounterPtr, fh); SaveEncounter (EncounterPtr, fh);
UnlockEncounter (hEncounter); UnlockEncounter (hEncounter);
hEncounter = hNextEncounter; hEncounter = hNextEncounter;
@@ -416,54 +662,55 @@ RetrySave:
if (fp) if (fp)
{ {
flen = LengthStateFile (fp); flen = LengthStateFile (fp);
// (DWORD) Write the uncompressed size. // Write the uncompressed size.
cwrite ((PBYTE)&flen, sizeof (flen), 1, fh); cwrite_32 (fh, flen);
while (flen) while (flen)
{ {
COUNT num_bytes; COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
ReadStateFile (buf, num_bytes, 1, fp); ReadStateFile (buf, num_bytes, 1, fp);
cwrite ((PBYTE)buf, num_bytes, 1, fh); cwrite (buf, num_bytes, 1, fh);
flen -= num_bytes; flen -= num_bytes;
} }
CloseStateFile (fp); CloseStateFile (fp);
} }
// Copy the ? groupinfo file into the memory file (compressed). // Copy the defined groupinfo file into the memory file (compressed)
fp = OpenStateFile (DEFGRPINFO_FILE, "rb"); fp = OpenStateFile (DEFGRPINFO_FILE, "rb");
if (fp) if (fp)
{ {
flen = LengthStateFile (fp); flen = LengthStateFile (fp);
// (DWORD) Write the uncompressed size. // Write the uncompressed size.
cwrite ((PBYTE)&flen, sizeof (flen), 1, fh); cwrite_32 (fh, flen);
while (flen) while (flen)
{ {
COUNT num_bytes; COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
ReadStateFile (buf, num_bytes, 1, fp); ReadStateFile (buf, num_bytes, 1, fp);
cwrite ((PBYTE)buf, num_bytes, 1, fh); cwrite (buf, num_bytes, 1, fh);
flen -= num_bytes; flen -= num_bytes;
} }
CloseStateFile (fp); CloseStateFile (fp);
} }
// Copy the ? groupinfo file into the memory file (compressed). // Copy the random groupinfo file into the memory file (compressed)
fp = OpenStateFile (RANDGRPINFO_FILE, "rb"); fp = OpenStateFile (RANDGRPINFO_FILE, "rb");
if (fp) if (fp)
{ {
flen = LengthStateFile (fp); flen = LengthStateFile (fp);
cwrite ((PBYTE)&flen, sizeof (flen), 1, fh); // Write the uncompressed size.
cwrite_32 (fh, flen);
while (flen) while (flen)
{ {
COUNT num_bytes; COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen; num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
ReadStateFile (buf, num_bytes, 1, fp); ReadStateFile (buf, num_bytes, 1, fp);
cwrite ((PBYTE)buf, num_bytes, 1, fh); cwrite (buf, num_bytes, 1, fh);
flen -= num_bytes; flen -= num_bytes;
} }
@@ -471,22 +718,19 @@ RetrySave:
} }
// Write the current star desc into the memory file (compressed). // Write the current star desc into the memory file (compressed).
cwrite ((PBYTE)&SD, sizeof (SD), 1, fh); SaveStarDesc (&SD, fh);
flen = cclose (fh); flen = cclose (fh);
// Write the memory file to the actual savegame file. // Write the memory file to the actual savegame file.
sprintf (file, "starcon2.%02u", which_game); sprintf (file, "starcon2.%02u", which_game);
log_add (log_Debug, "'%s' is %u bytes long", file, log_add (log_Debug, "'%s' is %u bytes long", file,
flen + sizeof (*summary_desc)); flen + sizeof (*SummPtr));
if (flen && (out_fp = (PVOID)res_OpenResFile (saveDir, file, "wb"))) if (flen && (out_fp = res_OpenResFile (saveDir, file, "wb")))
{ {
PrepareSummary (summary_desc); PrepareSummary (SummPtr);
// First write the summary.
success = (BOOLEAN)(WriteResFile (
summary_desc, sizeof (*summary_desc), 1, out_fp) != 0);
success = SaveSummary (SummPtr, out_fp);
// Then write the rest of the data. // Then write the rest of the data.
if (success && WriteResFile (mem_lock (h), (COUNT)flen, 1, if (success && WriteResFile (mem_lock (h), (COUNT)flen, 1,
out_fp) == 0) out_fp) == 0)
@@ -513,4 +757,3 @@ RetrySave:
return (success); return (success);
} }
+1 -2
View File
@@ -43,7 +43,7 @@ static RACE_DESC androsynth_desc =
FIRES_FORE | SEEKING_WEAPON, FIRES_FORE | SEEKING_WEAPON,
15, /* Super Melee cost */ 15, /* Super Melee cost */
~0, /* Initial sphere of influence radius */ ~0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1, MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1,
@@ -51,7 +51,6 @@ static RACE_DESC androsynth_desc =
(STRING)ANDROSYNTH_RACE_STRINGS, (STRING)ANDROSYNTH_RACE_STRINGS,
(FRAME)ANDROSYNTH_ICON_MASK_PMAP_ANIM, (FRAME)ANDROSYNTH_ICON_MASK_PMAP_ANIM,
(FRAME)ANDROSYNTH_MICON_MASK_PMAP_ANIM, (FRAME)ANDROSYNTH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC arilou_desc =
/* FIRES_FORE | */ IMMEDIATE_WEAPON, /* FIRES_FORE | */ IMMEDIATE_WEAPON,
16, /* Super Melee cost */ 16, /* Super Melee cost */
250 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 250 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
438, 6372, 438, 6372,
@@ -53,7 +53,6 @@ static RACE_DESC arilou_desc =
(STRING)ARILOU_RACE_STRINGS, (STRING)ARILOU_RACE_STRINGS,
(FRAME)ARILOU_ICON_MASK_PMAP_ANIM, (FRAME)ARILOU_ICON_MASK_PMAP_ANIM,
(FRAME)ARILOU_MICON_MASK_PMAP_ANIM, (FRAME)ARILOU_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC black_urquan_desc =
FIRES_FORE, FIRES_FORE,
30, /* Super Melee cost */ 30, /* Super Melee cost */
2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
6000, 6250, 6000, 6250,
@@ -55,7 +55,6 @@ static RACE_DESC black_urquan_desc =
(STRING)KOHR_AH_RACE_STRINGS, (STRING)KOHR_AH_RACE_STRINGS,
(FRAME)KOHR_AH_ICON_MASK_PMAP_ANIM, (FRAME)KOHR_AH_ICON_MASK_PMAP_ANIM,
(FRAME)KOHR_AH_MICON_MASK_PMAP_ANIM, (FRAME)KOHR_AH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -50,7 +50,7 @@ static RACE_DESC chenjesu_desc =
FIRES_FORE | SEEKING_SPECIAL | SEEKING_WEAPON, FIRES_FORE | SEEKING_SPECIAL | SEEKING_WEAPON,
28, /* Super Melee cost */ 28, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -58,7 +58,6 @@ static RACE_DESC chenjesu_desc =
(STRING)CHENJESU_RACE_STRINGS, (STRING)CHENJESU_RACE_STRINGS,
(FRAME)CHENJESU_ICON_MASK_PMAP_ANIM, (FRAME)CHENJESU_ICON_MASK_PMAP_ANIM,
(FRAME)CHENJESU_MICON_MASK_PMAP_ANIM, (FRAME)CHENJESU_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC chmmr_desc =
FIRES_FORE | IMMEDIATE_WEAPON | SEEKING_SPECIAL | POINT_DEFENSE, FIRES_FORE | IMMEDIATE_WEAPON | SEEKING_SPECIAL | POINT_DEFENSE,
30, /* Super Melee cost */ 30, /* Super Melee cost */
0, /* Initial sphere of influence radius */ 0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -55,7 +55,6 @@ static RACE_DESC chmmr_desc =
(STRING)CHMMR_RACE_STRINGS, (STRING)CHMMR_RACE_STRINGS,
(FRAME)CHMMR_ICON_MASK_PMAP_ANIM, (FRAME)CHMMR_ICON_MASK_PMAP_ANIM,
(FRAME)CHMMR_MICON_MASK_PMAP_ANIM, (FRAME)CHMMR_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -43,7 +43,7 @@ static RACE_DESC druuge_desc =
FIRES_FORE, FIRES_FORE,
17, /* Super Melee cost */ 17, /* Super Melee cost */
1400 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 1400 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
9500, 2792, 9500, 2792,
@@ -51,7 +51,6 @@ static RACE_DESC druuge_desc =
(STRING)DRUUGE_RACE_STRINGS, (STRING)DRUUGE_RACE_STRINGS,
(FRAME)DRUUGE_ICON_MASK_PMAP_ANIM, (FRAME)DRUUGE_ICON_MASK_PMAP_ANIM,
(FRAME)DRUUGE_MICON_MASK_PMAP_ANIM, (FRAME)DRUUGE_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC human_desc =
FIRES_FORE | SEEKING_WEAPON | POINT_DEFENSE, FIRES_FORE | SEEKING_WEAPON | POINT_DEFENSE,
11, /* Super Melee cost */ 11, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
1752, 1450, 1752, 1450,
@@ -55,7 +55,6 @@ static RACE_DESC human_desc =
(STRING)HUMAN_RACE_STRINGS, (STRING)HUMAN_RACE_STRINGS,
(FRAME)HUMAN_ICON_MASK_PMAP_ANIM, (FRAME)HUMAN_ICON_MASK_PMAP_ANIM,
(FRAME)HUMAN_MICON_MASK_PMAP_ANIM, (FRAME)HUMAN_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC ilwrath_desc =
FIRES_FORE, FIRES_FORE,
10, /* Super Melee cost */ 10, /* Super Melee cost */
1410 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 1410 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
48, 1700, 48, 1700,
@@ -53,7 +53,6 @@ static RACE_DESC ilwrath_desc =
(STRING)ILWRATH_RACE_STRINGS, (STRING)ILWRATH_RACE_STRINGS,
(FRAME)ILWRATH_ICON_MASK_PMAP_ANIM, (FRAME)ILWRATH_ICON_MASK_PMAP_ANIM,
(FRAME)ILWRATH_MICON_MASK_PMAP_ANIM, (FRAME)ILWRATH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -50,7 +50,7 @@ static RACE_DESC samatra_desc =
/* FIRES_FORE | */ IMMEDIATE_WEAPON | CREW_IMMUNE, /* FIRES_FORE | */ IMMEDIATE_WEAPON | CREW_IMMUNE,
16, /* Super Melee cost */ 16, /* Super Melee cost */
0, /* Initial sphere of influence radius */ 0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -58,7 +58,6 @@ static RACE_DESC samatra_desc =
(STRING)0, (STRING)0,
(FRAME)0, (FRAME)0,
(FRAME)0, (FRAME)0,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC melnorme_desc =
FIRES_FORE, FIRES_FORE,
18, /* Super Melee cost */ 18, /* Super Melee cost */
~0, /* Initial sphere of influence radius */ ~0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1, MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1,
@@ -54,7 +54,6 @@ static RACE_DESC melnorme_desc =
(STRING)MELNORME_RACE_STRINGS, (STRING)MELNORME_RACE_STRINGS,
(FRAME)MELNORME_ICON_MASK_PMAP_ANIM, (FRAME)MELNORME_ICON_MASK_PMAP_ANIM,
(FRAME)MELNORME_MICON_MASK_PMAP_ANIM, (FRAME)MELNORME_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -58,7 +58,7 @@ static RACE_DESC mmrnmhrm_desc =
FIRES_FORE | IMMEDIATE_WEAPON, FIRES_FORE | IMMEDIATE_WEAPON,
19, /* Super Melee cost */ 19, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -66,7 +66,6 @@ static RACE_DESC mmrnmhrm_desc =
(STRING)MMRNMHRM_RACE_STRINGS, (STRING)MMRNMHRM_RACE_STRINGS,
(FRAME)MMRNMHRM_ICON_MASK_PMAP_ANIM, (FRAME)MMRNMHRM_ICON_MASK_PMAP_ANIM,
(FRAME)MMRNMHRM_MICON_MASK_PMAP_ANIM, (FRAME)MMRNMHRM_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC mycon_desc =
FIRES_FORE | SEEKING_WEAPON, FIRES_FORE | SEEKING_WEAPON,
21, /* Super Melee cost */ 21, /* Super Melee cost */
1070 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 1070 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
6392, 2200, 6392, 2200,
@@ -54,7 +54,6 @@ static RACE_DESC mycon_desc =
(STRING)MYCON_RACE_STRINGS, (STRING)MYCON_RACE_STRINGS,
(FRAME)MYCON_ICON_MASK_PMAP_ANIM, (FRAME)MYCON_ICON_MASK_PMAP_ANIM,
(FRAME)MYCON_MICON_MASK_PMAP_ANIM, (FRAME)MYCON_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -48,7 +48,7 @@ static RACE_DESC orz_desc =
FIRES_FORE | SEEKING_SPECIAL, FIRES_FORE | SEEKING_SPECIAL,
23, /* Super Melee cost */ 23, /* Super Melee cost */
333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
3608, 2637, 3608, 2637,
@@ -56,7 +56,6 @@ static RACE_DESC orz_desc =
(STRING)ORZ_RACE_STRINGS, (STRING)ORZ_RACE_STRINGS,
(FRAME)ORZ_ICON_MASK_PMAP_ANIM, (FRAME)ORZ_ICON_MASK_PMAP_ANIM,
(FRAME)ORZ_MICON_MASK_PMAP_ANIM, (FRAME)ORZ_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC pkunk_desc =
FIRES_FORE | FIRES_LEFT | FIRES_RIGHT, FIRES_FORE | FIRES_LEFT | FIRES_RIGHT,
20, /* Super Melee cost */ 20, /* Super Melee cost */
666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
502, 401, 502, 401,
@@ -54,7 +54,6 @@ static RACE_DESC pkunk_desc =
(STRING)PKUNK_RACE_STRINGS, (STRING)PKUNK_RACE_STRINGS,
(FRAME)PKUNK_ICON_MASK_PMAP_ANIM, (FRAME)PKUNK_ICON_MASK_PMAP_ANIM,
(FRAME)PKUNK_MICON_MASK_PMAP_ANIM, (FRAME)PKUNK_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -40,7 +40,7 @@ static RACE_DESC probe_desc =
0, 0,
0, /* Super Melee cost */ 0, /* Super Melee cost */
0, /* Initial sphere of influence radius */ 0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -48,7 +48,6 @@ static RACE_DESC probe_desc =
0, 0,
0, 0,
(FRAME)PROBE_MICON_MASK_PMAP_ANIM, (FRAME)PROBE_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC shofixti_desc =
FIRES_FORE, FIRES_FORE,
5, /* Super Melee cost */ 5, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -54,7 +54,6 @@ static RACE_DESC shofixti_desc =
(STRING)SHOFIXTI_RACE_STRINGS, (STRING)SHOFIXTI_RACE_STRINGS,
(FRAME)SHOFIXTI_ICON_MASK_PMAP_ANIM, (FRAME)SHOFIXTI_ICON_MASK_PMAP_ANIM,
(FRAME)SHOFIXTI_MICON_MASK_PMAP_ANIM, (FRAME)SHOFIXTI_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -52,7 +52,7 @@ static RACE_DESC sis_desc =
0, 0,
16, /* Super Melee cost */ 16, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -60,7 +60,6 @@ static RACE_DESC sis_desc =
0, 0,
(FRAME)SIS_ICON_MASK_PMAP_ANIM, (FRAME)SIS_ICON_MASK_PMAP_ANIM,
0, 0,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC slylandro_desc =
SEEKING_WEAPON | CREW_IMMUNE, SEEKING_WEAPON | CREW_IMMUNE,
17, /* Super Melee cost */ 17, /* Super Melee cost */
~0, /* Initial sphere of influence radius */ ~0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
333, 9812, 333, 9812,
@@ -53,7 +53,6 @@ static RACE_DESC slylandro_desc =
(STRING)SLYLANDRO_RACE_STRINGS, (STRING)SLYLANDRO_RACE_STRINGS,
(FRAME)SLYLANDRO_ICON_MASK_PMAP_ANIM, (FRAME)SLYLANDRO_ICON_MASK_PMAP_ANIM,
(FRAME)SLYLANDRO_MICON_MASK_PMAP_ANIM, (FRAME)SLYLANDRO_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -43,7 +43,7 @@ static RACE_DESC spathi_desc =
FIRES_FORE | FIRES_AFT | SEEKING_SPECIAL | DONT_CHASE, FIRES_FORE | FIRES_AFT | SEEKING_SPECIAL | DONT_CHASE,
18, /* Super Melee cost */ 18, /* Super Melee cost */
1000 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 1000 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
2549, 3600, 2549, 3600,
@@ -51,7 +51,6 @@ static RACE_DESC spathi_desc =
(STRING)SPATHI_RACE_STRINGS, (STRING)SPATHI_RACE_STRINGS,
(FRAME)SPATHI_ICON_MASK_PMAP_ANIM, (FRAME)SPATHI_ICON_MASK_PMAP_ANIM,
(FRAME)SPATHI_MICON_MASK_PMAP_ANIM, (FRAME)SPATHI_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC supox_desc =
FIRES_FORE, FIRES_FORE,
16, /* Super Melee cost */ 16, /* Super Melee cost */
333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
7468, 9246, 7468, 9246,
@@ -53,7 +53,6 @@ static RACE_DESC supox_desc =
(STRING)SUPOX_RACE_STRINGS, (STRING)SUPOX_RACE_STRINGS,
(FRAME)SUPOX_ICON_MASK_PMAP_ANIM, (FRAME)SUPOX_ICON_MASK_PMAP_ANIM,
(FRAME)SUPOX_MICON_MASK_PMAP_ANIM, (FRAME)SUPOX_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC syreen_desc =
FIRES_FORE, FIRES_FORE,
13, /* Super Melee cost */ 13, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, SYREEN_MAX_CREW_SIZE,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
0, 0, 0, 0,
@@ -54,7 +54,6 @@ static RACE_DESC syreen_desc =
(STRING)SYREEN_RACE_STRINGS, (STRING)SYREEN_RACE_STRINGS,
(FRAME)SYREEN_ICON_MASK_PMAP_ANIM, (FRAME)SYREEN_ICON_MASK_PMAP_ANIM,
(FRAME)SYREEN_MICON_MASK_PMAP_ANIM, (FRAME)SYREEN_MICON_MASK_PMAP_ANIM,
MAX_CREW, SYREEN_MAX_CREW_SIZE,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC thraddash_desc =
FIRES_FORE, FIRES_FORE,
10, /* Super Melee cost */ 10, /* Super Melee cost */
833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
2535, 8358, 2535, 8358,
@@ -54,7 +54,6 @@ static RACE_DESC thraddash_desc =
(STRING)THRADDASH_RACE_STRINGS, (STRING)THRADDASH_RACE_STRINGS,
(FRAME)THRADDASH_ICON_MASK_PMAP_ANIM, (FRAME)THRADDASH_ICON_MASK_PMAP_ANIM,
(FRAME)THRADDASH_MICON_MASK_PMAP_ANIM, (FRAME)THRADDASH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC umgah_desc =
FIRES_FORE | IMMEDIATE_WEAPON, FIRES_FORE | IMMEDIATE_WEAPON,
7, /* Super Melee cost */ 7, /* Super Melee cost */
833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
1798, 6000, 1798, 6000,
@@ -53,7 +53,6 @@ static RACE_DESC umgah_desc =
(STRING)UMGAH_RACE_STRINGS, (STRING)UMGAH_RACE_STRINGS,
(FRAME)UMGAH_ICON_MASK_PMAP_ANIM, (FRAME)UMGAH_ICON_MASK_PMAP_ANIM,
(FRAME)UMGAH_MICON_MASK_PMAP_ANIM, (FRAME)UMGAH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC urquan_desc =
FIRES_FORE | SEEKING_SPECIAL, FIRES_FORE | SEEKING_SPECIAL,
30, /* Super Melee cost */ 30, /* Super Melee cost */
2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
5750, 6000, 5750, 6000,
@@ -55,7 +55,6 @@ static RACE_DESC urquan_desc =
(STRING)URQUAN_RACE_STRINGS, (STRING)URQUAN_RACE_STRINGS,
(FRAME)URQUAN_ICON_MASK_PMAP_ANIM, (FRAME)URQUAN_ICON_MASK_PMAP_ANIM,
(FRAME)URQUAN_MICON_MASK_PMAP_ANIM, (FRAME)URQUAN_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC utwig_desc =
FIRES_FORE | POINT_DEFENSE | SHIELD_DEFENSE, FIRES_FORE | POINT_DEFENSE | SHIELD_DEFENSE,
22, /* Super Melee cost */ 22, /* Super Melee cost */
666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY >> 1, MAX_ENERGY, MAX_ENERGY >> 1, MAX_ENERGY,
{ {
8534, 8797, 8534, 8797,
@@ -55,7 +55,6 @@ static RACE_DESC utwig_desc =
(STRING)UTWIG_RACE_STRINGS, (STRING)UTWIG_RACE_STRINGS,
(FRAME)UTWIG_ICON_MASK_PMAP_ANIM, (FRAME)UTWIG_ICON_MASK_PMAP_ANIM,
(FRAME)UTWIG_MICON_MASK_PMAP_ANIM, (FRAME)UTWIG_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -48,7 +48,7 @@ static RACE_DESC vux_desc =
FIRES_FORE | SEEKING_SPECIAL | IMMEDIATE_WEAPON, FIRES_FORE | SEEKING_SPECIAL | IMMEDIATE_WEAPON,
12, /* Super Melee cost */ 12, /* Super Melee cost */
900 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 900 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
4412, 1558, 4412, 1558,
@@ -56,7 +56,6 @@ static RACE_DESC vux_desc =
(STRING)VUX_RACE_STRINGS, (STRING)VUX_RACE_STRINGS,
(FRAME)VUX_ICON_MASK_PMAP_ANIM, (FRAME)VUX_ICON_MASK_PMAP_ANIM,
(FRAME)VUX_MICON_MASK_PMAP_ANIM, (FRAME)VUX_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC yehat_desc =
FIRES_FORE | SHIELD_DEFENSE, FIRES_FORE | SHIELD_DEFENSE,
23, /* Super Melee cost */ 23, /* Super Melee cost */
750 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 750 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
4970, 40, 4970, 40,
@@ -53,7 +53,6 @@ static RACE_DESC yehat_desc =
(STRING)YEHAT_RACE_STRINGS, (STRING)YEHAT_RACE_STRINGS,
(FRAME)YEHAT_ICON_MASK_PMAP_ANIM, (FRAME)YEHAT_ICON_MASK_PMAP_ANIM,
(FRAME)YEHAT_MICON_MASK_PMAP_ANIM, (FRAME)YEHAT_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC zoqfotpik_desc =
FIRES_FORE, FIRES_FORE,
6, /* Super Melee cost */ 6, /* Super Melee cost */
320 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */ 320 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */ MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY, MAX_ENERGY, MAX_ENERGY,
{ {
3761, 5333, 3761, 5333,
@@ -54,7 +54,6 @@ static RACE_DESC zoqfotpik_desc =
(STRING)ZOQFOTPIK_RACE_STRINGS, (STRING)ZOQFOTPIK_RACE_STRINGS,
(FRAME)ZOQFOTPIK_ICON_MASK_PMAP_ANIM, (FRAME)ZOQFOTPIK_ICON_MASK_PMAP_ANIM,
(FRAME)ZOQFOTPIK_MICON_MASK_PMAP_ANIM, (FRAME)ZOQFOTPIK_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
}, },
{ {
MAX_THRUST, MAX_THRUST,
+5 -3
View File
@@ -196,6 +196,8 @@ enum
#define STATUS_MESSAGE_WIDTH 60 #define STATUS_MESSAGE_WIDTH 60
#define STATUS_MESSAGE_HEIGHT 7 #define STATUS_MESSAGE_HEIGHT 7
#define SIS_NAME_SIZE 16
typedef struct typedef struct
{ {
SDWORD log_x, log_y; SDWORD log_x, log_y;
@@ -216,9 +218,9 @@ typedef struct
COUNT ElementAmounts[NUM_ELEMENT_CATEGORIES]; COUNT ElementAmounts[NUM_ELEMENT_CATEGORIES];
UNICODE ShipName[16]; UNICODE ShipName[SIS_NAME_SIZE];
UNICODE CommanderName[16]; UNICODE CommanderName[SIS_NAME_SIZE];
UNICODE PlanetName[16]; UNICODE PlanetName[SIS_NAME_SIZE];
} SIS_STATE; } SIS_STATE;
typedef SIS_STATE *PSIS_STATE; typedef SIS_STATE *PSIS_STATE;
+33 -43
View File
@@ -54,7 +54,7 @@ OpenStateFile (int stateFile, const char *mode)
GAME_STATE_FILE *fp; GAME_STATE_FILE *fp;
if (stateFile < 0 || stateFile >= NUM_STATE_FILES) if (stateFile < 0 || stateFile >= NUM_STATE_FILES)
return NULL_PTR; return NULL;
fp = &state_files[stateFile]; fp = &state_files[stateFile];
fp->open_count++; fp->open_count++;
@@ -67,7 +67,7 @@ OpenStateFile (int stateFile, const char *mode)
{ {
fp->data = HMalloc (fp->size_hint); fp->data = HMalloc (fp->size_hint);
if (!fp->data) if (!fp->data)
return NULL_PTR; return NULL;
fp->size = fp->size_hint; fp->size = fp->size_hint;
} }
@@ -185,15 +185,6 @@ WriteStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp)
return (bytes / size); return (bytes / size);
} }
int
PutStateFileChar (char ch, GAME_STATE_FILE *fp)
{
if (1 == WriteStateFile (&ch, sizeof(ch), 1, fp))
return ch;
else
return EOF;
}
int int
SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence) SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence)
{ {
@@ -220,14 +211,13 @@ InitPlanetInfo (void)
fp = OpenStateFile (STARINFO_FILE, "wb"); fp = OpenStateFile (STARINFO_FILE, "wb");
if (fp) if (fp)
{ {
DWORD offset;
STAR_DESCPTR pSD; STAR_DESCPTR pSD;
offset = 0; // Set record offsets for all stars to 0 (not present)
pSD = &star_array[0]; pSD = &star_array[0];
do do
{ {
WriteStateFile (&offset, sizeof (offset), 1, fp); swrite_32 (fp, 0);
++pSD; ++pSD;
} while (pSD->star_pt.x <= MAX_X_UNIVERSE } while (pSD->star_pt.x <= MAX_X_UNIVERSE
&& pSD->star_pt.y <= MAX_Y_UNIVERSE); && pSD->star_pt.y <= MAX_Y_UNIVERSE);
@@ -242,6 +232,9 @@ UninitPlanetInfo (void)
DeleteStateFile (STARINFO_FILE); DeleteStateFile (STARINFO_FILE);
} }
#define OFFSET_SIZE (sizeof (DWORD))
#define SCAN_RECORD_SIZE (sizeof (DWORD) * NUM_SCAN_TYPES)
void void
GetPlanetInfo (void) GetPlanetInfo (void)
{ {
@@ -266,27 +259,24 @@ GetPlanetInfo (void)
moon_index = (COUNT)(pSolarSysState->pOrbitalDesc moon_index = (COUNT)(pSolarSysState->pOrbitalDesc
- pSolarSysState->MoonDesc + 1); - pSolarSysState->MoonDesc + 1);
SeekStateFile (fp, star_index * sizeof (offset), SEEK_SET); SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET);
ReadStateFile (&offset, sizeof (offset), 1, fp); sread_32 (fp, &offset);
if (offset) if (offset)
{ {
COUNT i; COUNT i;
// Skip scan records for all preceeding planets to the one we need
for (i = 0; i < planet_index; ++i) for (i = 0; i < planet_index; ++i)
offset += sizeof ( offset += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) *
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask SCAN_RECORD_SIZE;
) * (pSolarSysState->PlanetDesc[i].NumPlanets + 1);
offset += sizeof ( // Skip scan records for all preceeding moons to the one we need
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask offset += moon_index * SCAN_RECORD_SIZE;
) * moon_index;
SeekStateFile (fp, offset, SEEK_SET); SeekStateFile (fp, offset, SEEK_SET);
ReadStateFile (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask, sread_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
sizeof ( NUM_SCAN_TYPES);
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
), 1, fp);
} }
CloseStateFile (fp); CloseStateFile (fp);
@@ -314,11 +304,11 @@ PutPlanetInfo (void)
moon_index = (COUNT)(pSolarSysState->pOrbitalDesc moon_index = (COUNT)(pSolarSysState->pOrbitalDesc
- pSolarSysState->MoonDesc + 1); - pSolarSysState->MoonDesc + 1);
SeekStateFile (fp, star_index * sizeof (offset), SEEK_SET); SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET);
ReadStateFile (&offset, sizeof (offset), 1, fp); sread_32 (fp, &offset);
if (offset == 0) if (offset == 0)
{ { // Scan record not present yet -- init it
DWORD ScanRetrieveMask[NUM_SCAN_TYPES] = DWORD ScanRetrieveMask[NUM_SCAN_TYPES] =
{ {
0, 0, 0, 0, 0, 0,
@@ -326,34 +316,34 @@ PutPlanetInfo (void)
offset = LengthStateFile (fp); offset = LengthStateFile (fp);
SeekStateFile (fp, star_index * sizeof (offset), SEEK_SET); // Write the record offset
WriteStateFile (&offset, sizeof (offset), 1, fp); SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET);
swrite_32 (fp, offset);
// Init scan records for all planets and moons in the system
SeekStateFile (fp, offset, SEEK_SET); SeekStateFile (fp, offset, SEEK_SET);
for (i = 0; i < pSolarSysState->SunDesc[0].NumPlanets; ++i) for (i = 0; i < pSolarSysState->SunDesc[0].NumPlanets; ++i)
{ {
COUNT j; COUNT j;
WriteStateFile (ScanRetrieveMask, sizeof (ScanRetrieveMask), 1, fp); swrite_a32 (fp, ScanRetrieveMask, NUM_SCAN_TYPES);
// init moons
for (j = 0; j < pSolarSysState->PlanetDesc[i].NumPlanets; ++j) for (j = 0; j < pSolarSysState->PlanetDesc[i].NumPlanets; ++j)
WriteStateFile (ScanRetrieveMask, sizeof (ScanRetrieveMask), 1, fp); swrite_a32 (fp, ScanRetrieveMask, NUM_SCAN_TYPES);
} }
} }
// Skip scan records for all preceeding planets to the one we need
for (i = 0; i < planet_index; ++i) for (i = 0; i < planet_index; ++i)
offset += sizeof ( offset += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) *
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask SCAN_RECORD_SIZE;
) * (pSolarSysState->PlanetDesc[i].NumPlanets + 1);
offset += sizeof ( // Skip scan records for all preceeding moons to the one we need
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask offset += moon_index * SCAN_RECORD_SIZE;
) * moon_index;
SeekStateFile (fp, offset, SEEK_SET); SeekStateFile (fp, offset, SEEK_SET);
WriteStateFile (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask, swrite_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
sizeof ( NUM_SCAN_TYPES);
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
), 1, fp);
CloseStateFile (fp); CloseStateFile (fp);
} }
+71 -1
View File
@@ -19,7 +19,9 @@
#ifndef _STATE_H #ifndef _STATE_H
#define _STATE_H #define _STATE_H
#include "port.h"
#include "libs/compiler.h" #include "libs/compiler.h"
#include <assert.h>
extern void InitPlanetInfo (void); extern void InitPlanetInfo (void);
extern void UninitPlanetInfo (void); extern void UninitPlanetInfo (void);
@@ -67,8 +69,76 @@ void DeleteStateFile (int stateFile);
DWORD LengthStateFile (GAME_STATE_FILE *fp); DWORD LengthStateFile (GAME_STATE_FILE *fp);
int ReadStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp); int ReadStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp);
int WriteStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp); int WriteStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp);
int PutStateFileChar (char ch, GAME_STATE_FILE *fp);
int SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence); int SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence);
static inline COUNT
sread_8 (PVOID fp, PBYTE v)
{
BYTE t;
if (!v) /* read value ignored */
v = &t;
return ReadStateFile (v, 1, 1, fp);
}
static inline COUNT
sread_16 (PVOID fp, PUWORD v)
{
UWORD t;
if (!v) /* read value ignored */
v = &t;
return ReadStateFile (v, 2, 1, fp);
}
static inline COUNT
sread_32 (PVOID fp, PDWORD v)
{
DWORD t;
if (!v) /* read value ignored */
v = &t;
return ReadStateFile (v, 4, 1, fp);
}
static inline COUNT
sread_a32 (PVOID fp, PDWORD ar, COUNT count)
{
assert (ar != NULL);
for ( ; count > 0; --count, ++ar)
{
if (sread_32 (fp, ar) != 1)
return 0;
}
return 1;
}
static inline COUNT
swrite_8 (PVOID fp, BYTE v)
{
return WriteStateFile (&v, 1, 1, fp);
}
static inline COUNT
swrite_16 (PVOID fp, UWORD v)
{
return WriteStateFile (&v, 2, 1, fp);
}
static inline COUNT
swrite_32 (PVOID fp, DWORD v)
{
return WriteStateFile (&v, 4, 1, fp);
}
static inline COUNT
swrite_a32 (PVOID fp, PDWORD ar, COUNT count)
{
for ( ; count > 0; --count, ++ar)
{
if (swrite_32 (fp, *ar) != 1)
return 0;
}
return 1;
}
#endif /* _STATE_H */ #endif /* _STATE_H */