示例#1
0
        /// <summary>
        /// Verifies if the stream points to a valid blf start chunk and set the endian format.
        /// </summary>
        /// <param name="reader"></param>
        /// <returns></returns>
        private bool IsValid(EndianReader reader)
        {
            var position = reader.Position;

            try
            {
                Format        = FindChunkEndianFormat(reader);
                reader.Format = Format;
            }
            catch (Exception e)
            {
                Console.WriteLine($"BLF file is invalid: {e.Message}");
                return(false);
            }

            var deserializer = new TagDeserializer(Version);
            var dataContext  = new DataSerializationContext(reader);

            var header = (BlfChunkHeader)deserializer.Deserialize(dataContext, typeof(BlfChunkHeader));

            reader.SeekTo(position);

            if (header.Signature == "_blf")
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#2
0
        public CacheFile(GameCache cacheContext, FileInfo file, CacheVersion version, bool memory)
        {
            CacheContext = cacheContext;
            File         = file;
            Version      = version;
            Deserializer = new TagDeserializer(Version);

            Stream = memory ? new MemoryStream() : (Stream)file.OpenRead();

            if (memory)
            {
                using (var fileStream = file.OpenRead())
                {
                    fileStream.Seek(0, SeekOrigin.Begin);
                    fileStream.CopyTo(Stream);
                }
            }

            Reader = new EndianReader(Stream, EndianFormat.LittleEndian);

            Reader.SeekTo(0);
            if (Reader.ReadTag() == "daeh")
            {
                Reader.Format = EndianFormat.BigEndian;
            }

            Reader.SeekTo(0);
            Header = Deserializer.Deserialize <CacheFileHeader>(new DataSerializationContext(Reader));
        }
示例#3
0
        public void Read(EndianReader reader)
        {
            EndianFormat = DetectEndianFormat(reader);
            MapVersion   = GetMapFileVersion(reader);
            Version      = DetectCacheVersion(reader);
            var deserializer = new TagDeserializer(Version);

            reader.SeekTo(0);
            var dataContext = new DataSerializationContext(reader);

            Header = (CacheFileHeader)deserializer.Deserialize(dataContext, typeof(CacheFileHeader));

            // temporary code until map file format cleanup
            if (MapVersion == CacheFileVersion.HaloOnline)
            {
                var mapFileHeaderSize = (int)TagStructure.GetTagStructureInfo(typeof(CacheFileHeader), Version).TotalSize;

                // Seek to the blf
                reader.SeekTo(mapFileHeaderSize);
                // Read blf
                MapFileBlf = new Blf(Version);
                if (!MapFileBlf.Read(reader))
                {
                    MapFileBlf = null;
                }
            }
        }
示例#4
0
        public void ExtractDds(TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream outStream)
        {
            // TODO: Make sure 3D textures and cube maps work

            // Deserialize the resource definition and verify it
            var resource        = bitmap.Resources[imageIndex];
            var resourceContext = new ResourceSerializationContext(resource.Resource);
            var definition      = deserializer.Deserialize <BitmapTextureResourceDefinition>(resourceContext);

            if (definition.Texture == null || definition.Texture.Definition == null)
            {
                throw new ArgumentException("Invalid bitmap definition");
            }
            var dataReference = definition.Texture.Definition.Data;

            if (dataReference.Address.Type != ResourceAddressType.Resource)
            {
                throw new InvalidOperationException("Invalid resource data address");
            }

            var header             = CreateDdsHeader(definition);
            var resourceDataStream = new MemoryStream();

            _resourceManager.Extract(resource.Resource, resourceDataStream);
            header.WriteTo(outStream);
            resourceDataStream.Position = dataReference.Address.Offset;
            StreamUtil.Copy(resourceDataStream, outStream, dataReference.Size);
        }
示例#5
0
        public void Load(FileInfo file)
        {
            if (!file.Exists)
            {
                throw new FileNotFoundException(file.FullName);
            }

            if (file.Length < typeof(ModPackageHeader).GetSize())
            {
                throw new FormatException(file.FullName);
            }

            using (var stream = file.OpenRead())
                using (var reader = new EndianReader(stream, leaveOpen: true))
                {
                    var dataContext  = new DataSerializationContext(reader);
                    var deserializer = new TagDeserializer(CacheVersion.HaloOnline106708);

                    Header = deserializer.Deserialize <ModPackageHeaderExtended>(dataContext);

                    ReadMetadataSection(reader, dataContext, deserializer);
                    ReadTagsSection(reader);
                    ReadTagNamesSection(reader, dataContext, deserializer);
                    ReadResourcesSection(reader);
                    ReadMapFilesSection(reader);
                    ReadCampaignFileSection(reader);

                    Tags      = new TagCache(TagsStream, TagNames);
                    Resources = new ResourceCache(ResourcesStream);
                }
        }
示例#6
0
        public GameCacheHaloOnline(DirectoryInfo directory)
        {
            Directory         = directory;
            TagsFile          = new FileInfo(Path.Combine(directory.FullName, "tags.dat"));
            TagNamesFile      = new FileInfo(Path.Combine(directory.FullName, "tag_list.csv"));
            StringIdCacheFile = new FileInfo(Path.Combine(directory.FullName, "string_ids.dat"));

            Endianness = EndianFormat.LittleEndian;

            var names = TagCacheHaloOnline.LoadTagNames(TagNamesFile.FullName);

            using (var stream = TagsFile.OpenRead())
                TagCacheGenHO = new TagCacheHaloOnline(stream, names);

            if (CacheVersion.Unknown == (Version = CacheVersionDetection.DetectFromTimestamp(TagCacheGenHO.Header.CreationTime, out var closestVersion)))
            {
                Version = closestVersion;
            }

            using (var stream = StringIdCacheFile.OpenRead())
                StringTableHaloOnline = new StringTableHaloOnline(Version, stream);

            DisplayName  = Version.ToString();
            Deserializer = new TagDeserializer(Version);
            Serializer   = new TagSerializer(Version);

            ResourceCaches = new ResourceCachesHaloOnline(this);
        }
        public void InjectDds(Bitmap bitmap, int imageIndex, Stream ddsStream)
        {
            // Deserialize the old definition
            var resourceContext = new ResourceSerializationContext(bitmap.Resources[imageIndex].Resource);
            var definition      = TagDeserializer.Deserialize <BitmapTextureResourceDefinition>(resourceContext);

            if (definition.Texture == null || definition.Texture.Definition == null)
            {
                throw new ArgumentException("Invalid bitmap definition");
            }
            var texture = definition.Texture.Definition;

            // Read the DDS header and modify the definition to match
            var dds      = DdsHeader.Read(ddsStream);
            var dataSize = (int)(ddsStream.Length - ddsStream.Position);

            texture.Data            = new ResourceDataReference(dataSize, new ResourceAddress(ResourceAddressType.Resource, 0));
            texture.Width           = (short)dds.Width;
            texture.Height          = (short)dds.Height;
            texture.Depth           = (sbyte)Math.Max(1, dds.Depth);
            texture.Levels          = (sbyte)Math.Max(1, dds.MipMapCount);
            texture.Type            = BitmapDdsFormatDetection.DetectType(dds);
            texture.D3DFormatUnused = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2"));
            texture.Format          = BitmapDdsFormatDetection.DetectFormat(dds);

            // Set flags based on the format
            switch (definition.Texture.Definition.Format)
            {
            case BitmapFormat.Dxt1:
            case BitmapFormat.Dxt3:
            case BitmapFormat.Dxt5:
            case BitmapFormat.Dxn:
                definition.Texture.Definition.Flags = BitmapFlags.Compressed;
                break;

            default:
                definition.Texture.Definition.Flags = BitmapFlags.None;
                break;
            }

            // Inject the resource data
            _resourceManager.Replace(bitmap.Resources[imageIndex].Resource, ddsStream);

            // Serialize the new resource definition
            TagSerializer.Serialize(resourceContext, definition);

            // Modify the image data in the bitmap tag to match the definition
            var imageData = bitmap.Images[imageIndex];

            imageData.Width       = texture.Width;
            imageData.Height      = texture.Height;
            imageData.Depth       = texture.Depth;
            imageData.Type        = texture.Type;
            imageData.Format      = texture.Format;
            imageData.Flags       = texture.Flags;
            imageData.MipmapCount = (sbyte)(texture.Levels - 1);
            imageData.DataOffset  = texture.Data.Address.Offset;
            imageData.DataSize    = texture.Data.Size;
        }
示例#8
0
        private void Read(Stream stream)
        {
            // don't use using{}, we want to maintain the stream open. reader/writers will automatically close the stream when done in an using.
            var reader = new EndianReader(stream, EndianFormat.LittleEndian);

            stream.Position = 0;
            var addresses    = new List <uint>();
            var sizes        = new List <uint>();
            var dataContext  = new DataSerializationContext(reader);
            var deserializer = new TagDeserializer(Version);

            Header = deserializer.Deserialize <ResourceCacheHaloOnlineHeader>(dataContext);

            reader.SeekTo(Header.ResourceTableOffset);

            // read all resource offsets

            if (Header.ResourceCount == 0)
            {
                return;
            }

            for (var i = 0; i < Header.ResourceCount; i++)
            {
                var address = reader.ReadUInt32();

                if (!addresses.Contains(address) && (address != uint.MaxValue))
                {
                    addresses.Add(address);
                }

                Resources.Add(new Resource {
                    Offset = address
                });
            }

            // compute chunk sizes

            addresses.Sort((a, b) => a.CompareTo(b));

            for (var i = 0; i < addresses.Count - 1; i++)
            {
                sizes.Add(addresses[i + 1] - addresses[i]);
            }

            sizes.Add(Header.ResourceTableOffset - addresses.Last());

            foreach (var resource in Resources)
            {
                if (resource.Offset == uint.MaxValue)
                {
                    continue;
                }

                resource.ChunkSize = sizes[addresses.IndexOf(resource.Offset)];
            }
        }
示例#9
0
 public GameCacheModPackage(ModPackage modPackage, FileInfo file)
 {
     BaseModPackage = modPackage;
     Directory      = file.Directory;
     DisplayName    = BaseModPackage.Metadata.Name + ".pak";
     Version        = CacheVersion.HaloOnline106708;
     Endianness     = EndianFormat.LittleEndian;
     Deserializer   = new TagDeserializer(Version);
     Serializer     = new TagSerializer(Version);
 }
        private void EditHlmtTag(HaloTag tag)
        {
            Model model;

            using (var stream = _fileInfo.OpenRead())
                model = TagDeserializer.Deserialize <Model>(new TagSerializationContext(stream, _cache, tag));
            var context = HlmtContextFactory.Create(_stack.Context, _fileInfo, _cache, _stringIds, tag, model);

            _stack.Push(context);
        }
        private void EditBitmTag(HaloTag tag)
        {
            Bitmap bitmap;

            using (var stream = _fileInfo.OpenRead())
                bitmap = TagDeserializer.Deserialize <Bitmap>(new TagSerializationContext(stream, _cache, tag));
            var context = BitmContextFactory.Create(_stack.Context, _fileInfo, _cache, tag, bitmap);

            _stack.Push(context);
        }
        private void EditVfslTag(HaloTag tag)
        {
            VFilesList vfsl;

            using (var stream = _fileInfo.OpenRead())
                vfsl = TagDeserializer.Deserialize <VFilesList>(new TagSerializationContext(stream, _cache, tag));
            var context = VfslContextFactory.Create(_stack.Context, _fileInfo, _cache, tag, vfsl);

            _stack.Push(context);
        }
        private void EditUnicTag(HaloTag tag)
        {
            MultilingualUnicodeStringList unic;

            using (var stream = _fileInfo.OpenRead())
                unic = TagDeserializer.Deserialize <MultilingualUnicodeStringList>(new TagSerializationContext(stream, _cache, tag));
            var context = UnicContextFactory.Create(_stack.Context, _fileInfo, _cache, tag, unic, _stringIds);

            _stack.Push(context);
        }
示例#14
0
        private MapFile GenerateMapFile(CachedTagInstance scenarioTag, Blf mapInfo = null)
        {
            MapFile  map    = new MapFile();
            var      header = new MapFileHeader();
            Scenario scnr;

            using (var stream = CacheContext.OpenTagCacheRead())
            {
                var deserializer = new TagDeserializer(CacheContext.Version);
                scnr = (Scenario)CacheContext.Deserialize(stream, scenarioTag);
            }

            map.Version      = CacheContext.Version;
            map.EndianFormat = EndianFormat.LittleEndian;
            map.MapVersion   = MapFileVersion.HaloOnline;

            header.HeadTag = new Tag("head");
            header.FootTag = new Tag("foot");
            header.Version = (int)map.MapVersion;
            header.Build   = CacheVersionDetection.GetBuildName(CacheContext.Version);

            switch (scnr.MapType)
            {
            case ScenarioMapType.MainMenu:
                header.CacheType = CacheFileType.MainMenu;
                break;

            case ScenarioMapType.SinglePlayer:
                header.CacheType = CacheFileType.Campaign;
                break;

            case ScenarioMapType.Multiplayer:
                header.CacheType = CacheFileType.Multiplayer;
                break;
            }
            header.SharedType = CacheFileSharedType.None;

            header.MapId            = scnr.MapId;
            header.ScenarioTagIndex = scenarioTag.Index;
            header.Name             = scenarioTag.Name.Split('\\').Last();
            header.ScenarioPath     = scenarioTag.Name;

            map.Header = header;

            header.FileLength = 0x3390;

            if (mapInfo != null)
            {
                if (mapInfo.ContentFlags.HasFlag(BlfFileContentFlags.StartOfFile) && mapInfo.ContentFlags.HasFlag(BlfFileContentFlags.EndOfFile) && mapInfo.ContentFlags.HasFlag(BlfFileContentFlags.Scenario))
                {
                    map.MapFileBlf = mapInfo;
                }
            }
            return(map);
        }
        public void InjectDds(TagSerializer serializer, TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream ddsStream)
        {
            // Deserialize the old definition
            var resourceContext = new ResourceSerializationContext(bitmap.Resources[imageIndex].Resource);
            var definition = deserializer.Deserialize<BitmapTextureResourceDefinition>(resourceContext);
            if (definition.Texture == null || definition.Texture.Definition == null)
                throw new ArgumentException("Invalid bitmap definition");
            var texture = definition.Texture.Definition;

            // Read the DDS header and modify the definition to match
            var dds = DdsHeader.Read(ddsStream);
            var dataSize = (int)(ddsStream.Length - ddsStream.Position);
            texture.Data = new ResourceDataReference(dataSize, new ResourceAddress(ResourceAddressType.Resource, 0));
            texture.Width = (short)dds.Width;
            texture.Height = (short)dds.Height;
            texture.Depth = (sbyte)Math.Max(1, dds.Depth);
            texture.Levels = (sbyte)Math.Max(1, dds.MipMapCount);
            texture.Type = BitmapDdsFormatDetection.DetectType(dds);
            texture.D3DFormatUnused = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2"));
            texture.Format = BitmapDdsFormatDetection.DetectFormat(dds);

            // Set flags based on the format
            switch (definition.Texture.Definition.Format)
            {
                case BitmapFormat.Dxt1:
                case BitmapFormat.Dxt3:
                case BitmapFormat.Dxt5:
                case BitmapFormat.Dxn:
                    definition.Texture.Definition.Flags = BitmapFlags.Compressed;
                    break;
                default:
                    definition.Texture.Definition.Flags = BitmapFlags.None;
                    break;
            }

            // Inject the resource data
            _resourceManager.Replace(bitmap.Resources[imageIndex].Resource, ddsStream);

            // Serialize the new resource definition
            serializer.Serialize(resourceContext, definition);

            // Modify the image data in the bitmap tag to match the definition
            var imageData = bitmap.Images[imageIndex];
            imageData.Width = texture.Width;
            imageData.Height = texture.Height;
            imageData.Depth = texture.Depth;
            imageData.Type = texture.Type;
            imageData.Format = texture.Format;
            imageData.Flags = texture.Flags;
            imageData.MipmapCount = (sbyte)(texture.Levels - 1);
            imageData.DataOffset = texture.Data.Address.Offset;
            imageData.DataSize = texture.Data.Size;
        }
示例#16
0
        public TagCacheGen1(EndianReader reader, MapFile mapFile)
        {
            var tagDataSectionOffset = mapFile.Header.TagsHeaderAddress32;

            reader.SeekTo(tagDataSectionOffset);

            var dataContext  = new DataSerializationContext(reader);
            var deserializer = new TagDeserializer(mapFile.Version);

            Header = deserializer.Deserialize <TagCacheGen1Header>(dataContext);

            if (mapFile.Version == CacheVersion.HaloXbox)
            {
                BaseTagAddress = 0x803A6000;
            }
            else
            {
                BaseTagAddress = 0x40440000;
            }

            //
            // Read all tags offsets are all broken, need some proper look
            //

            reader.SeekTo(Header.CachedTagArrayAddress - BaseTagAddress + tagDataSectionOffset);

            for (int i = 0; i < Header.TagCount; i++)
            {
                var group = new TagGroup()
                {
                    Tag            = new Tag(reader.ReadInt32()),
                    ParentTag      = new Tag(reader.ReadInt32()),
                    GrandparentTag = new Tag(reader.ReadInt32())
                };
                var    tagID = reader.ReadUInt32();
                var    tagPathNameAddress = reader.ReadUInt32();
                var    currentPos         = reader.Position;
                string name = "";
                if (tagPathNameAddress != 0)
                {
                    reader.SeekTo(tagPathNameAddress - BaseTagAddress + tagDataSectionOffset);
                    name = reader.ReadNullTerminatedString();
                    reader.SeekTo(currentPos);
                }
                var tagDataAddress = reader.ReadUInt32();
                var weird2         = reader.ReadUInt32();
                var unused         = reader.ReadUInt32();
                Tags.Add(new CachedTagGen1((int)(tagID & 0xFFFF), tagID, group, tagDataAddress, name));
            }
        }
示例#17
0
        public GameCacheGen3(MapFile mapFile, FileInfo file)
        {
            BaseMapFile  = mapFile;
            Version      = BaseMapFile.Version;
            CacheFile    = file;
            Deserializer = new TagDeserializer(Version);
            Serializer   = new TagSerializer(Version);
            Endianness   = BaseMapFile.EndianFormat;
            var interop = mapFile.Header.SectionTable;

            DisplayName = mapFile.Header.Name + ".map";

            Directory = file.Directory;

            using (var cacheStream = OpenCacheRead())
                using (var reader = new EndianReader(cacheStream, Endianness))
                {
                    StringTableGen3   = new StringTableGen3(reader, BaseMapFile);
                    TagCacheGen3      = new TagCacheGen3(reader, BaseMapFile, StringTableGen3);
                    ResourceCacheGen3 = new ResourceCacheGen3(this);

                    if (TagCacheGen3.Instances.Count > 0)
                    {
                        if (BaseMapFile.Header.SectionTable.Sections[(int)CacheFileSectionType.LocalizationSection].Size == 0)
                        {
                            LocaleTables = new List <LocaleTable>();
                        }
                        else
                        {
                            var globals = Deserialize <Globals>(cacheStream, TagCacheGen3.GlobalInstances["matg"]);
                            LocaleTables = LocalesTableGen3.CreateLocalesTable(reader, BaseMapFile, globals);
                        }
                    }
                }

            // unused but kept for future uses
            switch (Version)
            {
            case CacheVersion.Halo3Beta:
            case CacheVersion.Halo3Retail:
            case CacheVersion.Halo3ODST:
                NetworkKey = "";
                break;

            case CacheVersion.HaloReach:
                NetworkKey = "SneakerNetReigns";
                break;
            }
        }
示例#18
0
        public override void LoadResourceTags()
        {
            TagDeserializer deserializer = new TagDeserializer(Version);

            foreach (IndexItem item in IndexItems)
            {
                if (item.GroupTag == "play")
                {
                    CacheFile cacheFile   = this;
                    var       blamContext = new CacheSerializationContext(ref cacheFile, item);
                    if (cacheFile.File.FullName != File.FullName)
                    {
                        throw new InvalidOperationException();
                    }

                    ResourceLayoutTable = deserializer.Deserialize <CacheFileResourceLayoutTable>(blamContext);
                    break;
                }
            }

            foreach (IndexItem item in IndexItems)
            {
                if (item.GroupTag == "zone")
                {
                    CacheFile cacheFile   = this;
                    var       blamContext = new CacheSerializationContext(ref cacheFile, item);
                    if (cacheFile.File.FullName != File.FullName)
                    {
                        throw new InvalidOperationException();
                    }

                    ResourceGestalt = deserializer.Deserialize <CacheFileResourceGestalt>(blamContext);

                    foreach (var tagresource in ResourceGestalt.TagResources)
                    {
                        foreach (var fixup in tagresource.ResourceFixups)
                        {
                            fixup.Offset     = (int)(fixup.Address.Value & 0x0FFFFFFF);
                            fixup.Type       = (int)(fixup.Address.Value >> 28) & 0xF;
                            fixup.RawAddress = (int)fixup.Address.Value;
                        }
                    }

                    break;
                }
            }
        }
示例#19
0
        public GameCacheModPackage(FileInfo file)
        {
            ModPackageFile = file;
            Version        = CacheVersion.HaloOnline106708;
            Endianness     = EndianFormat.LittleEndian;
            Deserializer   = new TagDeserializer(Version);
            Serializer     = new TagSerializer(Version);
            Directory      = file.Directory;

            // load mod package
            BaseModPackage = new ModPackage(file);
            DisplayName    = BaseModPackage.Metadata.Name + ".pak";

            ResourceCaches        = new ResourceCachesModPackage(BaseModPackage);
            TagCacheGenHO         = new TagCacheHaloOnline(BaseModPackage.TagCachesStreams[0], BaseModPackage.TagCacheNames[0]);
            StringTableHaloOnline = BaseModPackage.StringTable;
        }
示例#20
0
        public GameCacheGen1(MapFile mapFile, FileInfo file)
        {
            BaseMapFile  = mapFile;
            CacheFile    = file;
            Version      = BaseMapFile.Version;
            CacheFile    = file;
            Deserializer = new TagDeserializer(Version);
            Serializer   = new TagSerializer(Version);
            Endianness   = BaseMapFile.EndianFormat;
            DisplayName  = mapFile.Header.NameOld + ".map";
            Directory    = file.Directory;

            using (var cacheStream = OpenCacheRead())
                using (var reader = new EndianReader(cacheStream, Endianness))
                {
                    TagCacheGen1 = new TagCacheGen1(reader, mapFile);
                }
        }
示例#21
0
        public static byte[] ConvertHkpMoppData(CacheVersion sourceVersion, CacheVersion destVersion, byte[] data)
        {
            if (data == null || data.Length == 0)
            {
                return(data);
            }

            byte[] result;
            using (var inputReader = new EndianReader(new MemoryStream(data), CacheVersionDetection.IsLittleEndian(sourceVersion) ? EndianFormat.LittleEndian : EndianFormat.BigEndian))
                using (var outputStream = new MemoryStream())
                    using (var outputWriter = new EndianWriter(outputStream, CacheVersionDetection.IsLittleEndian(destVersion) ? EndianFormat.LittleEndian : EndianFormat.BigEndian))
                    {
                        var dataContext  = new DataSerializationContext(inputReader, outputWriter);
                        var deserializer = new TagDeserializer(sourceVersion);
                        var serializer   = new TagSerializer(destVersion);
                        while (!inputReader.EOF)
                        {
                            var         header      = deserializer.Deserialize <HkpMoppCode>(dataContext);
                            var         dataSize    = header.ArrayBase.GetCapacity();
                            var         alignedSize = dataSize + 0xf & ~0xf;
                            var         nextOffset  = inputReader.Position + alignedSize;
                            List <byte> moppCodes   = new List <byte>();
                            for (int j = 0; j < header.ArrayBase.GetCapacity(); j++)
                            {
                                moppCodes.Add(inputReader.ReadByte());
                            }
                            inputReader.SeekTo(nextOffset);

                            moppCodes = ConvertMoppCodes(sourceVersion, destVersion, moppCodes);

                            serializer.Serialize(dataContext, header);
                            for (int j = 0; j < moppCodes.Count; j++)
                            {
                                outputWriter.Write(moppCodes[j]);
                            }

                            StreamUtil.Align(outputStream, 0x10);
                        }
                        result = outputStream.ToArray();
                    }
            return(result);
        }
示例#22
0
        public override bool Execute(List <string> args)
        {
            if (args.Count != 1 && args.Count != 2)
            {
                return(false);
            }
            GameLanguage language;

            if (!ArgumentParser.ParseLanguage(args[0], out language))
            {
                return(false);
            }
            var filter = (args.Count == 2) ? args[1] : null;

            var found = false;

            using (var stream = _fileInfo.OpenRead())
            {
                foreach (var unicTag in _cache.Tags.FindAllByClass("unic"))
                {
                    var unic    = TagDeserializer.Deserialize <MultilingualUnicodeStringList>(new TagSerializationContext(stream, _cache, unicTag));
                    var strings = LocalizedStringPrinter.PrepareForDisplay(unic, _stringIds, unic.Strings, language, filter);
                    if (strings.Count == 0)
                    {
                        continue;
                    }
                    if (found)
                    {
                        Console.WriteLine();
                    }
                    Console.WriteLine("Strings found in {0:X8}.unic:", unicTag.Index);
                    LocalizedStringPrinter.PrintStrings(strings);
                    found = true;
                }
            }
            if (!found)
            {
                Console.Error.WriteLine("No strings found.");
            }

            return(true);
        }
示例#23
0
        public HaloOnlineCacheContext(DirectoryInfo directory) :
            base(directory)
        {
            var tagNames = LoadTagNames();

            using (var stream = OpenTagCacheRead())
                TagCache = new TagCache(stream, tagNames);

            if (CacheVersion.Unknown == (Version = CacheVersionDetection.DetectFromTagCache(TagCache, out var closestVersion)))
            {
                Version = closestVersion;
            }

            Deserializer = new TagDeserializer(Version == CacheVersion.Unknown ? closestVersion : Version);
            Serializer   = new TagSerializer(Version == CacheVersion.Unknown ? closestVersion : Version);

            StringIdResolver stringIdResolver = null;

            if (CacheVersionDetection.Compare(Version, CacheVersion.HaloOnline700123) >= 0)
            {
                stringIdResolver = new StringIdResolverMS30();
            }
            else if (CacheVersionDetection.Compare(Version, CacheVersion.HaloOnline498295) >= 0)
            {
                stringIdResolver = new StringIdResolverMS28();
            }
            else
            {
                stringIdResolver = new StringIdResolverMS23();
            }

            using (var stream = OpenStringIdCacheRead())
                StringIdCache = new StringIdCache(stream, stringIdResolver);

            TagGroup.Instances[new Tag("obje")] = new TagGroup(new Tag("obje"), Tag.Null, Tag.Null, GetStringId("object"));
            TagGroup.Instances[new Tag("item")] = new TagGroup(new Tag("item"), new Tag("obje"), Tag.Null, GetStringId("item"));
            TagGroup.Instances[new Tag("devi")] = new TagGroup(new Tag("devi"), new Tag("obje"), Tag.Null, GetStringId("device"));
            TagGroup.Instances[new Tag("unit")] = new TagGroup(new Tag("unit"), new Tag("obje"), Tag.Null, GetStringId("unit"));
            TagGroup.Instances[new Tag("rm  ")] = new TagGroup(new Tag("rm  "), Tag.Null, Tag.Null, GetStringId("render_method"));
            TagGroup.Instances[new Tag("test")] = new TagGroup(new Tag("test"), Tag.Null, Tag.Null, GetStringId("test_blah"));
        }
示例#24
0
        public void Load(FileInfo file)
        {
            if (!file.Exists)
            {
                throw new FileNotFoundException(file.FullName);
            }

            if (file.Length < typeof(ModPackageHeader).GetSize())
            {
                throw new FormatException(file.FullName);
            }

            using (var stream = file.OpenRead())
                using (var reader = new EndianReader(stream, leaveOpen: true))
                {
                    var dataContext  = new DataSerializationContext(reader);
                    var deserializer = new TagDeserializer(CacheVersion.HaloOnline106708);

                    Header = deserializer.Deserialize <ModPackageHeader>(dataContext);

                    ReadMetadataSection(reader, dataContext, deserializer);
                    ReadTagsSection(reader, dataContext, deserializer);
                    ReadTagNamesSection(reader, dataContext, deserializer);
                    ReadResourcesSection(reader);
                    ReadMapFilesSection(reader);
                    ReadCampaignFileSection(reader);
                    ReadStringIdSection(reader);
                    ReadFontSection(reader);
                    ReadFileEntries(reader, dataContext, deserializer);

                    int tagCacheCount = TagCachesStreams.Count;

                    TagCaches = new List <TagCacheHaloOnline>();
                    for (int i = 0; i < tagCacheCount; i++)
                    {
                        TagCaches.Add(new TagCacheHaloOnline(TagCachesStreams[i], TagCacheNames[i]));
                    }

                    Resources = new ResourceCacheHaloOnline(CacheVersion.HaloOnline106708, ResourcesStream);
                }
        }
        public void ExtractDds(TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream outStream)
        {
            // TODO: Make sure 3D textures and cube maps work

            // Deserialize the resource definition and verify it
            var resource = bitmap.Resources[imageIndex];
            var resourceContext = new ResourceSerializationContext(resource.Resource);
            var definition = deserializer.Deserialize<BitmapTextureResourceDefinition>(resourceContext);
            if (definition.Texture == null || definition.Texture.Definition == null)
                throw new ArgumentException("Invalid bitmap definition");
            var dataReference = definition.Texture.Definition.Data;
            if (dataReference.Address.Type != ResourceAddressType.Resource)
                throw new InvalidOperationException("Invalid resource data address");

            var header = CreateDdsHeader(definition);
            var resourceDataStream = new MemoryStream();
            _resourceManager.Extract(resource.Resource, resourceDataStream);
            header.WriteTo(outStream);
            resourceDataStream.Position = dataReference.Address.Offset;
            StreamUtil.Copy(resourceDataStream, outStream, dataReference.Size);
        }
示例#26
0
        private void ReadTagsSection(EndianReader reader, DataSerializationContext context, TagDeserializer deserializer)
        {
            var section = GetSectionHeader(reader, ModPackageSection.Tags);

            if (!GoToSectionHeaderOffset(reader, section))
            {
                return;
            }

            var entry      = new GenericSectionEntry(reader);
            var cacheCount = entry.Count;

            TagCachesStreams = new List <Stream>();
            CacheNames       = new List <string>();

            for (int i = 0; i < cacheCount; i++)
            {
                var tagStream = new MemoryStream();

                reader.BaseStream.Position = entry.TableOffset + 0x28 * i + section.Offset;
                var tableEntry = deserializer.Deserialize <CacheTableEntry>(context);
                CacheNames.Add(tableEntry.CacheName);
                reader.BaseStream.Position = tableEntry.Offset + section.Offset;

                if (section.Size > int.MaxValue)
                {
                    throw new Exception("Tag cache size not supported");
                }
                int size = (int)section.Size;

                byte[] data = new byte[size];
                reader.Read(data, 0, size);
                tagStream.Write(data, 0, size);
                tagStream.Position = 0;
                TagCachesStreams.Add(tagStream);
            }
        }
示例#27
0
        public void InjectDds(TagSerializer serializer, TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream ddsStream)
        {
            var resource = bitmap.Resources[imageIndex].Resource;
            var newResource = (resource == null);
            ResourceSerializationContext resourceContext;
            BitmapTextureResourceDefinition definition;
            if (newResource)
            {
                // Create a new resource reference
                resource = new ResourceReference
                {
                    DefinitionFixups = new List<ResourceDefinitionFixup>(),
                    D3DObjectFixups = new List<D3DObjectFixup>(),
                    Type = 1, // TODO: Map out this type enum instead of using numbers
                    Unknown68 = 1
                };
                bitmap.Resources[imageIndex].Resource = resource;
                resourceContext = new ResourceSerializationContext(resource);
                definition = new BitmapTextureResourceDefinition
                {
                    Texture = new D3DPointer<BitmapTextureResourceDefinition.BitmapDefinition>
                    {
                        Definition = new BitmapTextureResourceDefinition.BitmapDefinition()
                    }
                };
            }
            else
            {
                // Deserialize the old definition
                resourceContext = new ResourceSerializationContext(resource);
                definition = deserializer.Deserialize<BitmapTextureResourceDefinition>(resourceContext);
            }
            if (definition.Texture == null || definition.Texture.Definition == null)
                throw new ArgumentException("Invalid bitmap definition");
            var texture = definition.Texture.Definition;
            var imageData = bitmap.Images[imageIndex];

            // Read the DDS header and modify the definition to match
            var dds = DdsHeader.Read(ddsStream);
            var dataSize = (int)(ddsStream.Length - ddsStream.Position);
            texture.Data = new ResourceDataReference(dataSize, new ResourceAddress(ResourceAddressType.Resource, 0));
            texture.Width = (short)dds.Width;
            texture.Height = (short)dds.Height;
            texture.Depth = (sbyte)Math.Max(1, dds.Depth);
            texture.Levels = (sbyte)Math.Max(1, dds.MipMapCount);
            texture.Type = BitmapDdsFormatDetection.DetectType(dds);
            texture.D3DFormatUnused = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2"));
            texture.Format = BitmapDdsFormatDetection.DetectFormat(dds);

            // Set flags based on the format
            switch (texture.Format)
            {
                case BitmapFormat.Dxt1:
                case BitmapFormat.Dxt3:
                case BitmapFormat.Dxt5:
                case BitmapFormat.Dxn:
                    texture.Flags = BitmapFlags.Compressed;
                    break;
                default:
                    texture.Flags = BitmapFlags.None;
                    break;
            }
            if ((texture.Width & (texture.Width - 1)) == 0 && (texture.Height & (texture.Height - 1)) == 0)
                texture.Flags |= BitmapFlags.PowerOfTwoDimensions;

            // If creating a new image, then add a new resource, otherwise replace the existing one
            if (newResource)
                _resourceManager.Add(resource, ResourceLocation.Textures, ddsStream);
            else
                _resourceManager.Replace(resource, ddsStream);

            // Serialize the new resource definition
            serializer.Serialize(resourceContext, definition);

            // Modify the image data in the bitmap tag to match the definition
            imageData.Width = texture.Width;
            imageData.Height = texture.Height;
            imageData.Depth = texture.Depth;
            imageData.Type = texture.Type;
            imageData.Format = texture.Format;
            imageData.Flags = texture.Flags;
            imageData.MipmapCount = (sbyte)(texture.Levels - 1);
            imageData.DataOffset = texture.Data.Address.Offset;
            imageData.DataSize = texture.Data.Size;
            imageData.Unknown15 = texture.Unknown35;
        }
示例#28
0
        public void InjectDds(TagSerializer serializer, TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream ddsStream)
        {
            var resource    = bitmap.Resources[imageIndex].Resource;
            var newResource = (resource == null);
            ResourceSerializationContext    resourceContext;
            BitmapTextureResourceDefinition definition;

            if (newResource)
            {
                // Create a new resource reference
                resource = new ResourceReference
                {
                    DefinitionFixups = new List <ResourceDefinitionFixup>(),
                    D3DObjectFixups  = new List <D3DObjectFixup>(),
                    Type             = 1, // TODO: Map out this type enum instead of using numbers
                    Unknown68        = 1
                };
                bitmap.Resources[imageIndex].Resource = resource;
                resourceContext = new ResourceSerializationContext(resource);
                definition      = new BitmapTextureResourceDefinition
                {
                    Texture = new D3DPointer <BitmapTextureResourceDefinition.BitmapDefinition>
                    {
                        Definition = new BitmapTextureResourceDefinition.BitmapDefinition()
                    }
                };
            }
            else
            {
                // Deserialize the old definition
                resourceContext = new ResourceSerializationContext(resource);
                definition      = deserializer.Deserialize <BitmapTextureResourceDefinition>(resourceContext);
            }
            if (definition.Texture == null || definition.Texture.Definition == null)
            {
                throw new ArgumentException("Invalid bitmap definition");
            }
            var texture   = definition.Texture.Definition;
            var imageData = bitmap.Images[imageIndex];

            // Read the DDS header and modify the definition to match
            var dds      = DdsHeader.Read(ddsStream);
            var dataSize = (int)(ddsStream.Length - ddsStream.Position);

            texture.Data            = new ResourceDataReference(dataSize, new ResourceAddress(ResourceAddressType.Resource, 0));
            texture.Width           = (short)dds.Width;
            texture.Height          = (short)dds.Height;
            texture.Depth           = (sbyte)Math.Max(1, dds.Depth);
            texture.Levels          = (sbyte)Math.Max(1, dds.MipMapCount);
            texture.Type            = BitmapDdsFormatDetection.DetectType(dds);
            texture.D3DFormatUnused = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2"));
            texture.Format          = BitmapDdsFormatDetection.DetectFormat(dds);

            // Set flags based on the format
            switch (texture.Format)
            {
            case BitmapFormat.Dxt1:
            case BitmapFormat.Dxt3:
            case BitmapFormat.Dxt5:
            case BitmapFormat.Dxn:
                texture.Flags = BitmapFlags.Compressed;
                break;

            default:
                texture.Flags = BitmapFlags.None;
                break;
            }
            if ((texture.Width & (texture.Width - 1)) == 0 && (texture.Height & (texture.Height - 1)) == 0)
            {
                texture.Flags |= BitmapFlags.PowerOfTwoDimensions;
            }

            // If creating a new image, then add a new resource, otherwise replace the existing one
            if (newResource)
            {
                _resourceManager.Add(resource, ResourceLocation.Textures, ddsStream);
            }
            else
            {
                _resourceManager.Replace(resource, ddsStream);
            }

            // Serialize the new resource definition
            serializer.Serialize(resourceContext, definition);

            // Modify the image data in the bitmap tag to match the definition
            imageData.Width       = texture.Width;
            imageData.Height      = texture.Height;
            imageData.Depth       = texture.Depth;
            imageData.Type        = texture.Type;
            imageData.Format      = texture.Format;
            imageData.Flags       = texture.Flags;
            imageData.MipmapCount = (sbyte)(texture.Levels - 1);
            imageData.DataOffset  = texture.Data.Address.Offset;
            imageData.DataSize    = texture.Data.Size;
            imageData.Unknown15   = texture.Unknown35;
        }
示例#29
0
        public override bool Execute(List <string> args)
        {
            if (args.Count != 2)
            {
                return(false);
            }

            var destDir = new DirectoryInfo(args[1]);

            if (!destDir.Exists)
            {
                WriteLine($"Destination cache directory does not exist: {destDir.FullName}");
                return(false);
            }

            var destTagsFile = new FileInfo(Combine(destDir.FullName, "tags.dat"));

            if (!destTagsFile.Exists)
            {
                WriteLine($"Destination tag cache file does not exist: {destTagsFile.FullName}");
                return(false);
            }

            var destStringIDsFile = new FileInfo(Combine(destDir.FullName, "string_ids.dat"));

            if (!destStringIDsFile.Exists)
            {
                WriteLine($"Destination string id cache file does not exist: {destStringIDsFile.FullName}");
                return(false);
            }

            var destResourcesFile = new FileInfo(Combine(destDir.FullName, "resources.dat"));

            if (!destResourcesFile.Exists)
            {
                WriteLine($"Destination resource cache file does not exist: {destResourcesFile.FullName}");
                return(false);
            }

            var destTexturesFile = new FileInfo(Combine(destDir.FullName, "textures.dat"));

            if (!destTexturesFile.Exists)
            {
                WriteLine($"Destination texture cache file does not exist: {destTexturesFile.FullName}");
                return(false);
            }

            var destTexturesBFile = new FileInfo(Combine(destDir.FullName, "textures_b.dat"));

            if (!destTexturesBFile.Exists)
            {
                WriteLine($"Destination texture cache file does not exist: {destTexturesBFile.FullName}");
                return(false);
            }

            var destAudioFile = new FileInfo(Combine(destDir.FullName, "audio.dat"));

            if (!destAudioFile.Exists)
            {
                WriteLine($"Destination audio cache file does not exist: {destAudioFile.FullName}");
                return(false);
            }

            TagCache destTagCache;

            using (var stream = destTagsFile.OpenRead())
                destTagCache = new TagCache(stream);

            DefinitionSet guessedVersion;
            var           destVersion = Detect(destTagCache, out guessedVersion);

            if (destVersion == Unknown)
            {
                WriteLine($"Unrecognized target version! (guessed {GetVersionString(guessedVersion)})");
                return(true);
            }

            WriteLine($"Destination cache version: {GetVersionString(destVersion)}");

            StringIDCache destStringIDCache;

            using (var stream = destStringIDsFile.OpenRead())
                destStringIDCache = new StringIDCache(stream, Create(destVersion));

            var destResources = new ResourceDataManager();

            destResources.LoadCachesFromDirectory(destDir.FullName);

            var srcResources = new ResourceDataManager();

            srcResources.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);

            var destSerializer   = new TagSerializer(destVersion);
            var destDeserializer = new TagDeserializer(destVersion);

            var destInfo = new OpenTagCache
            {
                Cache         = destTagCache,
                CacheFile     = destTagsFile,
                StringIDs     = destStringIDCache,
                StringIDsFile = destStringIDsFile,
                Version       = destVersion,
                Serializer    = destSerializer,
                Deserializer  = destDeserializer
            };

            var destTag = ParseTagIndex(destInfo, args[0]);

            if (destTag == null || !destTag.IsInGroup(new Tag("mode")))
            {
                WriteLine("Destination tag must be of group 'mode'.");
                return(false);
            }

            RenderModel destDefinition;

            using (var destStream = destInfo.OpenCacheRead())
            {
                var context = new TagSerializationContext(destStream, destInfo.Cache, destInfo.StringIDs, destTag);
                destDefinition = destInfo.Deserializer.Deserialize <RenderModel>(context);
            }

            using (MemoryStream inStream = new MemoryStream(), outStream = new MemoryStream())
            {
                // First extract the model data
                srcResources.Extract(Definition.Geometry.Resource, inStream);

                // Now open source and destination vertex streams
                inStream.Position = 0;
                var inVertexStream  = VertexStreamFactory.Create(Info.Version, inStream);
                var outVertexStream = VertexStreamFactory.Create(destInfo.Version, outStream);

                // Deserialize the definition data
                var resourceContext = new ResourceSerializationContext(Definition.Geometry.Resource);
                var definition      = Info.Deserializer.Deserialize <RenderGeometryResourceDefinition>(resourceContext);

                // Convert each vertex buffer
                foreach (var buffer in definition.VertexBuffers)
                {
                    TagConverter.ConvertVertexBuffer(buffer.Definition, inStream, inVertexStream, outStream, outVertexStream);
                }

                // Copy each index buffer over
                foreach (var buffer in definition.IndexBuffers)
                {
                    if (buffer.Definition.Data.Size == 0)
                    {
                        continue;
                    }
                    inStream.Position = buffer.Definition.Data.Address.Offset;
                    buffer.Definition.Data.Address = new ResourceAddress(ResourceAddressType.Resource, (int)outStream.Position);
                    var bufferData = new byte[buffer.Definition.Data.Size];
                    inStream.Read(bufferData, 0, bufferData.Length);
                    outStream.Write(bufferData, 0, bufferData.Length);
                    StreamUtil.Align(outStream, 4);
                }

                destInfo.Serializer.Serialize(resourceContext, definition);

                outStream.Position = 0;
                destResources.Replace(destDefinition.Geometry.Resource, outStream);
            }

            return(true);
        }
