Пример #1
0
        private void SaveZoneSetTable(IZoneSet[] sets, StructureValueCollection tagValues, string countName, string addressName, TagBlockCache <int> cache, IStream stream)
        {
            if (!tagValues.HasInteger(countName) || !tagValues.HasInteger(addressName))
            {
                return;
            }

            var count = (int)tagValues.GetInteger(countName);

            if (count != sets.Length)
            {
                throw new InvalidOperationException("Zone set count does not match");
            }

            uint address = (uint)tagValues.GetInteger(addressName);

            long expand = _expander.Expand(address);

            StructureLayout layout = _buildInfo.Layouts.GetLayout("zone set definition");
            List <StructureValueCollection> entries =
                sets.Select(set => ((ThirdGenZoneSet)set).Serialize(stream, _allocator, cache, _expander)).ToList();

            TagBlockWriter.WriteTagBlock(entries, expand, layout, _metaArea, stream);
        }
Пример #2
0
        private void Load(StructureValueCollection values, IReader reader, FileSegmentGroup metaArea, StringIDSource stringIDs,
                          EngineDescription buildInfo)
        {
            Name = values.HasInteger("name index")
                                ? stringIDs.GetString(new StringID(values.GetInteger("name index")))
                                : values.GetString("name");
            ExecutionType       = (short)values.GetInteger("execution type");
            ReturnType          = (short)values.GetInteger("return type");
            RootExpressionIndex = new DatumIndex(values.GetInteger("first expression index"));
            if (Name == null)
            {
                Name = "script_" + RootExpressionIndex.Value.ToString("X8");
            }

            Parameters = LoadParameters(reader, values, metaArea, buildInfo);
        }
Пример #3
0
        private void SaveTags(StructureValueCollection headerValues, int offset, IStream stream)
        {
            StructureLayout layout = _buildInfo.Layouts.GetLayout("tag element");
            IEnumerable <StructureValueCollection> entries = _tags.Select(t => ((SecondGenTag)t).Serialize());
            var addr = _metaArea.OffsetToPointer(_metaArea.Offset + offset);

            TagBlockWriter.WriteTagBlock(entries, addr, layout, _metaArea, stream);

            uint adjustedOffset = (uint)offset;

            if (headerValues.HasInteger("meta header mask"))
            {
                adjustedOffset += (uint)headerValues.GetInteger("meta header mask");
            }

            headerValues.SetInteger("number of tags", (uint)_tags.Count);
            headerValues.SetInteger("tag table offset", adjustedOffset);
        }
Пример #4
0
        private SecondGenHeader LoadHeader(IReader reader, out uint primaryMask)
        {
            primaryMask = 0;
            reader.SeekTo(0);
            StructureValueCollection values = StructureReader.ReadStructure(reader, _buildInfo.Layouts.GetLayout("header"));

            //set up a mask for xbox if needed
            if (!values.HasInteger("meta offset mask"))
            {
                //oh boy
                StructureLayout indexHeaderLayout = _buildInfo.Layouts.GetLayout("meta header");
                StructureLayout tagElementLayout  = _buildInfo.Layouts.GetLayout("tag element");

                uint indexHeaderOffset = (uint)values.GetInteger("meta offset");

                reader.SeekTo(indexHeaderOffset + indexHeaderLayout.GetFieldOffset("tag table offset"));
                uint tagTableAddress = reader.ReadUInt32();

                uint maskReference;
                if (indexHeaderLayout.HasField("tag group table offset"))
                {
                    reader.SeekTo(indexHeaderOffset + indexHeaderLayout.GetFieldOffset("tag group table offset"));
                    maskReference = reader.ReadUInt32();
                }
                else
                {
                    maskReference = tagTableAddress;
                }

                primaryMask = maskReference - (uint)indexHeaderLayout.Size;
                uint tagTableOffset = tagTableAddress - primaryMask + indexHeaderOffset;

                reader.SeekTo(tagTableOffset + tagElementLayout.GetFieldOffset("offset"));
                uint firstTagAddress = reader.ReadUInt32();

                values.SetInteger("xbox meta offset mask", firstTagAddress - (uint)values.GetInteger("tag data offset"));
            }

            return(new SecondGenHeader(values, _buildInfo, _segmenter));
        }
