public void AddTextureIfNotExists(uint key, DuplicatableStream texture)
        {
            SkitTex containedTexture;

            if (Cache.TryGetValue(key, out containedTexture))
            {
                const bool verify = false;
                if (verify)
                {
                    using (DuplicatableStream otex = containedTexture.Stream.Duplicate())
                        using (DuplicatableStream ntex = texture.Duplicate()) {
                            otex.Position = 0;
                            ntex.Position = 0;
                            if (!(otex.Length == ntex.Length && StreamUtils.IsIdentical(otex, ntex, otex.Length)))
                            {
                                throw new Exception("texture added does not match known texture");
                            }
                        }
                }
            }
            else
            {
                Cache.Add(key, new SkitTex()
                {
                    Stream = texture.Duplicate()
                });
            }
        }
Beispiel #2
0
 public FPS4(DuplicatableStream headerStream, DuplicatableStream contentStream = null)
 {
     if (!LoadFile(headerStream, contentStream != null ? contentStream : headerStream))
     {
         throw new Exception("Failed loading FPS4.");
     }
 }
Beispiel #3
0
 public SE3(DuplicatableStream stream, EndianUtils.Endianness?endian, TextUtils.GameTextEncoding encoding)
 {
     if (!LoadFile(stream, endian, encoding))
     {
         throw new Exception("Loading SE3 failed!");
     }
 }
Beispiel #4
0
 public FPS4(DuplicatableStream headerStream, DuplicatableStream contentStream = null, bool printProgressToConsole = false)
 {
     if (!LoadFile(headerStream, contentStream != null ? contentStream : headerStream, printProgressToConsole))
     {
         throw new Exception("Failed loading FPS4.");
     }
 }
Beispiel #5
0
		public PackFileInfo(PackFileInfo other) {
			Name = other.Name;
			Length = other.Length;
			RelativePath = other.RelativePath;
			DataStream = other.DataStream != null ? other.DataStream.Duplicate() : null;
			DuplicateOf = other.DuplicateOf;
		}
Beispiel #6
0
        public PartialStream(DuplicatableStream stream, long position, long length)
        {
            if (position < 0)
            {
                throw new Exception("Invalid position, must be positive.");
            }
            if (length < 0)
            {
                throw new Exception("Invalid length, must be positive.");
            }

            if (stream is PartialStream)
            {
                // optimization to better chain partial stream of partial stream
                PartialStream parent = stream as PartialStream;
                BaseStreamInternal = parent.BaseStreamInternal.Duplicate();
                Initialized        = false;
                PartialStart       = parent.PartialStart + position;
                PartialLength      = length;
                CurrentPosition    = 0;
            }
            else
            {
                BaseStreamInternal = stream.Duplicate();
                Initialized        = false;
                PartialStart       = position;
                PartialLength      = length;
                CurrentPosition    = 0;
            }
        }
Beispiel #7
0
        public EndianUtils.Endianness Endian;         // not actually a field in the header, at least not here -- might be the first byte?

        public NubHeader(DuplicatableStream stream, EndianUtils.Endianness?endian)
        {
            Magic = stream.ReadUInt64(EndianUtils.Endianness.LittleEndian);

            EndianUtils.Endianness suspectedEndian;
            if (Magic == 0x10200)
            {
                suspectedEndian = EndianUtils.Endianness.BigEndian;
            }
            else if (Magic == 0x10201)
            {
                suspectedEndian = EndianUtils.Endianness.LittleEndian;
            }
            else
            {
                throw new Exception("unexpected magic in NUB");
            }

            EndianUtils.Endianness e = endian ?? suspectedEndian;
            Fileid         = stream.ReadUInt32(e);     // or something like that? seems unique per archive in each game
            EntryCount     = stream.ReadUInt32(e);
            StartOfFiles   = stream.ReadUInt32(e);
            FilesSize      = stream.ReadUInt32(e);
            StartOfEntries = stream.ReadUInt32(e);
            StartOfHeaders = stream.ReadUInt32(e);

            Endian = e;
        }
