Example #1
0
        internal static long CopyFile(ref long nullsPos, ConvertFile conFile, FstFile prevFile, Stream dest, ref long srcPos, long dstPos, Stream srcStream, JunkStream junkNStream, long imageSize, out bool missing)
        {
            //long pos = dest.Position;
            missing = false;
            FstFile file = conFile.FstFile;

            long size = file.Length + (file.Length % 4 == 0 ? 0 : (4 - (file.Length % 4)));

            if (srcPos + size > imageSize)
            {
                size = file.Length; //some rare GC demos end at the end of a non aligned file. This fixes it - v1.2 bugfix
            }

            long written = size;

            byte[] f = new byte[Math.Min(0x30, size)];
            srcStream.Read(f, 0, f.Length);                                                         //then read while junk is created

            if (prevFile != null && prevFile.DataOffset == file.DataOffset && prevFile.Length == 0) //null file overlapped this file so set nullsPos to have a gap (XGIII) needs fst sorting by offset then size
            {
                nullsPos = srcPos + 0x1CL;                                                          //will already be aligned
            }

            int nulls      = (int)(nullsPos - srcPos);
            int countNulls = 0;

            if (f.Length > nulls)
            {
                junkNStream.Position = file.DataOffset; //async junk gen
                for (int i = 0; i < f.Length && f[i] == 0; i++)
                {
                    countNulls++;
                }

                if (countNulls < f.Length) //don't test all nulls
                {
                    missing = junkNStream.Compare(f, 0, f.Length, Math.Max(0, countNulls)) == f.Length;
                }
            }

            if (missing) //start of file is junk
            {
                //check the remainder of the file
                MemorySection junkFile = MemorySection.Read(srcStream, size - f.Length);
                missing = junkNStream.Compare(junkFile.Data, 0, (int)junkFile.Size, 0) == junkFile.Size;

                if (missing)
                {
                    written = 0;
                    conFile.Gap.SetJunkFile((uint)conFile.FstFile.Length, countNulls);
                }
                else //not 100% junk, write the file out
                {
                    dest.Write(f, 0, f.Length);
                    dest.Write(junkFile.Data, 0, (int)junkFile.Size);
                }
                junkFile = null;
            }
            else
            {
                dest.Write(f, 0, f.Length);
                srcStream.Copy(dest, size - f.Length); //copy file
            }

            if (!missing) //reset the gap when no junk
            {
                nullsPos = srcPos + size + 0x1c;
                if (nullsPos % 4 != 0)
                {
                    nullsPos += 4 - (nullsPos % 4);
                }
            }

            srcPos += size;
            return(written);
        }
Example #2
0
        internal int WriteRecoveryPartitionFiller(Stream crcStream, JunkStream junk, long pos, bool isUpdate, bool isNkit, WiiFillerSection fs, NStream target, string tmpFileName, ref string fileName, Crc crc, bool logAsDetail)
        {
            long nullBlocks = 0; //check for random junk - only on a handful of launch releases (Rampage, Ant Bully, Grim Adventures, Happy Feet etc)

            junk.Position = pos;
            long leadingNullsPos = pos;

            foreach (WiiFillerSectionItem fi in fs.Sections)
            {
                crcStream.Write(fi.Data, 0, (int)fi.Size);

                for (int i = 0; i < fi.Size; i += 0x8000)
                {
                    int  len   = (int)Math.Min(0x8000L, fi.Size - (long)i);
                    bool match = junk.Compare(fi.Data, i, len, junk.Position == leadingNullsPos ? 0x1c : 0) == len;

                    if (match)
                    {
                        nullBlocks++;
                    }
                    else
                    {
                        if (nullBlocks != 0)
                        {
                            if (pos == leadingNullsPos)
                            {
                                ByteStream.Zeros.Copy(target, 0x1cL);
                                junk.Position = pos + 0x1cL;
                                junk.Copy(target, (nullBlocks * 0x8000L) - 0x1cL);
                            }
                            else
                            {
                                junk.Position = pos;
                                junk.Copy(target, nullBlocks * 0x8000L);
                            }
                            pos += nullBlocks * 0x8000L;
                        }
                        nullBlocks = 0;
                        target.Write(fi.Data, i, len);
                    }
                }
            }
            target.Close();
            crcStream.Close();

            string fName = (fileName += crc.Value.ToString("X8"));
            bool   redump;

            if (isUpdate)
            {
                redump = this.Settings.RedumpUpdateCrcs.Contains(crc.Value);
            }
            else
            {
                redump = this.Settings.RedumpChannels.FirstOrDefault(a => fName.StartsWith(a.Item1)) != null;
            }
            if (isNkit)
            {
                Directory.CreateDirectory(Settings.NkitRecoveryFilesPath);
            }

            return(storeRecoveryFile(redump, tmpFileName, fileName, Settings.RecoveryFilesPath, isNkit ? Settings.NkitRecoveryFilesPath : Settings.OtherRecoveryFilesPath, logAsDetail));
            //rename the file, delete if dupe
        }