RocksmithToolkitLib.PsarcLoader.PSARC.Read C# (CSharp) Method

Read() public method

public Read ( Stream psarc, bool lazy = false ) : void
psarc Stream
lazy bool
return void
        public void Read(Stream psarc, bool lazy = false)
        {
            _toc.Clear();
            _reader = new BigEndianBinaryReader(psarc);
            _header.MagicNumber = _reader.ReadUInt32();
            if (_header.MagicNumber == 1347633490U) //PSAR (BE)
            {
                //Parse Header
                _header.VersionNumber = _reader.ReadUInt32();
                _header.CompressionMethod = _reader.ReadUInt32();
                _header.TotalTOCSize = _reader.ReadUInt32();
                _header.TOCEntrySize = _reader.ReadUInt32();
                _header.NumFiles = _reader.ReadUInt32();
                _header.BlockSizeAlloc = _reader.ReadUInt32();
                _header.ArchiveFlags = _reader.ReadUInt32();
                //Read TOC
                int tocSize = (int)(_header.TotalTOCSize - 32U);
                if (_header.ArchiveFlags == 4) //TOC_ENCRYPTED
                {
                    // Decrypt TOC
                    var tocStream = new MemoryStream();
                    using (var decStream = new MemoryStream())
                    {
                        RijndaelEncryptor.DecryptPSARC(psarc, decStream, _header.TotalTOCSize);

                        int bytesRead;
                        int decSize = 0;
                        var buffer = new byte[_header.BlockSizeAlloc];
                        while ((bytesRead = decStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            decSize += bytesRead;
                            if (decSize > tocSize)
                                bytesRead = tocSize - (decSize - bytesRead);
                            tocStream.Write(buffer, 0, bytesRead);
                        }
                    }
                    tocStream.Position = 0;
                    _reader = new BigEndianBinaryReader(tocStream);
                }
                ParseTOC();
                //Parse zBlocksSizeList
                int tocChunkSize = (int)(_header.NumFiles * _header.TOCEntrySize); //(int)_reader.BaseStream.Position //don't alter this with. causes issues
                int zNum = (tocSize - tocChunkSize) / bNum;
                var zLengths = new uint[zNum];
                for (int i = 0; i < zNum; i++)
                {
                    switch (bNum)
                    {
                        case 2: //64KB
                            zLengths[i] = _reader.ReadUInt16();
                            break;
                        case 3: //16MB
                            zLengths[i] = _reader.ReadUInt24();
                            break;
                        case 4: //4GB
                            zLengths[i] = _reader.ReadUInt32();
                            break;
                    }
                }
                _zBlocksSizeList = zLengths; //TODO: validate

                _reader.BaseStream.Flush(); //Free tocStream resources
                _reader = new BigEndianBinaryReader(psarc);

                // Validate psarc size
                // if (psarc.Length < RequiredPsarcSize())
                // throw new InvalidDataException("Truncated psarc.");
                // try to unpack corrupt CDLC for now

                switch (_header.CompressionMethod)
                {
                    case 2053925218: //zlib (BE)
                        ReadManifest();
                        psarc.Seek(_header.TotalTOCSize, SeekOrigin.Begin);
                        if (!lazy)
                        {
                            // Decompress Data
                            InflateEntries();
                        }
                        break;
                    case 1819962721: //lzma (BE)
                        throw new NotImplementedException("LZMA compression not supported.");
                    default:
                        throw new InvalidDataException("Unknown compression.");
                }
            }
            psarc.Flush();
        }

Usage Example

        public static bool RemoveArchiveEntry(string psarcPath, string entryName)
        {
            if (!File.Exists(psarcPath))
            {
                return(false);
            }

            using (PSARC archive = new PSARC(true))
                using (var psarcStream = File.OpenRead(psarcPath))
                {
                    archive.Read(psarcStream);
                    psarcStream.Dispose(); // CRITICAL

                    var tocEntry = archive.TOC.FirstOrDefault(entry => entry.Name == entryName);

                    if (tocEntry == null)
                    {
                        archive.Dispose(); // CRITICAL
                        return(true);
                    }

                    archive.TOC.Remove(tocEntry);
                    archive.TOC.Insert(0, new Entry()
                    {
                        Name = "NamesBlock.bin"
                    });

                    using (var fs = File.Create(psarcPath))
                        archive.Write(fs, true);

                    archive.Dispose(); // CRITICAL
                    return(true);
                }
        }
All Usage Examples Of RocksmithToolkitLib.PsarcLoader.PSARC::Read