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;
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 built_ship_q;
/* Queue of SIS escort ships */
BYTE GameState[(NUM_GAME_STATE_BITS + 7) >> 3];
} GAME_STATE;
typedef GAME_STATE *PGAME_STATE;
typedef struct
{
+116 -37
View File
@@ -38,11 +38,95 @@ static BYTE LastEncGroup;
typedef struct
{
BYTE NumGroups, day_index, month_index;
BYTE NumGroups;
BYTE day_index, month_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];
// 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;
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
InitGroupInfo (BOOLEAN FirstTime)
{
@@ -56,14 +140,16 @@ InitGroupInfo (BOOLEAN FirstTime)
GH.NumGroups = 0;
GH.star_index = (COUNT)~0;
GH.GroupOffset[0] = 0;
WriteStateFile (&GH, sizeof (GH), 1, fp);
WriteGroupHeader (fp, &GH);
CloseStateFile (fp);
}
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);
}
@@ -297,11 +383,11 @@ FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID fp)
&GLOBAL (npc_built_ship_q), hStarShip);
RaceType = GET_RACE_ID (FragPtr);
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);
}
SeekStateFile (fp, offset, SEEK_SET);
WriteStateFile (pGH, sizeof (*pGH), 1, fp);
WriteGroupHeader (fp, pGH);
#ifdef DEBUG_GROUPS
log_add (log_Debug, "1)FlushGroupInfo(%lu): WG = %u(%lu), NG = %u, "
"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));
if (which_group != GROUP_LIST)
{
SeekStateFile (fp, pGH->GroupOffset[which_group]
+ sizeof (LastEncGroup), SEEK_SET);
{ // skip RaceType
SeekStateFile (fp, pGH->GroupOffset[which_group] + 1, SEEK_SET);
}
else
{
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));
while (NumShips--)
{
HSTARSHIP hNextShip;
PBYTE Ptr;
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (
&GLOBAL (npc_built_ship_q), hStarShip
@@ -334,7 +418,7 @@ FlushGroupInfo (GROUP_HEADER *pGH, DWORD offset, BYTE which_group, PVOID fp)
hNextShip = _GetSuccLink (FragPtr);
RaceType = GET_RACE_ID (FragPtr);
WriteStateFile (&RaceType, sizeof (RaceType), 1, fp);
swrite_8 (fp, RaceType);
#ifdef DEBUG_GROUPS
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_DEST (FragPtr));
#endif /* DEBUG_GROUPS */
Ptr = (PBYTE)&FragPtr->RaceDescPtr;
WriteStateFile (Ptr,
((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, 1, fp);
WriteShipFragment (fp, FragPtr);
UnlockStarShip (&GLOBAL (npc_built_ship_q), hStarShip);
hStarShip = hNextShip;
}
@@ -372,7 +454,7 @@ GetGroupInfo (DWORD offset, BYTE which_group)
SHIP_FRAGMENTPTR FragPtr;
SeekStateFile (fp, offset, SEEK_SET);
ReadStateFile (&GH, sizeof (GH), 1, fp);
ReadGroupHeader (fp, &GH);
#ifdef DEBUG_GROUPS
log_add (log_Debug, "GetGroupInfo(%lu): %u(%lu) out of %u", offset,
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,
year_index);
#endif /* DEBUG_GROUPS */
// Erase random groups (out of date)
fp = OpenStateFile (RANDGRPINFO_FILE, "wb");
GH.NumGroups = 0;
GH.star_index = (COUNT)~0;
GH.GroupOffset[0] = 0;
WriteStateFile (&GH, sizeof (GH), 1, fp);
WriteGroupHeader (fp, &GH);
}
else
{
@@ -417,8 +500,8 @@ GetGroupInfo (DWORD offset, BYTE which_group)
continue;
SeekStateFile (fp, GH.GroupOffset[which_group], SEEK_SET);
ReadStateFile (&RaceType, sizeof (RaceType), 1, fp);
ReadStateFile (&NumShips, sizeof (NumShips), 1, fp);
sread_8 (fp, &RaceType);
sread_8 (fp, &NumShips);
if (NumShips)
{
@@ -516,7 +599,7 @@ GetGroupInfo (DWORD offset, BYTE which_group)
if (which_group == GROUP_LIST)
{
SeekStateFile (fp, GH.GroupOffset[0], SEEK_SET);
ReadStateFile (&LastEncGroup, sizeof (LastEncGroup), 1, fp);
sread_8 (fp, &LastEncGroup);
if (LastEncGroup)
{
@@ -536,25 +619,20 @@ GetGroupInfo (DWORD offset, BYTE which_group)
}
ReinitQueue (&GLOBAL (npc_built_ship_q));
SeekStateFile (fp, GH.GroupOffset[which_group]
+ sizeof (LastEncGroup), SEEK_SET);
ReadStateFile (&NumShips, sizeof (NumShips), 1, fp);
// skip RaceType
SeekStateFile (fp, GH.GroupOffset[which_group] + 1, SEEK_SET);
sread_8 (fp, &NumShips);
while (NumShips--)
{
PBYTE Ptr;
ReadStateFile (&RaceType, sizeof (RaceType), 1, fp);
sread_8 (fp, &RaceType);
hStarShip = CloneShipFragment (RaceType,
&GLOBAL (npc_built_ship_q), 0);
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (
&GLOBAL (npc_built_ship_q), hStarShip);
Ptr = (PBYTE)&FragPtr->RaceDescPtr;
ReadStateFile (Ptr,
((PBYTE)&FragPtr->ShipInfo.race_strings) - Ptr, 1,
fp);
ReadShipFragment (fp, FragPtr);
#ifdef DEBUG_GROUPS
if (which_group == GROUP_LIST)
@@ -625,12 +703,13 @@ PutGroupInfo (DWORD offset, BYTE which_group)
if (offset == GROUPS_ADD_NEW)
{
offset = LengthStateFile (fp);
GH.NumGroups = 0;
GH.GroupOffset[0] = 0;
SeekStateFile (fp, offset, SEEK_SET);
WriteStateFile (&GH, sizeof (GH), 1, fp);
// XXX: It seems that GH is not completely initialised.
// Some garbage is saved. -- SvdB
// XXX: All important fields are inited here, and the
// rest are inited below
GH.NumGroups = 0;
GH.star_index = (COUNT)~0;
GH.GroupOffset[0] = 0;
WriteGroupHeader (fp, &GH);
}
if (which_group != GROUP_LIST)
@@ -642,7 +721,7 @@ PutGroupInfo (DWORD offset, BYTE which_group)
which_group = GROUP_LIST;
}
}
ReadStateFile (&GH, sizeof (GH), 1, fp);
ReadGroupHeader (fp, &GH);
#ifdef NEVER
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.
*/
#include <assert.h>
#include "load.h"
#include "build.h"
@@ -35,62 +37,166 @@
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
LoadShipQueue (DECODE_REF fh, PQUEUE pQueue, BOOLEAN MakeQ)
{
COUNT num_links;
cread ((PBYTE)&num_links, sizeof (num_links), 1, fh);
if (num_links)
cread_16 (fh, &num_links);
if (num_links && MakeQ)
InitQueue (pQueue, num_links, sizeof (SHIP_FRAGMENT));
while (num_links--)
{
if (MakeQ)
InitQueue (pQueue, num_links, sizeof (SHIP_FRAGMENT));
HSTARSHIP hStarShip;
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;
SHIP_FRAGMENTPTR FragPtr;
COUNT Index, Offset;
PBYTE Ptr;
// avail_race_q contains information not about specific ships,
// but about a race.
EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr =
(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))
{
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);
UnlockStarShip (pQueue, hStarShip);
}
}
@@ -98,278 +204,448 @@ static void
LoadEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh)
{
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:
LOAD_BLOCK(fh, EncounterPtr, EncounterPtr->SD.ShipList);
cread_ptr (fh); /* useless ptr; HENCOUNTER pred */
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:
for (i = 0; i < MAX_HYPER_SHIPS; i++)
{
SHIP_INFO *ShipInfo = &EncounterPtr->SD.ShipList[i];
LOAD_BLOCK(fh, ShipInfo, &ShipInfo->crew_level);
ShipInfo->crew_level = ShipInfo->dummy_crew_level;
ShipInfo->max_crew = ShipInfo->dummy_max_crew;
SHIP_INFOPTR ShipInfo = &EncounterPtr->SD.ShipList[i];
BYTE tmpb;
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_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
LoadSummary (uio_Stream *in_fp)
LoadSisState (PSIS_STATE SSPtr, PVOID fp)
{
// XXX: This function seems to be unused.
SUMMARY_DESC S;
if (
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
LoadGame (COUNT which_game, SUMMARY_DESC *summary_desc)
LoadGame (COUNT which_game, SUMMARY_DESC *SummPtr)
{
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);
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;
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);
log_add (log_Always, "Warning: Savegame is corrupt");
res_CloseResFile (in_fp);
return FALSE;
}
EncounterGroup = 0;
EncounterRace = -1;
ReinitQueue (&race_q[0]);
ReinitQueue (&race_q[1]);
CurStarDescPtr = FindStar (NULL_PTR, &SD.star_pt, 0, 0);
if (!(NextActivity & START_ENCOUNTER)
&& LOBYTE (NextActivity) == IN_INTERPLANETARY)
NextActivity |= START_INTERPLANETARY;
GLOBAL (DisplayArray) = DisplayArray;
if (!SummPtr)
{
SummPtr = &loc_sd;
}
else
{ // only need summary for displaying to user
memcpy (SummPtr, &loc_sd, sizeof (*SummPtr));
res_CloseResFile (in_fp);
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;
BYTE var1, var2;
BYTE dummy_crew_level, dummy_max_crew;
/* Necessary for savegame backwards compatibility.
* Unused during the game, only used during save/load.
*/
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. */
BYTE energy_level, max_energy;
POINT loc;
@@ -115,9 +114,6 @@ typedef struct
STRING race_strings;
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)
} SHIP_INFO;
typedef SHIP_INFO *PSHIP_INFO;
@@ -164,10 +160,9 @@ typedef struct
BYTE days_left;
/* Days left before the fleet reachers 'dest_loc'. */
BYTE growth_fract;
BYTE dummy_crew_level, dummy_max_crew;
/* Necessary for savegame backwards compatibility.
* Unused during the game, only used during save/load.
*/
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. */
BYTE energy_level, max_energy;
POINT loc;
/* Location of the fleet (center) */
@@ -175,9 +170,6 @@ typedef struct
STRING race_strings;
/* Race specific strings, see doc/devel/racestrings. */
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. ==- */
+341 -98
View File
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <assert.h>
#include "save.h"
#include "build.h"
@@ -35,6 +37,78 @@
#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
SaveShipQueue (DECODE_REF fh, PQUEUE pQueue)
{
@@ -43,67 +117,62 @@ SaveShipQueue (DECODE_REF fh, PQUEUE pQueue)
// Write the number of entries in the queue.
num_links = CountLinks (pQueue);
cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh);
cwrite_16 (fh, num_links);
hStarShip = GetHeadLink (pQueue);
while (num_links--)
{
HSTARSHIP hNextShip;
SHIP_FRAGMENTPTR FragPtr;
COUNT Index, Offset;
PBYTE Ptr;
COUNT Index;
FragPtr = (SHIP_FRAGMENTPTR)LockStarShip (pQueue, hStarShip);
hNextShip = _GetSuccLink (FragPtr);
if (pQueue == &GLOBAL (avail_race_q))
{
Index = GetIndexFromStarShip (pQueue, hStarShip);
// The index is the position in the queue.
Offset = 0;
}
else
{
Index = GET_RACE_ID (FragPtr);
Offset = (PBYTE)&FragPtr->ShipInfo
- (PBYTE)&FragPtr->RaceDescPtr;
}
// Write the number identifying this ship type.
// 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
// increasing crew_level and max_crew from BYTE to COUNT.
// For the queues that are saved here, a BYTE is large enough.
FragPtr->ShipInfo.dummy_max_crew = FragPtr->ShipInfo.max_crew;
FragPtr->ShipInfo.dummy_crew_level = FragPtr->ShipInfo.crew_level;
// Write part of FragPtr, starting with FragPtr->ShipInfo for
// 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 (pQueue != &GLOBAL (avail_race_q))
{ // queues other than avail_race_q save SHIP_FRAGMENT elements
// Write SHIP_FRAGMENT elements
cwrite_16 (fh, FragPtr->s.Player);
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);
if (Offset == 0)
if (pQueue == &GLOBAL (avail_race_q))
{
// The queue being saved is avail_race_q.
// It contains information not about specific ships, but about
// a race. What is saved is everything in the EXTENDED_SHIP_INFO
// structure from the field 'actual_strength' onwards,
// for each of the races.
EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr;
// avail_race_q contains information not about specific ships,
// but about a race.
EXTENDED_SHIP_FRAGMENTPTR ExtFragPtr =
(EXTENDED_SHIP_FRAGMENTPTR) FragPtr;
ExtFragPtr = (EXTENDED_SHIP_FRAGMENTPTR)FragPtr;
Ptr = (PBYTE)&ExtFragPtr->ShipInfo.actual_strength;
cwrite ((PBYTE)Ptr, ((PBYTE)&ExtFragPtr[1]) - Ptr, 1, fh);
// XXX: This saves padding too, which may contain
// garbage.
cwrite_16 (fh, ExtFragPtr->ShipInfo.actual_strength);
cwrite_16 (fh, ExtFragPtr->ShipInfo.known_strength);
cwrite_16 (fh, ExtFragPtr->ShipInfo.known_loc.x);
cwrite_16 (fh, ExtFragPtr->ShipInfo.known_loc.y);
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);
@@ -115,59 +184,234 @@ static void
SaveEncounter (ENCOUNTERPTR EncounterPtr, DECODE_REF fh)
{
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:
SAVE_BLOCK(fh, EncounterPtr, EncounterPtr->SD.ShipList);
cwrite_ptr (fh); /* useless ptr; HENCOUNTER pred */
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:
for (i = 0; i < MAX_HYPER_SHIPS; i++)
{
SHIP_INFO *ShipInfo = &EncounterPtr->SD.ShipList[i];
ShipInfo->dummy_crew_level = (BYTE) ShipInfo->crew_level;
ShipInfo->dummy_max_crew = (BYTE) ShipInfo->max_crew;
SAVE_BLOCK(fh, ShipInfo, &ShipInfo->crew_level);
SHIP_INFOPTR ShipInfo = &EncounterPtr->SD.ShipList[i];
cwrite_16 (fh, ShipInfo->ship_flags);
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_BLOCK(fh, &EncounterPtr->log_x, &EncounterPtr[1]);
cwrite_32 (fh, EncounterPtr->log_x);
cwrite_32 (fh, EncounterPtr->log_y);
}
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:
if (GET_GAME_STATE (ARILOU_SPACE_SIDE) > 1)
summary_desc->Activity = IN_QUASISPACE;
SummPtr->Activity = IN_QUASISPACE;
break;
case IN_INTERPLANETARY:
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)
summary_desc->Activity = IN_PLANET_ORBIT;
SummPtr->Activity = IN_PLANET_ORBIT;
break;
}
summary_desc->MCreditLo = GET_GAME_STATE (MELNORME_CREDIT0);
summary_desc->MCreditHi = GET_GAME_STATE (MELNORME_CREDIT1);
SummPtr->MCreditLo = GET_GAME_STATE (MELNORME_CREDIT0);
SummPtr->MCreditHi = GET_GAME_STATE (MELNORME_CREDIT1);
{
HSTARSHIP hStarShip, hNextShip;
for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), summary_desc->NumShips = 0;
hStarShip; hStarShip = hNextShip, ++summary_desc->NumShips)
for (hStarShip = GetHeadLink (&GLOBAL (built_ship_q)), SummPtr->NumShips = 0;
hStarShip; hStarShip = hNextShip, ++SummPtr->NumShips)
{
SHIP_FRAGMENTPTR StarShipPtr;
@@ -175,26 +419,26 @@ PrepareSummary (SUMMARY_DESC *summary_desc)
&GLOBAL (built_ship_q), hStarShip
);
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);
}
}
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_CARGO) << (4 + 1))
| (GET_GAME_STATE (IMPROVED_LANDER_SHOT) << (4 + 2))
| ((GET_GAME_STATE (CHMMR_BOMB_STATE) < 2 ? 0 : 1) << (4 + 3));
summary_desc->day_index = GLOBAL (GameClock.day_index);
summary_desc->month_index = GLOBAL (GameClock.month_index);
summary_desc->year_index = GLOBAL (GameClock.year_index);
SummPtr->day_index = GLOBAL (GameClock.day_index);
SummPtr->month_index = GLOBAL (GameClock.month_index);
SummPtr->year_index = GLOBAL (GameClock.year_index);
}
static void
SaveProblemMessage (STAMP *MsgStamp)
SaveProblemMessage (PSTAMP MsgStamp)
{
#define MAX_MSG_LINES 1
RECT r;
@@ -299,7 +543,7 @@ SaveProblem (void)
// This function first writes to a memory file, and then writes the whole
// lot to the actual save file at once.
BOOLEAN
SaveGame (COUNT which_game, SUMMARY_DESC *summary_desc)
SaveGame (COUNT which_game, SUMMARY_DESC *SummPtr)
{
BOOLEAN success, made_room;
PVOID out_fp;
@@ -346,6 +590,8 @@ RetrySave:
else
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);
pt = GLOBAL (ip_location);
SaveFlagshipState ();
@@ -354,10 +600,10 @@ RetrySave:
& (START_ENCOUNTER | START_INTERPLANETARY)))
PutGroupInfo (GROUPS_RANDOM, GROUP_SAVE_IP);
cwrite ((PBYTE)&GlobData.Game_state, sizeof (GlobData.Game_state),
1, fh);
SaveGameState (&GlobData.Game_state, fh);
GLOBAL (ip_location) = pt;
// XXX: Restore: ShipStamp.frame is abused to store DWORD info
GLOBAL (ShipStamp.frame) = frame;
SaveShipQueue (fh, &GLOBAL (avail_race_q));
@@ -367,7 +613,7 @@ RetrySave:
// Save the number of game events (compressed).
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):
{
HEVENT hEvent;
@@ -381,7 +627,7 @@ RetrySave:
LockEvent (hEvent, &EventPtr);
hNextEvent = GetSuccEvent (EventPtr);
cwrite ((PBYTE)EventPtr, sizeof (*EventPtr), 1, fh);
SaveEvent (EventPtr, fh);
UnlockEvent (hEvent);
hEvent = hNextEvent;
@@ -391,7 +637,7 @@ RetrySave:
// Save the number of encounters (black globes in HS/QS (compressed))
num_links = CountLinks (&GLOBAL (encounter_q));
// Save the encounters themselves (compressed):
cwrite ((PBYTE)&num_links, sizeof (num_links), 1, fh);
cwrite_16 (fh, num_links);
{
HENCOUNTER hEncounter;
@@ -404,7 +650,7 @@ RetrySave:
LockEncounter (hEncounter, &EncounterPtr);
hNextEncounter = GetSuccEncounter (EncounterPtr);
SaveEncounter(EncounterPtr, fh);
SaveEncounter (EncounterPtr, fh);
UnlockEncounter (hEncounter);
hEncounter = hNextEncounter;
@@ -416,54 +662,55 @@ RetrySave:
if (fp)
{
flen = LengthStateFile (fp);
// (DWORD) Write the uncompressed size.
cwrite ((PBYTE)&flen, sizeof (flen), 1, fh);
// Write the uncompressed size.
cwrite_32 (fh, flen);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
ReadStateFile (buf, num_bytes, 1, fp);
cwrite ((PBYTE)buf, num_bytes, 1, fh);
cwrite (buf, num_bytes, 1, fh);
flen -= num_bytes;
}
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");
if (fp)
{
flen = LengthStateFile (fp);
// (DWORD) Write the uncompressed size.
cwrite ((PBYTE)&flen, sizeof (flen), 1, fh);
// Write the uncompressed size.
cwrite_32 (fh, flen);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
ReadStateFile (buf, num_bytes, 1, fp);
cwrite ((PBYTE)buf, num_bytes, 1, fh);
cwrite (buf, num_bytes, 1, fh);
flen -= num_bytes;
}
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");
if (fp)
{
flen = LengthStateFile (fp);
cwrite ((PBYTE)&flen, sizeof (flen), 1, fh);
// Write the uncompressed size.
cwrite_32 (fh, flen);
while (flen)
{
COUNT num_bytes;
num_bytes = flen >= sizeof (buf) ? sizeof (buf) : (COUNT)flen;
ReadStateFile (buf, num_bytes, 1, fp);
cwrite ((PBYTE)buf, num_bytes, 1, fh);
cwrite (buf, num_bytes, 1, fh);
flen -= num_bytes;
}
@@ -471,22 +718,19 @@ RetrySave:
}
// Write the current star desc into the memory file (compressed).
cwrite ((PBYTE)&SD, sizeof (SD), 1, fh);
SaveStarDesc (&SD, fh);
flen = cclose (fh);
// Write the memory file to the actual savegame file.
sprintf (file, "starcon2.%02u", which_game);
log_add (log_Debug, "'%s' is %u bytes long", file,
flen + sizeof (*summary_desc));
if (flen && (out_fp = (PVOID)res_OpenResFile (saveDir, file, "wb")))
flen + sizeof (*SummPtr));
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.
if (success && WriteResFile (mem_lock (h), (COUNT)flen, 1,
out_fp) == 0)
@@ -513,4 +757,3 @@ RetrySave:
return (success);
}
+1 -2
View File
@@ -43,7 +43,7 @@ static RACE_DESC androsynth_desc =
FIRES_FORE | SEEKING_WEAPON,
15, /* Super Melee cost */
~0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1,
@@ -51,7 +51,6 @@ static RACE_DESC androsynth_desc =
(STRING)ANDROSYNTH_RACE_STRINGS,
(FRAME)ANDROSYNTH_ICON_MASK_PMAP_ANIM,
(FRAME)ANDROSYNTH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC arilou_desc =
/* FIRES_FORE | */ IMMEDIATE_WEAPON,
16, /* Super Melee cost */
250 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
438, 6372,
@@ -53,7 +53,6 @@ static RACE_DESC arilou_desc =
(STRING)ARILOU_RACE_STRINGS,
(FRAME)ARILOU_ICON_MASK_PMAP_ANIM,
(FRAME)ARILOU_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC black_urquan_desc =
FIRES_FORE,
30, /* Super Melee cost */
2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
6000, 6250,
@@ -55,7 +55,6 @@ static RACE_DESC black_urquan_desc =
(STRING)KOHR_AH_RACE_STRINGS,
(FRAME)KOHR_AH_ICON_MASK_PMAP_ANIM,
(FRAME)KOHR_AH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -50,7 +50,7 @@ static RACE_DESC chenjesu_desc =
FIRES_FORE | SEEKING_SPECIAL | SEEKING_WEAPON,
28, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
0, 0,
@@ -58,7 +58,6 @@ static RACE_DESC chenjesu_desc =
(STRING)CHENJESU_RACE_STRINGS,
(FRAME)CHENJESU_ICON_MASK_PMAP_ANIM,
(FRAME)CHENJESU_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC chmmr_desc =
FIRES_FORE | IMMEDIATE_WEAPON | SEEKING_SPECIAL | POINT_DEFENSE,
30, /* Super Melee cost */
0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
0, 0,
@@ -55,7 +55,6 @@ static RACE_DESC chmmr_desc =
(STRING)CHMMR_RACE_STRINGS,
(FRAME)CHMMR_ICON_MASK_PMAP_ANIM,
(FRAME)CHMMR_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -43,7 +43,7 @@ static RACE_DESC druuge_desc =
FIRES_FORE,
17, /* Super Melee cost */
1400 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
9500, 2792,
@@ -51,7 +51,6 @@ static RACE_DESC druuge_desc =
(STRING)DRUUGE_RACE_STRINGS,
(FRAME)DRUUGE_ICON_MASK_PMAP_ANIM,
(FRAME)DRUUGE_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC human_desc =
FIRES_FORE | SEEKING_WEAPON | POINT_DEFENSE,
11, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
1752, 1450,
@@ -55,7 +55,6 @@ static RACE_DESC human_desc =
(STRING)HUMAN_RACE_STRINGS,
(FRAME)HUMAN_ICON_MASK_PMAP_ANIM,
(FRAME)HUMAN_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC ilwrath_desc =
FIRES_FORE,
10, /* Super Melee cost */
1410 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
48, 1700,
@@ -53,7 +53,6 @@ static RACE_DESC ilwrath_desc =
(STRING)ILWRATH_RACE_STRINGS,
(FRAME)ILWRATH_ICON_MASK_PMAP_ANIM,
(FRAME)ILWRATH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -50,7 +50,7 @@ static RACE_DESC samatra_desc =
/* FIRES_FORE | */ IMMEDIATE_WEAPON | CREW_IMMUNE,
16, /* Super Melee cost */
0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
0, 0,
@@ -58,7 +58,6 @@ static RACE_DESC samatra_desc =
(STRING)0,
(FRAME)0,
(FRAME)0,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC melnorme_desc =
FIRES_FORE,
18, /* Super Melee cost */
~0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
MAX_X_UNIVERSE >> 1, MAX_Y_UNIVERSE >> 1,
@@ -54,7 +54,6 @@ static RACE_DESC melnorme_desc =
(STRING)MELNORME_RACE_STRINGS,
(FRAME)MELNORME_ICON_MASK_PMAP_ANIM,
(FRAME)MELNORME_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -58,7 +58,7 @@ static RACE_DESC mmrnmhrm_desc =
FIRES_FORE | IMMEDIATE_WEAPON,
19, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
0, 0,
@@ -66,7 +66,6 @@ static RACE_DESC mmrnmhrm_desc =
(STRING)MMRNMHRM_RACE_STRINGS,
(FRAME)MMRNMHRM_ICON_MASK_PMAP_ANIM,
(FRAME)MMRNMHRM_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC mycon_desc =
FIRES_FORE | SEEKING_WEAPON,
21, /* Super Melee cost */
1070 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
6392, 2200,
@@ -54,7 +54,6 @@ static RACE_DESC mycon_desc =
(STRING)MYCON_RACE_STRINGS,
(FRAME)MYCON_ICON_MASK_PMAP_ANIM,
(FRAME)MYCON_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -48,7 +48,7 @@ static RACE_DESC orz_desc =
FIRES_FORE | SEEKING_SPECIAL,
23, /* Super Melee cost */
333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
3608, 2637,
@@ -56,7 +56,6 @@ static RACE_DESC orz_desc =
(STRING)ORZ_RACE_STRINGS,
(FRAME)ORZ_ICON_MASK_PMAP_ANIM,
(FRAME)ORZ_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC pkunk_desc =
FIRES_FORE | FIRES_LEFT | FIRES_RIGHT,
20, /* Super Melee cost */
666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
502, 401,
@@ -54,7 +54,6 @@ static RACE_DESC pkunk_desc =
(STRING)PKUNK_RACE_STRINGS,
(FRAME)PKUNK_ICON_MASK_PMAP_ANIM,
(FRAME)PKUNK_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -40,7 +40,7 @@ static RACE_DESC probe_desc =
0,
0, /* Super Melee cost */
0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
0, 0,
@@ -48,7 +48,6 @@ static RACE_DESC probe_desc =
0,
0,
(FRAME)PROBE_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC shofixti_desc =
FIRES_FORE,
5, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
0, 0,
@@ -54,7 +54,6 @@ static RACE_DESC shofixti_desc =
(STRING)SHOFIXTI_RACE_STRINGS,
(FRAME)SHOFIXTI_ICON_MASK_PMAP_ANIM,
(FRAME)SHOFIXTI_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -52,7 +52,7 @@ static RACE_DESC sis_desc =
0,
16, /* Super Melee cost */
0 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
0, 0,
@@ -60,7 +60,6 @@ static RACE_DESC sis_desc =
0,
(FRAME)SIS_ICON_MASK_PMAP_ANIM,
0,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC slylandro_desc =
SEEKING_WEAPON | CREW_IMMUNE,
17, /* Super Melee cost */
~0, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
333, 9812,
@@ -53,7 +53,6 @@ static RACE_DESC slylandro_desc =
(STRING)SLYLANDRO_RACE_STRINGS,
(FRAME)SLYLANDRO_ICON_MASK_PMAP_ANIM,
(FRAME)SLYLANDRO_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -43,7 +43,7 @@ static RACE_DESC spathi_desc =
FIRES_FORE | FIRES_AFT | SEEKING_SPECIAL | DONT_CHASE,
18, /* Super Melee cost */
1000 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
2549, 3600,
@@ -51,7 +51,6 @@ static RACE_DESC spathi_desc =
(STRING)SPATHI_RACE_STRINGS,
(FRAME)SPATHI_ICON_MASK_PMAP_ANIM,
(FRAME)SPATHI_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC supox_desc =
FIRES_FORE,
16, /* Super Melee cost */
333 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
7468, 9246,
@@ -53,7 +53,6 @@ static RACE_DESC supox_desc =
(STRING)SUPOX_RACE_STRINGS,
(FRAME)SUPOX_ICON_MASK_PMAP_ANIM,
(FRAME)SUPOX_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC syreen_desc =
FIRES_FORE,
13, /* Super Melee cost */
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,
{
0, 0,
@@ -54,7 +54,6 @@ static RACE_DESC syreen_desc =
(STRING)SYREEN_RACE_STRINGS,
(FRAME)SYREEN_ICON_MASK_PMAP_ANIM,
(FRAME)SYREEN_MICON_MASK_PMAP_ANIM,
MAX_CREW, SYREEN_MAX_CREW_SIZE,
},
{
MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC thraddash_desc =
FIRES_FORE,
10, /* Super Melee cost */
833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
2535, 8358,
@@ -54,7 +54,6 @@ static RACE_DESC thraddash_desc =
(STRING)THRADDASH_RACE_STRINGS,
(FRAME)THRADDASH_ICON_MASK_PMAP_ANIM,
(FRAME)THRADDASH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC umgah_desc =
FIRES_FORE | IMMEDIATE_WEAPON,
7, /* Super Melee cost */
833 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
1798, 6000,
@@ -53,7 +53,6 @@ static RACE_DESC umgah_desc =
(STRING)UMGAH_RACE_STRINGS,
(FRAME)UMGAH_ICON_MASK_PMAP_ANIM,
(FRAME)UMGAH_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC urquan_desc =
FIRES_FORE | SEEKING_SPECIAL,
30, /* Super Melee cost */
2666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
5750, 6000,
@@ -55,7 +55,6 @@ static RACE_DESC urquan_desc =
(STRING)URQUAN_RACE_STRINGS,
(FRAME)URQUAN_ICON_MASK_PMAP_ANIM,
(FRAME)URQUAN_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -47,7 +47,7 @@ static RACE_DESC utwig_desc =
FIRES_FORE | POINT_DEFENSE | SHIELD_DEFENSE,
22, /* Super Melee cost */
666 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY >> 1, MAX_ENERGY,
{
8534, 8797,
@@ -55,7 +55,6 @@ static RACE_DESC utwig_desc =
(STRING)UTWIG_RACE_STRINGS,
(FRAME)UTWIG_ICON_MASK_PMAP_ANIM,
(FRAME)UTWIG_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -48,7 +48,7 @@ static RACE_DESC vux_desc =
FIRES_FORE | SEEKING_SPECIAL | IMMEDIATE_WEAPON,
12, /* Super Melee cost */
900 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
4412, 1558,
@@ -56,7 +56,6 @@ static RACE_DESC vux_desc =
(STRING)VUX_RACE_STRINGS,
(FRAME)VUX_ICON_MASK_PMAP_ANIM,
(FRAME)VUX_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -45,7 +45,7 @@ static RACE_DESC yehat_desc =
FIRES_FORE | SHIELD_DEFENSE,
23, /* Super Melee cost */
750 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
4970, 40,
@@ -53,7 +53,6 @@ static RACE_DESC yehat_desc =
(STRING)YEHAT_RACE_STRINGS,
(FRAME)YEHAT_ICON_MASK_PMAP_ANIM,
(FRAME)YEHAT_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+1 -2
View File
@@ -46,7 +46,7 @@ static RACE_DESC zoqfotpik_desc =
FIRES_FORE,
6, /* Super Melee cost */
320 / SPHERE_RADIUS_INCREMENT, /* Initial sphere of influence radius */
0, 0, /* Hack; old crew field */
MAX_CREW, MAX_CREW,
MAX_ENERGY, MAX_ENERGY,
{
3761, 5333,
@@ -54,7 +54,6 @@ static RACE_DESC zoqfotpik_desc =
(STRING)ZOQFOTPIK_RACE_STRINGS,
(FRAME)ZOQFOTPIK_ICON_MASK_PMAP_ANIM,
(FRAME)ZOQFOTPIK_MICON_MASK_PMAP_ANIM,
MAX_CREW, MAX_CREW,
},
{
MAX_THRUST,
+5 -3
View File
@@ -196,6 +196,8 @@ enum
#define STATUS_MESSAGE_WIDTH 60
#define STATUS_MESSAGE_HEIGHT 7
#define SIS_NAME_SIZE 16
typedef struct
{
SDWORD log_x, log_y;
@@ -216,9 +218,9 @@ typedef struct
COUNT ElementAmounts[NUM_ELEMENT_CATEGORIES];
UNICODE ShipName[16];
UNICODE CommanderName[16];
UNICODE PlanetName[16];
UNICODE ShipName[SIS_NAME_SIZE];
UNICODE CommanderName[SIS_NAME_SIZE];
UNICODE PlanetName[SIS_NAME_SIZE];
} SIS_STATE;
typedef SIS_STATE *PSIS_STATE;
+33 -43
View File
@@ -54,7 +54,7 @@ OpenStateFile (int stateFile, const char *mode)
GAME_STATE_FILE *fp;
if (stateFile < 0 || stateFile >= NUM_STATE_FILES)
return NULL_PTR;
return NULL;
fp = &state_files[stateFile];
fp->open_count++;
@@ -67,7 +67,7 @@ OpenStateFile (int stateFile, const char *mode)
{
fp->data = HMalloc (fp->size_hint);
if (!fp->data)
return NULL_PTR;
return NULL;
fp->size = fp->size_hint;
}
@@ -185,15 +185,6 @@ WriteStateFile (PVOID lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp)
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
SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence)
{
@@ -220,14 +211,13 @@ InitPlanetInfo (void)
fp = OpenStateFile (STARINFO_FILE, "wb");
if (fp)
{
DWORD offset;
STAR_DESCPTR pSD;
offset = 0;
// Set record offsets for all stars to 0 (not present)
pSD = &star_array[0];
do
{
WriteStateFile (&offset, sizeof (offset), 1, fp);
swrite_32 (fp, 0);
++pSD;
} while (pSD->star_pt.x <= MAX_X_UNIVERSE
&& pSD->star_pt.y <= MAX_Y_UNIVERSE);
@@ -242,6 +232,9 @@ UninitPlanetInfo (void)
DeleteStateFile (STARINFO_FILE);
}
#define OFFSET_SIZE (sizeof (DWORD))
#define SCAN_RECORD_SIZE (sizeof (DWORD) * NUM_SCAN_TYPES)
void
GetPlanetInfo (void)
{
@@ -266,27 +259,24 @@ GetPlanetInfo (void)
moon_index = (COUNT)(pSolarSysState->pOrbitalDesc
- pSolarSysState->MoonDesc + 1);
SeekStateFile (fp, star_index * sizeof (offset), SEEK_SET);
ReadStateFile (&offset, sizeof (offset), 1, fp);
SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET);
sread_32 (fp, &offset);
if (offset)
{
COUNT i;
// Skip scan records for all preceeding planets to the one we need
for (i = 0; i < planet_index; ++i)
offset += sizeof (
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
) * (pSolarSysState->PlanetDesc[i].NumPlanets + 1);
offset += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) *
SCAN_RECORD_SIZE;
offset += sizeof (
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
) * moon_index;
// Skip scan records for all preceeding moons to the one we need
offset += moon_index * SCAN_RECORD_SIZE;
SeekStateFile (fp, offset, SEEK_SET);
ReadStateFile (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
sizeof (
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
), 1, fp);
sread_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
NUM_SCAN_TYPES);
}
CloseStateFile (fp);
@@ -314,11 +304,11 @@ PutPlanetInfo (void)
moon_index = (COUNT)(pSolarSysState->pOrbitalDesc
- pSolarSysState->MoonDesc + 1);
SeekStateFile (fp, star_index * sizeof (offset), SEEK_SET);
ReadStateFile (&offset, sizeof (offset), 1, fp);
SeekStateFile (fp, star_index * OFFSET_SIZE, SEEK_SET);
sread_32 (fp, &offset);
if (offset == 0)
{
{ // Scan record not present yet -- init it
DWORD ScanRetrieveMask[NUM_SCAN_TYPES] =
{
0, 0, 0,
@@ -326,34 +316,34 @@ PutPlanetInfo (void)
offset = LengthStateFile (fp);
SeekStateFile (fp, star_index * sizeof (offset), SEEK_SET);
WriteStateFile (&offset, sizeof (offset), 1, fp);
// Write the record offset
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);
for (i = 0; i < pSolarSysState->SunDesc[0].NumPlanets; ++i)
{
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)
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)
offset += sizeof (
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
) * (pSolarSysState->PlanetDesc[i].NumPlanets + 1);
offset += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) *
SCAN_RECORD_SIZE;
offset += sizeof (
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
) * moon_index;
// Skip scan records for all preceeding moons to the one we need
offset += moon_index * SCAN_RECORD_SIZE;
SeekStateFile (fp, offset, SEEK_SET);
WriteStateFile (pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
sizeof (
pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask
), 1, fp);
swrite_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
NUM_SCAN_TYPES);
CloseStateFile (fp);
}
+71 -1
View File
@@ -19,7 +19,9 @@
#ifndef _STATE_H
#define _STATE_H
#include "port.h"
#include "libs/compiler.h"
#include <assert.h>
extern void InitPlanetInfo (void);
extern void UninitPlanetInfo (void);
@@ -67,8 +69,76 @@ void DeleteStateFile (int stateFile);
DWORD LengthStateFile (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 PutStateFileChar (char ch, GAME_STATE_FILE *fp);
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 */