Esempio n. 1
0
 private void set(GapBlockType type)
 {
     if (_current == null || _current.Type != type)
     {
         _blocks.Add(_current = new GapBlock()
         {
             Type = type, Count = 1
         });
     }
     else
     {
         _current.Count++;
     }
     this.Length += BlockSize;
 }
Esempio n. 2
0
        private long writeGap(ConvertFile file, ref long nullsPos, ref long srcPos, long dstPos, NStream inStream, Stream target, bool firstOrLastFile)
        {
            if (file.GapLength == 0)
            {
                if (file.FstFile.Length == 0)
                {
                    nullsPos = dstPos + 0x1c;
                }
                return(0);
            }

            MemorySection ms = MemorySection.Read(inStream, 4);

            srcPos += 4;
            long    size = ms.ReadUInt32B(0);
            GapType gt   = (GapType)(size & 0b11);

            size &= 0xFFFFFFFC;
            if (size == 0xFFFFFFFC) //for wii only. not a thing for GC
            {
                srcPos += 4;
                inStream.Read(ms.Data, 0, 4);
                size = 0xFFFFFFFCL + (long)ms.ReadUInt32B(0); //cater for files > 0xFFFFFFFF
            }

            long nulls;
            long junkFileLen = 0;

            //set nullsPos value if zerobyte file without junk
            if (gt == GapType.JunkFile)
            {
                nullsPos = Math.Min(nullsPos - dstPos, 0);
                nulls    = (size & 0xFC) >> 2;
                inStream.Read(ms.Data, 0, 4);
                srcPos             += 4;
                junkFileLen         = ms.ReadUInt32B(0);
                file.FstFile.Length = junkFileLen;
                junkFileLen        += junkFileLen % 4 == 0 ? 0 : 4 - (junkFileLen % 4);
                ByteStream.Zeros.Copy(target, nulls);
                inStream.JunkStream.Position = dstPos + nulls;
                inStream.JunkStream.Copy(target, junkFileLen - nulls);
                dstPos += junkFileLen;

                if (file.GapLength <= 8)
                {
                    return(junkFileLen);
                }
                else
                {
                    //read gap
                    inStream.Read(ms.Data, 0, 4);
                    srcPos += 4;
                    size    = ms.ReadUInt32B(0);
                    gt      = (GapType)(size & 0b11);
                    size   &= 0xFFFFFFFC;
                }
            }
            else if (file.FstFile.Length == 0) //last zero byte file was legit
            {
                nullsPos = dstPos + 0x1c;
            }


            long maxNulls = Math.Max(0, nullsPos - dstPos); //0x1cL

            if (size < maxNulls)                            //need to test this commented if
            {
                nulls = size;
            }
            else
            {
                nulls = size >= 0x40000 && !firstOrLastFile ? 0 : maxNulls;
            }

            if (gt == GapType.AllJunk)
            {
                ByteStream.Zeros.Copy(target, nulls);
                inStream.JunkStream.Position = dstPos + nulls;
                inStream.JunkStream.Copy(target, size - nulls);
                dstPos += size;
            }
            else if (gt == GapType.AllScrubbed)
            {
                ByteStream.Zeros.Copy(target, size);
                dstPos += size;
            }
            else
            {
                long         prg    = size;
                byte         btByte = 0x00;
                GapBlockType bt     = GapBlockType.Junk; //should never be used

                while (prg > 0)
                {
                    inStream.Read(ms.Data, 0, 4);
                    srcPos += 4;
                    long         bytes;
                    long         blk      = ms.ReadUInt32B(0);
                    GapBlockType btType   = (GapBlockType)(blk >> 30);
                    bool         btRepeat = btType == GapBlockType.Repeat;
                    if (!btRepeat)
                    {
                        bt = btType;
                    }

                    long cnt = 0x3FFFFFFF & blk;

                    if (bt == GapBlockType.NonJunk)
                    {
                        bytes = Math.Min(cnt * Gap.BlockSize, prg);

                        inStream.Copy(target, bytes);
                        srcPos += bytes;
                    }
                    else if (bt == GapBlockType.ByteFill)
                    {
                        if (!btRepeat)
                        {
                            btByte = (byte)(0xFF & cnt); //last 8 bits when not repeating are the byte
                            cnt  >>= 8;
                        }

                        bytes = Math.Min(cnt * Gap.BlockSize, prg);
                        Stream bs;
                        switch (btByte)
                        {
                        case 0x00: bs = ByteStream.Zeros; break;

                        case 0x55: bs = ByteStream.Fives; break;

                        case 0xff: bs = ByteStream.FFs; break;

                        default: bs = new ByteStream(btByte); break;
                        }
                        bs.Copy(target, bytes);
                    }
                    else //if (bt == GapBlockType.Junk)
                    {
                        bytes = Math.Min(cnt * Gap.BlockSize, prg);

                        maxNulls = Math.Max(0, nullsPos - dstPos); //0x1cL
                        if (prg < maxNulls)
                        {
                            nulls = bytes;
                        }
                        else
                        {
                            nulls = bytes >= 0x40000 && !firstOrLastFile ? 0 : maxNulls;
                        }

                        ByteStream.Zeros.Copy(target, nulls);
                        inStream.JunkStream.Position = dstPos + nulls;
                        inStream.JunkStream.Copy(target, bytes - nulls);
                    }
                    prg    -= bytes;
                    dstPos += bytes;
                }
            }

            return(size + junkFileLen);
        }
