示例#1
0
        public IList <IArchiveFileInfo> Load(Stream input)
        {
            // Prepare binary readers
            using var br = new BinaryReaderX(input, true);

            var isoStream = new SubStream(input, 0x1800, input.Length - 0x1800);

            // Read header
            _header     = br.ReadType <CvmHeader>();
            _zoneInfo   = br.ReadType <CvmZoneInfo>();
            _unkDataLoc = br.ReadBytes(0x800);

            // Prepare decryption stream
            Stream decStream = isoStream;

            if (_header.IsEncrypted)
            {
                _detectedPassword = DetectPassword(isoStream);
                decStream         = new RofsCryptoStream(isoStream, _detectedPassword, 0, 0x800);
            }

            using var decBr = new BinaryReaderX(decStream);

            // Read ISO primary descriptor
            decStream.Position = 0x8000;
            _primeDesc         = decBr.ReadType <IsoPrimaryDescriptor>();

            // Read record tree
            return(ParseDirTree(decBr, isoStream, _primeDesc.rootDirRecord.extentLe, _primeDesc.rootDirRecord.sizeLe, UPath.Root).ToArray());
        }
示例#2
0
        private string DetectPassword(Stream input)
        {
            input = new SubStream(input, 0x8000, 0x800);

            foreach (var pw in Passwords)
            {
                using var cipher   = new RofsCryptoStream(input, pw, 0x10, 0x800);
                using var cipherBr = new BinaryReaderX(cipher);

                cipher.Position = 1;
                if (cipherBr.ReadString(5) == "CD001")
                {
                    return(pw);
                }
            }

            throw new InvalidOperationException("Password could not be detected. Please report this on the github of the developers of Kuriimu2.");
        }
示例#3
0
        public void Save(Stream output, IList <IArchiveFileInfo> files)
        {
            var fileTree = files.ToTree();

            // Pre-calculate size of the TOC
            var dirSize = CalculateDirTreeSize(fileTree);

            // Prepare streams
            output.SetLength(0xB800 + dirSize);
            Stream tocStream = new SubStream(output, 0x1800, 0xA000 + dirSize);

            if (_header.IsEncrypted)
            {
                tocStream = new RofsCryptoStream(tocStream, _detectedPassword, 0, 0x800);
            }

            // Write files and TOC
            using var tocBw = new BinaryWriterX(tocStream);
            var fileOffset = (long)(0xB800 + dirSize);

            WriteDirTree(fileTree, output, tocBw, 0xA000, ref fileOffset);

            // Write pre TOC information
            _primeDesc.volSizeBe            = (int)((output.Length - 0x1800 + 0x7FF) & ~0x7FF);
            _primeDesc.volSizeLe            = (int)((output.Length - 0x1800 + 0x7FF) & ~0x7FF);
            _primeDesc.logicalBlockSizeLe   = 0x800;
            _primeDesc.logicalBlockSizeBe   = 0x800;
            _primeDesc.rootDirRecord.sizeLe = (uint)dirSize;
            _primeDesc.rootDirRecord.sizeBe = (uint)dirSize;

            tocStream.Position = 0x8000;
            tocBw.WriteType(_primeDesc);
            tocBw.WriteAlignment(0x800);

            // Write end ISO sector
            tocBw.Write((byte)0xFF);
            tocBw.WriteString("CD001", Encoding.ASCII, false, false);
            tocBw.Write((short)0x1);
            tocBw.WriteAlignment(0x800);

            // Write root dir information in little endian
            tocBw.Write((short)0x1);
            tocBw.Write(0x14);
            tocBw.Write((short)1);
            tocBw.WriteAlignment(0x800);

            // Write root dir information in big endian
            tocBw.Write((short)0x1);
            tocBw.ByteOrder = ByteOrder.BigEndian;
            tocBw.Write(0x14);
            tocBw.Write((short)1);

            // Write CVM header information
            _header.fileSize            = output.Length;
            _zoneInfo.isoDataLoc.length = output.Length - 0x1800;

            using var bw    = new BinaryWriterX(output);
            output.Position = 0;
            bw.WriteType(_header);
            bw.WriteType(_zoneInfo);
            bw.Write(_unkDataLoc);
        }