Beispiel #8
0
 public static void ExtractNub(DuplicatableStream duplicatableStream, string targetFolder, EndianUtils.Endianness?e)
 {
     Directory.CreateDirectory(targetFolder);
     using (var nub = new NUB(duplicatableStream, e)) {
         nub.Extract(targetFolder);
     }
 }
Beispiel #9
0
        public TrophyTrp(HyoutaPluginBase.DuplicatableStream stream, EndianUtils.Endianness endian = EndianUtils.Endianness.BigEndian)
        {
            Stream = stream.Duplicate();
            Endian = endian;
            try {
                Stream.ReStart();
                Magic = Stream.ReadUInt32().FromEndian(EndianUtils.Endianness.LittleEndian);
                if (Magic != 0x004DA2DC)
                {
                    throw new Exception("invalid magic");
                }
                Unknown2 = Stream.ReadUInt32().FromEndian(endian);
                Unknown3 = Stream.ReadUInt32().FromEndian(endian);
                Filesize = Stream.ReadUInt32().FromEndian(endian);

                Filecount = Stream.ReadUInt32().FromEndian(endian);
                Unknown6  = Stream.ReadUInt32().FromEndian(endian);
                Unknown7  = Stream.ReadUInt32().FromEndian(endian);
                Unknown8  = Stream.ReadUInt32().FromEndian(endian);

                Unknown9  = Stream.ReadUInt32().FromEndian(endian);
                Unknown10 = Stream.ReadUInt32().FromEndian(endian);
                Unknown11 = Stream.ReadUInt32().FromEndian(endian);
                Unknown12 = Stream.ReadUInt32().FromEndian(endian);

                Unknown13 = Stream.ReadUInt32().FromEndian(endian);
                Unknown14 = Stream.ReadUInt32().FromEndian(endian);
                Unknown15 = Stream.ReadUInt32().FromEndian(endian);
                Unknown16 = Stream.ReadUInt32().FromEndian(endian);
            } finally {
                Stream.End();
            }
        }
Beispiel #10
0
        public static Compression.IHyoutaArchiveCompressionInfo?Deserialize(DuplicatableStream stream, long maxBytes, EndianUtils.Endianness endian)
        {
            if (maxBytes < 8)
            {
                stream.DiscardBytes(maxBytes);
                return(null);
            }

            ulong identifier = stream.ReadUInt64(EndianUtils.Endianness.BigEndian);

            switch (identifier)
            {
            case 0:
                // archive has compression, but this file is not compressed
                stream.DiscardBytes(maxBytes - 8);
                return(null);

            case DeflateSharpCompressionInfo.Identifier:
                return(DeflateSharpCompressionInfo.Deserialize(stream, maxBytes - 8, endian));

            default:
                Console.WriteLine("Unknown compression type: " + identifier.ToString("x16"));
                stream.DiscardBytes(maxBytes - 8);
                return(null);
            }
        }
