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)); }
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 static void OutputResources(string dir, CacheFileGen3 cf, cache_file_resource_layout_table def) { pages_block.OutputResources(dir, cf, def.Pages); }
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); }
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; }
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); }