Esempio n. 3
0
        private long writeGap(ref long fileLength, LongRef gapLength, ref long nullsPos, ref long srcPos, long dstPos, Stream inStream, Stream target, JunkStream junk, bool firstOrLastFile, ScrubManager scrub)
        {
            if (gapLength.Value == 0)
            {
                if (fileLength == 0)
                {
                    nullsPos = dstPos + 0x1c;
                }
                return(0);
            }
            long          srcLen = gapLength.Value; //fix added for (padding between junk files) - Zumba Fitness (Europe) (En,Fr,De,Es,It)
            MemorySection ms     = MemorySection.Read(inStream, 4);

            srcPos += 4;
            long    size = ms.ReadUInt32B(0);
            GapType gt   = (GapType)(size & 0b11);

            size &= 0xFFFFFFFC;
            if (size == 0xFFFFFFFC) //for wii only. not a thing for GC
            {
                srcPos += 4;
                inStream.Read(ms.Data, 0, 4);
                size = 0xFFFFFFFCL + (long)ms.ReadUInt32B(0); //cater for files > 0xFFFFFFFF
            }
            gapLength.Value = size;

            scrub.AddGap(fileLength, dstPos, size); //keep track of trailing nulls when restoring scrubbed images

            long nulls;
            long junkFileLen = 0;

            //set nullsPos value if zerobyte file without junk
            if (gt == GapType.JunkFile)
            {
                nullsPos = Math.Min(nullsPos - dstPos, 0);
                nulls    = (size & 0xFC) >> 2;
                inStream.Read(ms.Data, 0, 4);
                srcPos      += 4;
                junkFileLen  = ms.ReadUInt32B(0);
                fileLength   = junkFileLen;
                junkFileLen += junkFileLen % 4 == 0 ? 0 : 4 - (junkFileLen % 4);
                ByteStream.Zeros.Copy(target, nulls);
                junk.Position = dstPos + nulls;
                junk.Copy(target, junkFileLen - nulls);
                dstPos += junkFileLen;

                if (srcLen <= 8)
                {
                    return(junkFileLen);
                }
                else
                {
                    //read gap
                    inStream.Read(ms.Data, 0, 4);
                    srcPos         += 4;
                    size            = ms.ReadUInt32B(0);
                    gt              = (GapType)(size & 0b11);
                    size           &= 0xFFFFFFFC;
                    gapLength.Value = size;
                }
            }
            else if (fileLength == 0) //last zero byte file was legit
            {
                nullsPos = dstPos + 0x1c;
            }


            long maxNulls = Math.Max(0, nullsPos - dstPos); //0x1cL

            if (size < maxNulls)                            //need to test this commented if
            {
                nulls = size;
            }
            else
            {
                nulls = size >= 0x40000 && !firstOrLastFile ? 0 : maxNulls;
            }
            nullsPos = dstPos + nulls; //belt and braces

            if (gt == GapType.AllJunk)
            {
                ByteStream.Zeros.Copy(target, nulls);
                junk.Position = dstPos + nulls;
                junk.Copy(target, size - nulls);
                dstPos += size;
            }
            else if (gt == GapType.AllScrubbed)
            {
                scrub.Scrub(target, dstPos, size, 0);
                dstPos += size;
            }
            else
            {
                long         prg    = size;
                byte         btByte = 0x00;
                GapBlockType bt     = GapBlockType.Junk; //should never be used

                while (prg > 0)
                {
                    inStream.Read(ms.Data, 0, 4);
                    srcPos += 4;
                    long         bytes;
                    long         blk      = ms.ReadUInt32B(0);
                    GapBlockType btType   = (GapBlockType)(blk >> 30);
                    bool         btRepeat = btType == GapBlockType.Repeat;
                    if (!btRepeat)
                    {
                        bt = btType;
                    }

                    long cnt = 0x3FFFFFFF & blk;

                    if (bt == GapBlockType.NonJunk)
                    {
                        bytes = Math.Min(cnt * Gap.BlockSize, prg);

                        inStream.Copy(target, bytes);
                        srcPos += bytes;
                    }
                    else if (bt == GapBlockType.ByteFill)
                    {
                        if (!btRepeat)
                        {
                            btByte = (byte)(0xFF & cnt); //last 8 bits when not repeating are the byte
                            cnt  >>= 8;
                        }

                        bytes = Math.Min(cnt * Gap.BlockSize, prg);
                        scrub.Scrub(target, dstPos, bytes, btByte);
                    }
                    else //if (bt == GapBlockType.Junk)
                    {
                        bytes = Math.Min(cnt * Gap.BlockSize, prg);

                        maxNulls = Math.Max(0, nullsPos - dstPos); //0x1cL
                        if (prg < maxNulls)
                        {
                            nulls = bytes;
                        }
                        else
                        {
                            nulls = bytes >= 0x40000 && !firstOrLastFile ? 0 : maxNulls;
                        }

                        ByteStream.Zeros.Copy(target, nulls);
                        junk.Position = dstPos + nulls;
                        junk.Copy(target, bytes - nulls);
                    }
                    prg    -= bytes;
                    dstPos += bytes;
                }
            }

            return(gapLength.Value + junkFileLen);
        }
