public static IEnumerable<Base> Read(Stream stream)
        {
            while(stream.Position<stream.Length)
            {
                var nodeType = stream.ReadUtf8String(4);
                switch (nodeType)
                {
                    case "AVAL":
                        {
                            var result = new Aval();
                            var b = (byte)stream.ReadByte();
                            result.unknown = (b & 0x80) == 0x80;
                            if (!result.unknown) throw new UnknownNodeFlagException();

                            result.nameLength = (short)(b & 0x7f);
                            result.name = stream.ReadUtf8String(result.nameLength);
                            result.value = Value.Base.Read(stream);

                            yield return result;
                            break;
                        }
                    case "BLCK":
                        {
                            yield return Blck.Read(stream);
                            break;
                        }
                    case "ROTS":
                        {
                            yield return Rots.Read(stream);
                            break;
                        }
                    case "KCUP":
                        {
                            yield return Kcup.Read(stream);
                            break;
                        }
                    default:
                        throw new UnknownNodeTypeException(nodeType);
                }
            }
        }
        //public List<KeyValuePair<string, Base>> value;
        private static IEnumerable<KeyValuePair<string, Base>> ReadAllValues(Stream stream)
        {
            while (stream.Position < stream.Length)
            {
                var b = (byte)stream.ReadByte();
                bool f = (b & 0x80) == 0x80;
                if (!f) throw new UnknownNodeFlagException();

                var fieldName = stream.ReadUtf8String(b & 0x7f);

                yield return new KeyValuePair<string, Base>(fieldName,Read(stream));
            }
        }
        internal static IEnumerable<Section> Read(Stream stream)
        {
            for (var i = 0; i < 32; i++)
            {
                // ReSharper disable UseObjectOrCollectionInitializer
                var result = new Section();
                // ReSharper restore UseObjectOrCollectionInitializer
                result.name = stream.ReadUtf8String(32).TrimEnd(char.MinValue);
                if (string.IsNullOrEmpty(result.name)) yield break;

                result.offset = stream.ReadInt32();
                yield return result;
            }
        }
        public int unknown2; // 4 bytes, 1

        #endregion Fields

        #region Methods

        internal static W2Save Read(Stream stream)
        {
            // ReSharper disable UseObjectOrCollectionInitializer
            var result = new W2Save();
            // ReSharper restore UseObjectOrCollectionInitializer
            result.header = stream.ReadUtf8String(4);
            result.unknown1 = stream.ReadInt32();
            result.unknown2 = stream.ReadInt32();
            result.section = Section.Read(stream).ToList();

            foreach (var sec in result.section)
                sec.ReadData(stream);
            return result;
        }
        public void ReadData(Stream stream)
        {
            stream.Seek(offset, SeekOrigin.Begin);

            string nodeType = stream.ReadUtf8String(4);
            switch (nodeType)
            {
                case "BLCK":
                    {
                        data = Blck.Read(stream);
                        break;
                    }
                default:
                    throw new UnknownNodeTypeException(nodeType);
            }
        }
        public static Blck Read(Stream stream)
        {
            var result = new Blck();
            var b = (byte)stream.ReadByte();
            result.unknown = (b & 0x80) == 0x80;
            if (!result.unknown) throw new UnknownNodeFlagException();

            result.nameLength = (short)(b & 0x7f);
            result.name = stream.ReadUtf8String(result.nameLength);

            result.length = stream.ReadInt32();
            using (var memStream = new MemoryStream(stream.ReadBytes(result.length)))
                result.children = Aval.Read(memStream).ToList();

            return result;
        }
        public long unknown; //crc?

        #endregion Fields

        #region Methods

        public static List<FileEntry> Read(Stream stream, int count, out long memoryGate)
        {
            memoryGate = 0;
            var result = new List<FileEntry>(count);
            for (var i=0;i<count;i++)
            {
                var entry = new FileEntry();
                var filenameLength = stream.ReadInt16();
                entry.filename = stream.ReadUtf8String(filenameLength).TrimEnd(char.MinValue);
                entry.unknown = stream.ReadInt64();
                entry.decompressedLength = stream.ReadInt64();
                entry.offset = stream.ReadInt64();
                entry.compressedLength = stream.ReadInt64();
                result.Add(entry);
                var estimatedBufferSize = entry.compressedLength + entry.decompressedLength;
                if (memoryGate < estimatedBufferSize) memoryGate = estimatedBufferSize;
            }
            return result;
        }