Exemple #1
0
        internal static void LogNkitInfo(NkitInfo imageInfo, ILog log, string id, bool isDisc)
        {
            string pfx = string.Format("NKit {0} [{1}]", isDisc ? "Disc" : "Prtn", SourceFiles.CleanseFileName(id).PadRight(4));

            log?.LogDetail(string.Format("{0}: In [{1,2:#.0} MiB] ({2} bytes), Out [{3,2:#.0} MiB] (bytes {4})", pfx, imageInfo.BytesReadSize / (double)(1024 * 1024), imageInfo.BytesReadSize.ToString(), imageInfo.BytesWriteSize / (double)(1024 * 1024), imageInfo.BytesWriteSize.ToString()));
            if (imageInfo.BytesGcz != 0)
            {
                log?.LogDetail(string.Format("{0}: GCZ Out [{1,2:#.0} MiB] ({2} bytes)", pfx, imageInfo.BytesGcz / (double)(1024 * 1024), imageInfo.BytesGcz.ToString()));
            }

            if (imageInfo.BytesJunkFiles != 0)
            {
                log?.LogDetail(string.Format("{0}: Junk Files Removed [{1,2:#.0} MiB] ({2} bytes)", pfx, imageInfo.BytesJunkFiles / (double)(1024 * 1024), imageInfo.BytesJunkFiles.ToString()));
            }

            if (imageInfo.BytesHashesData != 0 || imageInfo.BytesHashesPreservation != 0)
            {
                log?.LogDetail(string.Format("{0}: Hashes In [{1,2:#.0} MiB] ({2} bytes), Preserved [{3,2:#.0} MiB] (bytes {4})", pfx, imageInfo.BytesHashesData / (double)(1024 * 1024), imageInfo.BytesHashesData.ToString(), imageInfo.BytesHashesPreservation / (double)(1024 * 1024), imageInfo.BytesHashesPreservation.ToString()));
            }

            if (imageInfo.BytesPreservationData != 0)
            {
                log?.LogDetail(string.Format("{0}: Preservation Data [{1,2:#.0} MiB] {2} bytes", pfx, imageInfo.BytesPreservationData / (double)(1024 * 1024), imageInfo.BytesPreservationData.ToString()));
            }

            if (imageInfo.BytesPreservationDiscPadding != 0)
            {
                log?.LogDetail(string.Format("{0}: Preservation Padding [{1,2:#.0} MiB] {2} bytes", pfx, imageInfo.BytesPreservationDiscPadding / (double)(1024 * 1024), imageInfo.BytesPreservationDiscPadding.ToString()));
            }

            if (imageInfo.FilesTotal != 0 || imageInfo.FilesAligned != 0)
            {
                log?.LogDetail(string.Format("{0}: {1} Total Files, {2} aligning boundary preserved", pfx, imageInfo.FilesTotal.ToString(), imageInfo.FilesAligned.ToString()));
            }
        }
Exemple #2
0
        private void btnSettingsProcess_Click(object sender, EventArgs e)
        {
            ListViewItem[] items = itemsToProcess().ToArray();

            if (_state == State.New) //if not resuming
            {
                _processFileIndex  = 0;
                _processFilesCount = items.Length;
            }

            setPaths(txtSettingsOutputPathBase.Text);

            _state = State.Processing;
            setScreenState();

            process(cboSettingsMode.SelectedIndex, items,
                    item => //started item
            {
                Invoke((MethodInvoker) delegate
                {
                    if (lvw.SelectedItems.Count == 0 || lvw.SelectedItems[0] == _processingItem)
                    {
                        item.Selected = true;     //move the logging on
                    }

                    _processingItem = item;
                });
            },
                    item => //completed item
            {
                Invoke((MethodInvoker) delegate
                {
                    setLog(((ProcessFile)item.Tag).Log);
                    _processFileIndex++;
                    OutputResults results = ((ProcessFile)item.Tag).Results;
                    if (results != null)
                    {
                        item.SubItems[1].Text = results.DiscType.ToString();
                        item.SubItems[2].Text = results.ValidateReadResult.ToString();
                        item.SubItems[3].Text = results.VerifyOutputResult.ToString();
                        item.SubItems[4].Text = results.OutputCrc.ToString("X8") ?? "";
                        item.SubItems[5].Text = SourceFiles.CleanseFileName(results.OutputId4 ?? "");
                        item.SubItems[6].Text = (results.RedumpInfo?.MatchType.ToString() ?? "") + (results.IsRecoverable ? "Recoverable" : "");
                        item.SubItems[7].Text = (results.OutputSize / (double)(1024 * 1024)).ToString("#.0") + " MiB";
                        item.SubItems[8].Text = results.RedumpInfo?.MatchName ?? "";
                    }
                    else
                    {
                        item.SubItems[1].Text = "Error";
                    }
                });
                return(_state != State.Stopping); //stop
            }).ContinueWith(
                t =>                              //finished processing
            {
                _state = _processFileIndex == _processFilesCount ? State.Complete : State.Stopped;
                setScreenState();
            });
        }