Esempio n. 4
0
        private long write(Stream s, bool writeHeader)
        {
            if (_gapLength % 4 != 0) //right most 2 bits will be 00
            {
                throw new Exception("GapLength should be on a 4 byte boundary");
            }
            long          written = 0;
            MemorySection m       = new MemorySection(new byte[0x10]);

            //for junk files % 4 (0 to 3) - load the 4 bytes, in a real iso the last byte would always be null (if not a legit junk file)
            //if a removed juk file the last byte will end with 2 bits (GapType.JunkFile) the rest of the 4 bytes is the file size / 4
            //multiply value by 4 and add the fst file size.

            if (writeHeader)
            {
                if (JunkFile != 0)
                {
                    m.WriteUInt32B(0, (uint)(JunkFileNulls << 2) | (uint)GapType.JunkFile); //junk file nulls (first 3 bytes are unused)
                    m.WriteUInt32B(4, JunkFile);                                            //length of file
                    s.Write(m.Data, 0, 8);
                    written += 8;
                }
            }
            else if (_blocks.Count == 0)
            {
                return(0);
            }

            if (_blocks.Count == 0) //non if padding for 32k alignment, or junk file with no padding
            {
                Set();              //add a junk item, length will be 0
            }
            GapType gt;

            if (_blocks.Count == 1 && _blocks[0].Type == GapBlockType.Junk)
            {
                gt = GapType.AllJunk;
            }
            else if (_blocks.Count == 1 && _blocks[0].Type == GapBlockType.ByteFill && _blocks[0].Byte == 0) //00 scrubbed
            {
                gt = GapType.AllScrubbed;
            }
            else
            {
                gt = GapType.Mixed;
            }

            if (writeHeader)
            {
                long hdr = _gapLength >= 0xFFFFFFFCL ? 0xFFFFFFFCL : (uint)_gapLength; //always use 4 bytes if the gap is <= 0xFFFFFFFF - it should never be larger than that anyway. if so then use another 4 bytes
                hdr |= (uint)gt;
                m.WriteUInt32B(0, (uint)hdr);
                s.Write(m.Data, 0, 4);
                written += 4;

                if (hdr >= 0xFFFFFFFCL && _gapLength >= 0xFFFFFFFC)
                {
                    m.WriteUInt32B(0, (uint)(_gapLength - 0xFFFFFFFCL)); //will cater for dual layer where most or all of it is empty
                    s.Write(m.Data, 0, 4);
                    written += 4;
                }
            }

            if (gt == GapType.Mixed || !writeHeader) //mixed
            {
                foreach (GapBlock b in _blocks)
                {
                    if (b.NonJunk != null)
                    {
                        b.NonJunk.Position = 0;
                    }

                    uint         cnt = (uint)b.Count; //total amount of blocks
                    uint         max;
                    uint         v = 0;
                    uint         w = 0;
                    GapBlockType t = b.Type;
                    while (cnt != 0)
                    {
                        if (t == GapBlockType.Junk || t == GapBlockType.NonJunk || t == GapBlockType.Repeat)
                        {
                            max = 0x3FFFFFFF;
                            if (cnt > max)
                            {
                                v = max;
                            }
                            else
                            {
                                v = cnt;
                            }
                            cnt -= v;
                            w    = (uint)t << 30 | v; //type | count of 256 byte blocks
                        }
                        else if (t == GapBlockType.ByteFill)
                        {
                            max = 0x3FFFFF;
                            if (cnt > max)
                            {
                                v = max;
                            }
                            else
                            {
                                v = cnt;
                            }
                            cnt -= v;
                            w    = (uint)t << 30 | v << 8 | b.Byte; //type | count of 256 byte blocks | fill byte
                        }

                        m.WriteUInt32B(0, w);
                        s.Write(m.Data, 0, 4); //write encoded bytes
                        written += 4;

                        if (b.Type == GapBlockType.NonJunk)
                        {
                            written += b.NonJunk.Copy(s, Math.Min(b.NonJunk.Length - b.NonJunk.Position, v * Gap.BlockSize));
                            b.NonJunk.Close();
                            b.NonJunk = null; //free it
                        }
                        t = GapBlockType.Repeat;
                    }
                }
            }
            _blocks.Clear();
            _current = null;
            return(written);
        }