예제 #1
0
        private byte[] ReadStream(Stream stream, string path)
        {
            var key = FileList.GetIndex(path);

            if (key == -1)
            {
                throw new FileNotFoundException("Not found in archive (" + ArchivePath + "): " + path);
            }
            var entry = FileIndex.Entries[key];

            if (entry.Length > int.MaxValue)
            {
                throw new NotImplementedException("Unable to read large file: " + path);
            }

            using (var reader = new BinaryReader(stream))
            {
                stream.Seek(entry.Location, SeekOrigin.Begin);

                if (entry.Compression == 1)
                {
                    var length = reader.ReadUInt32();
                    return(Lzss.Decompress(reader.ReadBytes((int)length)));
                }

                if (entry.Compression == 2)
                {
                    var length = reader.ReadUInt32();
                    return(Lz4.Decompress(reader.ReadBytes((int)length)));
                }

                return(reader.ReadBytes((int)entry.Length));
            }
        }
예제 #2
0
        private Result ReadSegmentImpl(ref NsoHeader.SegmentHeader segment, uint fileSize, Buffer32 fileHash,
                                       bool isCompressed, bool checkHash, Span <byte> buffer)
        {
            // Select read size based on compression.
            if (!isCompressed)
            {
                fileSize = segment.Size;
            }

            // Validate size.
            if (fileSize > segment.Size)
            {
                return(ResultLoader.InvalidNso.Log());
            }

            // Load data from file.
            uint loadAddress = isCompressed ? (uint)buffer.Length - fileSize : 0;

            Result rc = NsoFile.Read(out long bytesRead, segment.FileOffset, buffer.Slice((int)loadAddress), ReadOption.None);

            if (rc.IsFailure())
            {
                return(rc);
            }

            if (bytesRead != fileSize)
            {
                return(ResultLoader.InvalidNso.Log());
            }

            // Uncompress if necessary.
            if (isCompressed)
            {
                // todo: Fix in-place decompression
                // Lz4.Decompress(buffer.Slice((int)loadAddress), buffer);
                byte[] decomp = Lz4.Decompress(buffer.Slice((int)loadAddress).ToArray(), buffer.Length);
                decomp.CopyTo(buffer);
            }

            // Check hash if necessary.
            if (checkHash)
            {
                Buffer32 hash = default;
                Crypto.Sha256.GenerateSha256Hash(buffer.Slice(0, (int)segment.Size), hash.Bytes);

                if (hash.Bytes.SequenceCompareTo(fileHash.Bytes) != 0)
                {
                    return(ResultLoader.InvalidNso.Log());
                }
            }

            return(Result.Success);
        }
예제 #3
0
 private void Fill()
 {
     if (!_eof)
     {
         int num = _targetStream.Read(_header, 0, 8);
         if (num == 0)
         {
             _unpackedBuffer = null;
             _eof            = true;
         }
         else
         {
             if (num != 8)
             {
                 throw new InvalidDataException("input buffer corrupted (header)");
             }
             int compressedSize = Lz4.GetCompressedSize(_header);
             if (compressedSize == 0)
             {
                 _unpackedBuffer = null;
                 _eof            = true;
             }
             else
             {
                 if ((_readBuffer == null) || (_readBuffer.Length < (compressedSize + 8)))
                 {
                     _readBuffer = new byte[compressedSize + 8];
                 }
                 Buffer.BlockCopy(_header, 0, _readBuffer, 0, 8);
                 if (_targetStream.Read(_readBuffer, 8, compressedSize) != compressedSize)
                 {
                     throw new InvalidDataException("input buffer corrupted (body)");
                 }
                 _unpackedLength   = Lz4.Decompress(_readBuffer, 0, ref _unpackedBuffer);
                 _unpackedOffset   = 0;
                 CompressedLength += _unpackedLength;
             }
         }
     }
 }