Exemple #3
0
        public string GetFilename(OutputResults results, string mask)
        {
            try
            {
                string fileName  = SourceFiles.CleanseFileName(SourceFiles.RemoveExtension(results.InputFileName, true));
                string titleName = SourceFiles.CleanseFileName(results.OutputTitle) ?? fileName;
                string tgdbName  = SourceFiles.CleanseFileName(GameTdbData.FirstOrDefault(a => a.Item1 == results.OutputId6)?.Item2) ?? titleName;
                string matchName = results.RedumpInfo?.MatchName != null?SourceFiles.CleanseFileName(results.RedumpInfo.MatchName) : (tgdbName ?? fileName);

                Dictionary <string, string> values = new Dictionary <string, string>
                {
                    { "%src", results.InputFileName ?? Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) },
                    { "%nmo", fileName },
                    { "%nmg", tgdbName },
                    { "%nmd", titleName },
                    { "%nmm", matchName },
                    { "%dno", results.OutputDiscNo == 0 ? "" : string.Format("(Disc {0})", results.OutputDiscNo.ToString()) },
                    { "%ver", results.OutputDiscVersion == 0 ? "" : string.Format("(v1.{0})", results.OutputDiscVersion.ToString("D2")) },
                    { "%rev", results.OutputDiscVersion == 0 ? "" : string.Format("(Rev {0})", results.OutputDiscVersion.ToString("D2")) },
                    { "%crc", results.OutputCrc.ToString("X8") },
                    { "%md5", results.OutputMd5 == null ? "" : BitConverter.ToString(results.OutputMd5).Replace("-", "") },
                    { "%sha", results.OutputSha1 == null ? "" : BitConverter.ToString(results.OutputSha1).Replace("-", "") },
                    { "%id4", SourceFiles.CleanseFileName(results.OutputId4).PadRight(4) },
                    { "%id6", SourceFiles.CleanseFileName(results.OutputId6).PadRight(6) },
                    { "%id8", SourceFiles.CleanseFileName(results.OutputId8).PadRight(8) }
                };

                string[] braces = new[] { "%crc", "%md5", "%sha", "%id4", "%id6", "%id8" };

                string fn = mask;
                foreach (KeyValuePair <string, string> v in values)
                {
                    if (fn.Contains(v.Key))
                    {
                        if (string.IsNullOrEmpty(v.Value) || Regex.IsMatch(fn, Regex.Escape(v.Value), RegexOptions.IgnoreCase))
                        {
                            fn = Regex.Replace(fn, string.Format(@"[ ._-]?{0}", v.Key), "", RegexOptions.IgnoreCase);
                        }
                        else
                        {
                            fn = fn.Replace(v.Key, string.Concat(braces.Contains(v.Key) ? "[" : "", v.Value, braces.Contains(v.Key) ? "]" : ""));
                        }
                    }
                }
                return(SourceFiles.GetUniqueName(fn.Replace("%ext", results.OutputFileExt.Trim('.'))));
            }
            catch (Exception ex)
            {
                throw new HandledException(ex, "DatData.GetFilename - Replace masks");
            }
        }
