/// <summary> /// This will iterate through each of the superbundles and get the information that is needed for Rime to operate /// </summary> /// <param name="p_BaseLayout">The base layout</param> /// <param name="p_AuthoritativeLayout">The authoritative layout</param> /// <returns></returns> protected SuperbundleBase CollectSuperbundleData(SuperbundleLayout p_BaseLayout, SuperbundleLayout p_AuthoritativeLayout) { SuperbundleBase s_Superbundle = null; // If we are only parsing a base game, with no authoritative (patch) data if (p_AuthoritativeLayout == null) { // Create an instance of a Superbundle, passing p_BaseLayout for the layout. // Within the superbundle create new Dictionary's for BundleEntries, and ChunkEntries. s_Superbundle = new Superbundle(p_BaseLayout) { BundleEntries = new System.Collections.Concurrent.ConcurrentDictionary <string, BundleEntry>(), ChunkEntries = new System.Collections.Concurrent.ConcurrentDictionary <RimeLib.Frostbite.Core.GUID, ChunkEntry>() }; return(s_Superbundle); } // This Superbundle has an authoritative version. // Collect chunks and bundles in order to be able to // properly delegate authoritative reading. s_Superbundle = new Superbundle(p_BaseLayout, p_AuthoritativeLayout) { BundleEntries = CollectSuperbundleBundles(p_BaseLayout, p_AuthoritativeLayout), ChunkEntries = CollectSuperbundleChunks(p_BaseLayout, p_AuthoritativeLayout) }; return(s_Superbundle); }
/// <summary> /// Helper function to mount a base bundle /// </summary> /// <param name="p_Superbundle">Superbundle to get bundles from</param> /// <param name="p_BundleEntry">The bundle entry information</param> /// <param name="p_BaseReader">The reader of the base file</param> /// <param name="p_PatchReader">The reader of the patch file</param> /// <returns>Loaded BundleBase object</returns> private BundleBase MountBundle(SuperbundleBase p_Superbundle, BundleEntry p_BundleEntry, RimeReader p_BaseReader, RimeReader p_PatchReader) { p_BaseReader.Seek(p_BundleEntry.Offset, SeekOrigin.Begin); var s_Manifest = new BundleManifest(p_BaseReader, p_BundleEntry); var s_Bundle = s_Manifest.RealManifest.Bundle; p_Superbundle.Bundles.TryAdd(p_BundleEntry.ID, s_Bundle); return(s_Bundle); }
/// <summary> /// Mounts a content addressable storage bundle /// </summary> /// <param name="p_Superbundle">Superbundle to get bundles from</param> /// <param name="p_BundleEntry">The bundle entry information</param> /// <param name="p_BaseReader">The reader of the base file</param> /// <param name="p_PatchReader">The reader of the patch file</param> /// <returns>Loaded BundleBase object</returns> private BundleBase MountCASBundle(SuperbundleBase p_Superbundle, BundleEntry p_BundleEntry, RimeReader p_BaseReader, RimeReader p_PatchReader) { p_BaseReader.Seek(p_BundleEntry.Offset, SeekOrigin.Begin); var s_Object = new DbObject(p_BaseReader, p_BundleEntry.Size); var s_Bundle = new Bundle(s_Object[0].Value as DbObject, p_BundleEntry); p_Superbundle.Bundles.TryAdd(p_BundleEntry.ID, s_Bundle); return(s_Bundle); }
/// <summary> /// Discovers the bundles within a superbundle /// </summary> /// <param name="p_Superbundle"></param> public override void DiscoverBundles(SuperbundleBase p_Superbundle) { foreach (var s_Bundle in p_Superbundle.BundleEntries) { var s_Entry = new InternalBundleEntry { BundleEntry = s_Bundle.Value, SuperbundleBase = p_Superbundle, Mounted = false }; m_Bundles.AddOrUpdate(s_Bundle.Key, s_Entry, (k, v) => s_Entry); } }
/// <summary> /// Mounts the loaded superbundle to the virtual file system /// </summary> /// <param name="p_Superbundle"></param> protected void MountSuperbundle(SuperbundleBase p_Superbundle) { MessageManager.SendMessageAsync(new LogWriteMessage { LogLevel = LogsLevel.Info, Message = $"Mounting superbundle '{p_Superbundle.Name}'..." }); // Mount superbundle to the VFS FileSystem.Mount("/sb", p_Superbundle); // Mount all of the chunks to the chunk VFS foreach (var l_Chunk in p_Superbundle.ChunkEntries) { FileSystem.Mount("/chunks", l_Chunk.Value); } MessageManager.SendMessage(new SuperbundleMountedMessage { Superbundle = p_Superbundle }); }
/// <summary> /// Helper function to mount patched bundles /// </summary> /// <param name="p_Superbundle">Superbundle to get bundles from</param> /// <param name="p_BundleEntry">The bundle entry information</param> /// <param name="p_BaseReader">The reader of the base file</param> /// <param name="p_PatchReader">The reader of the patch file</param> /// <returns>BundleBase object</returns> private BundleBase MountPatchedDeltaBundle(SuperbundleBase p_Superbundle, BundleEntry p_BundleEntry, RimeReader p_BaseReader, RimeReader p_PatchReader) { throw new NotImplementedException("Patch files for Frostbite 2013.2 not supported."); }
/// <summary> /// This mounts all bundles that have not been mounted already /// </summary> /// <param name="p_Superbundle">Superbundle to load all bundles that are contained within</param> public override void MountBundles(SuperbundleBase p_Superbundle) { var s_Endianness = p_Superbundle.BaseLayout.Cas ? Endianness.LittleEndian : Endianness.BigEndian; RimeReader s_BaseReader; if (!FileSystem.OpenFileRead(p_Superbundle.BasePath + ".sb", out s_BaseReader, s_Endianness)) { return; } RimeReader s_PatchReader = null; if (p_Superbundle.PatchPath != null && !FileSystem.OpenFileRead(p_Superbundle.PatchPath + ".sb", out s_PatchReader, s_Endianness)) { s_BaseReader.Dispose(); return; } foreach (var s_Bundle in p_Superbundle.BundleEntries) { MessageManager.SendMessageAsync(new LogWriteMessage { LogLevel = LogsLevel.Info, Message = $"Mounting superbundle '{p_Superbundle.Name}' bundle [{s_Bundle.Key}]..." }); BundleBase s_MountedBundle; if (p_Superbundle.AuthoritativeLayout != null && s_Bundle.Value.BaseSuperbundle.Cas) { s_MountedBundle = MountPatchedCASBundle(p_Superbundle, s_Bundle.Value, s_BaseReader, s_PatchReader); } else if (s_Bundle.Value.DeltaEntry != null && s_Bundle.Value.DeltaEntry.Delta) { s_MountedBundle = MountPatchedDeltaBundle(p_Superbundle, s_Bundle.Value, s_BaseReader, s_PatchReader); } else if (s_Bundle.Value.DeltaEntry != null) { s_MountedBundle = MountPatchedBundle(p_Superbundle, s_Bundle.Value, s_BaseReader, s_PatchReader); } else if (s_Bundle.Value.BaseSuperbundle.Cas) { s_MountedBundle = MountCASBundle(p_Superbundle, s_Bundle.Value, s_BaseReader, s_PatchReader); } else { s_MountedBundle = MountBundle(p_Superbundle, s_Bundle.Value, s_BaseReader, s_PatchReader); } // VFS if (s_MountedBundle == null) { return; } MountBundleToVFS(s_MountedBundle); } s_BaseReader.Dispose(); s_PatchReader?.Dispose(); MessageManager.SendMessage(new SuperbundleBundlesMountedMessage { SuperbundleBase = p_Superbundle }); MessageManager.SendMessageAsync(new LogWriteMessage { LogLevel = LogsLevel.Info, Message = $"Finished mounting superbundle '{p_Superbundle.Name}' bundles!" }); }