示例#1
0
        private Stream Decompress(Stream input)
        {
            using var br = new BinaryReaderX(input, true);

            input.Position = 5;
            var magic = br.ReadString(4);

            if (magic != "F3XT")
            {
                _wasCompressed = false;
                return(input);
            }

            _wasCompressed = true;

            var ms = new MemoryStream();

            input.Position = 0;

            _compMethod = NintendoCompressor.PeekCompressionMethod(input);
            NintendoCompressor.Decompress(input, ms);

            ms.Position = 0;
            return(ms);
        }
示例#2
0
        public async Task Load(IFileSystem fileSystem, UPath filePath, LoadContext loadContext)
        {
            var fileStream = await fileSystem.OpenFileAsync(filePath);

            // Decompress, if necessary
            using var br        = new BinaryReaderX(fileStream, true);
            fileStream.Position = 9;
            if (br.ReadString(4) == "nns_")
            {
                _wasCompressed = true;

                fileStream.Position = 0;

                var decompressedStream = new MemoryStream();
                NintendoCompressor.Decompress(fileStream, decompressedStream);

                fileStream.Close();
                fileStream = decompressedStream;
            }

            fileStream.Position = 0;
            Images = new List <IKanvasImage> {
                new KanvasImage(EncodingDefinition, _img.Load(fileStream))
            };
        }
示例#3
0
        public static ArchiveFileInfo CreateAfi(Stream file, string fileName)
        {
            var compressionIdent = file.ReadByte();
            var isCompressed     = compressionIdent == 0x10 ||
                                   compressionIdent == 0x11 ||
                                   compressionIdent == 0x24 ||
                                   compressionIdent == 0x28 ||
                                   compressionIdent == 0x30;

            file.Position--;
            if (!isCompressed)
            {
                return(new ArchiveFileInfo(file, fileName));
            }

            var sizeBuffer = new byte[4];

            file.Read(sizeBuffer, 0, 4);
            file.Position = 0;

            var method           = (NintendoCompressionMethod)(BinaryPrimitives.ReadUInt32LittleEndian(sizeBuffer) & 0xFF);
            var decompressedSize = BinaryPrimitives.ReadUInt32LittleEndian(sizeBuffer) >> 8;

            if (decompressedSize <= file.Length)
            {
                return(new ArchiveFileInfo(file, fileName));
            }

            return(new ArchiveFileInfo(file, fileName, NintendoCompressor.GetConfiguration(method), decompressedSize));
        }
示例#4
0
        public IList <IArchiveFileInfo> Load(Stream incStream, Stream datStream, string version)
        {
            using var incBr = new BinaryReaderX(incStream);

            var entryCount = (int)(incStream.Length / FileEntrySize);
            var entries    = incBr.ReadMultiple <AAPackFileEntry>(entryCount);

            var nameMapping = AAPackSupport.GetMapping(version);

            var result = new IArchiveFileInfo[entryCount];

            for (var i = 0; i < entryCount; i++)
            {
                var subStream = new SubStream(datStream, entries[i].offset, entries[i].compSize);

                var compressionMethod = NintendoCompressor.PeekCompressionMethod(subStream);

                var fileName = $"{i:00000000}.bin";
                if (nameMapping.ContainsKey(entries[i].hash))
                {
                    fileName = nameMapping[entries[i].hash];
                }

                result[i] = new AAPackArchiveFileInfo(subStream, fileName,
                                                      NintendoCompressor.GetConfiguration(compressionMethod), entries[i].uncompSize, entries[i]);
            }

            return(result);
        }
示例#5
0
        private IList <ChnkSection> ReadSections(BinaryReaderX br)
        {
            // Read raw chunks
            var chunks = new List <ChnkSection>();

            while (br.BaseStream.Position < br.BaseStream.Length)
            {
                chunks.Add(br.ReadType <ChnkSection>());
            }

            // Decompress chunk data
            foreach (var chunk in chunks)
            {
                if (chunk.decompressedSize == 0)
                {
                    continue;
                }

                var ms = new MemoryStream();
                NintendoCompressor.Decompress(new MemoryStream(chunk.data), ms);

                ms.Position = 0;
                chunk.data  = ms.ToArray();
            }

            return(chunks);
        }
示例#6
0
        private IArchiveFileInfo CreateAfi(Stream file, string name)
        {
            file.Position = 0;

            var method = NintendoCompressor.PeekCompressionMethod(file);
            var size   = NintendoCompressor.PeekDecompressedSize(file);

            return(new ArchiveFileInfo(file, name, NintendoCompressor.GetConfiguration(method), size));
        }
示例#7
0
        private Stream Decompress(Stream input)
        {
            var output = new MemoryStream();

            NintendoCompressor.Decompress(input, output);

            output.Position = 0;
            return(output);
        }
示例#8
0
        private IArchiveFileInfo CreateAfi(Stream file, string name, TarcEntry entry)
        {
            if (entry.compSize != 0 && entry.compSize != entry.decompSize)
            {
                var method = NintendoCompressor.PeekCompressionMethod(file);
                return(new TarcArchiveFileInfo(file, name, entry, NintendoCompressor.GetConfiguration(method), entry.decompSize));
            }

            return(new TarcArchiveFileInfo(file, name, entry));
        }
示例#9
0
        private IArchiveFileInfo CreateAfi(Stream input, string fileName, PackEntry entry)
        {
            var method = NintendoCompressor.PeekCompressionMethod(input);

            if (!NintendoCompressor.IsValidCompressionMethod(method))
            {
                return(new PackArchiveFileInfo(input, fileName, entry));
            }

            return(new PackArchiveFileInfo(input, fileName, entry, NintendoCompressor.GetConfiguration(method), NintendoCompressor.PeekDecompressedSize(input)));
        }
