Пример #1
0
 public void Set(byte b)
 {
     if (_current == null || _current.Type != GapBlockType.ByteFill || _current.Byte != b)
     {
         _blocks.Add(_current = new GapBlock()
         {
             Type = GapBlockType.ByteFill, Count = 1, Byte = b
         });
     }
     else
     {
         _current.Count++;
     }
     this.Length += BlockSize;
 }
Пример #2
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;
 }
Пример #3
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);
        }