Пример #5
0
        private FirstGenHeader LoadHeader(IReader reader, out uint mask)
        {
            mask = 0;
            reader.SeekTo(0);
            StructureValueCollection values = StructureReader.ReadStructure(reader, _buildInfo.Layouts.GetLayout("header"));

            // hack to pack meta header size for metaOffsetMask calculation
            var oldReadPos = reader.Position;

            if (values.HasInteger("tag data offset"))
            {
                //oh boy
                StructureLayout indexHeaderLayout = _buildInfo.Layouts.GetLayout("meta header");
                StructureLayout tagElementLayout  = _buildInfo.Layouts.GetLayout("tag element");

                uint indexHeaderOffset = (uint)values.GetInteger("meta offset");
                reader.SeekTo(indexHeaderOffset);
                uint firstVal = reader.ReadUInt32();
                reader.SeekTo(indexHeaderOffset + indexHeaderLayout.GetFieldOffset("tag table offset"));
                uint tagTableAddress = reader.ReadUInt32();
                mask = firstVal - (uint)indexHeaderLayout.Size;
                uint tagTableOffset = tagTableAddress - mask + indexHeaderOffset;

                reader.SeekTo(tagTableOffset + tagElementLayout.GetFieldOffset("offset"));
                uint firstTagAddress = reader.ReadUInt32();

                values.SetInteger("xbox meta offset mask", firstTagAddress - (uint)values.GetInteger("tag data offset"));
            }
            else
            {
                reader.SeekTo((long)values.GetInteger("meta offset"));
                var tagTableOffset = reader.ReadUInt32();
                values.SetInteger("meta header size", (ulong)_buildInfo.Layouts.GetLayout("meta header").Size);
                values.SetInteger("tag table offset", (ulong)tagTableOffset);
            }


            return(new FirstGenHeader(values, _buildInfo, _segmenter));
        }
Пример #6
0
        private void CalculateStringGroup(StructureValueCollection values, FileSegmenter segmenter)
        {
            if (DebugPointerConverter == null)
            {
                return;
            }

            StringArea = new FileSegmentGroup(DebugPointerConverter);

            // StringIDs
            StringIDCount = (int)values.GetInteger("string table count");
            if (StringIDCount > 0)
            {
                int sidIndexTableOff = DebugPointerConverter.PointerToOffset((uint)values.GetInteger("string index table offset"));
                int sidDataOff       = DebugPointerConverter.PointerToOffset((uint)values.GetInteger("string table offset"));

                var sidTableSize = (int)values.GetInteger("string table size");
                StringIDIndexTable = segmenter.WrapSegment(sidIndexTableOff, StringIDCount * 4, 4, SegmentResizeOrigin.End);
                StringIDData       = segmenter.WrapSegment(sidDataOff, sidTableSize, 1, SegmentResizeOrigin.End);

                StringIDIndexTableLocation = StringArea.AddSegment(StringIDIndexTable);
                StringIDDataLocation       = StringArea.AddSegment(StringIDData);

                // idk what this is, but H3Beta has it
                if (values.HasInteger("string block offset"))
                {
                    int sidBlockOff = DebugPointerConverter.PointerToOffset((uint)values.GetInteger("string block offset"));
                    StringBlock         = segmenter.WrapSegment(sidBlockOff, StringIDCount * 0x80, 0x80, SegmentResizeOrigin.End);
                    StringBlockLocation = StringArea.AddSegment(StringBlock);
                }

                // newest reach mcc caches store namespace information, hopefully others follow because thats one less thing to worry about every update
                if (values.HasInteger("string namespace table count"))
                {
                    StringIDNamespaceCount = (int)values.GetInteger("string namespace table count");
                    if (StringIDNamespaceCount > 0)
                    {
                        int namespaceTableOff = DebugPointerConverter.PointerToOffset((uint)values.GetInteger("string namespace table offset"));

                        StringIDNamespaceTable = segmenter.WrapSegment(namespaceTableOff, StringIDNamespaceCount * 4, 4, SegmentResizeOrigin.End);

                        StringIDNamespaceTableLocation = StringArea.AddSegment(StringIDNamespaceTable);
                    }
                }
            }

            // Tag names
            FileNameCount = (int)values.GetInteger("file table count");
            if (FileNameCount > 0)
            {
                int nameIndexTableOff = DebugPointerConverter.PointerToOffset((uint)values.GetInteger("file index table offset"));
                int nameDataOff       = DebugPointerConverter.PointerToOffset((uint)values.GetInteger("file table offset"));

                var fileTableSize = (int)values.GetInteger("file table size");
                FileNameIndexTable = segmenter.WrapSegment(nameIndexTableOff, FileNameCount * 4, 4, SegmentResizeOrigin.End);
                FileNameData       = segmenter.WrapSegment(nameDataOff, fileTableSize, 1, SegmentResizeOrigin.End);

                FileNameIndexTableLocation = StringArea.AddSegment(FileNameIndexTable);
                FileNameDataLocation       = StringArea.AddSegment(FileNameData);
            }

            // Some H4-only unknown table
            if (values.HasInteger("unknown table count") && values.HasInteger("unknown table offset"))
            {
                UnknownCount = (int)values.GetInteger("unknown table count");
                if (UnknownCount > 0)
                {
                    int unknownOff = DebugPointerConverter.PointerToOffset((uint)values.GetInteger("unknown table offset"));
                    UnknownTable         = segmenter.WrapSegment(unknownOff, UnknownCount * 0x10, 0x10, SegmentResizeOrigin.End);
                    UnknownTableLocation = StringArea.AddSegment(UnknownTable);
                }
            }
        }
