/// <summary> /// Adds raw, pre-compressed resource data to a cache. /// </summary> /// <param name="resource">The resource reference to initialize.</param> /// <param name="location">The location where the resource should be stored.</param> /// <param name="data">The pre-compressed data to store.</param> public void AddRaw(ResourceReference resource, ResourceLocation location, byte[] data) { if (resource == null) throw new ArgumentNullException("resource"); resource.ChangeLocation(location); resource.DisableChecksum(); var cache = GetCache(resource); using (var stream = cache.File.Open(FileMode.Open, FileAccess.ReadWrite)) resource.Index = cache.Cache.AddRaw(stream, data); }
/// <summary> /// Extracts and decompresses the data for a resource. /// </summary> /// <param name="resource">The resource.</param> /// <param name="outStream">The stream to write the extracted data to.</param> /// <exception cref="System.ArgumentException">Thrown if the output stream is not open for writing.</exception> /// <exception cref="System.InvalidOperationException">Thrown if the file containing the resource has not been loaded.</exception> public void Extract(ResourceReference resource, Stream outStream) { if (resource == null) throw new ArgumentNullException("resource"); if (!outStream.CanWrite) throw new ArgumentException("The output stream is not open for writing", "outStream"); var cache = GetCache(resource); using (var stream = cache.File.OpenRead()) cache.Cache.Decompress(stream, resource.Index, resource.CompressedSize, outStream); }
/// <summary> /// Adds a new resource to a cache. /// </summary> /// <param name="resource">The resource reference to initialize.</param> /// <param name="location">The location where the resource should be stored.</param> /// <param name="dataStream">The stream to read the resource data from.</param> /// <exception cref="System.ArgumentNullException">resource</exception> /// <exception cref="System.ArgumentException">The input stream is not open for reading;dataStream</exception> public void Add(ResourceReference resource, ResourceLocation location, Stream dataStream) { if (resource == null) throw new ArgumentNullException("resource"); if (!dataStream.CanRead) throw new ArgumentException("The input stream is not open for reading", "dataStream"); resource.ChangeLocation(location); var cache = GetCache(resource); using (var stream = cache.File.Open(FileMode.Open, FileAccess.ReadWrite)) { var dataSize = (int)(dataStream.Length - dataStream.Position); var data = new byte[dataSize]; dataStream.Read(data, 0, dataSize); uint compressedSize; resource.Index = cache.Cache.Add(stream, data, out compressedSize); resource.CompressedSize = compressedSize; resource.DecompressedSize = (uint)dataSize; resource.DisableChecksum(); } }
public void InjectDds(TagSerializer serializer, TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream ddsStream) { var resource = bitmap.Resources[imageIndex].Resource; var newResource = (resource == null); ResourceSerializationContext resourceContext; BitmapTextureResourceDefinition definition; if (newResource) { // Create a new resource reference resource = new ResourceReference { DefinitionFixups = new List<ResourceDefinitionFixup>(), D3DObjectFixups = new List<D3DObjectFixup>(), Type = 1, // TODO: Map out this type enum instead of using numbers Unknown68 = 1 }; bitmap.Resources[imageIndex].Resource = resource; resourceContext = new ResourceSerializationContext(resource); definition = new BitmapTextureResourceDefinition { Texture = new D3DPointer<BitmapTextureResourceDefinition.BitmapDefinition> { Definition = new BitmapTextureResourceDefinition.BitmapDefinition() } }; } else { // Deserialize the old definition resourceContext = new ResourceSerializationContext(resource); definition = deserializer.Deserialize<BitmapTextureResourceDefinition>(resourceContext); } if (definition.Texture == null || definition.Texture.Definition == null) throw new ArgumentException("Invalid bitmap definition"); var texture = definition.Texture.Definition; var imageData = bitmap.Images[imageIndex]; // Read the DDS header and modify the definition to match var dds = DdsHeader.Read(ddsStream); var dataSize = (int)(ddsStream.Length - ddsStream.Position); texture.Data = new ResourceDataReference(dataSize, new ResourceAddress(ResourceAddressType.Resource, 0)); texture.Width = (short)dds.Width; texture.Height = (short)dds.Height; texture.Depth = (sbyte)Math.Max(1, dds.Depth); texture.Levels = (sbyte)Math.Max(1, dds.MipMapCount); texture.Type = BitmapDdsFormatDetection.DetectType(dds); texture.D3DFormatUnused = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2")); texture.Format = BitmapDdsFormatDetection.DetectFormat(dds); // Set flags based on the format switch (texture.Format) { case BitmapFormat.Dxt1: case BitmapFormat.Dxt3: case BitmapFormat.Dxt5: case BitmapFormat.Dxn: texture.Flags = BitmapFlags.Compressed; break; default: texture.Flags = BitmapFlags.None; break; } if ((texture.Width & (texture.Width - 1)) == 0 && (texture.Height & (texture.Height - 1)) == 0) texture.Flags |= BitmapFlags.PowerOfTwoDimensions; // If creating a new image, then add a new resource, otherwise replace the existing one if (newResource) _resourceManager.Add(resource, ResourceLocation.Textures, ddsStream); else _resourceManager.Replace(resource, ddsStream); // Serialize the new resource definition serializer.Serialize(resourceContext, definition); // Modify the image data in the bitmap tag to match the definition imageData.Width = texture.Width; imageData.Height = texture.Height; imageData.Depth = texture.Depth; imageData.Type = texture.Type; imageData.Format = texture.Format; imageData.Flags = texture.Flags; imageData.MipmapCount = (sbyte)(texture.Levels - 1); imageData.DataOffset = texture.Data.Address.Offset; imageData.DataSize = texture.Data.Size; imageData.Unknown15 = texture.Unknown35; }
public ResourceSerializationContext(ResourceReference resource) { _resource = resource; }
private LoadedCache GetCache(ResourceReference resource) { LoadedCache cache; if (!_loadedCaches.TryGetValue(resource.GetLocation(), out cache)) throw new InvalidOperationException("The requested resource is located in " + resource.GetLocation() + ", but the corresponding cache file has not been loaded."); return cache; }
/// <summary> /// Replaces a resource with raw, pre-compressed data. /// </summary> /// <param name="resource">The resource whose data should be replaced. On success, the reference will be adjusted to account for the new data.</param> /// <param name="data">The raw, pre-compressed data to use.</param> public void ReplaceRaw(ResourceReference resource, byte[] data) { if (resource == null) throw new ArgumentNullException("resource"); resource.DisableChecksum(); var cache = GetCache(resource); using (var stream = cache.File.Open(FileMode.Open, FileAccess.ReadWrite)) cache.Cache.ImportRaw(stream, resource.Index, data); }
/// <summary> /// Extracts raw, compressed resource data. /// </summary> /// <param name="resource">The resource.</param> /// <returns>The raw, compressed resource data.</returns> public byte[] ExtractRaw(ResourceReference resource) { if (resource == null) throw new ArgumentNullException("resource"); var cache = GetCache(resource); using (var stream = cache.File.OpenRead()) return cache.Cache.ExtractRaw(stream, resource.Index, resource.CompressedSize); }
public override bool Execute(List<string> args) { if (args.Count != 2) return false; // // Verify the xbox scenario_structure_bsp tag // var bspName = args[0]; var newTagIndex = ArgumentParser.ParseTagIndex(Info, args[1]); CacheFile.IndexItem item = null; Console.WriteLine("Verifying xbox tag..."); foreach (var tag in BlamCache.IndexItems) { if (tag.ClassCode == "sbsp" && tag.Filename == bspName) { item = tag; break; } } if (item == null) { Console.WriteLine("Xbox tag does not exist: " + args[0]); return false; } // // Load the xbox scenario_structure_bsp tag // var xboxContext = new XboxSerializationContext(item); var deserializer = new TagDeserializer(BlamCache.Version); var sbsp = deserializer.Deserialize<ScenarioStructureBsp>(xboxContext); // blank resources that will be generated/converted from ODST automatically later var Resource1 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // render geo 1 var Resource2 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // render geo 2 var Resource3 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // collision BSP tag data var Resource4 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // other tag data and shit (unknown raw 3rd in halo 3, etc.) // Set the resource refs in the tag to the blank ones we just made sbsp.Geometry.Resource = Resource1; sbsp.Geometry2.Resource = Resource2; sbsp.CollisionBSPResource = Resource3; sbsp.Resource4 = Resource4; using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite)) { Console.WriteLine("Writing ElDewrito tag to tag " + newTagIndex+"..."); var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Info.Cache.Tags[newTagIndex.Index]); Info.Serializer.Serialize(context, sbsp); } return true; }