Beispiel #11
0
        private bool LoadFile(DuplicatableStream headerStream, DuplicatableStream contentStream)
        {
            DuplicatableStream infile = headerStream.Duplicate();

            contentFile = contentStream.Duplicate();

            infile.Seek(0x00, SeekOrigin.Begin);
            string magic = infile.ReadAscii(4);

            if (magic != "FPS4")
            {
                Console.WriteLine("Not an FPS4 file!");
                return(false);
            }

            Endian     = Util.Endianness.BigEndian;
            FileCount  = infile.ReadUInt32().FromEndian(Endian);
            HeaderSize = infile.ReadUInt32().FromEndian(Endian);

            // if header seems huge then we probably have assumed the wrong endianness
            if (HeaderSize > 0xFFFF)
            {
                Endian     = Util.Endianness.LittleEndian;
                FileCount  = FileCount.ToEndian(Util.Endianness.BigEndian).FromEndian(Endian);
                HeaderSize = HeaderSize.ToEndian(Util.Endianness.BigEndian).FromEndian(Endian);
            }

            FirstFileStart      = infile.ReadUInt32().FromEndian(Endian);
            EntrySize           = infile.ReadUInt16().FromEndian(Endian);
            ContentBitmask      = new ContentInfo(infile.ReadUInt16().FromEndian(Endian));
            Unknown2            = infile.ReadUInt32().FromEndian(Endian);
            ArchiveNameLocation = infile.ReadUInt32().FromEndian(Endian);
            infile.Position     = ArchiveNameLocation;
            if (ArchiveNameLocation > 0)
            {
                ArchiveName = infile.ReadShiftJisNullterm();
            }

            Alignment = FirstFileStart;

            Console.WriteLine("Content Bitmask: 0x" + ContentBitmask.Value.ToString("X4"));
            if (ContentBitmask.HasUnknownDataTypes)
            {
                Console.WriteLine("WARNING: Bitmask identifies unknown data types, data interpretation will probably be incorrect.");
            }

            Files = new List <FileInfo>((int)FileCount);
            for (uint i = 0; i < FileCount; ++i)
            {
                infile.Position = HeaderSize + (i * EntrySize);
                Files.Add(new FileInfo(infile, i, ContentBitmask, Endian, Util.GameTextEncoding.ASCII));
            }

            FileLocationMultiplier          = CalculateFileLocationMultiplier();
            ShouldGuessFilesizeFromNextFile = !ContentBitmask.ContainsFileSizes && !ContentBitmask.ContainsSectorSizes && CalculateIsLinear();

            infile.Dispose();
            return(true);
        }
Beispiel #12
0
        public CanDecompressAnswer CanDecompress(DuplicatableStream stream)
        {
            long pos = stream.Position;
            CanDecompressAnswer answer = stream.ReadAscii(4) == "TLZC" ? CanDecompressAnswer.Yes : CanDecompressAnswer.No;

            stream.Position = pos;
            return(answer);
        }
Beispiel #13
0
 public void Close()
 {
     if (contentFile != null)
     {
         contentFile.Close();
         contentFile = null;
     }
 }
Beispiel #14
0
 public NUB(DuplicatableStream duplicatableStream, EndianUtils.Endianness?e)
 {
     Stream          = duplicatableStream.Duplicate();
     Stream.Position = 0;
     Header          = new NubHeader(Stream, e);
     Endian          = Header.Endian;
     Stream.Position = Header.StartOfEntries;
     Entries         = Stream.ReadUInt32Array(Header.EntryCount, Endian);
 }
Beispiel #15
0
 public override void Dispose()
 {
     if (Stream != null)
     {
         Stream.Close();
         Stream.Dispose();
         Stream = null;
     }
 }
Beispiel #16
0
 public KnownFile(SHA1 hash, DuplicatableStream data, bool important = true, bool writeToBackup = true)
 {
     Hash = hash;
     AcquisitionMethods = new List <KnownFileAcquisitionMethod>()
     {
         new KnownFileAcquisitionFromStream(data, writeToBackup)
     };
     Important = important;
 }
 public override string ToString()
 {
     using (FPS4 fps4 = new FPS4(Stream.Duplicate()))
         using (DuplicatableStream txmvStream = fps4.GetChildByIndex(1).AsFile.DataStream.Duplicate())
             using (FPS4 txmv = new FPS4(txmvStream.Duplicate()))
                 using (DuplicatableStream txmStream = txmv.GetChildByIndex(0).AsFile.DataStream.Duplicate()) {
                     TXM txm = new TXM(txmStream.Duplicate());
                     return(txm.TXMRegulars[0].Name);
                 }
 }
