public TagWrapper(TagBlock tag, MapStream map, Tag meta) { tag_ = tag; /* Enumerate through all the StringIDs in this tag, check to see if they exist in the Globals list, * if not we should add them locally and update the StringID value to point to the list*/ foreach (StringID string_id in tag as IEnumerable<StringID>) { if (Halo2.Strings.Contains(string_id)) continue; else { var string_value = map.Strings[string_id.Index]; var entry = new KeyValuePair<StringID, string>(string_id, string_value); local_strings_.Add(entry); var index = local_strings_.IndexOf(entry); short string_id_index = (short)(index |= 0x8000); sbyte string_length = (sbyte)Encoding.UTF8.GetByteCount(string_value); var bytes = BitConverter.GetBytes((int)new StringID(string_id_index, string_length)); (string_id as IField).SetFieldData(bytes); } } foreach (TagIdentifier tag_id in tag as IEnumerable<TagIdentifier>) { tag_ids_.Add(tag_id); } /*Intent: to build a list of all tagblock addresses in tag */ foreach (var array in tag as IEnumerable<IFieldArray>) { var address = array.Address; if (array.Fields.Count() > 0) { var item = new { Address = address, Size = array.Fields[0].Size, Count = array.Fields.Count() }; tag_blocks.Add(item); if (meta.Contains(item.Address)) { } } } /* Intent: check every tag_block in the list for being external * if it is external build a reference list and add information about the tag_block * to that list. * address => [count, size]? * */ }
//public void SerializeTag(tag_info meta) //{ // string name = Paths[meta.Id.Index]; // TagBlock block = Halo2.CreateInstance(meta.Type); // (block as IPointable).Address = meta.VirtualAddress; // Memory memory = GetTagMemory(meta); // (block as IPointable).Parse(memory); // for (int i = 0; i < memory.instance_table.Count; ++i) // { // if (memory.instance_table[i].external && !memory.instance_table[i].isnull) // { // throw new Exception(":D \n\n\n\n\n"); // } // } // MemoryStream raw_data = new MemoryStream(); // if (meta.Type == (tag_class)"bitm") // { // Bitmap_Collection collection = (Bitmap_Collection)block; // foreach (var bitmap in collection.Bitmaps) // { // var resource = bitmap.get_resource(); // BinaryReader bin_reader = new BinaryReader(this); // bin_reader.BaseStream.Position = resource.offset0; // raw_data.Write(bin_reader.ReadBytes(resource.length0), 0, resource.length0); // } // } // //if (meta.Type == (tag_class)"mode") // //{ // // model collection = (model)block; // // foreach (var bitmap in collection.Sections) // // { // // var resource = bitmap.GetRawPointer(); // // BinaryReader bin_reader = new BinaryReader(this); // // bin_reader.BaseStream.Position = resource.Address; // // raw_data.Write(bin_reader.ReadBytes(resource.Length), 0, resource.Length); // // {//because // // {//f**k you // // Mesh mesh = new Mesh(); // // mesh.Load(raw_data.ToArray(), bitmap.GetSectionResources(), collection.GetBoundingBox().GetCompressionRanges()); // // //mesh.ExportAsWavefront(@"D:\halo_2\wavefront.obj"); // // } // // } // // } // //} // memory = memory.Copy(16);//setup for local // using (FileStream output = File.Create(@"D:\halo_2\shad.bin")) // { // BinaryWriter binary_writer = new BinaryWriter(output); // binary_writer.Write((int)meta.Type); // binary_writer.Write((int)meta.Id); // binary_writer.Write((int)(Padding.GetCount(memory.Length) + memory.Length)); // binary_writer.Write((int)raw_data.Length); // binary_writer.Write(memory.ToArray()); // binary_writer.Write(new byte[Padding.GetCount(output.Position)]); // binary_writer.Write(raw_data.ToArray()); // binary_writer.Write(new byte[Padding.GetCount(output.Position)]); // } //} Memory GetTagMemory(Tag meta) { //BinaryReader bin_reader = new BinaryReader(this); //this.Position = meta.VirtualAddress; //Memory mem = new Memory(bin_reader.ReadBytes(meta.Length), meta.VirtualAddress); //TagBlock block = Halo2.CreateInstance(meta.Type); //mem.instance_table.Add(new Memory.mem_ref() { address = meta.VirtualAddress, client = block, count = 1, external = false, type = block.GetType() }); //(block as IPointable).Address = meta.VirtualAddress; //(block as IPointable).Parse(mem); //return mem; return new Memory (); }
TagBlock GetTag(Tag tag) { TagBlock block = Halo2.CreateInstance(tag.Type); block.SetAddress(tag.VirtualAddress); block.Parse(this); return block; }
public IMap this[TagIdentifier tag_id] { get { if (current_tag.Identifier == tag_id) return this; current_tag = Tags[tag_id.Index]; return this; } }
public IMap this[string tag_class, string tag_name] { get { if (current_tag.Type == (TagClass)tag_class && current_tag.Path.Contains(tag_name)) return this; current_tag = FindFirst((TagClass)tag_class, tag_name); return this; } }
public MapStream(string filename) : base(filename, FileMode.Open, FileAccess.Read, FileShare.Read) { this.MemoryBlocks = new MemoryMappedAddress[2]; //HEADER BinaryReader bin = new BinaryReader(this, Encoding.UTF8); this.Lock(0, 2048); this.Seek(0, SeekOrigin.Begin); if (bin.ReadTagClass() != (TagClass)"head") throw new InvalidDataException("Not a halo-map file"); //this.Seek(36, SeekOrigin.Begin); //var version = bin.ReadInt32(); //switch (version) //{ // case 0: // BuildVersion = Version.XBOX_RETAIL; // break; // case -1: // BuildVersion = Version.PC_RETAIL; // break; // default: //} BuildVersion = Version.PC_RETAIL; this.Seek(16, SeekOrigin.Begin); int indexAddress = bin.ReadInt32(); int indexLength = bin.ReadInt32(); int tagCacheLength = bin.ReadInt32(); if (BuildVersion == Version.PC_RETAIL) this.Seek(12, SeekOrigin.Current); this.Seek(332, SeekOrigin.Current); int stringTableLength = bin.ReadInt32(); this.Seek(4, SeekOrigin.Current); int stringTableAddress = bin.ReadInt32(); this.Seek(36, SeekOrigin.Current); MapName = bin.ReadFixedString(32); this.Seek(4, SeekOrigin.Current); Scenario = bin.ReadFixedString(256); this.Seek(4, SeekOrigin.Current); int pathsCount = bin.ReadInt32(); int pathsTableAddress = bin.ReadInt32(); int pathsTableLength = bin.ReadInt32(); this.Unlock(0, 2048); this.Seek(pathsTableAddress, SeekOrigin.Begin); var Paths = Encoding.UTF8.GetString(bin.ReadBytes(pathsTableLength - 1)).Split(char.MinValue); //STRINGS this.Seek(stringTableAddress, SeekOrigin.Begin); Strings = Encoding.UTF8.GetString(bin.ReadBytes(stringTableLength - 1)).Split(char.MinValue); // INDEX /* * Vista doesn't use memory addresses for the following address-values. (they are instead 0-based from the index-address) * * 0x00 Address to Classes array * 0x04 Classes array length * 0x08 Address to Tags array * 0x0C Scenario tag_id * 0x10 Match-Globals tag_id * 0x14 ~ * 0x18 Tags array length * 0xC0 'sgat' four_cc * * */ this.Seek(indexAddress, SeekOrigin.Begin); int tagClassTableVirtualAddress = bin.ReadInt32(); this.IndexVirtualAddress = tagClassTableVirtualAddress - 32; this.Seek(4, SeekOrigin.Current); int tagDatumTableVirtualAddress = bin.ReadInt32(); var ScenarioID = bin.ReadTagID(); var GlobalsID = bin.ReadTagID(); int tagDatumTableOffset = tagDatumTableVirtualAddress - tagClassTableVirtualAddress; this.Seek(4, SeekOrigin.Current); int tagDatumCount = bin.ReadInt32(); this.Seek(4 + tagDatumTableOffset, SeekOrigin.Current); Tags = new Tag[tagDatumCount]; for (int i = 0; i < tagDatumCount; i++) { Tags[i] = new Tag() { Type = bin.ReadTagType(), Identifier = bin.ReadInt32(), VirtualAddress = bin.ReadInt32(), Length = bin.ReadInt32() }; if (i == 0) { SecondaryMagic = Tags[0].VirtualAddress - (indexAddress + indexLength); } //Borky vista fix - broken paths are broken //if (Tags[i].VirtualAddress == 0) continue; //var tag = Tags[i]; //Tags[i].Path = Paths[Tags[i].Identifier.SaltedIndex]; } this.MemoryBlocks[1] = new MemoryMappedAddress() { Address = Tags[0].VirtualAddress, Length = tagCacheLength, Magic = SecondaryMagic, }; /* Intent: read the sbsp and lightmap address and lengths from the scenario tag * and store them in the Tags array. */ if (BuildVersion == Version.XBOX_RETAIL) { this.Seek(Tags[ScenarioID.Index].VirtualAddress - SecondaryMagic + 528, SeekOrigin.Begin); var count = bin.ReadInt32(); var address = bin.ReadInt32(); for (int i = 0; i < count; ++i) { this.Seek(address - SecondaryMagic + i * 68, SeekOrigin.Begin); var sbsp_offset = bin.ReadInt32(); var sbsp_length = bin.ReadInt32(); var sbsp_virtual_address = bin.ReadInt32(); if (i == 0) { this.PrimaryMagic = sbsp_virtual_address - sbsp_offset; this.MemoryBlocks[0].Address = sbsp_virtual_address; this.MemoryBlocks[0].Magic = this.PrimaryMagic; } this.MemoryBlocks[0].Length += sbsp_length; Seek(8, SeekOrigin.Current); var sbsp_identifier = bin.ReadTagID(); Seek(4, SeekOrigin.Current); var ltmp_identifier = bin.ReadTagID(); var ltmp_offset = bin.ReadInt32(); var ltmp_length = sbsp_offset + sbsp_length - ltmp_offset; Tags[sbsp_identifier.Index].VirtualAddress = sbsp_virtual_address; Tags[sbsp_identifier.Index].Length = sbsp_length - ltmp_length; if (ltmp_identifier != TagIdentifier.null_identifier) { Tags[ltmp_identifier.Index].VirtualAddress = sbsp_virtual_address + ltmp_offset; Tags[ltmp_identifier.Index].Length = ltmp_length; } } //UNICODE this.Seek(Tags[GlobalsID.Index].VirtualAddress - SecondaryMagic + 400, SeekOrigin.Begin); int unicodeCount = bin.ReadInt32(); int unicodeTableLength = bin.ReadInt32(); int unicodeIndexAddress = bin.ReadInt32(); int unicodeTableAddress = bin.ReadInt32(); Unicode = new UnicodeValueNamePair[unicodeCount]; StringID[] strRefs = new StringID[unicodeCount]; int[] strOffsets = new int[unicodeCount]; this.Seek(unicodeIndexAddress, SeekOrigin.Begin); for (int i = 0; i < unicodeCount; i++) { strRefs[i] = (StringID)bin.ReadInt32(); strOffsets[i] = bin.ReadInt32(); } for (int i = 0; i < unicodeCount; i++) { this.Seek(unicodeTableAddress + strOffsets[i], SeekOrigin.Begin); StringBuilder unicodeString = new StringBuilder(byte.MaxValue); while (bin.PeekChar() != char.MinValue) unicodeString.Append(bin.ReadChar()); Unicode[i] = new UnicodeValueNamePair { Name = strRefs[i], Value = unicodeString.ToString() }; } } }