Пример #7
0
        private Resource LoadResource(StructureValueCollection values, int index, TagTable tags,
                                      IList <ResourcePointer> pointers, byte[] infoBuffer, IReader reader)
        {
            var result = new Resource();

            var parentTag = new DatumIndex(values.GetInteger("parent tag datum index"));

            result.ParentTag = parentTag.IsValid ? tags[parentTag] : null;
            var salt = (ushort)values.GetInteger("datum index salt");

            result.Index = new DatumIndex(salt, (ushort)index);
            var typeIndex = (int)values.GetInteger("resource type index");

            if (typeIndex >= 0 && typeIndex < _resourceTypes.Length)
            {
                result.Type = _resourceTypes[typeIndex].Name;
            }
            result.Flags = (uint)values.GetInteger("flags");

            var infoSize = (int)values.GetInteger("resource info size");

            if (infoSize > 0)
            {
                var infoOffset = 0;

                if (values.HasInteger("number of resource info offsets"))                //for h4
                {
                    var  infocount = (int)values.GetInteger("number of resource info offsets");
                    uint address   = (uint)values.GetInteger("resource info offsets table address");

                    long expand = _expander.Expand(address);

                    StructureLayout            layout  = _buildInfo.Layouts.GetLayout("resource info offset entry");
                    StructureValueCollection[] entries = ReflexiveReader.ReadReflexive(reader, infocount, expand, layout, _metaArea);

                    if (infocount > 0)
                    {
                        infoOffset = (int)entries[0].GetInteger("offset");
                    }
                }
                else
                {
                    infoOffset = (int)values.GetInteger("resource info offset");
                }

                // Copy the section of the info buffer that the resource is pointing to
                result.Info = new byte[infoSize];
                Buffer.BlockCopy(infoBuffer, infoOffset, result.Info, 0, infoSize);
            }

            result.ResourceBits = (ushort)values.GetInteger("resource bits");
            var segmentIndex = (int)values.GetInteger("segment index");

            result.Location = (segmentIndex >= 0) ? pointers[segmentIndex] : null;
            result.BaseDefinitionAddress = (int)values.GetInteger("base definition address");

            result.ResourceFixups.AddRange(LoadResourceFixups(values, reader));
            result.DefinitionFixups.AddRange(LoadDefinitionFixups(values, reader));

            return(result);
        }
