Example #1
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 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);
            }