Пример #1
0
        private void hashPatchGroup(NkitPartitionPatchInfo pi, WiiPartitionGroupSection wp)
        {
            int blockCount = (int)(wp.Size / 0x8000);

            for (int i = 0; i < blockCount; i++)
            {
                Array.Copy(pi.HashGroups[wp.DiscOffset].Data, i * 0x400, wp.Decrypted, i * 0x8000, 0x400);
            }

            byte[] e = wp.Encrypted;

            for (int bi = 0; bi < blockCount; bi++)
            {
                if (pi.ScrubManager.IsBlockScrubbed(wp.Offset + (bi * 0x8000), out byte byt))
                {
                    wp.MarkBlockDirty(bi); //will be reset by ApplyHashes
                    wp.SetScrubbed(bi, byt);
                }
            }
        }
Пример #2
0
        private void fstPatch(NkitPartitionPatchInfo pi, WiiPartitionGroupSection wp, long patchOffset, byte[] crcPatchData, Stream fst)
        {
            long fstOffset = pi.PartitionDataHeader.ReadUInt32B(0x424) * 4L;
            long length    = pi.Fst.Data.Length;
            //seek to fst group
            int baseGroupIdx = (int)((patchOffset - (pi.DiscOffset + wp.Header.Size)) / WiiPartitionSection.GroupSize);

            int gs = (int)(fstOffset / (0x7c00L * 64));
            int ge = (int)((fstOffset + length) / (0x7c00L * 64));

            if ((int)((fstOffset + length) % (0x7c00L * 64)) == 0)
            {
                ge--; //don't load the next group if the data will end on the last byte
            }
            if (gs > baseGroupIdx || ge < baseGroupIdx)
            {
                return;
            }

            using (MemoryStream dest = new MemoryStream(crcPatchData))
            {
                if (gs != baseGroupIdx)
                {
                    dest.Seek((gs - baseGroupIdx) * WiiPartitionSection.GroupSize, SeekOrigin.Current);
                }

                long dstOffset = NStream.DataToHashedLen(fstOffset) % WiiPartitionSection.GroupSize; //offset in hashed group
                long total     = 0;

                for (int i = gs; i <= ge; i++)
                {
                    long dataPos = 0x7c00 * 64 * i;
                    int  dataLen = (int)Math.Min(WiiPartitionSection.GroupSize, (wp.Header.ReadUInt32B(0x2bc) * 4L) - (WiiPartitionSection.GroupSize * i)); //can be less than 2mb if partition is small (or were are at the end)
                    int  read    = dest.Read(wp.Data, 0, wp.Data.Length);
                    if (read == 0)
                    {
                        break;
                    }
                    dest.Seek(-read, SeekOrigin.Current);

                    wp.Populate(i, wp.Data, patchOffset, dataLen); //auto decrypted

                    while (length != total && dstOffset != WiiPartitionSection.GroupSize)
                    {
                        dstOffset += 0x400;                                                                                            //skip hashes
                        long l = fst.Read(wp.Decrypted, (int)dstOffset, (int)Math.Min(length - total, 0x8000 - (dstOffset % 0x8000))); //no padding etc as fst will be the same size
                        dstOffset += l;
                        total     += l;
                    }

                    Array.Clear(wp.Decrypted, dataLen, (int)wp.Size - dataLen);

                    int bnkCount      = (int)(dataLen / 0x8000);
                    int scrubbedCount = 0;
                    for (int bi = 0; bi < bnkCount; bi++)
                    {
                        wp.MarkBlockDirty(bi); //set to force hash generation
                        byte byt;
                        if (pi.ScrubManager.IsBlockScrubbed(wp.Offset + (bi * 0x8000), out byt))
                        {
                            wp.SetScrubbed(bi, byt);
                            scrubbedCount++;
                        }
                    }

                    repairBlocks(wp, scrubbedCount, bnkCount, true, false);

#if DECRYPT
                    dest.Write(wp.Decrypted, 0, dataLen);
#else
                    dest.Write(wp.Encrypted, 0, dataLen);
#endif
                    dstOffset = 0;
                }
            }
        }