Пример #8
0
        public IEnumerable <ResourcePredictionD> LoadPredictions(IReader reader, TagTable tags, List <Resource> resources)
        {
            StructureValueCollection values = LoadTag(reader);

            if (!values.HasInteger("number of prediction d2s") || !values.HasInteger("prediction d2 table address"))
            {
                return(null);
            }

            int             subcount   = 2;
            StructureLayout templayout = _buildInfo.Layouts.GetLayout("raw segment table entry");

            if (templayout.HasField("tertiary page index"))
            {
                subcount = 3;
            }

            var result = new List <ResourcePredictionD>();

            StructureValueCollection[] d2entries = ReadReflexive(values, reader, "number of prediction d2s", "prediction d2 table address", "prediction d2 entry");
            StructureValueCollection[] dentries  = ReadReflexive(values, reader, "number of prediction ds", "prediction d table address", "prediction d entry");
            StructureValueCollection[] centries  = ReadReflexive(values, reader, "number of prediction cs", "prediction c table address", "prediction c entry");
            StructureValueCollection[] bentries  = ReadReflexive(values, reader, "number of prediction bs", "prediction b table address", "prediction b entry");
            StructureValueCollection[] aentries  = ReadReflexive(values, reader, "number of prediction as", "prediction a table address", "prediction a entry");

            for (int i = 0; i < d2entries.Length; i++)
            {
                ResourcePredictionD pd = new ResourcePredictionD();
                pd.Index = i;
                var tag = new DatumIndex(d2entries[i].GetInteger("tag datum"));
                pd.Tag      = tag.IsValid ? tags[tag] : null;
                pd.Unknown1 = (int)d2entries[i].GetInteger("unknown 1");
                pd.Unknown2 = (int)d2entries[i].GetInteger("unknown 2");

                var dccount = (int)dentries[i].GetInteger("c count");
                var dcindex = (int)dentries[i].GetInteger("c index");

                var dacount = (int)dentries[i].GetInteger("a count");
                var daindex = (int)dentries[i].GetInteger("a index");

                for (int c = dcindex; c < dcindex + dccount; c++)
                {
                    ResourcePredictionC pc = new ResourcePredictionC();
                    pc.Index = c;
                    var cbindex = (int)centries[c].GetInteger("b index");
                    pc.OverallIndex = (short)centries[c].GetInteger("overall index");

                    ResourcePredictionB pb = new ResourcePredictionB();
                    pb.Index = cbindex;
                    var bacount = (int)bentries[cbindex].GetInteger("a count");
                    var baindex = (int)bentries[cbindex].GetInteger("a index");
                    pb.OverallIndex = (short)bentries[cbindex].GetInteger("overall index");

                    for (int a = baindex; a < baindex + bacount; a++)
                    {
                        ResourcePredictionA pa = new ResourcePredictionA();
                        pa.Index = a;
                        pa.Value = new DatumIndex(aentries[a].GetInteger("value"));

                        int resolvedresource = pa.Value.Index / subcount;
                        int subresource      = pa.Value.Index - resolvedresource * subcount;

                        if (resolvedresource >= resources.Count)
                        {
                            continue;
                        }
                        var res = resources[resolvedresource];

                        pa.Resource    = res.Index;
                        pa.SubResource = subresource;

                        pb.AEntries.Add(pa);
                    }

                    pc.BEntry = pb;
                    pd.CEntries.Add(pc);
                }

                for (int a = daindex; a < daindex + dacount; a++)
                {
                    ResourcePredictionA pa = new ResourcePredictionA();
                    pa.Index = a;
                    pa.Value = new DatumIndex(aentries[a].GetInteger("value"));

                    int resolvedresource = pa.Value.Index / subcount;
                    int subresource      = pa.Value.Index - resolvedresource * subcount;

                    if (resolvedresource >= resources.Count)
                    {
                        continue;
                    }
                    var res = resources[resolvedresource];

                    pa.Resource    = res.Index;
                    pa.SubResource = subresource;

                    pd.AEntries.Add(pa);
                }
                result.Add(pd);
            }
            return(result);
        }
Пример #9
0
        private void Load(StructureValueCollection values, FileSegmenter segmenter)
        {
            _eofSegment = segmenter.WrapEOF((int)values.GetInteger("file size"));

            var metaOffset = (int)values.GetInteger("meta offset");

            int tagTableSize = (int)values.GetInteger("tag data offset");
            int tagDataSize  = (int)values.GetInteger("tag data size");

            var headSegment = new FileSegment(
                segmenter.DefineSegment(metaOffset, tagTableSize, 0x1000, SegmentResizeOrigin.Beginning), segmenter);

            //xbox haxx, we can assume thru the existance of the code-set xbox mask
            uint        metaOffsetMask;
            FileSegment metaSegment = null;

            if (values.HasInteger("xbox meta offset mask"))
            {
                // store the stock meta size since xbox's size is virtual
                //todo: figure out how this is calculated instead of doing a hack
                _saved_meta_size_hack = (uint)values.GetInteger("meta size");

                metaOffsetMask = (uint)values.GetInteger("xbox meta offset mask");

                metaSegment = new FileSegment(
                    segmenter.DefineSegment(metaOffset + tagTableSize, tagDataSize, 0x4, SegmentResizeOrigin.End), segmenter);
            }
            else
            {
                metaOffsetMask = (uint)values.GetInteger("meta offset mask");

                metaSegment = new FileSegment(
                    segmenter.DefineSegment(metaOffset + tagTableSize, tagDataSize, 0x1000, SegmentResizeOrigin.End), segmenter);
            }

            MetaArea = new FileSegmentGroup(new MetaOffsetConverter(headSegment, metaOffsetMask));

            IndexHeaderLocation = MetaArea.AddSegment(headSegment);
            MetaArea.AddSegment(metaSegment);

            Type = (CacheFileType)values.GetInteger("type");

            var headerGroup = new FileSegmentGroup();

            headerGroup.AddSegment(segmenter.WrapSegment(0, HeaderSize, 1, SegmentResizeOrigin.None));

            StringIDCount = (int)values.GetInteger("string table count");
            var sidDataSize = (int)values.GetInteger("string table size");

            StringIDData = segmenter.WrapSegment((int)values.GetInteger("string table offset"), sidDataSize, 1,
                                                 SegmentResizeOrigin.End);
            StringIDIndexTable = segmenter.WrapSegment((int)values.GetInteger("string index table offset"), StringIDCount * 4, 4,
                                                       SegmentResizeOrigin.End);

            if (values.HasInteger("file table count"))
            {
                FileNameCount = (int)values.GetInteger("file table count");
                var fileDataSize = (int)values.GetInteger("file table size");
                FileNameData = segmenter.WrapSegment((int)values.GetInteger("file table offset"), fileDataSize, 1,
                                                     SegmentResizeOrigin.End);
                FileNameIndexTable = segmenter.WrapSegment((int)values.GetInteger("file index table offset"), FileNameCount * 4, 4,
                                                           SegmentResizeOrigin.End);
            }

            InternalName = values.GetString("internal name");
            ScenarioName = values.GetString("scenario name");

            StringArea = new FileSegmentGroup();
            if (values.HasInteger("string block offset"))
            {
                StringArea.AddSegment(segmenter.WrapSegment((int)values.GetInteger("string block offset"), StringIDCount * 0x80, 0x80,
                                                            SegmentResizeOrigin.End));
            }
            StringArea.AddSegment(StringIDIndexTable);
            StringArea.AddSegment(StringIDData);

            StringIDIndexTableLocation = SegmentPointer.FromOffset(StringIDIndexTable.Offset, StringArea);
            StringIDDataLocation       = SegmentPointer.FromOffset(StringIDData.Offset, StringArea);

            if (FileNameIndexTable != null)
            {
                StringArea.AddSegment(FileNameIndexTable);
                StringArea.AddSegment(FileNameData);

                FileNameIndexTableLocation = SegmentPointer.FromOffset(FileNameIndexTable.Offset, StringArea);
                FileNameDataLocation       = SegmentPointer.FromOffset(FileNameData.Offset, StringArea);
            }

            int rawTableOffset;
            int rawTableSize;

            if (values.HasInteger("raw table offset"))
            {
                rawTableOffset = (int)values.GetInteger("raw table offset");
                rawTableSize   = (int)values.GetInteger("raw table size");
                // It is apparently possible to create a cache without a raw table, but -1 gets written as the offset
                if (rawTableOffset != -1)
                {
                    RawTable = segmenter.WrapSegment(rawTableOffset, rawTableSize, 0x80, SegmentResizeOrigin.End);
                }
            }

            Checksum = (uint)values.GetInteger("checksum");

            // Set up a bogus partition table
            Partitions    = new Partition[1];
            Partitions[0] = new Partition(SegmentPointer.FromOffset(MetaArea.Offset, MetaArea), (uint)MetaArea.Size);
        }
