예제 #1
0
파일: MtArc.cs 프로젝트: obluda3/Kuriimu2
        private IList <IArchiveFileInfo> LoadSwitch(Stream input)
        {
            using var br = new BinaryReaderX(input, true);

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

            // Read entries
            var entries = br.ReadMultiple <MtEntrySwitch>(_header.entryCount);

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

            foreach (var entry in entries)
            {
                var fileStream = new SubStream(input, entry.Offset, entry.CompSize);
                var fileName   = entry.FileName.TrimEnd('\0') + MtArcSupport.DetermineExtension(entry.ExtensionHash);

                // It seems every file is compressed with ZLib on Switch
                // Reasoning: Example file game.arc contains of at least one file "om120a" where compressed and uncompressed size are equal but the file is still compressed
                //            the decompressed file is really the same size; comparing with other entries no clear differences were found, that would indicate a
                //            compression flag
                result.Add(new MtArchiveFileInfo(fileStream, fileName, entry, Kompression.Implementations.Compressions.ZLib, entry.GetDecompressedSize(_platform)));
            }

            return(result);
        }
예제 #2
0
파일: MtArc.cs 프로젝트: obluda3/Kuriimu2
        private IList <IArchiveFileInfo> LoadLittleEndian(Stream input)
        {
            using var br = new BinaryReaderX(input, true);

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

            // Skip additional int under certain conditions
            if (_header.version != 7 && _header.version != 8)
            {
                br.ReadInt32();
            }

            // Read entries
            var entries = br.ReadMultiple <MtEntry>(_header.entryCount);

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

            foreach (var entry in entries)
            {
                var fileStream = new SubStream(input, entry.Offset, entry.CompSize);
                var fileName   = entry.FileName.TrimEnd('\0') + MtArcSupport.DetermineExtension(entry.ExtensionHash);

                result.Add(CreateAfi(fileStream, fileName, entry, _platform));
            }

            return(result);
        }
예제 #3
0
파일: Arcc.cs 프로젝트: obluda3/Kuriimu2
        public IList <IArchiveFileInfo> Load(Stream input)
        {
            using var br = new BinaryReaderX(input, true);

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

            // Read entries
            var key         = GetCipherKey("imaguy_uyrag_igurustim_", "enokok_ikorodo_odohuran");
            var entryStream = new MtBlowfishStream(new SubStream(input, HeaderSize, _header.entryCount * EntrySize), key);

            using var entryBr = new BinaryReaderX(entryStream);
            var entries = entryBr.ReadMultiple <MtEntry>(_header.entryCount);

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

            foreach (var entry in entries)
            {
                var fileStream = new MtBlowfishStream(new SubStream(input, entry.Offset, entry.CompSize), key);
                var name       = entry.FileName + MtArcSupport.DetermineExtension(entry.ExtensionHash);

                result.Add(MtArc.CreateAfi(fileStream, name, entry, MtArcPlatform.LittleEndian));
            }

            return(result);
        }
예제 #4
0
        public IList <IArchiveFileInfo> Load(Stream input)
        {
            _isEncrypted = IsEncrypted(input);
            var key = GetCipherKey("imaguy_uyrag_igurustim_", "enokok_ikorodo_odohuran");

            using var br = new BinaryReaderX(input, true);

            // Determine byte order
            var magic = br.ReadString(4);

            br.ByteOrder    = _byteOrder = magic == "\0CRA" ? ByteOrder.BigEndian : ByteOrder.LittleEndian;
            input.Position -= 4;

            // Header
            _header = br.ReadType <MtHeader>();

            // Determine possible platform the arc was found on
            _platform = MtArcSupport.DeterminePlatform(_byteOrder, _header);

            // Skip additional int under certain conditions
            if (_byteOrder == ByteOrder.LittleEndian && _header.version != 7 && _header.version != 8 && _header.version != 9)
            {
                br.ReadInt32();
            }

            // Read entries
            Stream entryStream = new SubStream(input, br.BaseStream.Position, input.Length - br.BaseStream.Position);

            if (_isEncrypted)
            {
                entryStream = new MtBlowfishStream(entryStream, key);
            }

            using var entryBr = new BinaryReaderX(entryStream);
            var entries = entryBr.ReadMultiple(_header.entryCount, _header.version == 9 ? typeof(MtEntrySwitch) : typeof(MtEntry)).Cast <IMtEntry>();

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

            foreach (var entry in entries)
            {
                Stream subStream = new SubStream(input, entry.Offset, entry.CompSize);
                var    fileName  = entry.FileName.TrimEnd('\0') + MtArcSupport.DetermineExtension(entry.ExtensionHash);

                if (_isEncrypted)
                {
                    subStream = new MtBlowfishStream(subStream, key);
                }

                result.Add(CreateAfi(subStream, fileName, entry, _platform));
            }

            return(result);
        }
