private ResourcePage LoadPage(StructureValueCollection values, int index, ThirdGenCacheFileReference[] externalFiles) { var result = new ResourcePage(); result.Index = index; result.Salt = (ushort)values.GetInteger("salt"); result.Flags = (byte)values.GetInteger("flags"); result.CompressionMethod = ((int)values.GetInteger("compression codec index") != -1) ? ResourcePageCompression.Deflate : ResourcePageCompression.None; // FIXME: hax/laziness var externalFile = (int)values.GetInteger("shared cache file index"); result.FilePath = (externalFile != -1) ? externalFiles[externalFile].Path : null; result.Unknown1 = (int)values.GetIntegerOrDefault("unknown 1", 0); result.Offset = (int)values.GetInteger("compressed block offset"); result.CompressedSize = (int)values.GetInteger("compressed block size"); result.UncompressedSize = (int)values.GetInteger("uncompressed block size"); result.Checksum = values.GetInteger("checksum"); result.Hash1 = values.GetRaw("hash 1"); result.Hash2 = values.GetRaw("hash 2"); result.Hash3 = values.GetRaw("hash 3"); result.Unknown2 = (int)values.GetIntegerOrDefault("unknown 2", 0); result.Unknown3 = (int)values.GetIntegerOrDefault("unknown 3", 0); return(result); }
private void SaveDefinitionFixups(IList <ResourceDefinitionFixup> fixups, StructureValueCollection values, IStream stream, TagBlockCache <ResourceDefinitionFixup> cache) { var oldCount = (int)values.GetIntegerOrDefault("number of definition fixups", 0); uint oldAddress = (uint)values.GetIntegerOrDefault("definition fixup table address", 0); long oldExpand = _expander.Expand(oldAddress); StructureLayout layout = _buildInfo.Layouts.GetLayout("definition fixup element"); long newAddress; if (!cache.TryGetAddress(fixups, out newAddress)) { // Write a new block IEnumerable <StructureValueCollection> entries = fixups.Select(f => SerializeDefinitionFixup(f)); newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, oldExpand, fixups.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, fixups); } else if (oldAddress != 0 && oldCount > 0) { // Block was cached - just free it _allocator.Free(oldExpand, oldCount * layout.Size); } uint cont = _expander.Contract(newAddress); values.SetInteger("number of definition fixups", (uint)fixups.Count); values.SetInteger("definition fixup table address", cont); }
private void SaveDefinitionFixups(IList <ResourceDefinitionFixup> fixups, StructureValueCollection values, IStream stream, ReflexiveCache <ResourceDefinitionFixup> cache) { var oldCount = (int)values.GetIntegerOrDefault("number of definition fixups", 0); uint oldAddress = values.GetIntegerOrDefault("definition fixup table address", 0); StructureLayout layout = _buildInfo.Layouts.GetLayout("definition fixup entry"); uint newAddress; if (!cache.TryGetAddress(fixups, out newAddress)) { // Write a new reflexive IEnumerable <StructureValueCollection> entries = fixups.Select(f => SerializeDefinitionFixup(f)); newAddress = ReflexiveWriter.WriteReflexive(entries, oldCount, oldAddress, fixups.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, fixups); } else if (oldAddress != 0 && oldCount > 0) { // Reflexive was cached - just free it _allocator.Free(oldAddress, oldCount * layout.Size); } values.SetInteger("number of definition fixups", (uint)fixups.Count); values.SetInteger("definition fixup table address", newAddress); }
private void SaveSizeParts(IList <ResourceSizePart> parts, StructureValueCollection values, IStream stream, TagBlockCache <ResourceSizePart> cache) { var oldCount = (int)values.GetIntegerOrDefault("number of size parts", 0); uint oldAddress = (uint)values.GetIntegerOrDefault("size part table address", 0); long expand = _expander.Expand(oldAddress); StructureLayout layout = _buildInfo.Layouts.GetLayout("size part table element"); long newAddress; if (!cache.TryGetAddress(parts, out newAddress)) { // Write a new block IEnumerable <StructureValueCollection> entries = parts.Select(p => SerializeSizePart(p)); newAddress = TagBlockWriter.WriteTagBlock(entries, oldCount, expand, parts.Count, layout, _metaArea, _allocator, stream); cache.Add(newAddress, parts); } else if (oldAddress != 0 && oldCount > 0) { // Block was cached - just free it _allocator.Free(expand, oldCount * layout.Size); } uint cont = _expander.Contract(newAddress); values.SetInteger("number of size parts", (uint)parts.Count); values.SetInteger("size part table address", cont); }
private void Load(StructureValueCollection values, ushort index, StringTableReader stringReader) { Index = new DatumIndex((ushort)values.GetInteger("datum index salt"), index); Opcode = (ushort)values.GetInteger("opcode"); ReturnType = (short)values.GetInteger("value type"); Type = (ScriptExpressionType)values.GetInteger("expression type"); _nextIndex = new DatumIndex(values.GetInteger("next expression index")); _stringTableOffset = (int)values.GetIntegerOrDefault("string table offset", 0); Value = values.GetInteger("value"); LineNumber = (short)values.GetIntegerOrDefault("source line", 0); stringReader.RequestString(_stringTableOffset); }
private void Load(StructureValueCollection values) { Magic = (int)values.GetInteger("magic"); ParentMagic = (int)values.GetInteger("parent magic"); GrandparentMagic = (int)values.GetInteger("grandparent magic"); Description = new StringID(values.GetIntegerOrDefault("stringid", 0)); }
/// <summary> /// Deserializes a bounding box from a set of values read from a structure. /// </summary> /// <param name="values">The values to use.</param> /// <returns>The bounding box.</returns> public static BoundingBox Deserialize(StructureValueCollection values) { var result = new BoundingBox(); result.MinX = values.GetFloat("min x"); result.MaxX = values.GetFloat("max x"); result.MinY = values.GetFloat("min y"); result.MaxY = values.GetFloat("max y"); result.MinZ = values.GetFloat("min z"); result.MaxZ = values.GetFloat("max z"); result.MinU = values.GetFloat("min u"); result.MaxU = values.GetFloat("max u"); result.MinV = values.GetFloat("min v"); result.MaxV = values.GetFloat("max v"); result.Unknown1 = (int)values.GetIntegerOrDefault("unknown 1", 3); result.Unknown2 = (int)values.GetIntegerOrDefault("unknown 2", 0); result.Unknown3 = (int)values.GetIntegerOrDefault("unknown 3", 0); result.Unknown4 = (int)values.GetIntegerOrDefault("unknown 4", 0); return(result); }
public IList <ResourcePointer> SaveResources(ICollection <Resource> resources, IStream stream) { StructureValueCollection values = LoadTag(stream); StructureLayout layout = _buildInfo.Layouts.GetLayout("resource table entry"); FreeResources(values, stream); FreeInfoBuffer(values); // Serialize each resource entry // This can't be lazily evaluated because allocations might cause the stream to expand int infoOffset = 0; int altInfoOffset = 0; var infocache = new ReflexiveCache <int>(); var pointers = new List <ResourcePointer>(); var entries = new List <StructureValueCollection>(); var fixupCache = new ReflexiveCache <ResourceFixup>(); var defFixupCache = new ReflexiveCache <ResourceDefinitionFixup>(); List <byte[]> paddedInfos = new List <byte[]>(); foreach (Resource resource in resources) { StructureValueCollection entry = SerializeResource(resource, (resource.Location != null) ? pointers.Count : -1, stream); entries.Add(entry); // Save fixups SaveResourceFixups(resource.ResourceFixups, entry, stream, fixupCache); SaveDefinitionFixups(resource.DefinitionFixups, entry, stream, defFixupCache); uint bits = (uint)entry.GetInteger("resource bits"); int size = (int)entry.GetInteger("resource info size"); List <int> offsets = new List <int>(); if (size > 0) { int dirtyoffset = infoOffset; infoOffset = AlignInfoBlockOffset(resource, infoOffset); offsets.Add(infoOffset); int padding = infoOffset - dirtyoffset; byte[] temp = new byte[padding + size]; Buffer.BlockCopy(resource.Info, 0, temp, padding, size); paddedInfos.Add(temp); infoOffset += size; } else { offsets.Add(0); } if ((bits & 2) > 0) { int tempalt = AlignInfoBlockOffset(resource, altInfoOffset); offsets.Add(tempalt); altInfoOffset += size; } else { offsets.Add(size > 0 ? -1 : 0); } if ((bits & 4) > 0) { int tempalt = AlignInfoBlockOffset(resource, altInfoOffset); offsets.Add(tempalt); altInfoOffset += size; } else { offsets.Add(size > 0 ? -1 : 0); } if (layout.HasField("number of resource info offsets")) { var oldCount = (int)entry.GetIntegerOrDefault("number of resource info offsets", 0); uint oldAddress = (uint)entry.GetIntegerOrDefault("resource info offsets table address", 0); long expand = _expander.Expand(oldAddress); StructureLayout infolayout = _buildInfo.Layouts.GetLayout("resource info offset entry"); if (size > 0) { long newBlockAddress; // Write a new reflexive IEnumerable <StructureValueCollection> infoentries = offsets.Select(f => SerializeInfos(f)); newBlockAddress = ReflexiveWriter.WriteReflexive(infoentries, oldCount, expand, offsets.Count, infolayout, _metaArea, _allocator, stream); infocache.Add(newBlockAddress, offsets); uint cont = _expander.Contract(newBlockAddress); entry.SetInteger("number of resource info offsets", (uint)offsets.Count); entry.SetInteger("resource info offsets table address", cont); } else { entry.SetInteger("number of resource info offsets", 0); entry.SetInteger("resource info offsets table address", 0); } } else { if (size > 0) { entry.SetInteger("resource info offset", (uint)offsets[0]); entry.SetInteger("alt resource info offset", (uint)offsets[1]); } else { entry.SetInteger("resource info offset", 0); entry.SetInteger("alt resource info offset", 0); } } // Update pointer info if (resource.Location != null) { pointers.Add(resource.Location); } } // Write the reflexive and update the tag values long newAddress = ReflexiveWriter.WriteReflexive(entries, layout, _metaArea, _allocator, stream); uint contr = _expander.Contract(newAddress); values.SetInteger("number of resources", (uint)entries.Count); values.SetInteger("resource table address", contr); // Save the info buffer SaveResourceInfoBuffer(paddedInfos.SelectMany(a => a).ToArray(), values, stream); SaveTag(values, stream); return(pointers); }