Beispiel #18
0
        private bool LoadFile(DuplicatableStream inputStream, EndianUtils.Endianness?endianParam, TextUtils.GameTextEncoding encoding)
        {
            DuplicatableStream stream = inputStream.Duplicate();

            stream.Position = 0;
            EndianUtils.Endianness endian;
            if (endianParam == null)
            {
                uint magic = stream.ReadUInt32().FromEndian(EndianUtils.Endianness.BigEndian);
                if (magic == 0x53453320)
                {
                    endian = EndianUtils.Endianness.BigEndian;
                }
                else if (magic == 0x20334553)
                {
                    endian = EndianUtils.Endianness.LittleEndian;
                }
                else
                {
                    Console.WriteLine("Invalid magic: " + magic);
                    return(false);
                }
            }
            else
            {
                endian = endianParam.Value;
                uint magic = stream.ReadUInt32(endian);
                if (magic != 0x53453320)
                {
                    Console.WriteLine("Invalid magic: " + magic);
                    return(false);
                }
            }

            this.Endian = endian;

            uint lengthOfFilenameSection = stream.ReadUInt32(endian);            // probably?
            uint startOfFilenameSection  = stream.ReadUInt32(endian);            // probably?

            DataBegin = stream.ReadUInt32(endian);

            stream.Position = startOfFilenameSection;
            uint magicOfFilenameSection = stream.ReadUInt32(endian);

            FileCount = stream.ReadUInt32(endian);
            Filenames = new List <string>((int)FileCount);
            for (uint i = 0; i < FileCount; ++i)
            {
                Filenames.Add(stream.ReadSizedString(48, encoding).TrimNull());
            }

            Data = stream;

            return(true);
        }
Beispiel #19
0
        public void PrintData(EndianUtils.Endianness endian, Dictionary <uint, TSS.TSSEntry> inGameDic, List <ItemDat.ItemDatSingle> itemDataSorted, T8BTEMST.T8BTEMST enemies)
        {
            using (DuplicatableStream stream = Stream.Duplicate()) {
                stream.ReadUInt32().FromEndian(endian);   // ?
                stream.ReadUInt32().FromEndian(endian);   // ?
                stream.ReadUInt32Array(9, endian);
                stream.ReadUInt32().FromEndian(endian);   // play time in frames, assuming 60 frames = 1 second
                stream.ReadUInt32().FromEndian(endian);   // gald
                stream.DiscardBytes(4);                   // ?
                uint[] itemCounts        = stream.ReadUInt32Array(3072, endian);
                uint[] itemBookBitfields = stream.ReadUInt32Array(3072 / 32, endian);
                stream.DiscardBytes(4);                   // ?
                stream.ReadUInt32Array(4, endian);        // control modes for the four active party slots
                stream.ReadUInt32Array(3, endian);        // strategies assigned to dpad directions
                stream.DiscardBytes(0x40);                // ??
                for (int i = 0; i < 8; ++i)
                {
                    // custom strategy names
                    // game seems to read these till null byte so this could totally be abused to buffer overflow...
                    stream.ReadAscii(0x40);
                }

                stream.DiscardBytes(0xA84D0 - 0xA7360);                   // ?
                uint[] monsterBookBitfieldsScanned = stream.ReadUInt32Array(0x48 / 4, endian);
                stream.DiscardBytes(0xA8680 - 0xA8518);                   // ?
                uint[] monsterBookBitfieldsSeen = stream.ReadUInt32Array(0x48 / 4, endian);
                stream.DiscardBytes(0xA8928 - 0xA86C8);                   // ?

                uint collectorsBookIndex = 0;
                foreach (var item in itemDataSorted)
                {
                    uint i = item.Data[(int)ItemDat.ItemData.ID];
                    if (item.Data[(int)ItemDat.ItemData.InCollectorsBook] > 0)
                    {
                        bool haveItem = ((itemBookBitfields[i / 32] >> (int)(i % 32)) & 1) > 0;
                        Console.WriteLine((haveItem ? "Y" : "N") + (collectorsBookIndex) + ": " + inGameDic[item.NamePointer].StringEngOrJpn);
                        ++collectorsBookIndex;
                    }
                }


                uint monsterBookIndex = 0;
                foreach (var enemy in enemies.EnemyList)
                {
                    uint i = enemy.InGameID;
                    if (enemy.InMonsterBook > 0)
                    {
                        bool haveSeen    = ((monsterBookBitfieldsSeen[i / 32] >> (int)(i % 32)) & 1) > 0;
                        bool haveScanned = ((monsterBookBitfieldsScanned[i / 32] >> (int)(i % 32)) & 1) > 0;
                        Console.WriteLine((haveSeen ? "Y" : "N") + (haveScanned ? "Y" : "N") + (monsterBookIndex) + ": " + inGameDic[enemy.NameStringDicID].StringEngOrJpn);
                        ++monsterBookIndex;
                    }
                }
            }
        }
