Ejemplo n.º 1
0
        public void Write(Context ctx, Stream inStream, Stream outStream, Coordinator pc)
        {
            try
            {
                long mlt       = 1L;                               //for Wii: 4L
                long imageSize = pc.OutputSize;                    //for Wii: pHdr.PartitionDataLength
                pc.WriterCheckPoint1WriteReady(out string junkId); //wait until read has written the header and set the length

                List <string> addedFiles = new List <string>();

                NCrc crc = new NCrc();
                long srcPos;
                long dstPos = 0;

                MemorySection hdr = MemorySection.Read(inStream, 0x440);
                string        id8 = string.Concat(hdr.ReadString(0, 6), hdr.Data[6].ToString("X2"), hdr.Data[7].ToString("X2"));

                if (junkId == null)
                {
                    junkId = ctx.Settings.JunkIdSubstitutions.FirstOrDefault(a => a.Id8 == id8)?.JunkId;
                    if (junkId != null)
                    {
                        _log?.LogDetail(string.Format("Using ID {0} for junk not image ID {1}", junkId, id8.Substring(0, 4)));
                    }
                }

                if (junkId == null)
                {
                    junkId = hdr.ReadString(0, 4);
                }

                MemorySection   fst;
                List <JunkDiff> junkDiffs   = new List <JunkDiff>();
                long            mainDolAddr = hdr.ReadUInt32B(0x420) * mlt;

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

                CryptoStream target = new CryptoStream(outStream, crc, CryptoStreamMode.Write);

                //############################################################################
                //# READ DISC START
                target.Write(hdr.Data, 0, (int)hdr.Size);
                crc.Snapshot("hdr.bin");

                inStream.Copy(target, (hdr.ReadUInt32B(0x424) * mlt) - hdr.Size);
                crc.Snapshot("bi2.bin, appldr.bin, main.dol");

                //read fst with 4 byte boundary
                fst = MemorySection.Read(inStream, (hdr.ReadUInt32B(0x428) * mlt) + (((hdr.ReadUInt32B(0x428) * mlt) % 4 == 0 ? 0 : 4 - ((hdr.ReadUInt32B(0x428) * mlt) % 4))));
                target.Write(fst.Data, 0, (int)fst.Size);
                crc.Snapshot("fst.bin");

                srcPos = (hdr.ReadUInt32B(0x424) * mlt) + fst.Size;

                long nullsPos = srcPos + 0x1c;
                dstPos = srcPos;

                //create as late as possible in case id is swaped  - Dairantou Smash Brothers DX (Japan) (Taikenban), Star Wars - Rogue Squadron II (Japan) (Jitsuen-you Sample)
                JunkStream         js       = new JunkStream(junkId, hdr.Read8(6), NStream.FullSizeGameCube);
                List <ConvertFile> conFiles = NkitFormat.GetConvertFstFiles(inStream, imageSize, hdr, fst, true, fstFileAlignment, out string error); //Size isn't important for writing //result.ImageInfo.IsoSize

                NkitInfo nkitInfo = new NkitInfo
                {
                    BytesData                    = srcPos,
                    BytesGaps                    = 0,
                    BytesJunkFiles               = 0,
                    BytesPreservationData        = 0,
                    BytesPreservationDiscPadding = 0
                };

                ScrubManager scrub = new ScrubManager();
                if (conFiles == null)
                {
                    if (error != null)
                    {
                        _log?.LogDetail(error);
                    }

                    ConvertFile cf = new ConvertFile(imageSize - srcPos, true) //Size isn't important for writing //result.ImageInfo.IsoSize
                    {
                        FstFile = new FstFile(null)
                        {
                            DataOffset = hdr.ReadUInt32B(0x424), Offset = hdr.ReadUInt32B(0x424), Length = (int)fst.Size
                        },
                    };
                    NkitFormat.ProcessGap(ref nullsPos, cf, ref srcPos, inStream, js, true, scrub, target, _log);
                }
                else
                {
                    //############################################################################
                    //# WRITE THE FILESYSTEM
                    NkitFormat.NkitWriteFileSystem(ctx, nkitInfo, mlt, inStream, ref srcPos, ref dstPos, hdr, fst, ref mainDolAddr, target, nullsPos, js, conFiles, out List <ConvertFile> missing, scrub, imageSize, _log);
                    if (missing.Count != 0)
                    {
                        _log?.LogDetail(string.Format("{0} Junk File{1} Removed (Files listed in the FST, but not in the image)", missing.Count.ToString(), missing.Count == 1 ? "" : "s"));
                        foreach (ConvertFile cf in missing)
                        {
                            _log?.LogDebug(string.Format("File content is Junk {0}: {1} - Size: {2}", cf.FstFile.DataOffset.ToString("X8"), cf.FstFile.Name, cf.FstFile.Length));
                        }
                    }
                }

                if (dstPos % 0x800 != 0)
                {
                    long l = 0x800 - (dstPos % 0x800);
                    ByteStream.Zeros.Copy(target, l);
                    dstPos += l;
                    nkitInfo.BytesPreservationDiscPadding += l;
                }
                crc.Snapshot("files");

                NkitFormat.LogNkitInfo(nkitInfo, _log, hdr.ReadString(0, 4), true);

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

                hdr.WriteUInt32B(0x420, (uint)mainDolAddr);

                hdr.WriteString(0x200, 8, "NKIT v01");             //header and version
                hdr.WriteUInt32B(0x208, readerCrcs.FullCrc(true)); //original crc
                hdr.WriteUInt32B(0x210, (uint)imageSize);          //result.ImageInfo.IsoSize);
                hdr.WriteString(0x214, 4, hdr.ReadString(0, 4) != junkId ? junkId : "\0\0\0\0");

                crc.Crcs[0].PatchCrc  = Crc.Compute(hdr.Data);
                crc.Crcs[0].PatchData = hdr.Data;
                crc.Crcs[2].PatchCrc  = Crc.Compute(fst.Data);
                crc.Crcs[2].PatchData = fst.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);

                pc.WriterCheckPoint3ApplyPatches(crc, false, crc.FullCrc(true), crc.FullCrc(true), VerifyIsWrite, "NKit Written");
            }
            catch (Exception ex)
            {
                throw pc.SetWriterException(ex, "NkitWriterGc.Write - Convert");
            }
        }
