void * LoadResourceFromPath (const char *path, ResourceLoadFileFun *loadFun) { uio_Stream *stream; unsigned long dataLen; void *resdata; stream = res_OpenResFile (contentDir, path, "rb"); if (stream == NULL) { log_add (log_Warning, "Warning: Can't open '%s'", path); return NULL; } dataLen = LengthResFile (stream); log_add (log_Info, "\t'%s' -- %lu bytes", path, dataLen); if (dataLen == 0) { log_add (log_Warning, "Warning: Trying to load empty file '%s'.", path); goto err; } _cur_resfile_name = path; resdata = (*loadFun) (stream, dataLen); _cur_resfile_name = NULL; res_CloseResFile (stream); return resdata; err: res_CloseResFile (stream); return NULL; }
MUSIC_REF LoadMusicFile (const char *pStr) { uio_Stream *fp; char filename[256]; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; strncpy (filename, pStr, sizeof(filename) - 1); filename[sizeof(filename) - 1] = '\0'; CheckMusicResName (filename); // Opening the res file is not technically necessary right now // since _GetMusicData() completely ignores the arguments // But just for the sake of correctness fp = res_OpenResFile (contentDir, filename, "rb"); if (fp) { MUSIC_REF hData; _cur_resfile_name = filename; hData = (MUSIC_REF)_GetMusicData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return hData; } return (0); }
SOUND_REF LoadSoundFile (const char *pStr) { uio_Stream *fp; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; fp = res_OpenResFile (contentDir, pStr, "rb"); if (fp) { SOUND_REF hData; _cur_resfile_name = pStr; hData = (SOUND_REF)_GetSoundBankData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return hData; } return NULL; }
BOOLEAN CloseJournal (void) { if (journal_fh) { uio_Stream *fp; cclose (journal_fh); journal_fh = 0; if (ArrowInput == DemoInput) { ArrowInput = OldArrowInput; return (FALSE); } #if CREATE_JOURNAL else if (fp = res_OpenResFile ("starcon.jnl", "wb")) { WriteResFile (journal_buf, 1, sizeof (journal_buf), fp); res_CloseResFile (fp); } #endif /* CREATE_JOURNAL */ } return (TRUE); }
STRING_TABLE LoadStringTableFile (uio_DirHandle *dir, const char *fileName) { uio_Stream *fp; // FIXME: this theoretically needs a mechanism to prevent races if (_cur_resfile_name) // something else is loading resources atm return 0; fp = res_OpenResFile (dir, fileName, "rb"); if (fp) { MEM_HANDLE hData; _cur_resfile_name = fileName; hData = _GetStringData (fp, LengthResFile (fp)); _cur_resfile_name = 0; res_CloseResFile (fp); return (BUILD_STRING_TABLE (hData)); } return (0); }
void PropFile_from_filename (uio_DirHandle *path, const char *fname, PROPERTY_HANDLER handler, const char *prefix) { uio_Stream *f = res_OpenResFile (path, fname, "rt"); if (!f) { return; } PropFile_from_file (f, handler, prefix); res_CloseResFile(f); }
void OpenJournal (void) { DWORD start_seed; #if CREATE_JOURNAL if (create_journal) { if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_WRITE)) { start_seed = SeedRandomNumbers (); cwrite ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); } } else #endif /* CREATE_JOURNAL */ { uio_Stream *fp; if (fp = res_OpenResFile ("starcon.jnl", "rb")) { ReadResFile (journal_buf, 1, sizeof (journal_buf), fp); res_CloseResFile (fp); if (journal_fh = copen (journal_buf, MEMORY_STREAM, STREAM_READ)) { OldArrowInput = ArrowInput; ArrowInput = DemoInput; PlayerInput[0] = PlayerInput[1] = DemoInput; FlushInput (); cread ((PBYTE)&start_seed, sizeof (start_seed), 1, journal_fh); TFB_SeedRandom (start_seed); } } } }
void _GetConversationData (const char *path, RESOURCE_DATA *resdata) { uio_Stream *fp; long dataLen; void *result; int n, path_len, num_data_sets; DWORD opos, slen[MAX_STRINGS], StringOffs, tot_string_size, clen[MAX_STRINGS], ClipOffs, tot_clip_size, tslen[MAX_STRINGS], TSOffs, tot_ts_size; char CurrentLine[1024], paths[1024], *clip_path, *ts_path, *strdata, *clipdata, *ts_data; uio_Stream *timestamp_fp = NULL; /* Parse out the conversation components. */ strncpy (paths, path, 1023); paths[1023] = '\0'; clip_path = strchr (paths, ':'); if (clip_path == NULL) { ts_path = NULL; } else { *clip_path = '\0'; clip_path++; ts_path = strchr (clip_path, ':'); if (ts_path != NULL) { *ts_path = '\0'; ts_path++; } } fp = res_OpenResFile (contentDir, paths, "rb"); if (fp == NULL) { log_add (log_Warning, "Warning: Can't open '%s'", paths); resdata->ptr = NULL; return; } dataLen = LengthResFile (fp); log_add (log_Info, "\t'%s' -- conversation phrases -- %lu bytes", paths, dataLen); if (clip_path) log_add (log_Info, "\t'%s' -- voice clip directory", clip_path); else log_add (log_Info, "\tNo associated voice clips"); if (ts_path) log_add (log_Info, "\t'%s' -- timestamps", ts_path); else log_add (log_Info, "\tNo associated timestamp file"); if (dataLen == 0) { log_add (log_Warning, "Warning: Trying to load empty file '%s'.", path); goto err; } if ((strdata = HMalloc (tot_string_size = POOL_SIZE)) == 0) goto err; if ((clipdata = HMalloc (tot_clip_size = POOL_SIZE)) == 0) { HFree (strdata); goto err; } ts_data = NULL; path_len = clip_path ? strlen (clip_path) : 0; if (ts_path && (timestamp_fp = uio_fopen (contentDir, ts_path, "rb"))) { if ((ts_data = HMalloc (tot_ts_size = POOL_SIZE)) == 0) goto err; } opos = uio_ftell (fp); n = -1; StringOffs = ClipOffs = TSOffs = 0; while (uio_fgets (CurrentLine, sizeof (CurrentLine), fp) && n < MAX_STRINGS - 1) { int l; if (CurrentLine[0] == '#') { char CopyLine[1024]; char *s; strcpy (CopyLine, CurrentLine); s = strtok (&CopyLine[1], "()"); if (s) { if (n >= 0) { while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n' || strdata[StringOffs - 2] == '\r')) { --slen[n]; --StringOffs; strdata[StringOffs - 1] = '\0'; } } slen[++n] = 0; // now lets check for timestamp data if (timestamp_fp) { char TimeStampLine[1024], *tsptr; BOOLEAN ts_ok = FALSE; uio_fgets (TimeStampLine, sizeof (TimeStampLine), timestamp_fp); if (TimeStampLine[0] == '#') { tslen[n] = 0; if ((tsptr = strstr (TimeStampLine,s)) && (tsptr += strlen(s)) && (++tsptr)) { ts_ok = TRUE; while (! strcspn(tsptr," \t\r\n") && *tsptr) tsptr++; if (*tsptr) { l = strlen (tsptr) + 1; if (TSOffs + l > tot_ts_size && (ts_data = HRealloc (ts_data, tot_ts_size += POOL_SIZE)) == 0) { HFree (strdata); goto err; } strcpy (&ts_data[TSOffs], tsptr); TSOffs += l; tslen[n] = l; } } } if (!ts_ok) { // timestamp data is invalid, remove all of it log_add (log_Warning, "Invalid timestamp data " "for '%s'. Disabling timestamps", s); HFree (ts_data); ts_data = NULL; uio_fclose (timestamp_fp); timestamp_fp = NULL; TSOffs = 0; } } clen[n] = 0; s = strtok (NULL, " \t\r\n)"); if (s) { l = path_len + strlen (s) + 1; if (ClipOffs + l > tot_clip_size && (clipdata = HRealloc (clipdata, tot_clip_size += POOL_SIZE)) == 0) { HFree (strdata); goto err; } if (clip_path) strcpy (&clipdata[ClipOffs], clip_path); strcpy (&clipdata[ClipOffs + path_len], s); ClipOffs += l; clen[n] = l; } } } else if (n >= 0) { char *s; l = strlen (CurrentLine) + 1; if (StringOffs + l > tot_string_size && (strdata = HRealloc (strdata, tot_string_size += POOL_SIZE)) == 0) { HFree (clipdata); goto err; } if (slen[n]) { --slen[n]; --StringOffs; } s = &strdata[StringOffs]; slen[n] += l; StringOffs += l; strcpy (s, CurrentLine); } if ((int)uio_ftell (fp) - (int)opos >= (int)dataLen) break; } if (n >= 0) { while (slen[n] > 1 && (strdata[StringOffs - 2] == '\n' || strdata[StringOffs - 2] == '\r')) { --slen[n]; --StringOffs; strdata[StringOffs - 1] = '\0'; } } if (timestamp_fp) uio_fclose (timestamp_fp); result = NULL; num_data_sets = (ClipOffs ? 1 : 0) + (TSOffs ? 1 : 0) + 1; if (++n) { int flags = 0; if (ClipOffs) flags |= HAS_SOUND_CLIPS; if (TSOffs) flags |= HAS_TIMESTAMP; result = AllocStringTable (n, flags); if (result) { int StringIndex, ClipIndex, TSIndex; STRING_TABLE_DESC *lpST; lpST = (STRING_TABLE) result; StringIndex = 0; ClipIndex = n; TSIndex = n * ((flags & HAS_SOUND_CLIPS) ? 2 : 1); StringOffs = ClipOffs = TSOffs = 0; for (n = 0; n < (int)lpST->size; ++n, ++StringIndex, ++ClipIndex, ++TSIndex) { set_strtab_entry(lpST, StringIndex, strdata + StringOffs, slen[n]); StringOffs += slen[n]; if (lpST->flags & HAS_SOUND_CLIPS) { set_strtab_entry(lpST, ClipIndex, clipdata + ClipOffs, clen[n]); ClipOffs += clen[n]; } if (lpST->flags & HAS_TIMESTAMP) { set_strtab_entry(lpST, TSIndex, ts_data + TSOffs, tslen[n]); TSOffs += tslen[n]; } } } } HFree (strdata); HFree (clipdata); if (ts_data) HFree (ts_data); resdata->ptr = result; return; err: res_CloseResFile (fp); resdata->ptr = NULL; }
BOOLEAN LoadGame (COUNT which_game, SUMMARY_DESC *SummPtr) { uio_Stream *in_fp; 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) return FALSE; if (!LoadSummary (&loc_sd, in_fp)) { log_add (log_Error, "Warning: Savegame is corrupt"); res_CloseResFile (in_fp); return FALSE; } 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; } // 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_Error, "Warning: Savegame corrupt or from " "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 (ip_group_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; LoadRaceQueue (fh, &GLOBAL (avail_race_q)); // START_INTERPLANETARY is only set when saving from Homeworld // encounter screen. When the game is loaded, the // GenerateOrbitalFunction for the current star system will // create the encounter anew and populate the npc queue. if (!(NextActivity & START_INTERPLANETARY)) { if (NextActivity & START_ENCOUNTER) LoadShipQueue (fh, &GLOBAL (npc_built_ship_q)); else if (LOBYTE (NextActivity) == IN_INTERPLANETARY) // XXX: Technically, this queue does not need to be // saved/loaded at all. IP groups will be reloaded // from group state files. But the original code did, // and so will we until we can prove we do not need to. LoadGroupQueue (fh, &GLOBAL (ip_group_q)); else // XXX: The empty queue read is only needed to maintain // the savegame compatibility LoadEmptyQueue (fh); } LoadShipQueue (fh, &GLOBAL (built_ship_q)); // 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; EVENT *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--) { HENCOUNTER hEncounter; ENCOUNTER *EncounterPtr; hEncounter = AllocEncounter (); LockEncounter (hEncounter, &EncounterPtr); LoadEncounter (EncounterPtr, fh); 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; }