Beispiel #20
0
 public TrophyTrpFile(DuplicatableStream stream, EndianUtils.Endianness endian)
 {
     Filename = stream.ReadAscii(0x20).TrimNull();
     Unknown1 = stream.ReadUInt32().FromEndian(endian);
     Start    = stream.ReadUInt32().FromEndian(endian);
     Unknown3 = stream.ReadUInt32().FromEndian(endian);
     Length   = stream.ReadUInt32().FromEndian(endian);
     Unknown5 = stream.ReadUInt32().FromEndian(endian);
     Unknown6 = stream.ReadUInt32().FromEndian(endian);
     Unknown7 = stream.ReadUInt32().FromEndian(endian);
     Unknown8 = stream.ReadUInt32().FromEndian(endian);
 }
 private HyoutaPluginBase.FileContainer.INode ReturnAndCache(HyoutaPluginBase.FileContainer.INode node, string path, Version version)
 {
     if (node != null && path != null)
     {
         Directory.CreateDirectory(Path.GetDirectoryName(path));
         using (FileStream fs = new FileStream(path, FileMode.Create)) {
             using (DuplicatableStream ds = node.AsFile.DataStream.Duplicate()) {
                 StreamUtils.CopyStream(ds, fs, ds.Length);
             }
         }
     }
     return(node);
 }
Beispiel #22
0
        private bool disposedValue = false;         // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    infile.Dispose();
                }

                infile           = null;
                toc_string_table = null;
                disposedValue    = true;
            }
        }
Beispiel #23
0
        public static DeflateSharpCompressionInfo?Deserialize(DuplicatableStream stream, long maxBytes, EndianUtils.Endianness endian)
        {
            // note: identifier has already been read
            if (maxBytes < 8)
            {
                stream.DiscardBytes(maxBytes);
                return(null);
            }

            ulong uncompressedFilesize = stream.ReadUInt64(endian);

            stream.DiscardBytes(maxBytes - 8);
            return(new DeflateSharpCompressionInfo(uncompressedFilesize));
        }