Ejemplo n.º 2
0
        private long partitionWrite(Stream inStream, NCrc crc, Stream target, WiiPartitionSection pHdr, Context ctx, Coordinator pc, NkitInfo imageInfo, ScrubManager scrub, WiiHashStore hashes, long fstFileAlignment)
        {
#if DEHASH
            return(pHdr.NewPartitionDataLength = inStream.Copy(target, pHdr.PartitionDataLength, null));
#elif DECRYPT
            inStream.Copy(target, pHdr.PartitionLength, null);
            return(pHdr.NewPartitionDataLength = pHdr.PartitionDataLength);
#endif
            MemorySection hdr = MemorySection.Read(inStream, 0x440);

            //ProgressResult result = ctx.Result;
            long   mlt          = 4L;                       //GC 1L
            long   logicalSize  = pHdr.PartitionDataLength; //GC: ctx.ImageLength;
            long   physicalSize = pHdr.PartitionDataLength; //GC: result.ImageInfo.IsoSize;
            string junkId       = hdr.ReadString(0, 4);
            //bool write = true;

            List <string> addedFiles = new List <string>();

            long srcPos;
            long dstPos = 0;

            JunkStream js = new JunkStream(junkId, hdr.Read8(6), logicalSize);

            try
            {
                if (junkId == "\0\0\0\0")
                {
                    srcPos = hdr.Size;
                    imageInfo.BytesData = srcPos;
                    _log?.LogDetail("Null Partition ID, preserving partition as raw");
                    ConvertFile cf = new ConvertFile(logicalSize - hdr.Size, true) //Size isn't important for writing //result.ImageInfo.IsoSize
                    {
                        FstFile = new FstFile(null)
                        {
                            DataOffset = hdr.Size, Offset = hdr.Size, Length = 0
                        },
                    };
                    long nullsPos = 0;
                    target.Write(hdr.Data, 0, (int)hdr.Size); //0x400
                    target.Write(pHdr.Header.Data, 0x2bc, 4); //copy the original partition length
                    dstPos += 0x440 + 4 + NkitFormat.ProcessGap(ref nullsPos, cf, ref srcPos, inStream, js, true, scrub, target, _log);
                }
                else
                {
                    hdr.WriteString(0x200, 8, "NKIT v01");
                    hdr.WriteUInt32B(0x210, (uint)(pHdr.PartitionLength / mlt));

                    MemorySection   fst;
                    List <JunkDiff> junkDiffs   = new List <JunkDiff>();
                    long            mainDolAddr = hdr.ReadUInt32B(0x420) * mlt;

                    //############################################################################
                    //# READ DISC START
                    target.Write(hdr.Data, 0, (int)hdr.Size);

                    inStream.Copy(target, (hdr.ReadUInt32B(0x424) * mlt) - hdr.Size);

                    //read fst with 4 byte boundary
                    fst = MemorySection.Read(inStream, (hdr.ReadUInt32B(0x428) * mlt) + (((hdr.ReadUInt32B(0x428) * mlt) % 4 == 0 ? 0 : 4 - ((hdr.ReadUInt32B(0x428) * mlt) % 4))));
                    crc.Snapshot(junkId + " PrtHdr");
                    target.Write(fst.Data, 0, (int)fst.Size);
                    crc.Snapshot(junkId + " Fst");
                    target.Write(hashes.FlagsToByteArray(), 0, (int)hashes.FlagsLength);
                    crc.Snapshot(junkId + " HashFlags");

                    srcPos = (hdr.ReadUInt32B(0x424) * mlt) + fst.Size;

                    long nullsPos = srcPos + 0x1c;
                    dstPos = srcPos + hashes.FlagsLength;

                    //create as late as possible in case id is swaped  - Dairantou Smash Brothers DX (Japan) (Taikenban), Star Wars - Rogue Squadron II (Japan) (Jitsuen-you Sample)

                    string             error;
                    List <ConvertFile> conFiles = NkitFormat.GetConvertFstFiles(inStream, physicalSize, hdr, fst, false, fstFileAlignment, out error);

                    imageInfo.BytesData = srcPos;

                    if (conFiles == null)
                    {
                        if (error != null)
                        {
                            _log?.LogDetail(error);
                        }
                        ConvertFile cf = new ConvertFile(pHdr.PartitionDataLength - srcPos, true) //Size isn't important for writing //result.ImageInfo.IsoSize
                        {
                            FstFile = new FstFile(null)
                            {
                                DataOffset = hdr.ReadUInt32B(0x424), Offset = hdr.ReadUInt32B(0x424), Length = (int)fst.Size
                            },
                        };
                        dstPos += NkitFormat.ProcessGap(ref nullsPos, cf, ref srcPos, inStream, js, true, scrub, target, _log);
                    }
                    else
                    {
                        //############################################################################
                        //# WRITE THE FILESYSTEM
                        List <ConvertFile> missing;
                        NkitFormat.NkitWriteFileSystem(ctx, imageInfo, mlt, inStream, ref srcPos, ref dstPos, hdr, fst, ref mainDolAddr, target, nullsPos, js, conFiles, out missing, scrub, pHdr.PartitionDataLength, _log);
                        dstPos += hashes.HashesToStream(target);

                        if (missing.Count != 0)
                        {
                            _log?.LogDetail(string.Format("{0} Junk File{1} Removed (Files listed in the FST, but not in the image)", missing.Count.ToString(), missing.Count == 1 ? "" : "s"));
                            foreach (ConvertFile cf in missing)
                            {
                                _log?.LogDebug(string.Format("File content is Junk {0}: {1} - Size: {2}", cf.FstFile.DataOffset.ToString("X8"), cf.FstFile.Name, cf.FstFile.Length));
                            }
                        }
                        crc.Crcs[crc.Crcs.Length - 1].PatchData = hashes.FlagsToByteArray();
                        crc.Crcs[crc.Crcs.Length - 1].PatchCrc  = Crc.Compute(crc.Crcs[crc.Crcs.Length - 2].PatchData);
                        crc.Crcs[crc.Crcs.Length - 2].PatchData = fst.Data;
                        crc.Crcs[crc.Crcs.Length - 2].PatchCrc  = Crc.Compute(fst.Data);
                    }
                }
            }
            catch (Exception ex)
            {
                throw new HandledException(ex, "NkitWriterGc.Write - Convert");
            }
            return(dstPos);
        }