Exemple #4
0
        public void Write(Context ctx, Stream inStream, Stream outStream, Coordinator pc)
        {
            try
            {
                WiiDiscHeaderSection      hdr   = null;
                WiiPartitionHeaderSection pHdr  = null;
                string        lastPartitionId   = null;
                PartitionType lastPartitionType = PartitionType.Other;
                NCrc          crc                 = new NCrc();
                Crc           updateCrc           = new Crc();
                bool          updateRemoved       = false;
                string        updateTmpFileName   = null;
                string        updateFileName      = null;
                bool          extractingUpdate    = false;
                CryptoStream  updateCrcStream     = null;
                NStream       updateTarget        = null;
                CryptoStream  target              = null;
                MemorySection removedUpdateFiller = null;
                int           preservedHashCount  = 0;

                NkitInfo nkitDiscInfo     = new NkitInfo();
                long     fstFileAlignment = -1;

                WiiPartitionSection lastPart = null;

                long dstPos = 0;

                long   imageSize = pc.OutputSize;                 //for Wii: pHdr.PartitionDataLength
                string ignoreJunkId;
                pc.WriterCheckPoint1WriteReady(out ignoreJunkId); //wait until read has written the header and set the length

                NDisc disc = new NDisc(_log, inStream);

                foreach (IWiiDiscSection s in disc.EnumerateSections(imageSize)) //no fixing, image should be good //ctx.ImageLength
                {
                    if (s is WiiDiscHeaderSection)
                    {
                        hdr = (WiiDiscHeaderSection)s;
                        hdr.Write8(0x60, 1);
                        hdr.Write8(0x61, 1);

                        fstFileAlignment = ctx?.Settings?.PreserveFstFileAlignment?.FirstOrDefault(a => a.Item1 == hdr.Id8)?.Item2 ?? -1;

                        target = new CryptoStream(outStream, crc, CryptoStreamMode.Write);
                        target.Write(hdr.Data, 0, hdr.Data.Length); //write the header
                        nkitDiscInfo.BytesData += hdr.Size;
                        dstPos += hdr.Size;

                        crc.Snapshot("Disc Header");
                    }
                    else if (s is WiiPartitionSection)
                    {
                        WiiPartitionSection ps     = (WiiPartitionSection)s;
                        WiiHashStore        hashes = new WiiHashStore(ps.PartitionDataLength);
                        ScrubManager        scrub  = ps.Header.ScrubManager;

                        NkitInfo nkitPartInfo = new NkitInfo();

                        if (ps.Header.Type == PartitionType.Update && ctx.Settings.NkitUpdatePartitionRemoval && hdr.Partitions.Count() > 1) //only remove update if there's more partitions
                        {
                            updateRemoved    = true;
                            extractingUpdate = true;

                            pHdr             = ps.Header;
                            extractingUpdate = true;
                            updateCrcStream  = new CryptoStream(ByteStream.Zeros, updateCrc, CryptoStreamMode.Write);
                            crc.Initialize();
                            nkitPartInfo.BytesData += disc.WriteRecoveryPartitionData(updateCrcStream, false, ps, 0, out updateTmpFileName, out updateFileName, out updateTarget);
                            _log?.LogDetail(string.Format("Extracted and Removed {0} Recovery Partition: [{1}]", ps.Header.Type.ToString(), SourceFiles.CleanseFileName(ps.Header.Id).PadRight(4)));
                            removedUpdateFiller = new MemorySection(new byte[0x8000]);
                            removedUpdateFiller.Write(0, hdr.Read(0x40000, 0x100)); //backup the original partition table in case it's non standard in some way
                        }
                        else
                        {
                            target.Write(ps.Header.Data, 0, (int)ps.Header.Size);
                            nkitDiscInfo.BytesData += ps.Header.Size;

                            crc.Snapshot(ps.Id + " Hdr");
                            crc.Crcs.Last().PatchData = ps.Header.Data;
                            dstPos          += ps.Header.Size;
                            ps.NewDiscOffset = dstPos;

                            //long written = 0;
                            using (StreamCircularBuffer decrypted = new StreamCircularBuffer(ps.PartitionDataLength, null, null, output =>
                            {
                                //read decrypted partition
                                foreach (WiiPartitionGroupSection pg in ps.Sections)
                                {
                                    nkitPartInfo.BytesHashesData += (pg.Size / 0x8000 * 0x400); //size of input hashes

                                    if (pg.PreserveHashes())
                                    {
                                        nkitPartInfo.BytesHashesPreservation += hashes.Preserve(pg.Offset, pg.Decrypted, pg.Size);
                                        if (++preservedHashCount >= 1500) //too many will bomb the patch caching when converting back. Something is wrong
                                        {
                                            throw pc.SetWriterException(new HandledException("Over 1500 hashes preserved, aborting as image is corrupt or poorly scrubbed."));
                                        }
                                    }
#if !DECRYPT
                                    for (int i = 0; i < pg.Size / 0x8000; i++)
                                    {
                                        output.Write(pg.Decrypted, (i * 0x8000) + 0x400, 0x7c00);
                                    }
#else
                                    output.Write(pg.Decrypted, 0, (int)pg.Size);
#endif
                                }
                            }))
                            {
                                long len = partitionWrite(decrypted, crc, target, ps, ctx, pc, nkitPartInfo, scrub, hashes, fstFileAlignment);
                                ps.NewPartitionDataLength = len;
                                dstPos  += len;
                                lastPart = ps;
                            }
                        }
                        NkitFormat.LogNkitInfo(nkitPartInfo, _log, ps.Id, false);

                        lastPartitionId   = ps.Id;
                        lastPartitionType = ps.Header.Type;
                    }
                    else if (s is WiiFillerSection)
                    {
                        WiiFillerSection fs    = (WiiFillerSection)s;
                        ScrubManager     scrub = new ScrubManager(null);
                        JunkStream       junk  = new JunkStream(lastPartitionType != PartitionType.Data ? hdr.ReadString(0, 4) : lastPartitionId, hdr.Read8(6), lastPartitionType == PartitionType.Update ? 0 : imageSize);

                        if (lastPartitionType == PartitionType.Update && updateRemoved)
                        {
                            //preserve the original partition table and update filename
                            target.Write(removedUpdateFiller.Data, 0, (int)removedUpdateFiller.Size); //remove update partition by adding a 32k placeholder. Avoid having a non update partition at 0x50000
                            nkitDiscInfo.BytesPreservationDiscPadding += removedUpdateFiller.Size;
                            nkitDiscInfo.BytesGaps += fs.Size;
                            dstPos += removedUpdateFiller.Size;

                            crc.Snapshot(string.Format("{0}Replacement Filler", string.IsNullOrEmpty(lastPartitionId) ? "" : (" " + SourceFiles.CleanseFileName(lastPartitionId).PadRight(4))));
                            if (extractingUpdate)
                            {
                                int storeType;
                                if ((storeType = disc.WriteRecoveryPartitionFiller(updateCrcStream, junk, fs.DiscOffset, true, true, fs, updateTarget, updateTmpFileName, ref updateFileName, updateCrc, true)) != 0)
                                {
                                    _log.LogDetail(string.Format("{0}Update recovery partition stored: {1}", storeType == 2 ? "Other " : "", updateFileName));
                                }
                                extractingUpdate = false;
                            }
                        }
                        else
                        {
                            if (fs.Size != 0)
                            {
                                using (StreamCircularBuffer filler = new StreamCircularBuffer(fs.Size, null, null, output =>
                                {
                                    foreach (WiiFillerSectionItem item in ((WiiFillerSection)s).Sections)
                                    {
                                        output.Write(item.Data, 0, (int)item.Size);
                                    }
                                }))
                                {
                                    Gap  gap    = new Gap(fs.Size, false);
                                    long srcPos = fs.DiscOffset;
                                    long gapLen = gap.Encode(filler, ref srcPos, lastPartitionType == PartitionType.Update ? fs.Size : 0x1cL, fs.Size, junk, scrub, target, _log);
                                    nkitDiscInfo.BytesPreservationData += gapLen;
                                    nkitDiscInfo.BytesGaps             += fs.Size;
                                    dstPos += gapLen;
                                    if (lastPart != null)
                                    {
                                        lastPart.NewPartitionDataLength += gapLen;
                                    }
                                }
                            }
                            //pad partition to 32k
                            int gapLen2 = (int)(dstPos % 0x8000 == 0 ? 0 : 0x8000 - (dstPos % 0x8000));
                            ByteStream.Zeros.Copy(target, gapLen2);
                            nkitDiscInfo.BytesPreservationDiscPadding += gapLen2;
                            dstPos += gapLen2;
                            if (lastPart != null)
                            {
                                lastPart.NewPartitionDataLength += gapLen2;
                            }

                            if (lastPart != null)
                            {
                                lastPart.Header.WriteUInt32B(0x2bc, (uint)(lastPart.NewPartitionDataLength / 4)); //updates the array in the crc data
                                hdr.Partitions.First(a => a.DiscOffset == lastPart.DiscOffset).DiscOffset = (lastPart.NewDiscOffset - 0x20000);
                            }
                            crc.Snapshot(string.Format("{0}{1}Files+Filler", lastPartitionId ?? "", string.IsNullOrEmpty(lastPartitionId) ? "" : " "));
                        }
                    }
                }

                NkitFormat.LogNkitInfo(nkitDiscInfo, _log, hdr.Id, true);

                foreach (CrcItem ci in crc.Crcs.Where(a => a.PatchData != null))
                {
                    ci.PatchCrc = Crc.Compute(ci.PatchData);
                }

                NCrc readerCrcs;
                uint validationCrc;
                pc.WriterCheckPoint2Complete(out readerCrcs, out validationCrc, hdr.Data, dstPos); //wait until reader has completed and get crc patches.

                if (updateRemoved && crc.Crcs.Length > 2)                                          //freeloader wii only has update partition
                {
                    hdr.RemoveUpdatePartition(crc.Crcs[2].Offset);
                }

                hdr.UpdateOffsets();
                hdr.WriteString(0x200, 8, "NKIT v01"); //header and version
                hdr.Write8(0x60, 1);
                hdr.Write8(0x61, 1);
                hdr.WriteUInt32B(0x208, readerCrcs.FullCrc(true)); //original crc
                hdr.WriteUInt32B(0x210, (uint)(imageSize / 4L));   //ctx.ImageLength
                hdr.WriteUInt32B(0x218, updateCrc.Value);          //Update crc - Only if removed
                crc.Crcs[0].PatchCrc  = Crc.Compute(hdr.Data);
                crc.Crcs[0].PatchData = hdr.Data;
                hdr.WriteUInt32B(0x20C, CrcForce.Calculate(crc.FullCrc(true), dstPos, readerCrcs.FullCrc(true), 0x20C, 0)); //magic to force crc
                crc.Crcs[0].PatchCrc = Crc.Compute(hdr.Data);                                                               //update with magic applied

                pc.WriterCheckPoint3ApplyPatches(crc, false, crc.FullCrc(true), crc.FullCrc(true), this.VerifyIsWrite, "NKit Written");
            }
            catch (Exception ex)
            {
                throw pc.SetWriterException(ex, "NkitWriterWii.Write - Convert");
            }
        }