Пример #10
0
        /*
         * private void LoadInteropData(StructureValueCollection map_values, StructureValueCollection tag_values)
         *      {
         *              // TODO: fix this shit for the h3beta
         *              //SectionOffsetMasks = headerValues.GetArray("offset masks").Select(v => v.GetInteger("mask")).ToArray();
         *              //Sections = headerValues.GetArray("sections").Select(v => new FourthGenInteropSection(v)).ToArray();
         *
         *              //DebugPointerConverter = MakePointerConverter(FourthGenInteropSectionType.Debug);
         *              //ResourcePointerConverter = MakePointerConverter(FourthGenInteropSectionType.Resource);
         *              //TagBufferPointerConverter = MakePointerConverter(FourthGenInteropSectionType.Tag);
         *              //LocalePointerConverter = MakePointerConverter(FourthGenInteropSectionType.Localization);
         *      }
         */
        /*
         *      private BasedPointerConverter MakePointerConverter(uint tags_data_size)
         *      {
         *
         *              if (Sections[(int) section].Size == 0)
         *                      return null;
         *
         *              uint baseAddress = Sections[(int) section].VirtualAddress;
         *              uint mask = SectionOffsetMasks[(int) section];
         *              return new BasedPointerConverter(baseAddress, (int) (baseAddress + mask));
         *
         *  return new BasedPointerConverter(0, 0);
         *      }
         */

        /*
         *      private FileSegment CalculateRawTableSegment(FileSegmenter segmenter)
         *      {
         *              if (ResourcePointerConverter != null)
         *              {
         *                      int rawTableOffset = ResourcePointerConverter.PointerToOffset(ResourcePointerConverter.BasePointer);
         *                      var rawTableSize = (int) Sections[(int) FourthGenInteropSectionType.Resource].Size;
         *                      return segmenter.WrapSegment(rawTableOffset, rawTableSize, 0x1000, SegmentResizeOrigin.End);
         *              }
         *              return null;
         *      }
         */
        /*
         * // TODO: Replace this function with the ability to parse the tags.dat file for this information.
         *      private FileSegment CalculateTagDataSegment(StructureValueCollection values, FileSegmenter segmenter)
         *      {
         *  int tagDataOffset = (int)values.GetInteger("tag buffer offset");
         *
         *
         *
         *              if (TagBufferPointerConverter != null)
         *              {
         *                      int tagDataOffset = TagBufferPointerConverter.PointerToOffset(TagBufferPointerConverter.BasePointer);
         *                      var tagDataSize = (int) values.GetInteger("virtual size");
         *                      return segmenter.WrapSegment(tagDataOffset, tagDataSize, 0x10000, SegmentResizeOrigin.Beginning);
         *              }
         *              return null;
         *      }
         */

        private void CalculateStringGroup(StructureValueCollection values, FileSegmenter segmenter)
        {
            if (DebugPointerConverter == null)
            {
                return;
            }

            StringArea = new FileSegmentGroup(DebugPointerConverter);

            // StringIDs
            StringIDCount = (int)values.GetInteger("string table count");
            if (StringIDCount > 0)
            {
                int sidIndexTableOff = DebugPointerConverter.PointerToOffset(values.GetInteger("string index table offset"));
                int sidDataOff       = DebugPointerConverter.PointerToOffset(values.GetInteger("string table offset"));

                var sidTableSize = (int)values.GetInteger("string table size");
                StringIDIndexTable = segmenter.WrapSegment(sidIndexTableOff, StringIDCount * 4, 4, SegmentResizeOrigin.End);
                StringIDData       = segmenter.WrapSegment(sidDataOff, sidTableSize, 1, SegmentResizeOrigin.End);

                StringIDIndexTableLocation = StringArea.AddSegment(StringIDIndexTable);
                StringIDDataLocation       = StringArea.AddSegment(StringIDData);

                // idk what this is, but H3Beta has it
                if (values.HasInteger("string block offset"))
                {
                    int sidBlockOff = DebugPointerConverter.PointerToOffset(values.GetInteger("string block offset"));
                    StringBlock         = segmenter.WrapSegment(sidBlockOff, StringIDCount * 0x80, 0x80, SegmentResizeOrigin.End);
                    StringBlockLocation = StringArea.AddSegment(StringBlock);
                }
            }

            /*
             *          // Tag names
             *          FileNameCount = (int) values.GetInteger("file table count");
             *          if (FileNameCount > 0)
             *          {
             *                  int nameIndexTableOff = DebugPointerConverter.PointerToOffset(values.GetInteger("file index table offset"));
             *                  int nameDataOff = DebugPointerConverter.PointerToOffset(values.GetInteger("file table offset"));
             *
             *                  var fileTableSize = (int) values.GetInteger("file table size");
             *                  FileNameIndexTable = segmenter.WrapSegment(nameIndexTableOff, FileNameCount*4, 4, SegmentResizeOrigin.End);
             *                  FileNameData = segmenter.WrapSegment(nameDataOff, fileTableSize, 1, SegmentResizeOrigin.End);
             *
             *                  FileNameIndexTableLocation = StringArea.AddSegment(FileNameIndexTable);
             *                  FileNameDataLocation = StringArea.AddSegment(FileNameData);
             *          }
             */
            /*
             * // Some H4-only unknown table
             * if (values.HasInteger("unknown table count") && values.HasInteger("unknown table offset"))
             * {
             *  UnknownCount = (int) values.GetInteger("unknown table count");
             *  if (UnknownCount > 0)
             *  {
             *      int unknownOff = DebugPointerConverter.PointerToOffset(values.GetInteger("unknown table offset"));
             *      UnknownTable = segmenter.WrapSegment(unknownOff, UnknownCount*0x10, 0x10, SegmentResizeOrigin.End);
             *      UnknownTableLocation = StringArea.AddSegment(UnknownTable);
             *  }
             * }
             */
        }
