summaryrefslogtreecommitdiff
path: root/src/uqm/state.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/uqm/state.c')
-rw-r--r--src/uqm/state.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/uqm/state.c b/src/uqm/state.c
new file mode 100644
index 0000000..3358b32
--- /dev/null
+++ b/src/uqm/state.c
@@ -0,0 +1,354 @@
+//Copyright Paul Reiche, Fred Ford. 1992-2002
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "state.h"
+
+#include "starmap.h"
+#include "libs/memlib.h"
+#include "libs/log.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <memory.h>
+
+// in-memory file i/o
+struct GAME_STATE_FILE
+{
+ const char *symname;
+ DWORD size_hint;
+ int open_count;
+ BYTE *data;
+ DWORD used;
+ DWORD size;
+ DWORD ptr;
+};
+#define STATE_FILE_ITRAILER 0, 0, 0, 0, 0
+
+#define NUM_STATE_FILES 3
+
+static GAME_STATE_FILE state_files[NUM_STATE_FILES] =
+{
+ {"STARINFO", STAR_BUFSIZE, STATE_FILE_ITRAILER},
+ {"RANDGRPINFO", RAND_BUFSIZE, STATE_FILE_ITRAILER},
+ {"DEFGRPINFO", DEF_BUFSIZE, STATE_FILE_ITRAILER}
+};
+
+
+GAME_STATE_FILE *
+OpenStateFile (int stateFile, const char *mode)
+{
+ GAME_STATE_FILE *fp;
+
+ if (stateFile < 0 || stateFile >= NUM_STATE_FILES)
+ return NULL;
+
+ fp = &state_files[stateFile];
+ fp->open_count++;
+ if (fp->open_count > 1)
+ log_add (log_Warning, "WARNING: "
+ "State file %s open count is %d after open()",
+ fp->symname, fp->open_count);
+
+ if (!fp->data)
+ {
+ fp->data = HMalloc (fp->size_hint);
+ if (!fp->data)
+ return NULL;
+ fp->size = fp->size_hint;
+ }
+
+ // we allow reading and writing for any open mode
+ // but the mode determines what happens to the file contents
+ if (mode[0] == 'w')
+ { // blow the file away
+ fp->used = 0;
+#ifdef DEBUG
+ // paint buffer for tracking writes
+ memset (fp->data, 0xCC, fp->size);
+#endif
+ }
+ else if (mode[0] == 'r')
+ { // nothing
+ }
+ else
+ {
+ log_add (log_Warning, "WARNING: "
+ "State file %s opened with unsupported mode '%s'",
+ fp->symname, mode);
+ }
+ fp->ptr = 0;
+
+ return fp;
+}
+
+void
+CloseStateFile (GAME_STATE_FILE *fp)
+{
+ fp->ptr = 0;
+ fp->open_count--;
+ if (fp->open_count < 0)
+ log_add (log_Warning, "WARNING: "
+ "State file %s open count is %d after close()",
+ fp->symname, fp->open_count);
+ // Erm, Ok, it's closed! Honest!
+}
+
+void
+DeleteStateFile (int stateFile)
+{
+ GAME_STATE_FILE *fp;
+
+ if (stateFile < 0 || stateFile >= NUM_STATE_FILES)
+ return;
+
+ fp = &state_files[stateFile];
+ if (fp->open_count != 0)
+ log_add (log_Warning, "WARNING: "
+ "State file %s open count is %d during delete()",
+ fp->symname, fp->open_count);
+
+ fp->used = 0;
+ fp->ptr = 0;
+ HFree (fp->data);
+ fp->data = 0;
+}
+
+DWORD
+LengthStateFile (GAME_STATE_FILE *fp)
+{
+ return fp->used;
+}
+
+int
+ReadStateFile (void *lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp)
+{
+ DWORD bytes = size * count;
+
+ if (fp->ptr >= fp->size)
+ { // EOF
+ return 0;
+ }
+ else if (fp->ptr + bytes > fp->size)
+ { // dont have that much data
+ bytes = fp->size - fp->ptr;
+ bytes -= bytes % size;
+ }
+
+ if (bytes > 0)
+ {
+ memcpy (lpBuf, fp->data + fp->ptr, bytes);
+ fp->ptr += bytes;
+ }
+ return (bytes / size);
+}
+
+int
+WriteStateFile (const void *lpBuf, COUNT size, COUNT count, GAME_STATE_FILE *fp)
+{
+ DWORD bytes = size * count;
+
+ if (fp->ptr + bytes > fp->size)
+ { // dont have that much space available
+ DWORD newsize = fp->ptr + bytes;
+ // grab more space in advance
+ if (newsize < fp->size * 3 / 2)
+ newsize = fp->size * 3 / 2;
+
+ fp->data = HRealloc (fp->data, newsize);
+ if (!fp->data)
+ return 0;
+
+ fp->size = newsize;
+ if (newsize > fp->size_hint)
+ fp->size_hint = newsize;
+ }
+
+ if (bytes > 0)
+ {
+ memcpy (fp->data + fp->ptr, lpBuf, bytes);
+ fp->ptr += bytes;
+ if (fp->ptr > fp->used)
+ fp->used = fp->ptr;
+ }
+ return (bytes / size);
+}
+
+int
+SeekStateFile (GAME_STATE_FILE *fp, long offset, int whence)
+{
+ if (whence == SEEK_CUR)
+ offset += fp->ptr;
+ else if (whence == SEEK_END)
+ offset += fp->used;
+
+ if (offset < 0)
+ {
+ fp->ptr = 0;
+ return 0;
+ }
+ fp->ptr = offset;
+ return 1;
+}
+
+
+void
+InitPlanetInfo (void)
+{
+ GAME_STATE_FILE *fp;
+
+ fp = OpenStateFile (STARINFO_FILE, "wb");
+ if (fp)
+ {
+ STAR_DESC *pSD;
+
+ // Set record offsets for all stars to 0 (not present)
+ pSD = &star_array[0];
+ do
+ {
+ swrite_32 (fp, 0);
+ ++pSD;
+ } while (pSD->star_pt.x <= MAX_X_UNIVERSE
+ && pSD->star_pt.y <= MAX_Y_UNIVERSE);
+
+ CloseStateFile (fp);
+ }
+}
+
+void
+UninitPlanetInfo (void)
+{
+ DeleteStateFile (STARINFO_FILE);
+}
+
+#define OFFSET_SIZE (sizeof (DWORD))
+#define SCAN_RECORD_SIZE (sizeof (DWORD) * NUM_SCAN_TYPES)
+
+void
+GetPlanetInfo (void)
+{
+ GAME_STATE_FILE *fp;
+
+ pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[BIOLOGICAL_SCAN] = 0;
+ pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[MINERAL_SCAN] = 0;
+ pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask[ENERGY_SCAN] = 0;
+
+ fp = OpenStateFile (STARINFO_FILE, "rb");
+ if (fp)
+ {
+ COUNT star_index, planet_index, moon_index;
+ DWORD offset;
+
+ star_index = (COUNT)(CurStarDescPtr - star_array);
+ planet_index = (COUNT)(pSolarSysState->pBaseDesc->pPrevDesc
+ - pSolarSysState->PlanetDesc);
+ if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc)
+ moon_index = 0;
+ else
+ moon_index = (COUNT)(pSolarSysState->pOrbitalDesc
+ - pSolarSysState->MoonDesc + 1);
+
+ 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 += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) *
+ SCAN_RECORD_SIZE;
+
+ // Skip scan records for all preceeding moons to the one we need
+ offset += moon_index * SCAN_RECORD_SIZE;
+
+ SeekStateFile (fp, offset, SEEK_SET);
+ sread_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
+ NUM_SCAN_TYPES);
+ }
+
+ CloseStateFile (fp);
+ }
+}
+
+void
+PutPlanetInfo (void)
+{
+ GAME_STATE_FILE *fp;
+
+ fp = OpenStateFile (STARINFO_FILE, "r+b");
+ if (fp)
+ {
+ COUNT i;
+ COUNT star_index, planet_index, moon_index;
+ DWORD offset;
+
+ star_index = (COUNT)(CurStarDescPtr - star_array);
+ planet_index = (COUNT)(pSolarSysState->pBaseDesc->pPrevDesc
+ - pSolarSysState->PlanetDesc);
+ if (pSolarSysState->pOrbitalDesc->pPrevDesc == pSolarSysState->SunDesc)
+ moon_index = 0;
+ else
+ moon_index = (COUNT)(pSolarSysState->pOrbitalDesc
+ - pSolarSysState->MoonDesc + 1);
+
+ 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,
+ };
+
+ offset = LengthStateFile (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;
+
+ swrite_a32 (fp, ScanRetrieveMask, NUM_SCAN_TYPES);
+ // init moons
+ for (j = 0; j < pSolarSysState->PlanetDesc[i].NumPlanets; ++j)
+ 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 += (pSolarSysState->PlanetDesc[i].NumPlanets + 1) *
+ SCAN_RECORD_SIZE;
+
+ // Skip scan records for all preceeding moons to the one we need
+ offset += moon_index * SCAN_RECORD_SIZE;
+
+ SeekStateFile (fp, offset, SEEK_SET);
+ swrite_a32 (fp, pSolarSysState->SysInfo.PlanetInfo.ScanRetrieveMask,
+ NUM_SCAN_TYPES);
+
+ CloseStateFile (fp);
+ }
+}
+