예제 #4
0
        public Nso(Stream Input)
        {
            BinaryReader Reader = new BinaryReader(Input);

            Input.Seek(0, SeekOrigin.Begin);

            int NsoMagic      = Reader.ReadInt32();
            int Version       = Reader.ReadInt32();
            int Reserved      = Reader.ReadInt32();
            int FlagsMsk      = Reader.ReadInt32();
            int TextOffset    = Reader.ReadInt32();
            int TextMemOffset = Reader.ReadInt32();
            int TextDecSize   = Reader.ReadInt32();
            int ModNameOffset = Reader.ReadInt32();
            int ROOffset      = Reader.ReadInt32();
            int ROMemOffset   = Reader.ReadInt32();
            int RODecSize     = Reader.ReadInt32();
            int ModNameSize   = Reader.ReadInt32();
            int DataOffset    = Reader.ReadInt32();
            int DataMemOffset = Reader.ReadInt32();
            int DataDecSize   = Reader.ReadInt32();
            int BssSize       = Reader.ReadInt32();

            byte[] BuildId = Reader.ReadBytes(0x20);

            int TextSize = Reader.ReadInt32();
            int ROSize   = Reader.ReadInt32();
            int DataSize = Reader.ReadInt32();

            Input.Seek(0x24, SeekOrigin.Current);

            int DynStrOffset = Reader.ReadInt32();
            int DynStrSize   = Reader.ReadInt32();
            int DynSymOffset = Reader.ReadInt32();
            int DynSymSize   = Reader.ReadInt32();

            byte[] TextHash = Reader.ReadBytes(0x20);
            byte[] ROHash   = Reader.ReadBytes(0x20);
            byte[] DataHash = Reader.ReadBytes(0x20);

            NsoFlags Flags = (NsoFlags)FlagsMsk;

            this.TextOffset = TextMemOffset;
            this.ROOffset   = ROMemOffset;
            this.DataOffset = DataMemOffset;
            this.BssSize    = BssSize;

            //Text segment
            Input.Seek(TextOffset, SeekOrigin.Begin);

            m_Text = Reader.ReadBytes(TextSize);

            if (Flags.HasFlag(NsoFlags.IsTextCompressed) || true)
            {
                m_Text = Lz4.Decompress(m_Text, TextDecSize);
            }

            //Read-only data segment
            Input.Seek(ROOffset, SeekOrigin.Begin);

            m_RO = Reader.ReadBytes(ROSize);

            if (Flags.HasFlag(NsoFlags.IsROCompressed) || true)
            {
                m_RO = Lz4.Decompress(m_RO, RODecSize);
            }

            //Data segment
            Input.Seek(DataOffset, SeekOrigin.Begin);

            m_Data = Reader.ReadBytes(DataSize);

            if (Flags.HasFlag(NsoFlags.IsDataCompressed) || true)
            {
                m_Data = Lz4.Decompress(m_Data, DataDecSize);
            }

            using (MemoryStream Text = new MemoryStream(m_Text))
            {
                BinaryReader TextReader = new BinaryReader(Text);

                Text.Seek(4, SeekOrigin.Begin);

                Mod0Offset = TextReader.ReadInt32();
            }
        }
예제 #5
0
        public NxStaticObject(Stream input)
        {
            BinaryReader reader = new BinaryReader(input);

            input.Seek(0, SeekOrigin.Begin);

            int nsoMagic      = reader.ReadInt32();
            int version       = reader.ReadInt32();
            int reserved      = reader.ReadInt32();
            int flagsMsk      = reader.ReadInt32();
            int textOffset    = reader.ReadInt32();
            int textMemOffset = reader.ReadInt32();
            int textDecSize   = reader.ReadInt32();
            int modNameOffset = reader.ReadInt32();
            int roOffset      = reader.ReadInt32();
            int roMemOffset   = reader.ReadInt32();
            int roDecSize     = reader.ReadInt32();
            int modNameSize   = reader.ReadInt32();
            int dataOffset    = reader.ReadInt32();
            int dataMemOffset = reader.ReadInt32();
            int dataDecSize   = reader.ReadInt32();
            int bssSize       = reader.ReadInt32();

            byte[] buildId = reader.ReadBytes(0x20);

            int textSize = reader.ReadInt32();
            int roSize   = reader.ReadInt32();
            int dataSize = reader.ReadInt32();

            input.Seek(0x24, SeekOrigin.Current);

            int dynStrOffset = reader.ReadInt32();
            int dynStrSize   = reader.ReadInt32();
            int dynSymOffset = reader.ReadInt32();
            int dynSymSize   = reader.ReadInt32();

            byte[] textHash = reader.ReadBytes(0x20);
            byte[] roHash   = reader.ReadBytes(0x20);
            byte[] dataHash = reader.ReadBytes(0x20);

            NsoFlags flags = (NsoFlags)flagsMsk;

            TextOffset = textMemOffset;
            RoOffset   = roMemOffset;
            DataOffset = dataMemOffset;
            BssSize    = bssSize;

            //Text segment
            input.Seek(textOffset, SeekOrigin.Begin);

            Text = reader.ReadBytes(textSize);

            if (flags.HasFlag(NsoFlags.IsTextCompressed) && textSize != 0)
            {
                Text = Lz4.Decompress(Text, textDecSize);
            }

            //Read-only data segment
            input.Seek(roOffset, SeekOrigin.Begin);

            Ro = reader.ReadBytes(roSize);

            if (flags.HasFlag(NsoFlags.IsRoCompressed) && roSize != 0)
            {
                Ro = Lz4.Decompress(Ro, roDecSize);
            }

            //Data segment
            input.Seek(dataOffset, SeekOrigin.Begin);

            Data = reader.ReadBytes(dataSize);

            if (flags.HasFlag(NsoFlags.IsDataCompressed) && dataSize != 0)
            {
                Data = Lz4.Decompress(Data, dataDecSize);
            }
        }