public static void Output(StreamWriter s, cache_file_resource_layout_table def)
 {
     compression_codec_block.Output(s, def.CompressionCodecs);
     shared_cache_block.Output(s, def.SharedCaches);
     pages_block.Output(s, def.Pages);
     cache_file_resource_layout_table_24_block.Output(s, def.Block24);
     page_segment_block.Output(s, def.PageSegments);
 }
        public TI.Definition LoadResources(DatumIndex resource, CacheFileGen3 c, cache_file_resource_layout_table cache_layout, bool mega_hack)
        {
            if (resource == DatumIndex.Null || c == null || cache_layout == null ||
                resource.Index < 0 || resource.Index > TagResources.Count)
            {
                return(null);
            }

            return(TagResources[resource.Index].LoadResources(c, this, cache_layout, mega_hack));
        }
示例#3
0
			internal byte[] GetSegmentData(CacheFileGen3 cf, cache_file_resource_layout_table owner, int segment_offset)
			{
				if (PageData == null)
				{
					#region shared cache handling
					if (SharedCache.Value != -1) return null;
					if (SharedCache.Value > -1) // above stmt disables this code for now
					{
						shared_cache_block scb = owner.SharedCaches[SharedCache.Value];
						bool is_internal;
						var scf = Program.GetManager(cf.EngineVersion).GetCacheFileFromLocation(cf.EngineVersion, scb.CachePath.Value, out is_internal) 
							as CacheFileGen3;
						if (!is_internal) cf = scf;
						// if it says its internal, the shared cache file wasn't loaded
						else throw new Debug.Exceptions.UnreachableException();
					}
					#endregion

					// If the page is valid, figure out the decompression size
					int size = BlockSizeUncompressed.Value;
					if (size <= 0) return null;

					#region Perform codec operations
					uint base_offset = (uint)(cf.Header as CacheHeaderGen3).Interop[Blam.CacheSectionType.Resource].CacheOffset;
					uint offset = base_offset + (uint)BlockOffset.Value;
					cf.InputStream.Seek(offset);
					if (CompressionCodec.Value != -1)
					{
						// TODO: we would need to test the GUID here if\when bungie adds
						// more compression codecs. Since deflation and no-codec are the 
						// only things they do use, we can just assume for now.
						using (var deflate = new System.IO.Compression.DeflateStream(cf.InputStream.BaseStream, System.IO.Compression.CompressionMode.Decompress, true))
						{
							PageData = new byte[size];
							deflate.Read(PageData, 0, PageData.Length);
						}
					}
					// No codec used, plain data
					else PageData = cf.InputStream.ReadBytes(size);
					#endregion
				}

				int segment_size = GetSegmentSize(segment_offset);
				if (segment_size == -1) return null; // offset was either invalid or sizes haven't been post-processed

				byte[] segment_data = new byte[segment_size];
				// Extract the segment data from the page
				Array.Copy(PageData, segment_offset, segment_data, 0, segment_data.Length);

				return segment_data;
			}
示例#4
0
		public static void OutputResources(string dir, CacheFileGen3 cf, cache_file_resource_layout_table def)
		{
			pages_block.OutputResources(dir, cf, def.Pages);
		}
示例#5
0
		public static void Output(StreamWriter s, cache_file_resource_layout_table def)
		{
			compression_codec_block.Output(s, def.CompressionCodecs);
			shared_cache_block.Output(s, def.SharedCaches);
			pages_block.Output(s, def.Pages);
			cache_file_resource_layout_table_24_block.Output(s, def.Block24);
			page_segment_block.Output(s, def.PageSegments);
		}
 public static void OutputResources(string dir, CacheFileGen3 cf, cache_file_resource_layout_table def)
 {
     pages_block.OutputResources(dir, cf, def.Pages);
 }
示例#7
0
		public TI.Definition LoadResources(DatumIndex resource, CacheFileGen3 c, cache_file_resource_layout_table cache_layout, bool mega_hack)
		{
			if (resource == DatumIndex.Null || c == null || cache_layout == null ||
				resource.Index < 0 || resource.Index > TagResources.Count)
				return null;

			return TagResources[resource.Index].LoadResources(c, this, cache_layout, mega_hack);
		}