示例#30
0
        private void ReadFileEntries(EndianReader reader, ISerializationContext context, TagDeserializer deserializer)
        {
            Files = new Dictionary <string, Stream>();

            var section = GetSectionHeader(reader, ModPackageSection.Files);

            if (!GoToSectionHeaderOffset(reader, section))
            {
                return;
            }

            var fileTable = new GenericSectionEntry(reader);

            reader.BaseStream.Position = fileTable.TableOffset + section.Offset;
            for (int i = 0; i < fileTable.Count; i++)
            {
                var tableEntry = deserializer.Deserialize <FileTableEntry>(context);

                var stream = new MemoryStream();
                StreamUtil.Copy(reader.BaseStream, stream, tableEntry.Size);

                Files.Add(tableEntry.Path, stream);
            }
        }
示例#31
0
        public void InjectDds(TagSerializer serializer, TagDeserializer deserializer, Bitmap bitmap, int imageIndex, Stream ddsStream, ResourceLocation location = ResourceLocation.Textures)
        {
            var resource    = bitmap.Resources[imageIndex].Resource;
            var newResource = (resource == null);
            ResourceSerializationContext resourceContext;
            BitmapTextureInteropResource definition;

            if (newResource)
            {
                // Create a new resource reference
                resource = new PageableResource
                {
                    Page     = new RawPage(),
                    Resource = new TagResourceGen3
                    {
                        ResourceFixups           = new List <TagResourceGen3.ResourceFixup>(),
                        ResourceDefinitionFixups = new List <TagResourceGen3.ResourceDefinitionFixup>(),
                        ResourceType             = TagResourceTypeGen3.Bitmap,
                        Unknown2 = 1
                    }
                };

                bitmap.Resources[imageIndex].Resource = resource;
                resourceContext = new ResourceSerializationContext(CacheContext, resource);
                definition      = new BitmapTextureInteropResource
                {
                    Texture = new TagStructureReference <BitmapTextureInteropResource.BitmapDefinition>
                    {
                        Definition = new BitmapTextureInteropResource.BitmapDefinition
                        {
                            Data        = new TagData(),
                            UnknownData = new TagData(),
                        }
                    }
                };
            }
            else
            {
                // Deserialize the old definition
                resourceContext = new ResourceSerializationContext(CacheContext, resource);
                definition      = deserializer.Deserialize <BitmapTextureInteropResource>(resourceContext);
            }
            if (definition.Texture == null || definition.Texture.Definition == null)
            {
                throw new ArgumentException("Invalid bitmap definition");
            }
            var texture   = definition.Texture.Definition;
            var imageData = bitmap.Images[imageIndex];

            // Read the DDS header and modify the definition to match
            var dds      = DdsHeader.Read(ddsStream);
            var dataSize = (int)(ddsStream.Length - ddsStream.Position);

            texture.Data        = new TagData(dataSize, new CacheResourceAddress(CacheResourceAddressType.Resource, 0));
            texture.Width       = (short)dds.Width;
            texture.Height      = (short)dds.Height;
            texture.Depth       = (sbyte)Math.Max(1, dds.Depth);
            texture.MipmapCount = (sbyte)Math.Max(1, dds.MipMapCount);
            texture.Type        = BitmapDdsFormatDetection.DetectType(dds);
            texture.D3DFormat   = (int)((dds.D3D10Format != DxgiFormat.Bc5UNorm) ? dds.FourCc : DdsFourCc.FromString("ATI2"));
            texture.Format      = BitmapDdsFormatDetection.DetectFormat(dds);

            // Set flags based on the format
            switch (texture.Format)
            {
            case BitmapFormat.Dxt1:
            case BitmapFormat.Dxt3:
            case BitmapFormat.Dxt5:
            case BitmapFormat.Dxn:
                texture.Flags = BitmapFlags.Compressed;
                break;

            default:
                texture.Flags = BitmapFlags.None;
                break;
            }
            if ((texture.Width & (texture.Width - 1)) == 0 && (texture.Height & (texture.Height - 1)) == 0)
            {
                texture.Flags |= BitmapFlags.PowerOfTwoDimensions;
            }

            // If creating a new image, then add a new resource, otherwise replace the existing one
            if (newResource)
            {
                resource.ChangeLocation(location);
                CacheContext.AddResource(resource, ddsStream);
            }
            else
            {
                CacheContext.ReplaceResource(resource, ddsStream);
            }

            // Serialize the new resource definition
            serializer.Serialize(resourceContext, definition);

            // Modify the image data in the bitmap tag to match the definition
            imageData.Width       = texture.Width;
            imageData.Height      = texture.Height;
            imageData.Depth       = texture.Depth;
            imageData.Type        = texture.Type;
            imageData.Format      = texture.Format;
            imageData.Flags       = texture.Flags;
            imageData.MipmapCount = (sbyte)(texture.MipmapCount - 1);
            imageData.DataOffset  = texture.Data.Address.Offset;
            imageData.DataSize    = texture.Data.Size;
            imageData.Curve       = (BitmapImageCurve)texture.Curve;
        }
