Пример #1
0
        public long Encode(Stream s, ref long srcPos, long nulls, long gapLength, JunkStream junk, ScrubManager scrub, Stream output, ILog log)
        {
            int  read    = 0;
            long written = 0;

            _headerWritten = false;
            junk.Position  = srcPos;

            if (gapLength != 0)
            {
                int[]  results    = new int[0x400];
                byte[] scrubBytes = new byte[results.Length];
                byte[] buff       = new byte[Math.Min(gapLength, Gap.BlockSize * results.Length)];
                byte[] jbuff      = new byte[buff.Length]; //cache some junk up front so we can thread the block comparisons
                long   start      = srcPos;

                do
                {
                    int req = (int)Math.Min(buff.Length, gapLength - this.Length);
                    Task.WaitAll(
                        Task.Run(() => read = s.Read(buff, 0, req)),
                        Task.Run(() => junk.Read(jbuff, 0, req))
                        );

                    int  blocks = (int)(read / Gap.BlockSize) + (int)Math.Min(1, read % Gap.BlockSize);
                    long pos    = srcPos;
                    Parallel.For(0, blocks, bb =>
                    {
                        byte?scrubByte;
                        if ((results[bb] = blockCompare(nulls, jbuff, junk.JunkLength, scrub, buff, (int)Gap.BlockSize * bb, (int)Math.Min(Gap.BlockSize * (bb + 1), read), pos, start == pos, out scrubByte)) == 1)
                        {
                            scrubBytes[bb] = scrubByte.Value;
                        }
                    });

                    for (int bb = 0; bb < blocks; bb++)
                    {
                        if (results[bb] == 0)
                        {
                            this.Set(); //junk
                        }
                        else if (results[bb] == 1)
                        {
                            this.Set(scrubBytes[bb]); //scrubbed
                            //log?.LogDebug(string.Format(">>> Scrubbed Written: {0} : {1}", srcPos.ToString("X8"), bb.ToString()));
                        }
                        else
                        {
                            //log?.LogDebug(string.Format(">>> NonJunk Written: {0} : {1}", srcPos.ToString("X8"), bb.ToString()));
                            written += this.Set(buff, (int)Gap.BlockSize * bb, (int)Math.Min(Gap.BlockSize * (bb + 1), read), output); //preserve (also data that's part scrubbed part junk in a 256 byte block)
                        }
                    }
                    srcPos += read;
                }while (this.Length < gapLength && read != 0); //sum of processed gap blocks < exact gap
            }

            written += write(output, !_headerWritten);
            return(written);
        }
Пример #2
0
 public void Populate(byte[] data, long discOffset, long size)
 {
     base.DiscOffset = discOffset;
     base.Size       = size;
     if (_junk != null)
     {
         _junk.Read(_junkData, 0, (int)base.Size);
     }
     base.Data = _useBuff ? data : _junkData;
 }
Пример #3
0
 internal WiiFillerSectionItem(NStream stream, long discOffset, byte[] data, long size, bool useBuff, JunkStream junk) : base(stream, discOffset, data, size)
 {
     _useBuff = useBuff;
     _junk    = junk;
     if (_junk != null)
     {
         _junk.Position = discOffset;
         _junkData      = new byte[this.Data.Length];
         _junk.Read(_junkData, 0, (int)base.Size);
         Array.Clear(_junkData, 0, 28);
         base.Data = _useBuff ? data : _junkData;
     }
 }
Пример #4
0
        public bool Unscrub(List <JunkRedumpPatch> junkPatches)
        {
            bool changed = false;
            //bool performCheck = true; //start on the assumption last was valid as it would be hassle to work out
            List <FstFile> nulls = new List <FstFile>();

            bool good = _data.IsValid(false);                                                    //forces decrypt and hash cache build and test - does not test data in blocks matchs H0 table

            Parallel.For(0, _data.UsedBlocks, bi => _unscrubValid[bi] = _data.BlockIsValid(bi)); //test data matches H0 table

            for (int bi = 0; bi < _data.UsedBlocks; bi++)
            {
                if (!_unscrubValid[bi])
                {
                    if (_junk == null)
                    {
                        _junk = new JunkStream(_partHdr.Id, _partHdr.DiscNo, _partHdr.PartitionDataSize);
                    }

                    _junk.Position = NStream.OffsetToData(this.Offset + _data.BlockDataOffset(bi), true);
                    _junk.Read(_data.Decrypted, _data.BlockDataOffset(bi), 0x7c00);
                    _data.MarkBlockUnscrubbedAndDirty(bi);
                    changed = true;
                }
            }

            if (junkPatches != null && junkPatches.Count != 0)
            {
                foreach (JunkRedumpPatch jp in junkPatches)
                {
                    if (jp.Offset >= this.DiscOffset && jp.Offset < this.DiscOffset + this.Size)
                    {
                        Array.Copy(jp.Data, 0, _data.Decrypted, jp.Offset - this.DiscOffset, jp.Data.Length);
                        _data.MarkBlockDirty((int)((jp.Offset - this.DiscOffset) / 0x8000));  //560de532
                    }
                }
            }

            if (changed)
            {
                good = _data.IsValid(true); //true as changes were made
                if (!good)
                {
                    bool zerod = false;
                    List <Tuple <long, int, FstFile> > h3Nulls = new List <Tuple <long, int, FstFile> >(_partHdr.ScrubManager.H3Nulls);

                    if (h3Nulls.Count != 0)
                    {
                        int dataLen = (int)NStream.HashedLenToData(this.Decrypted.Length);
                        foreach (Tuple <long, int, FstFile> n in h3Nulls)
                        {
                            if (n.Item1 >= this.DataOffset && n.Item1 < this.DataOffset + dataLen)
                            {
                                int idx = (int)((n.Item1 - this.DataOffset) / 0x7c00);
                                _data.MarkBlockDirty(idx);
                                int pos = (int)NStream.DataToOffset(n.Item1 - this.DataOffset, true);
                                Array.Clear(_data.Decrypted, pos, n.Item2);
                                zerod = true;
                            }
                        }
                    }
                    if (zerod)
                    {
                        good = _data.IsValid(true);
                    }
                    if (!good)
                    {
                        this.H3Errors++;
                    }
                }
            }

            return(changed);
        }