Пример #11
0
        private static void DecompressSecondGen(string file, StructureValueCollection headerValues)
        {
            using (MemoryStream msOutput = new MemoryStream())
            {
                using (FileStream fsInput = new FileStream(file, FileMode.Open))
                {
                    using (BinaryReader brInput = new BinaryReader(fsInput))
                    {
                        //constants
                        int headerSize = (int)headerValues.GetInteger("_header_length_");
                        int chunkSize  = headerValues.HasInteger("compression data chunk size") ?
                                         (int)headerValues.GetInteger("compression data chunk size") : 0x40000;
                        uint chunkTableOffset = headerValues.HasInteger("compression chunk table offset") ?
                                                (uint)headerValues.GetInteger("compression chunk table offset") : (uint)headerSize;
                        int chunkCount = headerValues.HasInteger("compression chunk table count") ?
                                         (int)headerValues.GetInteger("compression chunk table count") : 0x400;

                        //header is uncompressed
                        msOutput.Write(brInput.ReadBytes(headerSize), 0, headerSize);

                        List <Tuple <int, int> > Chunks = new List <Tuple <int, int> >();

                        fsInput.Seek(chunkTableOffset, SeekOrigin.Begin);

                        for (int i = 0; i < chunkCount; i++)
                        {
                            int csize  = brInput.ReadInt32();
                            int offset = brInput.ReadInt32();

                            if (csize == 0)
                            {
                                break;
                            }

                            if (offset >= fsInput.Length)
                            {
                                throw new ArgumentException("Chunk " + i + " has an offset past the end of the file.");
                            }

                            Chunks.Add(new Tuple <int, int>(csize, offset));
                        }

                        //Decompress and write each chunk
                        for (int i = 0; i < Chunks.Count; i++)
                        {
                            //check for faux-compression some other tools use
                            if (Chunks[i].Item1 < 0)
                            {
                                int    invertedSize = -Chunks[i].Item1;
                                byte[] aaa          = new byte[invertedSize];

                                fsInput.Seek(Chunks[i].Item2, SeekOrigin.Begin);

                                int readSize = fsInput.Read(aaa, 0, invertedSize);

                                msOutput.Write(aaa, 0, readSize);
                            }
                            else
                            {
                                fsInput.Seek(Chunks[i].Item2 + 2, SeekOrigin.Begin);

                                int    realsize  = chunkSize;
                                byte[] chunkData = new byte[realsize];

                                using (DeflateStream ds = new DeflateStream(fsInput, CompressionMode.Decompress, true))
                                {
                                    realsize = ds.Read(chunkData, 0, chunkData.Length);
                                }

                                msOutput.Write(chunkData, 0, realsize);
                            }
                        }

                        //clear compressed bit so it can run ingame
                        if (headerValues.HasInteger("flags"))
                        {
                            fsInput.Seek((long)headerValues.GetInteger("_header_flags_"), SeekOrigin.Begin);
                            int flags = brInput.ReadInt16();
                            flags &= 0x7FFFFFFE;

                            msOutput.Seek((long)headerValues.GetInteger("_header_flags_"), SeekOrigin.Begin);
                            msOutput.Write(BitConverter.GetBytes((short)flags), 0, 2);
                        }
                    }
                }
                File.WriteAllBytes(file, msOutput.ToArray());
            }
        }
