예제 #1
0
        public void Commit(EndianWriterEx writer)
        {
            if (!hasChanged)
            {
                return;
            }

            if (BlockRef != null && EntryCount != BlockRef.Count)
            {
                stream.ResizeTagBlock(writer, ref blockRef, EntrySize, EntryCount);

                //we dont know if our parent has already been written (or even will be)
                //just to be sure, we need to go back and update it with the new reference
                var refOffset = ParentBlock.EntrySize * ParentEntryIndex + OffsetInParent;
                writer.Seek(ParentBlock.PhysicalAddress + refOffset, SeekOrigin.Begin);
                BlockRef.Write(writer, null);
            }

            var rootAddress = BlockRef?.Pointer.Address ?? OffsetInParent;

            if (EntryCount > 0)
            {
                writer.Seek(rootAddress, SeekOrigin.Begin);
                writer.Write(data); //this writes our virtual pointers to disk (fix them below)
            }

            //the block references in our data array currently use virtual pointers
            //this restores the original pointers that got overwritten above
            foreach (var child in ChildBlocks)
            {
                writer.Seek(rootAddress + EntrySize * child.ParentEntryIndex + child.OffsetInParent + 4, SeekOrigin.Begin);
                writer.Write(child.BlockRef.Pointer.Value);
            }

            hasChanged = false;
        }
        public void AddMetadata(EndianWriterEx writer, int length, out int insertedAt, out int insertedCount)
        {
            length = metadataSegment.Expand(length);

            cache.Header.FileSize = eofSegment.Offset;

            var debugTranslator = new SectionAddressTranslator(cache, 0);
            //var metadataTranslator = new SectionAddressTranslator(cache, 2);
            var localeTranslator = new SectionAddressTranslator(cache, 3);

            var remaining = metadataSegment.AvailableSize - cache.Header.PartitionTable.Skip(1).Sum(p => (int)p.Size);
            var pointer   = cache.DefaultAddressTranslator.GetPointer(metadataSegment.Offset) - length; //DefaultAddressTranslator should always be the MetadataTranslator

            cache.Header.PartitionTable[0].Size    = (ulong)remaining;
            cache.Header.PartitionTable[0].Address = (ulong)pointer;

            var debugSection    = cache.Header.SectionTable[0];
            var resourceSection = cache.Header.SectionTable[1];
            var metadataSection = cache.Header.SectionTable[2];
            var localesSection  = cache.Header.SectionTable[3];

            resourceSection.Size = (uint)resourceSegment.AvailableSize;

            localesSection.Address = resourceSection.Address + resourceSection.Size;
            localesSection.Size    = (uint)localesGroup.AvailableSize;

            metadataSection.Address = resourceSection.Address + resourceSection.Size + localesSection.Size;
            metadataSection.Size    = (uint)metadataSegment.AvailableSize;

            debugSection.Address = resourceSection.Address + resourceSection.Size + localesSection.Size + metadataSection.Size;
            debugSection.Size    = (uint)stringsGroup.AvailableSize;

            if (debugSection.Address != 0 && cache.Header.SectionOffsetTable[0] != 0)
            {
                debugSection.Address -= (uint)cache.Header.PartitionTable[0].Size;
            }

            var offsets = cache.Header.SectionOffsetTable;

            offsets[0] = (uint)(stringsGroup.Offset - debugSection.Address);
            offsets[1] = (uint)(resourceSegment.Offset - resourceSection.Address);
            offsets[2] = (uint)(metadataSegment.Offset - metadataSection.Address);
            offsets[3] = (uint)(localesGroup.Offset - localesSection.Address);

            cache.Header.TagDataAddress     = (int)metadataSection.Address;
            cache.Header.VirtualBaseAddress = pointer;
            //index header address
            cache.Header.VirtualSize = metadataSegment.AvailableSize;

            pointer = debugTranslator.GetPointer(stringSegments[0].Offset);
            cache.Header.StringTableIndexPointer = new Pointer((int)pointer, cache.Header.StringTableIndexPointer);

            pointer = debugTranslator.GetPointer(stringSegments[1].Offset);
            cache.Header.StringTablePointer = new Pointer((int)pointer, cache.Header.StringTablePointer);

            pointer = debugTranslator.GetPointer(stringSegments[2].Offset);
            cache.Header.FileTableIndexPointer = new Pointer((int)pointer, cache.Header.FileTableIndexPointer);

            pointer = debugTranslator.GetPointer(stringSegments[3].Offset);
            cache.Header.FileTablePointer = new Pointer((int)pointer, cache.Header.FileTablePointer);

            //only exists in mcc reach (U3+)
            var mcc3 = cache.Header as IMccGen3Header;

            if (mcc3?.StringNamespaceCount > 0)
            {
                pointer = debugTranslator.GetPointer(stringSegments[4].Offset);
                mcc3.StringNamespaceTablePointer = new Pointer((int)pointer, mcc3.StringNamespaceTablePointer);
            }

            var gen4 = cache.Header as IGen4Header;

            if (gen4?.UnknownTableSize > 0)
            {
                pointer = debugTranslator.GetPointer(stringSegments[5].Offset);
                gen4.UnknownTablePointer = new Pointer((int)pointer, gen4.UnknownTablePointer);
            }

            foreach (var pair in localeSegments)
            {
                var def  = cache.LocaleIndex.Languages[pair.Key];
                var segs = pair.Value;

                def.IndicesOffset = (int)localeTranslator.GetPointer(segs[0].Offset);
                def.StringsOffset = (int)localeTranslator.GetPointer(segs[1].Offset);
            }

            insertedAt    = metadataSegment.Offset;
            insertedCount = length;

            writer.Seek(0, SeekOrigin.Begin);
            writer.WriteObject(cache.Header, (int)cache.CacheType);

            writer.Seek(metadataSegment.Offset, SeekOrigin.Begin);
            writer.Insert(0, length);

            var globalsTag = cache.TagIndex.GetGlobalTag("matg");

            writer.Seek(globalsTag.MetaPointer.Address, SeekOrigin.Begin);
            writer.WriteObject(cache.LocaleIndex);
        }