Exemple #5
0
        public virtual OutputResults Process(Context ctx, NStream input, Stream output)
        {
            OutputResults results = new OutputResults()
            {
                Conversion = ctx.ConversionName, VerifyOutputResult = VerifyResult.Unverified, ValidateReadResult = VerifyResult.Unverified
            };

            try
            {
                StreamCircularBuffer fs = null;

                _timer = new Timer
                {
                    Interval = 250
                };
                _timer.Elapsed += (s, e) =>
                {
                    if (_timerRunning)
                    {
                        return; //keep processing
                    }

                    try
                    {
                        _timerRunning = true;
                        _log.ProcessingProgress(((IProgress)fs)?.Value ?? 0);
                    }
                    catch { }
                    finally
                    {
                        _timerRunning = false;
                    }
                };
                _timer.Enabled = true;

                long size;
                switch (_sizeMode)
                {
                case ProcessorSizeMode.Source:
                    size = input.SourceSize;
                    break;

                case ProcessorSizeMode.Stream:
                    size = input.Length;
                    break;

                case ProcessorSizeMode.Image:
                    size = input.ImageSize;
                    break;

                case ProcessorSizeMode.Recover:
                default:
                    size = input.RecoverySize;
                    break;
                }

                Coordinator pc = new Coordinator(ctx.ValidationCrc, Reader, Writer, size);

                pc.Started += (s, e) =>
                {
                    _timer.Enabled      = true;
                    results.AliasJunkId = e.AliasJunkId;
                };
                pc.Completed += (s, e) =>
                {
                    _timer.Enabled = false;
                    if (Writer is HashWriter)
                    {
                        results.OutputMd5  = e.Md5;
                        results.OutputSha1 = e.Sha1;
                    }
                    else
                    {
                        MemorySection hdr = new MemorySection(e.Header ?? input.DiscHeader.Data);
                        results.OutputTitle       = hdr.ReadStringToNull(0x20, 0x60);
                        results.OutputDiscNo      = hdr.Read8(6);
                        results.OutputDiscVersion = hdr.Read8(7);
                        results.OutputId8         = string.Concat(hdr.ReadString(0, 6), results.OutputDiscNo.ToString("X2"), results.OutputDiscVersion.ToString("X2"));
                        results.ProcessorMessage  = e.ResultMessage;
                        results.OutputCrc         = e.PatchedCrc;
                        results.IsRecoverable     = e.IsRecoverable;
                        if (e.ValidationCrc != 0)
                        {
                            results.ValidationCrc      = e.ValidationCrc;
                            results.ValidateReadResult = e.ValidationCrc == e.PatchedCrc ? VerifyResult.VerifySuccess : VerifyResult.VerifyFailed;
                        }

                        if (!(Writer is VerifyWriter))
                        {
                            results.OutputSize = e.OutputSize; //never store the verify size
                        }
                        else
                        {
                            results.VerifyCrc = e.VerifyCrc;
                            if (e.VerifyIsWrite) //e.ValidationCrc can be set from a previous process run
                            {
                                results.VerifyOutputResult = results.ValidationCrc == results.VerifyCrc ? VerifyResult.VerifySuccess : VerifyResult.VerifyFailed;
                            }
                        }
                    }

                    bool l9 = pc.Patches.Crcs.Any(a => a.Offset > 0xFFFFFFFFL || a.Length > 0xFFFFFFFFL);
                    if (pc.ReaderCrcs != null)
                    {
                        foreach (CrcItem c in pc.ReaderCrcs.Crcs)
                        {
                            _log.LogDebug(string.Format("R-CRC {0}  Before:{1}  After:{2}  L:{3} {4}", c.Offset.ToString(l9 ? "X9" : "X8"), c.Value.ToString("X8"), c.PatchCrc == 0 ? "        " : c.PatchCrc.ToString("X8"), c.Length.ToString(l9 ? "X9" : "X8"), SourceFiles.CleanseFileName(c.Name)));
                        }

                        _log.LogDebug(string.Format("ReadCRC {0}Before:{1} After:{2}", l9 ? " " : "", pc.ReaderCrcs.FullCrc(false).ToString("X8"), pc.ReaderCrcs.FullCrc(true).ToString("X8")));
                    }
                    if (pc.WriterCrcs != null)
                    {
                        foreach (CrcItem c in pc.WriterCrcs.Crcs)
                        {
                            _log.LogDebug(string.Format("W-CRC {0}  Before:{1}  After:{2}  L:{3} {4}", c.Offset.ToString(l9 ? "X9" : "X8"), c.Value.ToString("X8"), c.PatchCrc == 0 ? "        " : c.PatchCrc.ToString("X8"), c.Length.ToString(l9 ? "X9" : "X8"), SourceFiles.CleanseFileName(c.Name)));
                        }

                        _log.LogDebug(string.Format("WriteCRC {0}Before:{1} After:{2}", l9 ? " " : "", pc.WriterCrcs.FullCrc(false).ToString("X8"), pc.WriterCrcs.FullCrc(true).ToString("X8")));
                    }
                    _log.ProcessingComplete(results.OutputSize, results.ProcessorMessage, true);
                };

                try
                {
                    _log.ProcessingStart(input.SourceSize, Title);

                    using (fs = new StreamCircularBuffer(size, input, null, s => Reader.Read(ctx, input, s, pc))) //read in stream and write to circular buffer
                    {
                        Writer.Write(ctx, fs, output, pc);
                    }
                }
                catch
                {
                    if (pc.Exception != null)
                    {
                        throw pc.Exception;
                    }

                    if (fs.WriterException != null)
                    {
                        throw fs.WriterException;
                    }

                    throw; //writer exception
                }

                foreach (CrcItem crc in pc.Patches.Crcs.Where(a => a.PatchData != null || a.PatchFile != null))
                {
                    output.Seek(crc.Offset, SeekOrigin.Begin);
                    if (crc.PatchFile == null)
                    {
                        output.Write(crc.PatchData, 0, (int)Math.Min(crc.Length, crc.PatchData.Length)); //PatchData might be larger
                    }
                    else
                    {
                        using (FileStream pf = File.OpenRead(crc.PatchFile))
                        {
                            pf.Copy(output, pf.Length);
                            ByteStream.Zeros.Copy(output, crc.Length - pf.Length);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (_timer != null)
                {
                    _timer.Enabled = false;
                }

                try
                {
                    _log.ProcessingComplete(results.OutputSize, results.ProcessorMessage, false); // force any log lines to be output - handy for diagnosis
                }
                catch { }
                throw new HandledException(ex, "Failed processing {0} -> {1}", Reader?.GetType()?.Name ?? "<null>", Writer?.GetType()?.Name ?? "<null>");
            }
            finally
            {
                if (_timer != null)
                {
                    _timer.Enabled = false;
                    _timer         = null;
                }
            }

            return(results);
        }
Exemple #6
0
        internal long WriteRecoveryPartitionData(Stream crcStream, bool unscrub, WiiPartitionSection ps, int channelNo, out string tempFileName, out string fileName, out NStream output)
        {
            if (ps.Header.Type == PartitionType.Update)
            {
                fileName = string.Format("{0}_{1}_", BitConverter.ToString(ps.Header.ContentSha1).Replace("-", ""), ps.Header.IsKorean ? "K" : "N");
            }
            else
            {
                fileName = string.Format("{0}_{1}_{2}_{3}_", this.NStream.Id8, channelNo.ToString().PadLeft(2, '0'), SourceFiles.CleanseFileName(ps.Header.Id).PadRight(4), ps.Header.IsKorean ? "K" : "N");
            }
            tempFileName = Path.Combine(Settings.OtherRecoveryFilesPath, fileName + "TEMP");

            Directory.CreateDirectory(Settings.OtherRecoveryFilesPath);
            output = new NStream(File.Create(tempFileName));
            output.Write(ps.Header.Data, 0, (int)ps.Header.Size);
            crcStream.Write(ps.Header.Data, 0, (int)ps.Header.Size);
            long read = ps.Header.Size;

            foreach (WiiPartitionGroupSection pg in ps.Sections)
            {
                if (unscrub)
                {
                    pg.Unscrub(null);
                }
                output.Write(pg.Encrypted, 0, (int)pg.Size);
                crcStream.Write(pg.Encrypted, 0, (int)pg.Size);
                read = ps.Size;
            }
            return(read);
        }
Exemple #7
0
        /// <summary>
        /// Extracts files from partitions, this is not random access. The iso is read in it's entirety
        /// </summary>
        public ExtractResult ExtractRecoveryFilesWii()
        {
            List <ExtractRecoveryResult> result    = new List <ExtractRecoveryResult>();
            List <WiiPartitionInfo>      toExtract = new List <WiiPartitionInfo>();
            WiiDiscHeaderSection         hdr       = null;
            WiiPartitionHeaderSection    pHdr      = null;
            NStream       target            = null;
            bool          extracting        = false;
            int           channel           = 1;
            string        lastPartitionId   = null;
            PartitionType lastPartitionType = PartitionType.Other;

            string fileName    = null;
            string tmpFileName = null;
            int    extracted   = 0;
            Crc    crc         = new Crc();
            Stream crcStream   = null;
            long   imageSize   = this.NStream.RecoverySize; //for Wii: pHdr.PartitionDataLength


            bool isIso = false; //force to always scrub //Path.GetExtension(_name).ToLower() == ".iso";

            foreach (IWiiDiscSection s in this.EnumerateSectionsFix(false, true, false))
            {
                if (s is WiiDiscHeaderSection)
                {
                    hdr = (WiiDiscHeaderSection)s;

                    Log?.Log(string.Format("Processing: {0}", SourceFileName));

                    toExtract = hdr.Partitions.Where(a => a.Type != PartitionType.Data && a.Type != PartitionType.GameData).ToList();
                    if (toExtract.Count() == 0)
                    {
                        Log?.Log(string.Format("    Skipped: No Recovery Partitions to extract - {0}", SourceFileName));
                        break;
                    }
                }
                else if (s is WiiPartitionSection)
                {
                    WiiPartitionSection ps = (WiiPartitionSection)s;

                    if (!toExtract.Any(a => a.DiscOffset == ps.DiscOffset))
                    {
                        Log?.Log(string.Format("    Skipping {0} Partition: [{1}]...", ps.Header.Type.ToString(), SourceFiles.CleanseFileName(ps.Header.Id).PadRight(4)));
                        continue;
                    }
                    extracting = true;

                    pHdr       = ps.Header;
                    extracting = true;
                    Log?.Log(string.Format("    {0} of {1} - Extracting {2} Recovery Partition: [{3}]", (extracted + 1).ToString(), toExtract.Count().ToString(), ps.Header.Type.ToString(), SourceFiles.CleanseFileName(ps.Header.Id).PadRight(4)));

                    crcStream = new CryptoStream(ByteStream.Zeros, crc, CryptoStreamMode.Write);
                    crc.Initialize();

                    WriteRecoveryPartitionData(crcStream, isIso, ps, channel, out tmpFileName, out fileName, out target);
                    lastPartitionId   = ps.Id;
                    lastPartitionType = ps.Header.Type;
                }
                else if (s is WiiFillerSection)
                {
                    JunkStream       junk = new JunkStream(lastPartitionType != PartitionType.Data ? hdr.ReadString(0, 4) : lastPartitionId, hdr.Read8(6), lastPartitionType == PartitionType.Update ? 0 : imageSize);
                    WiiFillerSection fs   = (WiiFillerSection)s;
                    if (extracting)
                    {
                        int storeType;
                        if ((storeType = WriteRecoveryPartitionFiller(crcStream, junk, fs.DiscOffset, pHdr.Type == PartitionType.Update, false, fs, target, tmpFileName, ref fileName, crc, false)) != 0)
                        {
                            result.Add(new ExtractRecoveryResult()
                            {
                                FileName = fileName, Extracted = true, Type = PartitionType.Other, IsNew = storeType == 2, IsGameCube = false
                            });
                        }

                        if (pHdr.Type != PartitionType.Update)
                        {
                            channel++;
                        }
                        extracted++;
                        extracting = false;
                        bool complete = (extracted == toExtract.Count());
                        if (complete)
                        {
                            break;
                        }
                    }
                }
            }
            return(createExtractResult((Region)hdr.ReadUInt32B(0x4e000), result.ToArray()));
        }