示例#8
0
		public TI.Definition LoadResources(DatumIndex resource, CacheFileGen3 c, cache_file_resource_layout_table cache_layout)
		{
			return LoadResources(resource, c, cache_layout, false);
		}
示例#9
0
			internal TI.Definition LoadResources(CacheFileGen3 c, cache_file_resource_gestalt_group owner, cache_file_resource_layout_table cache_layout, bool mega_hack)
			{
				if (Reference.Datum == DatumIndex.Null) return null; // this is a null entry
				if (loadedResources != null) return loadedResources; // data already loaded, return

				var rdf = c.GetCacheFileResourceDefinitionFactory();

				// pre-process cache for resource loading
				cache_layout.BuildInteropData();
				owner.BuildInteropData();

				int resource_stream_definition_size = BlockSize.Value;
				
				// sound resource case hack
				bool use_sound_resource_hack = false;
				if (resource_stream_definition_size == 0)
				{
					Debug.Assert.If(ResourceType.Value == owner.resource_index_sound_resource_definition);
					resource_stream_definition_size = sound_resource_definition.kSizeOf;
					use_sound_resource_hack = true;
				}

				int resource_stream_size_required = resource_stream_definition_size;
				// base address to use on cache fixups, cache data will be appended 
				// later on
				uint cache_required_base_address = 0, cache_optional_base_address = 0;
				byte[] resource_stream_data;

				#region create resource buffer
				{// Get our page segment data so we can build our resource buffer for loading
					int seg_index = SegmentIndex.Value;
					cache_file_resource_layout_table.page_segment_block page_segment = cache_layout.PageSegments[seg_index];
					int required_size = page_segment.GetRequiredSize();
					int optional_size = page_segment.GetOptionalSize();

					cache_required_base_address = (uint)resource_stream_size_required;
					if (required_size > 0) resource_stream_size_required += required_size;

					if (optional_size > 0) // optional isn't always used so don't set the base address if it isn't
					{
						cache_optional_base_address = (uint)resource_stream_size_required;
						resource_stream_size_required += optional_size;
					}

					// get our definition data buffer
					resource_stream_data = new byte[resource_stream_size_required];
					if (use_sound_resource_hack) // sound_resources don't occupy space in the resource-definition-data, so we have to create faux def data
					{
						int data_size = 0;
						if (required_size > 0) data_size += required_size;
						if (optional_size > 0) data_size += optional_size;
						if (data_size > 0) rdf.InsertDataSizeIntoFauxDefinitionData(resource_stream_data, (uint)data_size);
					}
					else
						Array.Copy(owner.ResourceDefinitionData.Value, BlockOffset.Value, resource_stream_data, 0, resource_stream_definition_size);

					{ // get cache data and append it
						byte[] page_data = 
							cache_layout.Pages[page_segment.RequiredPageIndex.Value].GetSegmentData(c, cache_layout, page_segment.RequiredSegmentOffset.Value);

						Array.Copy(page_data, 0, resource_stream_data, (int)cache_required_base_address, required_size);

						if (page_segment.OptionalPageIndex.Value >=0 && cache_optional_base_address > 0)
						{
							page_data = cache_layout.Pages[page_segment.OptionalPageIndex.Value].GetSegmentData(c, cache_layout, page_segment.OptionalSegmentOffset.Value);
							Array.Copy(page_data, 0, resource_stream_data, (int)cache_optional_base_address, optional_size);
						}
					}
				}
				#endregion

				Util.OptionalValue optv = new Util.OptionalValue((byte)resource_fixup_type.Count);

				#region perform fixups
				using (var ms = new System.IO.MemoryStream(resource_stream_data, true))
				{
					foreach (resource_fixup_block def in ResourceFixups)
					{
						uint address = (uint)def.Address.Value;
						uint address_offset = optv.GetValue(address);
						ms.Seek(def.BlockOffset.Value, System.IO.SeekOrigin.Begin);
						resource_fixup_type rft = (resource_fixup_type)optv.GetOption(address);

						switch (rft)
						{
							case resource_fixup_type.Data: break;
							case resource_fixup_type.CacheRequired: address_offset += cache_required_base_address; break;
							case resource_fixup_type.CacheOptional: address_offset += cache_optional_base_address; break;

							default: throw new Debug.Exceptions.UnreachableException();
						}

						IO.ByteSwap.SwapUDWordAndWrite(address_offset, ms);
						
						// hack identifier for StructReference fields when the definition is at offset '0' 
						// as that f***s with the init code
						//if (address_offset == 0) IO.ByteSwap.SwapUDWordAndWrite(1, ms);
					}

//					foreach (resource_definition_fixup_block def in ResourceDefinitionFixups)
//					{
//					}
				}
				#endregion

				#region create and stream definition
				using (var s = new IO.EndianReader(resource_stream_data, IO.EndianState.Big, null))
				{
					int res_type = ResourceType.Value;
					if (res_type == owner.resource_index_render_geometry_api_resource_definition)			loadedResources = rdf.GenerateRenderGeometryApiResource();
					else if (res_type == owner.resource_index_bitmap_texture_interop_resource)				loadedResources = rdf.GenerateBitmapTextureInteropResource();
					else if (res_type == owner.resource_index_model_animation_tag_resource)					loadedResources = rdf.GenerateModelAnimationTagResource();
					// TODO: haven't quite figured this one out yet. Currently using hacked up code (see [use_sound_resource_hack])
					else if (res_type == owner.resource_index_sound_resource_definition)					loadedResources = rdf.GenerateSoundResourceResource();
					else if (res_type == owner.resource_index_bitmap_texture_interleaved_interop_resource)	loadedResources = rdf.GenerateBitmapTextureInterleavedInteropResource();
					else if (res_type == owner.resource_index_structure_bsp_tag_resources)					loadedResources = rdf.GenerateStructureBspTagResource();
					// TODO: haven't figured this one out yet
					else if (res_type == owner.resource_index_structure_bsp_cache_file_tag_resources)		loadedResources = rdf.GenerateStructureBspCacheFileTagResource();
					else throw new Debug.Exceptions.UnreachableException();

					s.Seek(optv.GetValue((uint)DefinitionOffset.Value));
					IO.ITagStream ts = new resource_tag_stream(c, Reference.Datum, s);

					ts.Flags.Add(
						IO.ITagStreamFlags.UseStreamPositions |
						IO.ITagStreamFlags.DontStreamStringData |
						IO.ITagStreamFlags.DontStreamFieldSetHeader |
						IO.ITagStreamFlags.DontPostprocess);
					if (mega_hack) ts.Flags.Add(IO.ITagStreamFlags.Halo3VertexBufferMegaHack);
					loadedResources.Read(ts);
				}
				#endregion

				return loadedResources;
			}
            internal byte[] GetSegmentData(CacheFileGen3 cf, cache_file_resource_layout_table owner, int segment_offset)
            {
                if (PageData == null)
                {
                    #region shared cache handling
                    if (SharedCache.Value != -1)
                    {
                        return(null);
                    }
                    if (SharedCache.Value > -1)                     // above stmt disables this code for now
                    {
                        shared_cache_block scb = owner.SharedCaches[SharedCache.Value];
                        bool is_internal;
                        var  scf = Program.GetManager(cf.EngineVersion).GetCacheFileFromLocation(cf.EngineVersion, scb.CachePath.Value, out is_internal)
                                   as CacheFileGen3;
                        if (!is_internal)
                        {
                            cf = scf;
                        }
                        // if it says its internal, the shared cache file wasn't loaded
                        else
                        {
                            throw new Debug.Exceptions.UnreachableException();
                        }
                    }
                    #endregion

                    // If the page is valid, figure out the decompression size
                    int size = BlockSizeUncompressed.Value;
                    if (size <= 0)
                    {
                        return(null);
                    }

                    #region Perform codec operations
                    uint base_offset = (uint)(cf.Header as CacheHeaderGen3).Interop[Blam.CacheSectionType.Resource].CacheOffset;
                    uint offset      = base_offset + (uint)BlockOffset.Value;
                    cf.InputStream.Seek(offset);
                    if (CompressionCodec.Value != -1)
                    {
                        // TODO: we would need to test the GUID here if\when bungie adds
                        // more compression codecs. Since deflation and no-codec are the
                        // only things they do use, we can just assume for now.
                        using (var deflate = new System.IO.Compression.DeflateStream(cf.InputStream.BaseStream, System.IO.Compression.CompressionMode.Decompress, true))
                        {
                            PageData = new byte[size];
                            deflate.Read(PageData, 0, PageData.Length);
                        }
                    }
                    // No codec used, plain data
                    else
                    {
                        PageData = cf.InputStream.ReadBytes(size);
                    }
                    #endregion
                }

                int segment_size = GetSegmentSize(segment_offset);
                if (segment_size == -1)
                {
                    return(null);                                    // offset was either invalid or sizes haven't been post-processed
                }
                byte[] segment_data = new byte[segment_size];
                // Extract the segment data from the page
                Array.Copy(PageData, segment_offset, segment_data, 0, segment_data.Length);

                return(segment_data);
            }
 public TI.Definition LoadResources(DatumIndex resource, CacheFileGen3 c, cache_file_resource_layout_table cache_layout)
 {
     return(LoadResources(resource, c, cache_layout, false));
 }
            internal TI.Definition LoadResources(CacheFileGen3 c, cache_file_resource_gestalt_group owner, cache_file_resource_layout_table cache_layout, bool mega_hack)
            {
                if (Reference.Datum == DatumIndex.Null)
                {
                    return(null);                                                    // this is a null entry
                }
                if (loadedResources != null)
                {
                    return(loadedResources);                                         // data already loaded, return
                }
                var rdf = c.GetCacheFileResourceDefinitionFactory();

                // pre-process cache for resource loading
                cache_layout.BuildInteropData();
                owner.BuildInteropData();

                int resource_stream_definition_size = BlockSize.Value;

                // sound resource case hack
                bool use_sound_resource_hack = false;

                if (resource_stream_definition_size == 0)
                {
                    Debug.Assert.If(ResourceType.Value == owner.resource_index_sound_resource_definition);
                    resource_stream_definition_size = sound_resource_definition.kSizeOf;
                    use_sound_resource_hack         = true;
                }

                int resource_stream_size_required = resource_stream_definition_size;
                // base address to use on cache fixups, cache data will be appended
                // later on
                uint cache_required_base_address = 0, cache_optional_base_address = 0;

                byte[] resource_stream_data;

                #region create resource buffer
                {                // Get our page segment data so we can build our resource buffer for loading
                    int seg_index = SegmentIndex.Value;
                    cache_file_resource_layout_table.page_segment_block page_segment = cache_layout.PageSegments[seg_index];
                    int required_size = page_segment.GetRequiredSize();
                    int optional_size = page_segment.GetOptionalSize();

                    cache_required_base_address = (uint)resource_stream_size_required;
                    if (required_size > 0)
                    {
                        resource_stream_size_required += required_size;
                    }

                    if (optional_size > 0)                     // optional isn't always used so don't set the base address if it isn't
                    {
                        cache_optional_base_address    = (uint)resource_stream_size_required;
                        resource_stream_size_required += optional_size;
                    }

                    // get our definition data buffer
                    resource_stream_data = new byte[resource_stream_size_required];
                    if (use_sound_resource_hack)                     // sound_resources don't occupy space in the resource-definition-data, so we have to create faux def data
                    {
                        int data_size = 0;
                        if (required_size > 0)
                        {
                            data_size += required_size;
                        }
                        if (optional_size > 0)
                        {
                            data_size += optional_size;
                        }
                        if (data_size > 0)
                        {
                            rdf.InsertDataSizeIntoFauxDefinitionData(resource_stream_data, (uint)data_size);
                        }
                    }
                    else
                    {
                        Array.Copy(owner.ResourceDefinitionData.Value, BlockOffset.Value, resource_stream_data, 0, resource_stream_definition_size);
                    }

                    {                     // get cache data and append it
                        byte[] page_data =
                            cache_layout.Pages[page_segment.RequiredPageIndex.Value].GetSegmentData(c, cache_layout, page_segment.RequiredSegmentOffset.Value);

                        Array.Copy(page_data, 0, resource_stream_data, (int)cache_required_base_address, required_size);

                        if (page_segment.OptionalPageIndex.Value >= 0 && cache_optional_base_address > 0)
                        {
                            page_data = cache_layout.Pages[page_segment.OptionalPageIndex.Value].GetSegmentData(c, cache_layout, page_segment.OptionalSegmentOffset.Value);
                            Array.Copy(page_data, 0, resource_stream_data, (int)cache_optional_base_address, optional_size);
                        }
                    }
                }
                #endregion

                Util.OptionalValue optv = new Util.OptionalValue((byte)resource_fixup_type.Count);

                #region perform fixups
                using (var ms = new System.IO.MemoryStream(resource_stream_data, true))
                {
                    foreach (resource_fixup_block def in ResourceFixups)
                    {
                        uint address        = (uint)def.Address.Value;
                        uint address_offset = optv.GetValue(address);
                        ms.Seek(def.BlockOffset.Value, System.IO.SeekOrigin.Begin);
                        resource_fixup_type rft = (resource_fixup_type)optv.GetOption(address);

                        switch (rft)
                        {
                        case resource_fixup_type.Data: break;

                        case resource_fixup_type.CacheRequired: address_offset += cache_required_base_address; break;

                        case resource_fixup_type.CacheOptional: address_offset += cache_optional_base_address; break;

                        default: throw new Debug.Exceptions.UnreachableException();
                        }

                        IO.ByteSwap.SwapUDWordAndWrite(address_offset, ms);

                        // hack identifier for StructReference fields when the definition is at offset '0'
                        // as that f***s with the init code
                        //if (address_offset == 0) IO.ByteSwap.SwapUDWordAndWrite(1, ms);
                    }

//					foreach (resource_definition_fixup_block def in ResourceDefinitionFixups)
//					{
//					}
                }
                #endregion

                #region create and stream definition
                using (var s = new IO.EndianReader(resource_stream_data, IO.EndianState.Big, null))
                {
                    int res_type = ResourceType.Value;
                    if (res_type == owner.resource_index_render_geometry_api_resource_definition)
                    {
                        loadedResources = rdf.GenerateRenderGeometryApiResource();
                    }
                    else if (res_type == owner.resource_index_bitmap_texture_interop_resource)
                    {
                        loadedResources = rdf.GenerateBitmapTextureInteropResource();
                    }
                    else if (res_type == owner.resource_index_model_animation_tag_resource)
                    {
                        loadedResources = rdf.GenerateModelAnimationTagResource();
                    }
                    // TODO: haven't quite figured this one out yet. Currently using hacked up code (see [use_sound_resource_hack])
                    else if (res_type == owner.resource_index_sound_resource_definition)
                    {
                        loadedResources = rdf.GenerateSoundResourceResource();
                    }
                    else if (res_type == owner.resource_index_bitmap_texture_interleaved_interop_resource)
                    {
                        loadedResources = rdf.GenerateBitmapTextureInterleavedInteropResource();
                    }
                    else if (res_type == owner.resource_index_structure_bsp_tag_resources)
                    {
                        loadedResources = rdf.GenerateStructureBspTagResource();
                    }
                    // TODO: haven't figured this one out yet
                    else if (res_type == owner.resource_index_structure_bsp_cache_file_tag_resources)
                    {
                        loadedResources = rdf.GenerateStructureBspCacheFileTagResource();
                    }
                    else
                    {
                        throw new Debug.Exceptions.UnreachableException();
                    }

                    s.Seek(optv.GetValue((uint)DefinitionOffset.Value));
                    IO.ITagStream ts = new resource_tag_stream(c, Reference.Datum, s);

                    ts.Flags.Add(
                        IO.ITagStreamFlags.UseStreamPositions |
                        IO.ITagStreamFlags.DontStreamStringData |
                        IO.ITagStreamFlags.DontStreamFieldSetHeader |
                        IO.ITagStreamFlags.DontPostprocess);
                    if (mega_hack)
                    {
                        ts.Flags.Add(IO.ITagStreamFlags.Halo3VertexBufferMegaHack);
                    }
                    loadedResources.Read(ts);
                }
                #endregion

                return(loadedResources);
            }