Esempio n. 1
0
bool C4Language::Init()
{
	// Clear (to allow clean re-init)
	Clear();

	// Make sure Language.ocg is unpacked (TODO: This won't work properly if Language.ocg is in system data path)
	// Assume for now that Language.ocg is either at a writable location or unpacked already.
	// TODO: Use all Language.c4gs that we find, and merge them.
	// TODO: Use gettext instead?
	StdStrBuf langPath;
	C4Reloc::iterator iter;
	for(iter = Reloc.begin(); iter != Reloc.end(); ++iter)
	{
		langPath.Copy((*iter).strBuf + DirSep + C4CFN_Languages);
		if(ItemExists(langPath.getData()))
		{
			if(DirectoryExists(langPath.getData()))
				break;
			if(C4Group_UnpackDirectory(langPath.getData()))
				break;
		}
	}

	// Break if no language.ocg found
	if(iter != Reloc.end())
	{
		// Look for available language packs in Language.ocg
		C4Group *pPack;
		char strPackFilename[_MAX_FNAME + 1], strEntry[_MAX_FNAME + 1];
		if (PackDirectory.Open(langPath.getData()))
		{
			while (PackDirectory.FindNextEntry("*.ocg", strEntry))
			{
				sprintf(strPackFilename, "%s" DirSep "%s", C4CFN_Languages, strEntry);
				pPack = new C4Group();
				if (pPack->Open(strPackFilename))
				{
					Packs.RegisterGroup(*pPack, true, C4GSCnt_Language, false);
				}
				else
				{
					delete pPack;
				}
			}
		}

		// Now create a pack group for each language pack (these pack groups are child groups
		// that browse along each pack to access requested data)
		for (int iPack = 0; (pPack = Packs.GetGroup(iPack)); iPack++)
			PackGroups.RegisterGroup(*(new C4Group), true, C4GSPrio_Base, C4GSCnt_Language);
	}

	// Load language infos by scanning string tables (the engine doesn't really need this at the moment)
	InitInfos();

	// Done
	return true;
}
Esempio n. 2
0
BOOL C4Record::Start(bool fInitial) {
  // no double record
  if (fRecording) return FALSE;

  // create demos folder
  if (!Config.General.CreateSaveFolder(Config.General.SaveDemoFolder.getData(),
                                       LoadResStr("IDS_GAME_RECORDSTITLE")))
    return FALSE;

  // various infos
  StdStrBuf sDemoFolder;
  sDemoFolder.Ref(Config.General.SaveDemoFolder);
  char sScenName[_MAX_FNAME + 1];
  SCopy(GetFilenameOnly(Game.Parameters.Scenario.getFile()), sScenName,
        _MAX_FNAME);

  // remove trailing numbers from scenario name (e.g. from savegames) - could we
  // perhaps use C4S.Head.Origin instead...?
  char *pScenNameEnd = sScenName + SLen(sScenName);
  while (Inside<char>(*--pScenNameEnd, '0', '9'))
    if (pScenNameEnd == sScenName) break;
  pScenNameEnd[1] = 0;

  // determine index (by total number of records)
  Index = 1;
  for (DirectoryIterator i(Config.General.SaveDemoFolder.getData()); *i; ++i)
    if (WildcardMatch(C4CFN_ScenarioFiles, *i)) Index++;

  // compose record filename
  sFilename.Format("%s" DirSep "%03i-%s.c4s", sDemoFolder.getData(), Index,
                   sScenName);

  // log
  StdStrBuf sLog;
  sLog.Format(LoadResStr("IDS_PRC_RECORDINGTO"), sFilename.getData());
  if (Game.FrameCounter) sLog.AppendFormat(" (Frame %d)", Game.FrameCounter);
  Log(sLog.getData());

  // save game - this also saves player info list
  C4GameSaveRecord saveRec(fInitial, Index, Game.Parameters.isLeague());
  if (!saveRec.Save(sFilename.getData())) return FALSE;
  saveRec.Close();

  // unpack group, if neccessary
  if (!DirectoryExists(sFilename.getData()) &&
      !C4Group_UnpackDirectory(sFilename.getData()))
    return FALSE;

  // open control record file
  char szCtrlRecFilename[_MAX_PATH + 1 + _MAX_FNAME];
  sprintf(szCtrlRecFilename, "%s" DirSep C4CFN_CtrlRec, sFilename.getData());
  if (!CtrlRec.Create(szCtrlRecFilename)) return FALSE;

  // open record group
  if (!RecordGrp.Open(sFilename.getData())) return FALSE;

  // record go
  fStreaming = false;
  fRecording = true;
  iLastFrame = 0;
  return TRUE;
}
Esempio n. 3
0
bool C4Playback::StreamToRecord(const char *szStream, StdStrBuf *pRecordFile) {
  // Load data
  StdBuf CompressedData;
  Log("Reading stream...");
  if (!CompressedData.LoadFromFile(szStream)) return false;

  // Decompress
  unsigned long iStreamSize = CompressedData.getSize() * 5;
  StdBuf StreamData;
  StreamData.New(iStreamSize);
  while (true) {
    // Initialize stream
    z_stream strm;
    ZeroMem(&strm, sizeof strm);
    strm.next_in = getMBufPtr<BYTE>(CompressedData);
    strm.avail_in = CompressedData.getSize();
    strm.next_out = getMBufPtr<BYTE>(StreamData);
    strm.avail_out = StreamData.getSize();

    // Decompress
    if (inflateInit(&strm) != Z_OK) return false;
    int ret = inflate(&strm, Z_FINISH);
    if (ret == Z_STREAM_END) {
      inflateEnd(&strm);
      break;
    }
    if (ret != Z_BUF_ERROR) return false;

    // All input consumed?
    iStreamSize = strm.total_out;
    if (strm.avail_in == 0) {
      Log("Stream data incomplete, using as much data as possible");
      break;
    }

    // Larger buffer needed
    StreamData.Grow(CompressedData.getSize());
    iStreamSize = StreamData.getSize();
  }
  StreamData.SetSize(iStreamSize);

  // Parse
  C4Playback Playback;
  Playback.ReadBinary(StreamData);
  LogF("Got %d chunks from stream", Playback.chunks.size());

  // Get first chunk, which must contain the initial
  chunks_t::iterator chunkIter = Playback.chunks.begin();
  if (chunkIter == Playback.chunks.end() || chunkIter->Type != RCT_File)
    return false;

  // Get initial chunk, go over file name
  StdBuf InitialData = *chunkIter->pFileData;
  const char *szInitialFilename = chunkIter->Filename.getData();

  // Put to temporary file and unpack
  char szInitial[_MAX_PATH + 1] = "~initial.tmp";
  MakeTempFilename(szInitial);
  if (!InitialData.SaveToFile(szInitial) || !C4Group_UnpackDirectory(szInitial))
    return false;

  // Load Scenario.txt from Initial
  C4Group Grp;
  C4Scenario Initial;
  if (!Grp.Open(szInitial) || !Initial.Load(Grp) || !Grp.Close()) return false;

  // Copy original scenario
  const char *szOrigin = Initial.Head.Origin.getData();
  char szRecord[_MAX_PATH + 1];
  SCopy(szStream, szRecord, _MAX_PATH);
  if (GetExtension(szRecord)) *(GetExtension(szRecord) - 1) = 0;
  SAppend(".c4s", szRecord, _MAX_PATH);
  LogF("Original scenario is %s, creating %s.", szOrigin, szRecord);
  if (!C4Group_CopyItem(szOrigin, szRecord, false, false)) return false;

  // Merge initial
  if (!Grp.Open(szRecord) || !Grp.Merge(szInitial)) return false;

  // Process other files in stream
  chunkIter->Delete();
  chunkIter = Playback.chunks.erase(chunkIter);
  while (chunkIter != Playback.chunks.end())
    if (chunkIter->Type == RCT_File) {
      LogF("Inserting %s...", chunkIter->Filename.getData());
      StdStrBuf Temp;
      Temp.Copy(chunkIter->Filename);
      MakeTempFilename(&Temp);
      if (!chunkIter->pFileData->SaveToFile(Temp.getData())) return false;
      if (!Grp.Move(Temp.getData(), chunkIter->Filename.getData()))
        return false;
      chunkIter = Playback.chunks.erase(chunkIter);
    } else
      chunkIter++;

  // Write record data
  StdBuf RecordData = Playback.ReWriteBinary();
  if (!Grp.Add(C4CFN_CtrlRec, RecordData, false, true)) return false;

  // Done
  Log("Writing record file...");
  Grp.Close();
  pRecordFile->Copy(szRecord);
  return true;
}
Esempio n. 4
0
BOOL C4UpdatePackage::Execute(C4Group *pGroup) {
    // search target
    C4GroupEx TargetGrp;
    char strTarget[_MAX_PATH];
    SCopy(DestPath, strTarget, _MAX_PATH);
    char *p = strTarget, *lp = strTarget;
    while (p = strchr(p + 1, '\\')) {
        *p = 0;
        if (!*(p + 1)) break;
        if (!SEqual(lp, ".."))
            if (TargetGrp.Open(strTarget)) {
                // packed?
                bool fPacked = TargetGrp.IsPacked();
                // maker check (someone might try to unpack directories w/o asking user)
                if (fPacked)
                    if (!SEqual(TargetGrp.GetMaker(), pGroup->GetMaker())) return FALSE;
                // Close Group
                TargetGrp.Close(TRUE);
                if (fPacked)
                    // Unpack
                    C4Group_UnpackDirectory(strTarget);
            } else {
                // GrpUpdate -> file must exist
                if (GrpUpdate) return FALSE;
                // create dir
                CreateDirectory(strTarget, NULL);
            }
        *p = '\\';
        lp = p + 1;
    }

    // try to open it
    if (!TargetGrp.Open(strTarget, !GrpUpdate)) return FALSE;

    // check if the update is allowed
    if (GrpUpdate) {
        // maker must match
        /*if(!SEqual(TargetGrp.GetMaker(), pGroup->GetMaker())) - now allowing
           updates from different makers
                return FALSE;*/
        // check checksum
        uint32_t iCRC32;
        if (!C4Group_GetFileCRC(TargetGrp.GetFullName().getData(), &iCRC32))
            return FALSE;
        int i = 0;
        for (; i < UpGrpCnt; i++)
            if (iCRC32 == GrpChks1[i]) break;
        if (i >= UpGrpCnt) return FALSE;
    } else {
        // only allow Extra.c4g-Updates
        if (!SEqual2(DestPath, "Extra.c4g")) return FALSE;
    }

    // update children
    char ItemFileName[_MAX_PATH];
    pGroup->ResetSearch();
    while (pGroup->FindNextEntry("*", ItemFileName))
        if (!SEqual(ItemFileName, C4CFN_UpdateCore) &&
                !SEqual(ItemFileName, C4CFN_UpdateEntries))
            DoUpdate(pGroup, &TargetGrp, ItemFileName);

    // do GrpUpdate
    if (GrpUpdate) DoGrpUpdate(pGroup, &TargetGrp);

    // close the group
    TargetGrp.Close(FALSE);

    if (GrpUpdate) {
        // check the result
        uint32_t iResChks;
        if (!C4Group_GetFileCRC(strTarget, &iResChks)) return FALSE;
        if (iResChks != GrpChks2) {
#ifdef UPDATE_DEBUG
            char *pData;
            int iSize;
            CStdFile MyFile;
            MyFile.Load(strTarget, (BYTE **)&pData, &iSize, 0, TRUE);
            MyFile.Create("DiesesDingIstMist.txt", FALSE);
            MyFile.Write(pData, iSize, FALSE);
            MyFile.Close();
#endif
            return FALSE;
        }
    }

    return TRUE;
}