Пример #12
0
        private static void CompressSecondGen(string file, StructureValueCollection headerValues)
        {
            using (MemoryStream msOutput = new MemoryStream())
            {
                using (BinaryWriter bwOutput = new BinaryWriter(msOutput))
                {
                    using (FileStream fsInput = new FileStream(file, FileMode.Open))
                    {
                        List <Tuple <int, int> > Chunks = new List <Tuple <int, int> >();

                        //constants
                        int  headerSize    = (int)headerValues.GetInteger("_header_length_");
                        int  chunkSize     = 0x40000;
                        int  chunkSizeMask = 0x3FFFF;
                        bool newFormat     = headerValues.HasInteger("compression data chunk size");
                        uint dataStart     = newFormat ? (uint)headerSize : 0x3000;

                        //header is uncompressed
                        byte[] header = new byte[headerSize];
                        fsInput.Read(header, 0, headerSize);
                        msOutput.Write(header, 0, headerSize);

                        int datalength = (int)fsInput.Length - headerSize;
                        int chunkcount = ((datalength + chunkSizeMask) & ~chunkSizeMask) / chunkSize;

                        msOutput.Position = dataStart;

                        while (fsInput.Position < fsInput.Length)
                        {
                            int size = chunkSize;
                            if (fsInput.Length - fsInput.Position < size)
                            {
                                size = datalength % chunkSize;
                            }

                            int start = (int)msOutput.Position;

                            // 1) deflatestream doesnt write a header.
                            // 2) this specific header (x2815) is whats used internally, and h2 mcc wont load without it, regardless of the actual data
                            bwOutput.Write((short)5416);

                            using (DeflateStream ds = new DeflateStream(msOutput, CompressionMode.Compress, true))
                            {
                                byte[] chunkData = new byte[size];
                                fsInput.Read(chunkData, 0, size);
                                ds.Write(chunkData, 0, chunkData.Length);
                            }

                            int complength = (int)msOutput.Position - start;
                            Chunks.Add(new Tuple <int, int>(complength, start));

                            //each chunk is padded
                            long remainder = complength % 0x80;
                            msOutput.Seek(0x80 - remainder, SeekOrigin.Current);
                        }

                        uint tableOffset = newFormat ? (uint)msOutput.Position : (uint)headerSize;
                        int  tableSize   = chunkcount * 8;

                        msOutput.Position = tableOffset;

                        for (int i = 0; i < chunkcount; i++)
                        {
                            bwOutput.Write(Chunks[i].Item1);
                            bwOutput.Write(Chunks[i].Item2);
                        }

                        if (newFormat)
                        {
                            //table is padded in the new format
                            long remainder = tableSize % 0x80;
                            msOutput.Seek(0x80 - remainder - 1, SeekOrigin.Current);
                            bwOutput.Write((byte)0);

                            //write info to header
                            msOutput.Seek((long)headerValues.GetInteger("_header_chunk_size_"), SeekOrigin.Begin);
                            bwOutput.Write(chunkSize);

                            msOutput.Seek((long)headerValues.GetInteger("_header_data_offset_"), SeekOrigin.Begin);
                            bwOutput.Write(headerSize);

                            msOutput.Seek((long)headerValues.GetInteger("_header_chunks_offset_"), SeekOrigin.Begin);
                            bwOutput.Write(tableOffset);

                            msOutput.Seek((long)headerValues.GetInteger("_header_chunk_count_"), SeekOrigin.Begin);
                            bwOutput.Write(chunkcount);

                            //write compressed bit
                            int flags = BitConverter.ToInt16(header, (int)headerValues.GetInteger("_header_flags_"));

                            flags |= 1;

                            msOutput.Seek((long)headerValues.GetInteger("_header_flags_"), SeekOrigin.Begin);
                            bwOutput.Write((short)flags);
                        }
                    }
                    File.WriteAllBytes(file, msOutput.ToArray());
                }
            }
        }
