예제 #1
0
파일: ArcA5R.cs 프로젝트: zxc120/GARbro
 public A5rStream(ArcView file, A5rEntry entry)
 {
     m_file    = file;
     m_entry   = entry;
     m_segment = entry.Segments.GetEnumerator();
     NextSegment();
 }
예제 #2
0
파일: ArcA5R.cs 프로젝트: zxc120/GARbro
        public override ArcFile TryOpen(ArcView file)
        {
            uint id = file.View.ReadUInt32(0);

            if (file.View.ReadUInt32(4) != ~id)
            {
                return(null);
            }
            int count = file.View.ReadInt32(0x30);

            if (!IsSaneCount(count))
            {
                return(null);
            }
            uint index_offset = file.View.ReadUInt32(0x34);

            if (index_offset >= file.MaxOffset)
            {
                return(null);
            }

            var  base_name   = Path.GetFileNameWithoutExtension(file.Name);
            uint next_offset = file.View.ReadUInt32(index_offset);
            var  segments    = new A5Segment[count];

            for (int i = 0; i < count; ++i)
            {
                var segment = new A5Segment {
                    Offset       = next_offset,
                    UnpackedSize = file.View.ReadUInt32(index_offset + 4),
                    Type         = file.View.ReadByte(index_offset + 8),
                    Compression  = file.View.ReadByte(index_offset + 9),
                };
                next_offset = file.View.ReadUInt32(index_offset + 0xA);
                if (next_offset > file.MaxOffset || next_offset < segment.Offset)
                {
                    return(null);
                }
                segment.Size  = (uint)(next_offset - segment.Offset);
                segments[i]   = segment;
                index_offset += 0xA;
            }
            var dir         = new List <Entry> (count);
            var riff_buffer = new byte[8];

            for (int i = 0; i < count;)
            {
                A5rEntry entry;
                var      segment = segments[i];
                var      name    = string.Format("{0}#{1:D5}", base_name, i);
                if (0x3C == segment.Type)
                {
                    Stream input = file.CreateStream(segment.Offset, segment.Size);
                    if (3 == segment.Compression)
                    {
                        input = new ZLibStream(input, CompressionMode.Decompress);
                    }
                    using (input)
                    {
                        if (8 == input.Read(riff_buffer, 0, 8) && riff_buffer.AsciiEqual("RIFF"))
                        {
                            uint riff_size = riff_buffer.ToUInt32(4);
                            entry = new A5rEntry {
                                Name         = name + ".wav",
                                Type         = "audio",
                                Offset       = segment.Offset,
                                Size         = 0,
                                UnpackedSize = 0,
                            };
                            var segment_list = new List <A5Segment>();
                            for (;;)
                            {
                                entry.Size         += segment.Size;
                                entry.UnpackedSize += segment.UnpackedSize;
                                entry.IsPacked     |= segment.Compression == 3;
                                segment_list.Add(segment);
                                ++i;
                                if (i >= count || entry.UnpackedSize >= riff_size)
                                {
                                    break;
                                }
                                segment = segments[i];
                                if (segment.Type != 0x3C)
                                {
                                    break;
                                }
                            }
                            entry.Segments = segment_list;
                            dir.Add(entry);
                            continue;
                        }
                    }
                }
                if (0x3E == segment.Type)
                {
                    name += ".bmp";
                }
                entry = new A5rEntry {
                    Name         = name,
                    Type         = 0x3E == segment.Type ? "image" : "",
                    Offset       = segment.Offset,
                    Size         = segment.Size,
                    UnpackedSize = segment.UnpackedSize,
                    IsPacked     = segment.Compression == 3,
                    Segments     = new A5Segment[1] {
                        segment
                    },
                };
                dir.Add(entry);
                ++i;
            }
            return(new ArcFile(file, this, dir));
        }