Exemplo n.º 1
0
        private void patchGroups(NkitPartitionPatchInfo patchInfo, WiiDiscHeaderSection discHeader, long crcPatchOffset, byte[] crcPatchData)
        {
            long partDataOffset = patchInfo.DiscOffset + patchInfo.PartitionHeader.Size;
            int  groupIdx       = (int)((crcPatchOffset - partDataOffset) / WiiPartitionSection.GroupSize);

            byte[] data = new byte[WiiPartitionSection.GroupSize];

            WiiPartitionHeaderSection wh = new WiiPartitionHeaderSection(discHeader, null, partDataOffset, patchInfo.PartitionHeader.Data, patchInfo.PartitionHeader.Size)
            {
                ScrubManager = patchInfo.ScrubManager
            };

            wh.Initialise(true, patchInfo.PartitionDataHeader.ReadString(0, 4));
#if DECRYPT
            WiiPartitionGroupSection wp = new WiiPartitionGroupSection(discHeader, wh, ph.Data, , ph.Data.Length, false);
#else
            WiiPartitionGroupSection wp = new WiiPartitionGroupSection(discHeader, wh, data, partDataOffset, Math.Min(WiiPartitionSection.GroupSize, crcPatchData.Length), true);
#endif

            if (patchInfo.Fst != null)
            {
                using (MemoryStream fstStream = new MemoryStream(patchInfo.Fst.Data))
                {
                    fstPatch(patchInfo, wp, crcPatchOffset, crcPatchData, fstStream);
                }
            }

            MemorySection d = new MemorySection(crcPatchData);

            for (long i = 0; i < crcPatchData.Length; i += WiiPartitionSection.GroupSize)
            {
                Array.Copy(d.Data, (int)i, data, 0, Math.Min(WiiPartitionSection.GroupSize, d.Size - i));
                wp.Populate(groupIdx++, data, crcPatchOffset + i, Math.Min(WiiPartitionSection.GroupSize, d.Size - i));
                wp.ForceHashes(null);
                if (patchInfo.HashGroups.ContainsKey(wp.DiscOffset))
                {
                    hashPatchGroup(patchInfo, wp);
                    d.Write((int)i, wp.Encrypted, (int)wp.Size);
                }
            }
        }
Exemplo n.º 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;
                }
            }
        }