Ejemplo n.º 3
0
        internal static void NkitWriteFileSystem(Context ctx, NkitInfo imageInfo, long mlt, Stream inStream, ref long srcPos, ref long dstPos, MemorySection hdr, MemorySection fst, ref long mainDolAddr, Stream target, long nullsPos, JunkStream js, List <ConvertFile> conFiles, out List <ConvertFile> missingFiles, ScrubManager scrub, long imageSize, ILog log)
        {
            FstFile ff;
            //########### FILES
            bool        firstFile = true;
            ConvertFile lastf     = conFiles.Last();
            ConvertFile prevf     = null;

            missingFiles = new List <ConvertFile>();

            foreach (ConvertFile f in conFiles) //read the files and write them out as goodFiles (possible order difference
            {
                ff = f.FstFile;

                if (!firstFile)
                {
                    if (srcPos == mainDolAddr && mainDolAddr == (hdr.ReadUInt32B(0x420) * mlt))
                    {
                        mainDolAddr = dstPos; //main/default.dol is moving
                    }

                    //Debug.WriteLine(string.Format(@"{5} : {0} : {1} : {2} : {3}/{4}", ff.DataOffset.ToString("X8"), (ff.DataOffset + ff.Length).ToString("X8"), /*(nextFile.DataOffset - lastEnd).ToString("X8"),*/ ff.Length.ToString("X8"), ff.Path, ff.Name, ff.OffsetInFstFile.ToString("X8")));

                    //srcPos aligned at 32k and the length is 32k (audio file) ensure new dest is also aligned
                    if (f.Alignment == 0 || (f.Alignment != -1 && dstPos % f.Alignment != 0)) //XGIII audio in race, Zelda collection games for TGC
                    {
                        long pad;
                        if (f.Alignment == 0) //no shrinking
                        {
                            pad = Math.Max(0, ff.DataOffset - dstPos);
                        }
                        else //align
                        {
                            pad = (int)(dstPos % f.Alignment == 0 ? 0 : f.Alignment - (dstPos % f.Alignment));
                        }

                        imageInfo.FilesAligned += 1;
                        ByteStream.Zeros.Copy(target, pad);
                        imageInfo.BytesPreservationDiscPadding += pad;
                        dstPos += pad;
                    }

                    fst.WriteUInt32B(ff.OffsetInFstFile, (uint)(dstPos / mlt));

                    //replace copy with junk test - adjust fst length to %4
                    long l = srcPos;

                    imageInfo.FilesTotal += 1;
                    long written = NkitFormat.CopyFile(ref nullsPos, f, prevf?.FstFile, target, ref srcPos, dstPos, inStream, js, imageSize, out bool missing);
                    if (missing)
                    {
                        missingFiles.Add(f);
                    }

                    dstPos += written;
                    imageInfo.BytesData += srcPos - l; //read

                    if (f.Gap.JunkFile != 0)           //encode the gap and write - pad to %4
                    {
                        imageInfo.BytesJunkFiles += f.Gap.JunkFile + (f.Gap.JunkFile % 4 == 0 ? 0 : (4 - (f.Gap.JunkFile % 4)));
                        fst.WriteUInt32B(ff.OffsetInFstFile + 4, 0); //modify size to be remainder of 4
                    }
                }

                if (f.GapLength != 0 || f.Gap.JunkFile != 0)
                {
                    long l = NkitFormat.ProcessGap(ref nullsPos, f, ref srcPos, inStream, js, firstFile || f == lastf, scrub, target, log);

                    imageInfo.BytesGaps             += f.GapLength;
                    imageInfo.BytesPreservationData += l;
                    dstPos += l;
                }

                firstFile = false;
                prevf     = f;
            }
        }