예제 #5
0
        public async Task Load(IFileSystem fileSystem, UPath filePath, LoadContext loadContext)
        {
            _hasAddedFiles   = false;
            _hasDeletedFiles = false;

            var fileStream = await fileSystem.OpenFileAsync(filePath);

            var platform = MtArcSupport.DeterminePlatform(fileStream);

            Files = _arc.Load(fileStream, platform);
        }
예제 #6
0
파일: MtArc.cs 프로젝트: obluda3/Kuriimu2
        public static int GetArchiveSize(IList <IArchiveFileInfo> files, int version, ByteOrder byteOrder)
        {
            // Get header size
            var isExtendedHeader = version != 7 && version != 8;
            var headerSize       = HeaderSize + (isExtendedHeader ? 4 : 0);

            // Get file offset
            var fileOffset = MtArcSupport.DetermineFileOffset(byteOrder, version, files.Count, headerSize);

            // Add file sizes
            var fileRegionSize = (int)files.Cast <MtArchiveFileInfo>().Sum(x => x.GetFinalStream().Length);

            return(fileOffset + fileRegionSize);
        }
예제 #7
0
파일: Arcc.cs 프로젝트: obluda3/Kuriimu2
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            var key = GetCipherKey("imaguy_uyrag_igurustim_", "enokok_ikorodo_odohuran");

            using var bw = new BinaryWriterX(output);

            // Calculate offsets
            var entryOffset = HeaderSize;
            var fileOffset  = MtArcSupport.DetermineFileOffset(ByteOrder.LittleEndian, _header.version, files.Count, entryOffset);

            // Prepare output stream
            output.SetLength(MtArc.GetArchiveSize(files, _header.version, ByteOrder.LittleEndian));

            // Write files
            var entries = new List <IMtEntry>();

            var filePosition = fileOffset;

            foreach (var file in files.Cast <MtArchiveFileInfo>())
            {
                var    fileStream   = file.GetFinalStream();
                Stream targetStream = new SubStream(output, filePosition, fileStream.Length);
                targetStream = new MtBlowfishStream(targetStream, key);

                fileStream.CopyTo(targetStream);

                file.Entry.Offset = filePosition;
                file.Entry.SetDecompressedSize((int)file.FileSize, MtArcPlatform.LittleEndian);
                file.Entry.CompSize = (int)fileStream.Length;
                entries.Add(file.Entry);

                filePosition += (int)fileStream.Length;
            }

            // Write entries
            Stream entryStream = new SubStream(output, entryOffset, output.Length - entryOffset);

            entryStream       = new MtBlowfishStream(entryStream, key);
            using var entryBw = new BinaryWriterX(entryStream);

            entryBw.WriteMultiple(entries);

            // Write header
            _header.entryCount = (short)files.Count;

            output.Position = 0;
            bw.WriteType(_header);
        }
예제 #8
0
파일: MtArc.cs 프로젝트: obluda3/Kuriimu2
        public IArchiveFileInfo Add(Stream fileData, UPath filePath)
        {
            // Determine extension hash
            var extensionHash = Regex.IsMatch(filePath.GetExtensionWithDot(), @"\.[\da-fA-F]{8}") ?
                                uint.Parse(filePath.GetExtensionWithDot().Substring(1), NumberStyles.HexNumber) :
                                MtArcSupport.DetermineExtensionHash(filePath.GetExtensionWithDot());

            // Create entry
            IMtEntry entry;

            switch (_platform)
            {
            case MtArcPlatform.Switch:
                entry = new MtEntrySwitch
                {
                    ExtensionHash = extensionHash,
                    FileName      = (filePath.GetDirectory() / filePath.GetNameWithoutExtension()).FullName,
                    decompSize    = (int)fileData.Length
                };
                break;

            case MtArcPlatform.LittleEndian:
            case MtArcPlatform.BigEndian:
                entry = new MtEntry
                {
                    ExtensionHash = extensionHash,
                    FileName      = (filePath.GetDirectory() / filePath.GetNameWithoutExtension()).FullName,
                    decompSize    = (int)fileData.Length,
                };
                break;

            default:
                throw new InvalidOperationException();
            }

            // Create ArchiveFileInfo
            return(CreateAfi(fileData, filePath.FullName, entry, _platform));
        }