Beispiel #24
0
        public ScenarioDatEntry(DuplicatableStream data, uint FilesOffset)
        {
            Offset               = data.ReadUInt32().SwapEndian();
            FilesizeCompressed   = data.ReadUInt32().SwapEndian();
            FilesizeUncompressed = data.ReadUInt32().SwapEndian();

            if (FilesizeCompressed > 0)
            {
                DataStream = new PartialStream(data, Offset + FilesOffset, FilesizeCompressed);
            }
            else
            {
                DataStream = null;
            }
        }
        public static List <MainDolString> ReadElfStringsJp(DuplicatableStream filestream)
        {
            IRomMapper dol    = new Ps3ElfMapper();
            var        stream = filestream.CopyToMemory();
            var        data   = new List <MainDolString>();

            ReadStringsInBlocks(data, dol, stream, 0x842DF4, 0x0A00, 0x14, 1, true);             // battle field names?
            ReadStringsInBlocks(data, dol, stream, 0x8437F8, 0x0244, 0x04, 1, true);             // menu strings
            ReadStringsInBlocks(data, dol, stream, 0x843A7C, 0x006C, 0x04, 1, true);             // menu strings
            ReadStringsInBlocks(data, dol, stream, 0x845068, 0x083C, 0x04, 1, true);             // menu strings
            for (int i = 0; i < 4; ++i)
            {
                data.Add(new MainDolString(0, 0, null, 0));                           // JP and US desync here because of extra strings in US, compensate
            }
            ReadStringsInBlocks(data, dol, stream, 0x8458A4, 0x0714, 0x04, 1, true);  // menu strings
            ReadStringsInBlocks(data, dol, stream, 0x845FD4, 0x151C, 0x1C, 4, true);  // equipment effects
            ReadStringsInBlocks(data, dol, stream, 0x8475EC, 0x0074, 0x04, 1, true);  // attack types
            ReadStringsInBlocks(data, dol, stream, 0x847660, 0x0200, 0x08, 1, true);  // cooking effects
            ReadStringsInBlocks(data, dol, stream, 0x847858, 0x044C, 0x14, 2, true);  // item traits
            ReadStringsInBlocks(data, dol, stream, 0x847CAC, 0x004C, 0x04, 1, true);  // gem names
            ReadStringsInBlocks(data, dol, stream, 0x847D08, 0x00C0, 0x10, 4, true);  // tutorials short
            ReadStringsInBlocks(data, dol, stream, 0x847DC8, 0x0EA0, 0x20, 7, true);  // tutorials long
            ReadStringsInBlocks(data, dol, stream, 0x848C68, 0x0594, 0x1C, 7, true);  // tutorials long
            ReadStringsInBlocks(data, dol, stream, 0x8491FC, 0x01F0, 0x08, 1, true);  // books
            ReadStringsInBlocks(data, dol, stream, 0x8493EC, 0x00B4, 0x04, 1, true);  // books [synopsis]
            ReadStringsInBlocks(data, dol, stream, 0x8494A0, 0x0BB8, 0x0C, 1, true);  // books [sidequests]
            ReadStringsInBlocks(data, dol, stream, 0x84A058, 0x094C, 0x1C, 2, true);  // discoveries
            ReadStringsInBlocks(data, dol, stream, 0x84A9A8, 0x0520, 0x04, 1, true);  // enemy descriptions
            ReadStringsInBlocks(data, dol, stream, 0x84C20C, 0x1464, 0x24, 2, true);  // items
            ReadStringsInBlocks(data, dol, stream, 0x84D670, 0x2154, 0x24, 2, true);  // items
            ReadStringsInBlocks(data, dol, stream, 0x84F7C4, 0x02F4, 0x1C, 2, true);  // items
            ReadStringsInBlocks(data, dol, stream, 0x84FAB8, 0x13D8, 0x28, 2, true);  // items
            ReadStringsInBlocks(data, dol, stream, 0x850E90, 0x14AC, 0x24, 2, true);  // items
            ReadStringsInBlocks(data, dol, stream, 0x85233C, 0x071C, 0x1C, 2, true);  // items
            ReadStringsInBlocks(data, dol, stream, 0x852A58, 0x1770, 0x18, 2, true);  // valuable items
            ReadStringsInBlocks(data, dol, stream, 0x8541C8, 0x024C, 0x0C, 2, true);  // grade shop
            ReadStringsInBlocks(data, dol, stream, 0x854450, 0x2370, 0x24, 3, true);  // requests
            ReadStringsInBlocks(data, dol, stream, 0x856800, 0x6670, 0x58, 3, true);  // artes
            ReadStringsInBlocks(data, dol, stream, 0x85CF20, 0x0078, 0x0C, 2, true);  // strategy
            ReadStringsInBlocks(data, dol, stream, 0x85CF98, 0x00A0, 0x08, 2, true);  // strategy
            ReadStringsInBlocks(data, dol, stream, 0x87AA08, 0x0270, 0x0C, 2, true);  // title effects (?)
            ReadStringsInBlocks(data, dol, stream, 0x85D0A8, 0x1D960, 0x70, 2, true); // titles
            return(data);

            //ReadStringsInBlocks( data, dol, stream, 0x5624E8, 0x0258, 0x14, 1 ); // debug strings
            //ReadStringsInBlocks( data, dol, stream, 0x562740, 0x0154, 0x04, 1 ); // debug strings
            //ReadStringsInBlocks( data, dol, stream, 0x570DAC, 0x0040, 0x04, 1 ); // menu strings // seem to no longer exist?
        }
Beispiel #26
0
        public static DuplicatableStream ReadDuplicatableSubstream(this Stream stream, long bytecount)
        {
            DuplicatableStream ds = stream as DuplicatableStream;

            if (ds != null)
            {
                long          p  = ds.Position;
                PartialStream ps = new PartialStream(ds, p, bytecount);
                ds.Position = p + bytecount;
                return(ps);
            }
            else
            {
                return(new DuplicatableByteArrayStream(ReadBytes(stream, bytecount)));
            }
        }