示例#10
0
        private IArchiveFileInfo CreateAfi(Stream file, string fileName, Gk2Arc1Entry entry)
        {
            if (!entry.IsCompressed)
            {
                return(new Gk2Arc1ArchiveFileInfo(file, fileName, entry));
            }

            file.Position = 0;
            var compression      = NintendoCompressor.PeekCompressionMethod(file);
            var decompressedSize = NintendoCompressor.PeekDecompressedSize(file);

            return(new Gk2Arc1ArchiveFileInfo(file, fileName, entry, NintendoCompressor.GetConfiguration(compression), decompressedSize));
        }
示例#11
0
        public Task Save(IFileSystem fileSystem, UPath savePath, SaveContext saveContext)
        {
            var fileStream = _wasCompressed ? new MemoryStream() : fileSystem.OpenFile(savePath, FileMode.Create, FileAccess.Write);

            _img.Save(fileStream, Images[0].ImageInfo);

            if (_wasCompressed)
            {
                var compStream = fileSystem.OpenFile(savePath, FileMode.Create, FileAccess.Write);

                fileStream.Position = 0;
                NintendoCompressor.Compress(fileStream, compStream, _compMethod);
            }

            return(Task.CompletedTask);
        }
示例#12
0
        public async Task Load(IFileSystem fileSystem, UPath filePath, LoadContext loadContext)
        {
            var fileStream = await fileSystem.OpenFileAsync(filePath);

            if (IsCompressed(fileStream))
            {
                _method = NintendoCompressor.PeekCompressionMethod(fileStream);
            }

            if (_method != null)
            {
                fileStream = Decompress(fileStream);
            }

            Images = new List <IKanvasImage> {
                new KanvasImage(EncodingDefinition, _raw.Load(fileStream))
            };
        }
示例#13
0
        public IList <IArchiveFileInfo> Load(Stream dataStream, Stream matStream)
        {
            using var br    = new BinaryReaderX(dataStream, true);
            using var matBr = new BinaryReaderX(matStream);

            // Read entries
            var entries = matBr.ReadMultiple <SarEntry>((int)(matStream.Length / EntrySize));

            // Read header
            _header = br.ReadType <SarContainerHeader>();

            // Add files
            var result = new List <IArchiveFileInfo>();

            for (var i = 0; i < entries.Count; i++)
            {
                var entry = entries[i];
                dataStream.Position = entry.offset;

                // Read compression header
                var compHeader = br.ReadType <SarContainerHeader>();
                if (compHeader.magic != "cmp ")
                {
                    result.Add(new SarArchiveFileInfo(new SubStream(dataStream, entry.offset, entry.size), $"{i:00000000}.bin"));
                    continue;
                }

                compHeader = br.ReadType <SarContainerHeader>();
                if (compHeader.magic != "lz7 ")
                {
                    throw new InvalidOperationException($"Unknown compression container detected for file at index {i}.");
                }

                var fileStream = new SubStream(dataStream, entry.offset + 0x18, SarSupport.GetCompressedSize(dataStream, entry.offset + 0x18, compHeader.data2));
                var name       = $"{i:00000000}.bin";

                var compMethod = NintendoCompressor.PeekCompressionMethod(fileStream);
                result.Add(new SarArchiveFileInfo(fileStream, name, NintendoCompressor.GetConfiguration(compMethod), NintendoCompressor.PeekDecompressedSize(fileStream)));
            }

            return(result);
        }
示例#14
0
        public Task Save(IFileSystem fileSystem, UPath savePath, SaveContext saveContext)
        {
            var fileStream = _method != null ?
                             new MemoryStream() :
                             fileSystem.OpenFile(savePath, FileMode.Create, FileAccess.Write);

            _raw.Save(fileStream, Images[0].ImageInfo);

            if (_method == null)
            {
                return(Task.CompletedTask);
            }

            var output = fileSystem.OpenFile(savePath, FileMode.Create, FileAccess.Write);

            fileStream.Position = 0;
            NintendoCompressor.Compress(fileStream, output, _method.Value);

            return(Task.CompletedTask);
        }
示例#15
0
        public IList <IArchiveFileInfo> Load(Stream input)
        {
            using var br = new BinaryReaderX(input, true);

            var offsets = new List <long>();

            while (br.BaseStream.Position < br.BaseStream.Length)
            {
                var headerMagic = br.ReadString(6);
                if (headerMagic == "3DS-LZ")
                {
                    offsets.Add(br.BaseStream.Position + 2);
                }

                br.BaseStream.Position += 0x3A;
            }

            _sizes = new int[offsets.Count];
            for (var i = 0; i < offsets.Count; i++)
            {
                var endOffset = i + 1 == offsets.Count ? input.Length : (offsets[i + 1] - 8);
                _sizes[i] = (int)(endOffset - offsets[i]);
            }

            // Add files
            var result = new ArchiveFileInfo[offsets.Count];

            for (var i = 0; i < offsets.Count; i++)
            {
                var subStream = new SubStream(input, offsets[i], _sizes[i]);

                var compressionMethod = NintendoCompressor.PeekCompressionMethod(subStream);
                var decompressedSize  = NintendoCompressor.PeekDecompressedSize(subStream);

                result[i] = new ArchiveFileInfo(subStream, $"{i:00000000}{_3dsLzSupport.DetermineExtension(subStream)}",
                                                NintendoCompressor.GetConfiguration(compressionMethod), decompressedSize);
            }

            return(result);
        }