예제 #9
0
파일: MtArc.cs 프로젝트: obluda3/Kuriimu2
        private void SaveLittleEndian(Stream output, IList <IArchiveFileInfo> files)
        {
            using var bw = new BinaryWriterX(output);

            var isExtendedHeader = _header.version != 7 && _header.version != 8;

            // Calculate offsets
            var entryOffset = HeaderSize + (isExtendedHeader ? 4 : 0);
            var fileOffset  = MtArcSupport.DetermineFileOffset(ByteOrder.LittleEndian, _header.version, files.Count, entryOffset);

            // Write files
            var entries = new List <IMtEntry>();

            var filePosition = fileOffset;

            foreach (var file in files.Cast <MtArchiveFileInfo>())
            {
                output.Position = filePosition;
                var writtenSize = file.SaveFileData(output);

                file.Entry.Offset = filePosition;
                file.Entry.SetDecompressedSize((int)file.FileSize, _platform);
                file.Entry.CompSize = (int)writtenSize;
                entries.Add(file.Entry);

                filePosition += (int)writtenSize;
            }

            // Write entries
            output.Position = entryOffset;
            bw.WriteMultiple(entries);

            // Write header
            _header.entryCount = (short)files.Count;

            output.Position = 0;
            bw.WriteType(_header);
        }
예제 #10
0
파일: MtArc.cs 프로젝트: obluda3/Kuriimu2
        private IList <IArchiveFileInfo> LoadBigEndian(Stream input)
        {
            using var br = new BinaryReaderX(input, true, ByteOrder.BigEndian);

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

            // Read entries
            var entries = br.ReadMultiple <MtEntry>(_header.entryCount);

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

            foreach (var entry in entries)
            {
                var fileStream = new SubStream(input, entry.Offset, entry.CompSize);
                var fileName   = entry.FileName.TrimEnd('\0') + MtArcSupport.DetermineExtension(entry.ExtensionHash);

                result.Add(CreateAfi(fileStream, fileName, entry, _platform));
            }

            return(result);
        }
예제 #11
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            var key = GetCipherKey("imaguy_uyrag_igurustim_", "enokok_ikorodo_odohuran");

            using var bw = new BinaryWriterX(output, _byteOrder);

            var isExtendedHeader = _byteOrder == ByteOrder.LittleEndian && _header.version != 7 && _header.version != 8 && _header.version != 9;

            // Calculate offsets
            var entryOffset = HeaderSize + (isExtendedHeader ? 4 : 0);
            var fileOffset  = MtArcSupport.DetermineFileOffset(_byteOrder, _header.version, files.Count, entryOffset);

            // Write files
            var entries = new List <IMtEntry>();

            var filePosition = fileOffset;

            foreach (var file in files.Cast <MtArchiveFileInfo>())
            {
                output.Position = filePosition;

                long writtenSize;
                if (!_isEncrypted)
                {
                    writtenSize = file.SaveFileData(output);
                }
                else
                {
                    var fileStream = file.GetFinalStream();

                    var ms = new MemoryStream();
                    var encryptedStream = new MtBlowfishStream(ms, key);

                    fileStream.CopyTo(encryptedStream);

                    ms.Position = 0;
                    ms.CopyTo(output);

                    writtenSize = fileStream.Length;
                }

                file.Entry.Offset = filePosition;
                file.Entry.SetDecompressedSize((int)file.FileSize, _platform);
                file.Entry.CompSize = (int)writtenSize;
                entries.Add(file.Entry);

                filePosition += (int)writtenSize;
            }

            // Write entries
            Stream entryStream = new SubStream(output, entryOffset, output.Length - entryOffset);

            if (_isEncrypted)
            {
                entryStream = new MtBlowfishStream(entryStream, key);
            }

            using var entryBw = new BinaryWriterX(entryStream, _byteOrder);
            entryBw.WriteMultiple(entries);

            // Write header
            _header.entryCount = (short)files.Count;

            output.Position = 0;
            bw.WriteType(_header);
        }