示例#32
0
        private void ReadTagNamesSection(EndianReader reader, DataSerializationContext context, TagDeserializer deserializer)
        {
            var section = GetSectionHeader(reader, ModPackageSection.TagNames);

            if (!GoToSectionHeaderOffset(reader, section))
            {
                return;
            }

            var entry      = new GenericSectionEntry(reader);
            var cacheCount = entry.Count;

            TagCacheNames = new List <Dictionary <int, string> >();

            for (int i = 0; i < cacheCount; i++)
            {
                var nameDict = new Dictionary <int, string>();
                reader.BaseStream.Position = entry.TableOffset + 0x8 * i + section.Offset;

                var tagNamesTableEntry = new GenericTableEntry(reader);
                if (tagNamesTableEntry.Size == 0)
                {
                    throw new Exception("invalid tag name table entry size!");
                }

                reader.BaseStream.Position = tagNamesTableEntry.Offset + section.Offset;
                var tagNamesHeader = new GenericSectionEntry(reader);
                reader.BaseStream.Position = tagNamesHeader.TableOffset + section.Offset;

                for (int j = 0; j < tagNamesHeader.Count; j++)
                {
                    var tagNamesEntry = deserializer.Deserialize <ModPackageTagNamesEntry>(context);
                    nameDict.Add(tagNamesEntry.TagIndex, tagNamesEntry.Name);
                }

                TagCacheNames.Add(nameDict);
            }
        }
        public override bool Execute(List<string> args)
        {
            if (args.Count != 1)
                return false;

            var destDir = new DirectoryInfo(args[0]);
            if (!destDir.Exists)
            {
                Write("Destination directory does not exist. Create it? [y/n] ");
                var answer = ReadLine().ToLower();

                if (answer.Length == 0 || !(answer.StartsWith("y") || answer.StartsWith("n")))
                    return false;

                if (answer.StartsWith("y"))
                    destDir.Create();
                else
                    return false;
            }

            WriteLine($"Generating cache files in \"{destDir.FullName}\"...");

            var destTagsFile = new FileInfo(Combine(destDir.FullName, "tags.dat"));

            Write($"Generating {destTagsFile.FullName}...");
            using (var tagCacheStream = destTagsFile.Create())
            using (var writer = new BinaryWriter(tagCacheStream))
            {
                writer.Write((int)0); // padding
                writer.Write((int)0); // tag list offset
                writer.Write((int)0); // tag count
                writer.Write((int)0); // padding
                writer.Write((long)130713360239499012); // timestamp
                writer.Write((long)0); // padding
            }
            WriteLine("done.");

            var destStringIDsFile = new FileInfo(Combine(destDir.FullName, "string_ids.dat"));

            Write($"Generating {destStringIDsFile.FullName}...");
            using (var stringIDCacheStream = destStringIDsFile.Create())
            using (var writer = new BinaryWriter(stringIDCacheStream))
            {
                writer.Write((int)0); // string count
                writer.Write((int)0); // data size
            }
            WriteLine("done.");

            var resourceCachePaths = new string[]
            {
                Combine(destDir.FullName, "audio.dat"),
                Combine(destDir.FullName, "resources.dat"),
                Combine(destDir.FullName, "textures.dat"),
                Combine(destDir.FullName, "textures_b.dat"),
                Combine(destDir.FullName, "video.dat")
            };

            foreach (var resourceCachePath in resourceCachePaths)
            {
                Write($"Generating {resourceCachePath}...");
                using (var resourceCacheStream = File.Create(resourceCachePath))
                using (var writer = new BinaryWriter(resourceCacheStream))
                {
                    writer.Write((int)0); // padding
                    writer.Write((int)0); // table offset
                    writer.Write((int)0); // resource count
                    writer.Write((int)0); // padding
                }
                WriteLine("done.");
            }

            var dependencies = new Dictionary<int, TagInstance>();
            LoadTagDependencies(0, ref dependencies);
            LoadTagDependencies(0x16, ref dependencies);
            LoadTagDependencies(0x27D7, ref dependencies);
            
            var destResourcesFile = new FileInfo(Combine(destDir.FullName, "resources.dat"));
            if (!destResourcesFile.Exists)
            {
                WriteLine($"Destination resource cache file does not exist: {destResourcesFile.FullName}");
                return false;
            }

            var destTexturesFile = new FileInfo(Combine(destDir.FullName, "textures.dat"));
            if (!destTexturesFile.Exists)
            {
                WriteLine($"Destination texture cache file does not exist: {destTexturesFile.FullName}");
                return false;
            }

            var destTexturesBFile = new FileInfo(Combine(destDir.FullName, "textures_b.dat"));
            if (!destTexturesBFile.Exists)
            {
                WriteLine($"Destination texture cache file does not exist: {destTexturesBFile.FullName}");
                return false;
            }

            var destAudioFile = new FileInfo(Combine(destDir.FullName, "audio.dat"));
            if (!destAudioFile.Exists)
            {
                WriteLine($"Destination audio cache file does not exist: {destAudioFile.FullName}");
                return false;
            }
            
            TagCache destTagCache;
            using (var stream = destTagsFile.OpenRead())
                destTagCache = new TagCache(stream);

            DefinitionSet guessedVersion;
            var destVersion = Detect(destTagCache, out guessedVersion);
            if (destVersion == Unknown)
            {
                WriteLine($"Unrecognized target version! (guessed {GetVersionString(guessedVersion)})");
                return true;
            }

            WriteLine($"Destination cache version: {GetVersionString(destVersion)}");

            StringIDCache destStringIDCache;
            using (var stream = destStringIDsFile.OpenRead())
                destStringIDCache = new StringIDCache(stream, Create(destVersion));

            var destResources = new ResourceDataManager();
            destResources.LoadCachesFromDirectory(destDir.FullName);

            var srcResources = new ResourceDataManager();
            srcResources.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);

            var destSerializer = new TagSerializer(destVersion);
            var destDeserializer = new TagDeserializer(destVersion);

            var destInfo = new OpenTagCache
            {
                Cache = destTagCache,
                CacheFile = destTagsFile,
                StringIDs = destStringIDCache,
                StringIDsFile = destStringIDsFile,
                Version = destVersion,
                Serializer = destSerializer,
                Deserializer = destDeserializer
            };

            using (Stream srcStream = Info.OpenCacheRead(), destStream = destInfo.OpenCacheReadWrite())
            {
                var maxDependency = dependencies.Keys.Max();
                for (var i = 0; i <= maxDependency; i++)
                {
                    var srcTag = Info.Cache.Tags[i];
                    if (srcTag == null)
                    {
                        destInfo.Cache.AllocateTag();
                        continue;
                    }

                    var srcData = Info.Cache.ExtractTagRaw(srcStream, srcTag);

                    var destTag = destInfo.Cache.AllocateTag(srcTag.Group);
                    destInfo.Cache.SetTagDataRaw(destStream, destTag, srcData);

                    srcData = new byte[0];
                }
            }
            
            WriteLine($"Done generating cache files in \"{destDir.FullName}\".");

            return true;
        }
