/// <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);
        }
Example #9
0
        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;
        }