Beispiel #27
0
        public SHBP(DuplicatableStream duplicatableStream, EndianUtils.Endianness e = EndianUtils.Endianness.BigEndian)
        {
            using (DuplicatableStream s = duplicatableStream.Duplicate()) {
                uint magic = s.ReadUInt32(EndianUtils.Endianness.LittleEndian);
                if (magic != 0x50424853)
                {
                    throw new Exception("wrong magic");
                }

                uint count = s.ReadUInt32(e);
                Hashes = new List <uint>((int)count);
                for (uint i = 0; i < count; ++i)
                {
                    Hashes.Add(s.ReadUInt32(e));
                }
            }
        }
Beispiel #28
0
        public static DuplicatableStream CreateConcatenatedStream(List <DuplicatableStream> streams)
        {
            if (streams.Count == 0)
            {
                return(EmptyStream.Instance);
            }

            var  Streams          = new List <DuplicatableStream>(streams.Count);
            var  Offsets          = new List <long>(Streams.Count);
            var  InternalCanRead  = true;
            var  InternalCanSeek  = true;
            var  InternalCanWrite = true;
            long sum = 0;

            for (int i = 0; i < streams.Count; ++i)
            {
                DuplicatableStream s = streams[i].Duplicate();
                s.ReStart();
                long l = s.Length;
                if (l <= 0)
                {
                    s.End();
                    s.Dispose();
                    continue;
                }
                sum             += l;
                InternalCanRead  = InternalCanRead && s.CanRead;
                InternalCanSeek  = InternalCanSeek && s.CanSeek;
                InternalCanWrite = InternalCanWrite && s.CanWrite;
                s.End();
                Streams.Add(s);
                Offsets.Add(sum);
            }

            if (Streams.Count == 0)
            {
                return(EmptyStream.Instance);
            }

            if (Streams.Count == 1)
            {
                return(Streams[0]);
            }

            return(new ConcatenatedStream(Streams, Offsets, InternalCanRead, InternalCanSeek, InternalCanWrite));
        }
Beispiel #29
0
        public static DuplicatableStream ReadDuplicatableSubstreamFromLocationAndReset(this Stream stream, long position, long bytecount)
        {
            long p = stream.Position;
            DuplicatableStream ds = stream as DuplicatableStream;

            if (ds != null)
            {
                return(new PartialStream(ds, p, bytecount));
            }
            else
            {
                stream.Position = position;
                DuplicatableStream nds = new DuplicatableByteArrayStream(ReadBytes(stream, bytecount));
                stream.Position = p;
                return(nds);
            }
        }
Beispiel #30
0
        private static string?ReadString(DuplicatableStream s, uint maxBytes, EndianUtils.Endianness e)
        {
            if (maxBytes < 8)
            {
                // can't be a valid string
                s.DiscardBytes(maxBytes);
                return(null);
            }

            ulong rawlength = s.ReadUInt64(e);
            ulong length    = (rawlength & 0x7ffffffffffffffful);
            bool  hasOffset = (rawlength & 0x8000000000000000ul) > 0;

            if (hasOffset)
            {
                // format is 8 bytes length, then 8 bytes position of string in data
                if (maxBytes < 16)
                {
                    // can't be valid
                    s.DiscardBytes(maxBytes - 8);
                    return(null);
                }

                ulong offset = s.ReadUInt64(e);
                long  p      = s.Position + (maxBytes - 16);
                s.Position = (long)offset;
                string str = s.ReadSizedString((long)length, TextUtils.GameTextEncoding.UTF8);
                s.Position = p;
                return(str);
            }
            else
            {
                // format is 8 bytes length, then [number read] bytes string
                uint restBytes = maxBytes - 8;
                if (length > restBytes)
                {
                    // can't be a valid string
                    s.DiscardBytes(restBytes);
                    return(null);
                }

                string str = s.ReadSizedString((long)length, TextUtils.GameTextEncoding.UTF8);
                s.DiscardBytes(restBytes - length);
                return(str);
            }
        }