示例#34
0
        public override bool Execute(List <string> args)
        {
            if (args.Count != 1)
            {
                return(false);
            }

            var destDir = new DirectoryInfo(args[0]);

            if (!destDir.Exists)
            {
                Write("Destination directory does not exist. Create it? [y/n] ");
                var answer = ReadLine().ToLower();

                if (answer.Length == 0 || !(answer.StartsWith("y") || answer.StartsWith("n")))
                {
                    return(false);
                }

                if (answer.StartsWith("y"))
                {
                    destDir.Create();
                }
                else
                {
                    return(false);
                }
            }

            WriteLine($"Generating cache files in \"{destDir.FullName}\"...");

            var destTagsFile = new FileInfo(Combine(destDir.FullName, "tags.dat"));

            Write($"Generating {destTagsFile.FullName}...");
            using (var tagCacheStream = destTagsFile.Create())
                using (var writer = new BinaryWriter(tagCacheStream))
                {
                    writer.Write((int)0);                   // padding
                    writer.Write((int)0);                   // tag list offset
                    writer.Write((int)0);                   // tag count
                    writer.Write((int)0);                   // padding
                    writer.Write((long)130713360239499012); // timestamp
                    writer.Write((long)0);                  // padding
                }
            WriteLine("done.");

            var destStringIDsFile = new FileInfo(Combine(destDir.FullName, "string_ids.dat"));

            Write($"Generating {destStringIDsFile.FullName}...");
            using (var stringIDCacheStream = destStringIDsFile.Create())
                using (var writer = new BinaryWriter(stringIDCacheStream))
                {
                    writer.Write((int)0); // string count
                    writer.Write((int)0); // data size
                }
            WriteLine("done.");

            var resourceCachePaths = new string[]
            {
                Combine(destDir.FullName, "audio.dat"),
                Combine(destDir.FullName, "resources.dat"),
                Combine(destDir.FullName, "textures.dat"),
                Combine(destDir.FullName, "textures_b.dat"),
                Combine(destDir.FullName, "video.dat")
            };

            foreach (var resourceCachePath in resourceCachePaths)
            {
                Write($"Generating {resourceCachePath}...");
                using (var resourceCacheStream = File.Create(resourceCachePath))
                    using (var writer = new BinaryWriter(resourceCacheStream))
                    {
                        writer.Write((int)0); // padding
                        writer.Write((int)0); // table offset
                        writer.Write((int)0); // resource count
                        writer.Write((int)0); // padding
                    }
                WriteLine("done.");
            }

            var dependencies = new Dictionary <int, TagInstance>();

            LoadTagDependencies(0, ref dependencies);
            LoadTagDependencies(0x16, ref dependencies);
            LoadTagDependencies(0x27D7, ref dependencies);

            var destResourcesFile = new FileInfo(Combine(destDir.FullName, "resources.dat"));

            if (!destResourcesFile.Exists)
            {
                WriteLine($"Destination resource cache file does not exist: {destResourcesFile.FullName}");
                return(false);
            }

            var destTexturesFile = new FileInfo(Combine(destDir.FullName, "textures.dat"));

            if (!destTexturesFile.Exists)
            {
                WriteLine($"Destination texture cache file does not exist: {destTexturesFile.FullName}");
                return(false);
            }

            var destTexturesBFile = new FileInfo(Combine(destDir.FullName, "textures_b.dat"));

            if (!destTexturesBFile.Exists)
            {
                WriteLine($"Destination texture cache file does not exist: {destTexturesBFile.FullName}");
                return(false);
            }

            var destAudioFile = new FileInfo(Combine(destDir.FullName, "audio.dat"));

            if (!destAudioFile.Exists)
            {
                WriteLine($"Destination audio cache file does not exist: {destAudioFile.FullName}");
                return(false);
            }

            TagCache destTagCache;

            using (var stream = destTagsFile.OpenRead())
                destTagCache = new TagCache(stream);

            DefinitionSet guessedVersion;
            var           destVersion = Detect(destTagCache, out guessedVersion);

            if (destVersion == Unknown)
            {
                WriteLine($"Unrecognized target version! (guessed {GetVersionString(guessedVersion)})");
                return(true);
            }

            WriteLine($"Destination cache version: {GetVersionString(destVersion)}");

            StringIDCache destStringIDCache;

            using (var stream = destStringIDsFile.OpenRead())
                destStringIDCache = new StringIDCache(stream, Create(destVersion));

            var destResources = new ResourceDataManager();

            destResources.LoadCachesFromDirectory(destDir.FullName);

            var srcResources = new ResourceDataManager();

            srcResources.LoadCachesFromDirectory(Info.CacheFile.DirectoryName);

            var destSerializer   = new TagSerializer(destVersion);
            var destDeserializer = new TagDeserializer(destVersion);

            var destInfo = new OpenTagCache
            {
                Cache         = destTagCache,
                CacheFile     = destTagsFile,
                StringIDs     = destStringIDCache,
                StringIDsFile = destStringIDsFile,
                Version       = destVersion,
                Serializer    = destSerializer,
                Deserializer  = destDeserializer
            };

            using (Stream srcStream = Info.OpenCacheRead(), destStream = destInfo.OpenCacheReadWrite())
            {
                var maxDependency = dependencies.Keys.Max();
                for (var i = 0; i <= maxDependency; i++)
                {
                    var srcTag = Info.Cache.Tags[i];
                    if (srcTag == null)
                    {
                        destInfo.Cache.AllocateTag();
                        continue;
                    }

                    var srcData = Info.Cache.ExtractTagRaw(srcStream, srcTag);

                    var destTag = destInfo.Cache.AllocateTag(srcTag.Group);
                    destInfo.Cache.SetTagDataRaw(destStream, destTag, srcData);

                    srcData = new byte[0];
                }
            }

            WriteLine($"Done generating cache files in \"{destDir.FullName}\".");

            return(true);
        }
