private Tag LoadTag(string path) { int index = LocateTagByID(inverseDictionary[path]); Tag tag = new Tag(tags[index].Type); Bsp bsp = null; string[] stringArray = strings.ToArray(); switch (tags[index].Type) { case StructureBsp: bsp = GetBsp(tags[index].Identifier); map.Position = bsp.BspOffset; tag.ReadData(reader, shared, bsp.Magic - bsp.BspHeaderOffset, dictionary, stringArray, coconuts, globals, path); break; case StructureLightmap: bsp = GetBsp(tags[index].Identifier); map.Position = bsp.LightmapOffset; tag.ReadData(reader, shared, bsp.Magic - bsp.BspHeaderOffset, dictionary, stringArray, coconuts, globals, path); break; default: map.Position = unchecked (tags[index].Offset - magic); tag.ReadData(reader, shared, magic, dictionary, stringArray, coconuts, globals, path); break; } return(tag); }
public byte[] GetTag(string path) { Tag tag = LoadTag(path); TagFile tf = new TagFile(tag.GetTagData(), "Bungie", "Obtained from Halo 2 Xbox.", typeTable.LocateEntryByTypecode(tag.Type).FourCC, "????", "????", Halo2XboxGameDefinition.TagIdentifierStatic); tf.AddAttachment(ExtraTagDataAttachmentName); tf.AddAttachmentRevision(ExtraTagDataAttachmentName, tag.GetExtraData(), 1.0f, CompressionStyle.GZip); return(tf.ToBytes()); }
public void Load(string file) { filename = file; string directory = Path.GetDirectoryName(file) + '\\'; #region open maps shared = new SharedMaps(new FileStream(directory + MainMenu, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), new FileStream(directory + Shared, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), new FileStream(directory + SinglePlayerShared, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)); map = new FileStream(file, FileMode.Open, FileAccess.ReadWrite, FileShare.Read); reader = new BinaryReader(map); writer = new BinaryWriter(map); #endregion #region header and index header = Reinterpret.Memory <MapHeader>(reader.ReadBytes(Marshal.SizeOf(typeof(MapHeader)))); map.Position = header.IndexOffset; index = Reinterpret.Memory <IndexHeader>(reader.ReadBytes(Marshal.SizeOf(typeof(IndexHeader)))); magic = (index.MagicConstant - header.IndexOffset - Marshal.SizeOf(typeof(IndexHeader))) + (header.AllExceptRawLength - header.IndexAndMetaLength - header.IndexLength); // each "TagType" is three dwords map.Position += 12 * index.TagTypeCount; tags = new List <IndexElement>(index.TagCount); for (int i = 0; i < index.TagCount; i++) { tags.Add(Reinterpret.Memory <IndexElement>(reader.ReadBytes(Marshal.SizeOf(typeof(IndexElement))))); } #endregion #region bsps int bspCount = 0; int bspOffset = 0; if (header.HeadSignature == HeadSignature) { map.Position = 528 + unchecked (tags[LocateTagByID(index.ScenarioIdentifier)].Offset - magic); bspCount = reader.ReadInt32(); bspOffset = unchecked (reader.ReadInt32() - magic); bsps = new Bsp[bspCount]; for (int i = 0; i < bspCount; i++) { bsps[i] = new Bsp(); map.Position = bsps[i].LocationInScenario = bspOffset + 68 * i; bsps[i].BspHeaderOffset = reader.ReadInt32(); int totalBspSize = reader.ReadInt32(); bsps[i].Magic = reader.ReadInt32(); map.Position += 8; bsps[i].BspID = reader.ReadInt32(); map.Position += 4; bsps[i].LightmapID = reader.ReadInt32(); /* * HEADER FORMAT * total size * pointer to bsp location * pointer to lightmap location * 'sbsp' */ map.Position = bsps[i].BspHeaderOffset; int inHeaderBspSize = reader.ReadInt32(); int inHeaderBspOffset = reader.ReadInt32(); int lightmapOffset = reader.ReadInt32(); bsps[i].BspOffset = (inHeaderBspOffset - bsps[i].Magic) + bsps[i].BspHeaderOffset; if (bsps[i].LightmapID == -1) { bsps[i].BspSize = inHeaderBspSize; } else { bsps[i].LightmapOffset = unchecked (lightmapOffset - bsps[i].Magic) + bsps[i].BspHeaderOffset; bsps[i].BspSize = bsps[i].LightmapOffset - bsps[i].BspOffset; bsps[i].LightmapSize = totalBspSize - bsps[i].BspSize; } } } #endregion #region strings strings = new List <string>(header.StringIdCount); map.Position = header.StringIdTableOffset; for (int i = 0; i < header.StringIdCount; i++) { strings.Add(String.Empty); while (true) { byte character = reader.ReadByte(); if (character == 0) { break; } else { strings[i] += Convert.ToChar(character); } } } string[] stringArray = strings.ToArray(); #endregion #region names map.Position = header.NameTableOffset; names = new List <string>(header.NameTableCount); dictionary = new Dictionary <int, string>(header.NameTableCount); inverseDictionary = new Dictionary <string, int>(header.NameTableCount); for (int i = 0; i < header.NameTableCount; i++) { names.Add(String.Empty); while (true) { byte character = reader.ReadByte(); if (character == 0) { break; } else { names[i] += Convert.ToChar(character); } } string dictionaryName = names[i] + '.' + Singleton <ClassManager> .Instance.GetClassByID(tags[i].Type).Name; dictionary.Add(tags[i].Identifier, dictionaryName); inverseDictionary.Add(dictionaryName, tags[i].Identifier); } #endregion #region globals and coconuts if (header.HeadSignature == HeadSignature) { map.Position = unchecked (tags[LocateTagByID(index.GlobalsIdentifier)].Offset - magic); globals = new Globals(reader); map.Position = unchecked (tags[index.TagCount - 1].Offset - magic); coconuts = new Coconuts(reader, shared, magic, stringArray); } #endregion #region composition if (header.HeadSignature == HeadSignature) { for (int i = 0; i < index.TagCount; i++) { int result; switch (tags[i].Type) { case Animation: map.Position = unchecked (tags[i].Offset - magic); result = Tag.GetFirstInternalResourceOffset(reader, Animation, magic); if (result != -1) { if (result < animationStart || animationStart == -1) { animationStart = result; } } break; case Decorators: map.Position = unchecked (tags[i].Offset - magic); result = Tag.GetFirstInternalResourceOffset(reader, Decorators, magic); if (result != -1) { if (result < decoratorStart || decoratorStart == -1) { decoratorStart = result; } } break; case ParticleModel: map.Position = unchecked (tags[i].Offset - magic); result = Tag.GetFirstInternalResourceOffset(reader, ParticleModel, magic); if (result != -1) { if (result < particleModelStart || particleModelStart == -1) { particleModelStart = result; } } break; case WeatherSystem: map.Position = unchecked (tags[i].Offset - magic); result = Tag.GetFirstInternalResourceOffset(reader, WeatherSystem, magic); if (result != -1) { if (result < weatherStart || weatherStart == -1) { weatherStart = result; } } break; case RenderModel: map.Position = unchecked (tags[i].Offset - magic); result = Tag.GetFirstInternalResourceOffset(reader, RenderModel, magic); if (result != -1) { if (result < modelStart || modelStart == -1) { modelStart = result; } } break; } } // this is (should be anyways) constant soundStart = Marshal.SizeOf(typeof(MapHeader)); // this is a calculated value bitmapStart = header.CrazyDataOffset + header.CrazyDataSize; for (int i = 0; i < bspCount; i++) { Bsp bsp = bsps[i]; if (bsp.BspOffset < bspMetaStart || bspMetaStart == -1) { bspMetaStart = bsp.BspHeaderOffset; } else if (bsp.LightmapOffset < bspMetaStart || bspMetaStart == -1) { bspMetaStart = bsp.BspHeaderOffset; } int result; if (bsp.BspID != -1) { reader.BaseStream.Position = bsp.BspOffset; result = Tag.GetFirstInternalResourceOffset(reader, StructureBsp, bsp.Magic - bsp.BspHeaderOffset); if (result != -1) { if (result < bspRawStart || bspRawStart == -1 && result != -1) { bspRawStart = result; } } } if (bsp.LightmapID != -1) { reader.BaseStream.Position = bsp.LightmapOffset; result = Tag.GetFirstInternalResourceOffset(reader, StructureLightmap, bsp.Magic - bsp.BspHeaderOffset); if (result != -1) { if (result < bspRawStart || bspRawStart == -1) { bspRawStart = result; } } } } foreach (Coconuts.ExtraInfo extraInfo in coconuts.ExtraInfos) { if (extraInfo.ResourceBlock.RawSize > 0) { uint encoded = Conversion.ToUInt(extraInfo.ResourceBlock.RawOffset); if ((encoded & 0xc0000000) == 0) { if (extraInfo.ResourceBlock.RawOffset < coconutsModelStart || coconutsModelStart == -1) { coconutsModelStart = extraInfo.ResourceBlock.RawOffset; } } } } if (bspMetaStart < 0) { bspMetaStart = header.StringIdPaddedOffset; } if (animationStart < 0) { animationStart = bspMetaStart; } if (coconutsModelStart < 0) { coconutsModelStart = animationStart; } if (particleModelStart < 0) { particleModelStart = coconutsModelStart; } if (decoratorStart < 0) { decoratorStart = particleModelStart; } if (weatherStart < 0) { weatherStart = decoratorStart; } if (bspRawStart < 0) { bspRawStart = weatherStart; } if (modelStart < 0) { modelStart = bspRawStart; } // these are all duplicates stringPaddedStart = header.StringIdPaddedOffset; stringIndexStart = header.StringIdIndexOffset; stringTableStart = header.StringIdTableOffset; nameTableStart = header.NameTableOffset; nameIndexStart = header.NameIndexOffset; crazyStart = header.CrazyDataOffset; // this can be calculated a multitude of ways unicodeStart = header.NameIndexOffset + header.NameTableCount * sizeof(int); } #endregion valid = true; }