Пример #13
0
        private void Load(StructureValueCollection values, FileSegmenter segmenter)
        {
            _eofSegment = segmenter.WrapEOF((int)values.GetInteger("file size"));

            var metaOffset = (int)values.GetInteger("meta offset");

            int metaSize;

            if (values.HasInteger("tag data offset"))
            {
                metaSize = (int)values.GetInteger("tag data offset") + (int)values.GetInteger("tag data size");
            }
            else
            {
                metaSize = (int)values.GetInteger("meta size");
            }

            // store the stock meta size since xbox's size is virtual
            //todo: figure out how this is calculated instead of doing a hack
            _saved_meta_size_hack = (uint)values.GetInteger("meta size");

            var metaSegment = new FileSegment(
                segmenter.DefineSegment(metaOffset, metaSize, 0x4, SegmentResizeOrigin.Beginning), segmenter);

            uint metaOffsetMask;

            if (values.HasInteger("xbox meta offset mask"))
            {
                metaOffsetMask = (uint)values.GetInteger("xbox meta offset mask");
            }
            else
            {
                metaOffsetMask = (uint)(values.GetInteger("tag table offset") - values.GetInteger("meta header size"));
            }

            MetaArea = new FileSegmentGroup(new MetaOffsetConverter(metaSegment, metaOffsetMask));

            IndexHeaderLocation = MetaArea.AddSegment(metaSegment);

            Type = (CacheFileType)values.GetInteger("type");
            var headerGroup = new FileSegmentGroup();

            headerGroup.AddSegment(segmenter.WrapSegment(0, HeaderSize, 1, SegmentResizeOrigin.None));

            //h2 alpha forcing this to be shoved in
            if (values.HasInteger("string table count"))
            {
                StringIDCount = (int)values.GetInteger("string table count");
                var sidDataSize = (int)values.GetInteger("string table size");
                StringIDData = segmenter.WrapSegment((int)values.GetInteger("string table offset"), sidDataSize, 1,
                                                     SegmentResizeOrigin.End);
                StringIDIndexTable = segmenter.WrapSegment((int)values.GetInteger("string index table offset"), StringIDCount * 4, 4,
                                                           SegmentResizeOrigin.End);

                StringArea = new FileSegmentGroup();
                if (values.HasInteger("string block offset"))
                {
                    StringArea.AddSegment(segmenter.WrapSegment((int)values.GetInteger("string block offset"), StringIDCount * 0x80, 0x80,
                                                                SegmentResizeOrigin.End));
                }
                StringArea.AddSegment(StringIDIndexTable);
                StringArea.AddSegment(StringIDData);

                StringIDIndexTableLocation = SegmentPointer.FromOffset(StringIDIndexTable.Offset, StringArea);
                StringIDDataLocation       = SegmentPointer.FromOffset(StringIDData.Offset, StringArea);
            }
            else
            {
                //dummy
                StringIDCount      = 0;
                StringIDData       = _eofSegment;
                StringIDIndexTable = _eofSegment;
            }

            InternalName = values.GetString("internal name");

            Checksum = (uint)values.GetInteger("checksum");

            // dummy partition
            Partitions    = new Partition[1];
            Partitions[0] = new Partition(SegmentPointer.FromOffset(MetaArea.Offset, MetaArea), (uint)MetaArea.Size);
        }