示例#35
0
        public override bool Execute(List<string> args)
        {
            if (args.Count != 2)
                return false;

            //
            // Verify the xbox scenario_structure_bsp tag
            //

            var bspName = args[0];
            var newTagIndex = ArgumentParser.ParseTagIndex(Info, args[1]);

            CacheFile.IndexItem item = null;

            Console.WriteLine("Verifying xbox tag...");

            foreach (var tag in BlamCache.IndexItems)
            {
                if (tag.ClassCode == "sbsp" && tag.Filename == bspName)
                {
                    item = tag;
                    break;
                }
            }

            if (item == null)
            {
                Console.WriteLine("Xbox tag does not exist: " + args[0]);
                return false;
            }

            //
            // Load the xbox scenario_structure_bsp tag
            //

            var xboxContext = new XboxSerializationContext(item);
            var deserializer = new TagDeserializer(BlamCache.Version);
            var sbsp = deserializer.Deserialize<ScenarioStructureBsp>(xboxContext);

            // blank resources that will be generated/converted from ODST automatically later
            var Resource1 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // render geo 1
            var Resource2 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // render geo 2
            var Resource3 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // collision BSP tag data
            var Resource4 = new ResourceReference() { Index = 1337, Owner = newTagIndex }; // other tag data and shit (unknown raw 3rd in halo 3, etc.)

            // Set the resource refs in the tag to the blank ones we just made
            sbsp.Geometry.Resource = Resource1;
            sbsp.Geometry2.Resource = Resource2;
            sbsp.CollisionBSPResource = Resource3;
            sbsp.Resource4 = Resource4;

            using (var cacheStream = Info.CacheFile.Open(FileMode.Open, FileAccess.ReadWrite))
            {
                Console.WriteLine("Writing ElDewrito tag to tag " + newTagIndex+"...");

                var context = new TagSerializationContext(cacheStream, Info.Cache, Info.StringIDs, Info.Cache.Tags[newTagIndex.Index]);
                Info.Serializer.Serialize(context, sbsp);
            }

            return true;
        }