예제 #1
0
파일: Mpq.cs 프로젝트: bonomali/Ibasa
        private void ParseHET()
        {
            Reader.Seek((long)HetTablePos64, SeekOrigin.Begin);

            if (Reader.Read <Media.FourCC>() != new Media.FourCC("HET\x1A"))
            {
                throw new Exception("WTF");
            }

            if (Reader.ReadUInt32() != 1)
            {
                throw new Exception("WTF");
            }

            HetDataSize        = Reader.ReadUInt32();
            HetTableSize       = Reader.ReadUInt32();
            HetMaxFileCount    = Reader.ReadUInt16();
            HetHashTableSize   = Reader.ReadUInt16();
            HetHashEntrySize   = Reader.ReadUInt32();
            HetTotalIndexSize  = Reader.ReadUInt32();
            HetIndexSizeExtra  = Reader.ReadUInt32();
            HetIndexSize       = Reader.ReadUInt32();
            HetBlockTableSize  = Reader.ReadUInt32();
            HetHashTableOffset = Reader.Position;
        }
예제 #2
0
파일: Vtf.cs 프로젝트: bonomali/Ibasa
 private void ReadHeader70(Ibasa.IO.BinaryReader reader)
 {
     Width      = reader.ReadUInt16();
     Height     = reader.ReadUInt16();
     Flags      = (TextureFlags)reader.ReadInt32();
     Frames     = reader.ReadUInt16();
     StartFrame = reader.ReadUInt16();
     reader.ReadBytes(4); //skip padding
     Reflectivity = new Vector3f(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle());
     reader.ReadBytes(4); //skip padding
     BumpmapScale      = reader.ReadSingle();
     ImageFormat       = (ImageFormat)reader.ReadInt32();
     MipmapCount       = reader.ReadByte();
     LowResImageFormat = (ImageFormat)reader.ReadInt32();
     LowResImageWidth  = reader.ReadByte();
     LowResImageHeight = reader.ReadByte();
 }
예제 #3
0
파일: Vtf.cs 프로젝트: bonomali/Ibasa
 private void ReadHeader72(Ibasa.IO.BinaryReader reader)
 {
     if (VersionMinor >= 2)
     {
         Depth = reader.ReadUInt16();
         Depth = Depth == 0 ? 1 : Depth; //map 0 to 1
     }
     else
     {
         Depth = 1;
         reader.ReadBytes(1); //skip padding
     }
 }
예제 #4
0
        private void ReadColorMap(Ibasa.IO.BinaryReader reader)
        {
            if (Header.ColorMapType == 0)
            {
                return;
            }

            ColorMap = new uint[256];

            switch (Header.ColorMapDepth)
            {
            case 16:
            {
                for (int i = Header.ColourMapOrigin; i < Header.ColorMapLength; ++i)
                {
                    uint color = reader.ReadUInt16();
                    uint r     = (color >> 10) & 0x1F;
                    uint g     = (color >> 5) & 0x1F;
                    uint b     = (color) & 0x1F;
                    //expand 8 bits
                    r           = (r << 3) | (r >> 2);
                    g           = (g << 3) | (g >> 2);
                    b           = (b << 3) | (b >> 2);
                    ColorMap[i] = (r << 16) | (g << 8) | b;
                }
            } break;

            case 24:
            {
                for (int i = Header.ColourMapOrigin; i < Header.ColorMapLength; ++i)
                {
                    uint b = reader.ReadByte();
                    uint g = reader.ReadByte();
                    uint r = reader.ReadByte();
                    ColorMap[i] = (r << 16) | (g << 8) | b;
                }
            } break;

            case 32:
            {
                for (int i = Header.ColourMapOrigin; i < Header.ColorMapLength; ++i)
                {
                    ColorMap[i] = reader.ReadUInt32();
                }
            } break;

            default:
                throw new InvalidDataException("Unrecognized color map depth.");
            }
        }
예제 #5
0
        private void ReadDeveloper(Ibasa.IO.BinaryReader reader)
        {
            int tags = reader.ReadUInt16();

            uint[] tol = new uint[tags * 3];

            for (int i = 0; i < tags; ++i)
            {
                tol[i * 3 + 0] = reader.ReadUInt16();
                tol[i * 3 + 1] = reader.ReadUInt32();
                tol[i * 3 + 2] = reader.ReadUInt32();
            }

            for (int i = 0; i < tags; ++i)
            {
                int  tag    = (int)tol[i * 3 + 0];
                long offset = tol[i * 3 + 1];
                int  length = (int)tol[i * 3 + 2];

                reader.BaseStream.Seek(offset, SeekOrigin.Begin);
                DeveloperArea.Add(new KeyValuePair <int, byte[]>(tag, reader.ReadBytes(length)));
            }
        }
예제 #6
0
        private void ReadHeader(Ibasa.IO.BinaryReader reader)
        {
            Header.ImageId      = new byte[reader.ReadByte()];
            Header.ColorMapType = reader.ReadByte();
            Header.ImageType    = reader.ReadByte();

            Header.ColourMapOrigin = reader.ReadUInt16();
            Header.ColorMapLength  = reader.ReadUInt16();
            Header.ColorMapDepth   = reader.ReadByte();

            Header.XOrigin = reader.ReadUInt16();
            Header.YOrigin = reader.ReadUInt16();
            Header.Width   = reader.ReadUInt16();
            Header.Height  = reader.ReadUInt16();

            Header.PixelDepth      = reader.ReadByte();
            Header.ImageDescriptor = reader.ReadByte();

            reader.Read(Header.ImageId, 0, Header.ImageId.Length);
        }
예제 #7
0
파일: Mpq.cs 프로젝트: Frassle/Ibasa
        public Mpq(Stream stream)
        {
            Reader = new Ibasa.IO.BinaryReader(stream, Encoding.ASCII);

            long offset = 0;
            bool founda, foundb;
            {
                Ibasa.Media.FourCC mpqa = new Media.FourCC("MPQ\x1A");
                Ibasa.Media.FourCC mpqb = new Media.FourCC("MPQ\x1B");

                //find offset
                var fourcc = Reader.Read<Ibasa.Media.FourCC>();
                founda = fourcc == mpqa;
                foundb = fourcc == mpqb;

                while (!founda && !foundb)
                {
                    offset += 512;
                    fourcc = Reader.Read<Ibasa.Media.FourCC>();
                    founda = fourcc == mpqa;
                    foundb = fourcc == mpqb;
                }
            }

            if (foundb)
            {
                var userdatasize = Reader.ReadUInt32();
                offset += Reader.ReadUInt32();
                var userdataheader = Reader.ReadUInt32();
            }

            Reader.Seek(offset, SeekOrigin.Begin);

            if (Reader.Read<Media.FourCC>() != new Media.FourCC("MPQ\x1A"))
                throw new Exception("WTF");

            HeaderSize = Reader.ReadUInt32();
            ArchiveSize = Reader.ReadUInt32();
            FormatVersion = Reader.ReadUInt16();
            BlockSize = Reader.ReadUInt16();
            HashTablePos = Reader.ReadUInt32();
            BlockTablePos = Reader.ReadUInt32();
            HashTableSize = Reader.ReadUInt32();
            BlockTableSize = Reader.ReadUInt32();

            if (FormatVersion >= 2)
            {
                HiBlockTablePos64 = Reader.ReadUInt64();
                HashTablePosHi = Reader.ReadUInt16();
                BlockTablePosHi = Reader.ReadUInt16();
            }
            if (FormatVersion >= 3)
            {
                ArchiveSize64 = Reader.ReadUInt64();
                BetTablePos64 = Reader.ReadUInt64();
                HetTablePos64 = Reader.ReadUInt64();
            }
            if (FormatVersion >= 4)
            {
                hashtablesize64 = Reader.ReadUInt64();
                blocktablesize64 = Reader.ReadUInt64();
                hiblocktablesize64 = Reader.ReadUInt64();
                hettablesize64 = Reader.ReadUInt64();
                bettablesize64 = Reader.ReadUInt64();
                dawchunksize = Reader.ReadUInt32();
                md5_blocktable = Reader.ReadBytes(16);
                md5_hashtable = Reader.ReadBytes(16);
                md5_hiblocktable = Reader.ReadBytes(16);
                md5_bettable = Reader.ReadBytes(16);
                md5_hettable = Reader.ReadBytes(16);
                md5_mpqheader = Reader.ReadBytes(16);
            }

            if (HetTablePos64 != 0)
            {
                ParseHET();
            }
            if (BetTablePos64 != 0)
            {
                ParseBET();
            }
        }
예제 #8
0
파일: Mpq.cs 프로젝트: bonomali/Ibasa
        public Mpq(Stream stream)
        {
            Reader = new Ibasa.IO.BinaryReader(stream, Encoding.ASCII);

            long offset = 0;
            bool founda, foundb;

            {
                Ibasa.Media.FourCC mpqa = new Media.FourCC("MPQ\x1A");
                Ibasa.Media.FourCC mpqb = new Media.FourCC("MPQ\x1B");

                //find offset
                var fourcc = Reader.Read <Ibasa.Media.FourCC>();
                founda = fourcc == mpqa;
                foundb = fourcc == mpqb;

                while (!founda && !foundb)
                {
                    offset += 512;
                    fourcc  = Reader.Read <Ibasa.Media.FourCC>();
                    founda  = fourcc == mpqa;
                    foundb  = fourcc == mpqb;
                }
            }

            if (foundb)
            {
                var userdatasize = Reader.ReadUInt32();
                offset += Reader.ReadUInt32();
                var userdataheader = Reader.ReadUInt32();
            }

            Reader.Seek(offset, SeekOrigin.Begin);

            if (Reader.Read <Media.FourCC>() != new Media.FourCC("MPQ\x1A"))
            {
                throw new Exception("WTF");
            }

            HeaderSize     = Reader.ReadUInt32();
            ArchiveSize    = Reader.ReadUInt32();
            FormatVersion  = Reader.ReadUInt16();
            BlockSize      = Reader.ReadUInt16();
            HashTablePos   = Reader.ReadUInt32();
            BlockTablePos  = Reader.ReadUInt32();
            HashTableSize  = Reader.ReadUInt32();
            BlockTableSize = Reader.ReadUInt32();

            if (FormatVersion >= 2)
            {
                HiBlockTablePos64 = Reader.ReadUInt64();
                HashTablePosHi    = Reader.ReadUInt16();
                BlockTablePosHi   = Reader.ReadUInt16();
            }
            if (FormatVersion >= 3)
            {
                ArchiveSize64 = Reader.ReadUInt64();
                BetTablePos64 = Reader.ReadUInt64();
                HetTablePos64 = Reader.ReadUInt64();
            }
            if (FormatVersion >= 4)
            {
                hashtablesize64    = Reader.ReadUInt64();
                blocktablesize64   = Reader.ReadUInt64();
                hiblocktablesize64 = Reader.ReadUInt64();
                hettablesize64     = Reader.ReadUInt64();
                bettablesize64     = Reader.ReadUInt64();
                dawchunksize       = Reader.ReadUInt32();
                md5_blocktable     = Reader.ReadBytes(16);
                md5_hashtable      = Reader.ReadBytes(16);
                md5_hiblocktable   = Reader.ReadBytes(16);
                md5_bettable       = Reader.ReadBytes(16);
                md5_hettable       = Reader.ReadBytes(16);
                md5_mpqheader      = Reader.ReadBytes(16);
            }

            if (HetTablePos64 != 0)
            {
                ParseHET();
            }
            if (BetTablePos64 != 0)
            {
                ParseBET();
            }
        }
예제 #9
0
 /// <summary>
 /// Reads a <see cref="Vector8us"/> from an <see cref="Ibasa.IO.BinaryReader">.
 /// </summary>
 public static Vector8us ReadVector8us(this Ibasa.IO.BinaryReader reader)
 {
     return(new Vector8us(reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16(), reader.ReadUInt16()));
 }
예제 #10
0
파일: Bsp.cs 프로젝트: Frassle/Ibasa
        public Bsp(Stream stream, IEnumerable<Package.Wad> wads)
        {
            if (!stream.CanSeek || !stream.CanRead)
                throw new ArgumentException("stream must be seekable and readable.", "stream");
            if (wads == null)
                wads = System.Linq.Enumerable.Empty<Package.Wad>();

            Reader = new Ibasa.IO.BinaryReader(stream, Encoding.ASCII);

            if (Reader.ReadUInt32() != 30)
                throw new InvalidDataException("Version is not 30.");

            long entitiesOffset = Reader.ReadUInt32();
            long entitiesCount = Reader.ReadUInt32();
            long planesOffset = Reader.ReadUInt32();
            long planesCount = Reader.ReadUInt32();
            long texturesOffset = Reader.ReadUInt32();
            long texturesCount = Reader.ReadUInt32();
            long vertexesOffset = Reader.ReadUInt32();
            long vertexesCount = Reader.ReadUInt32();
            long visibilityOffset = Reader.ReadUInt32();
            long visibilityCount = Reader.ReadUInt32();
            long nodesOffset = Reader.ReadUInt32();
            long nodesCount = Reader.ReadUInt32();
            long texinfoOffset = Reader.ReadUInt32();
            long texinfoCount = Reader.ReadUInt32();
            long facesOffset = Reader.ReadUInt32();
            long facesCount = Reader.ReadUInt32();
            long lightingOffset = Reader.ReadUInt32();
            long lightingCount = Reader.ReadUInt32();
            long clipnodesOffset = Reader.ReadUInt32();
            long clipnodesCount = Reader.ReadUInt32();
            long leafsOffset = Reader.ReadUInt32();
            long leafsCount = Reader.ReadUInt32();
            long marksurfacesOffset = Reader.ReadUInt32();
            long marksurfacesCount = Reader.ReadUInt32();
            long edgesOffset = Reader.ReadUInt32();
            long edgesCount = Reader.ReadUInt32();
            long surfedgesOffset = Reader.ReadUInt32();
            long surfedgesCount = Reader.ReadUInt32();
            long modelsOffset = Reader.ReadUInt32();
            long modelsCount = Reader.ReadUInt32();

            //Entities
            Reader.Seek(entitiesOffset, SeekOrigin.Begin);
            Entities = Encoding.ASCII.GetString(Reader.ReadBytes((int)entitiesCount));

            //Planes
            Reader.Seek(planesOffset, SeekOrigin.Begin);
            Planes = new Planef[planesCount / 20];
            for (int i = 0; i < Planes.Length; ++i)
            {
                Planes[i] = new Planef(
                    Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle());

                uint type = Reader.ReadUInt32();
            }

            //Textures
            {
                Reader.Seek(texturesOffset, SeekOrigin.Begin);
                long[] offsets = new long[Reader.ReadUInt32()];
                for (int i = 0; i < offsets.Length; ++i)
                {
                    offsets[i] = Reader.ReadUInt32();
                }

                Textures = new Resource[offsets.Length];
                for (int i = 0; i < offsets.Length; ++i)
                {
                    Reader.Seek(texturesOffset + offsets[i], SeekOrigin.Begin);

                    string name = Encoding.ASCII.GetString(Reader.ReadBytes(16));
                    int nullbyte = name.IndexOf('\0');
                    name = nullbyte == -1 ? name : name.Substring(0, nullbyte);

                    int width = Reader.ReadInt32();
                    int height = Reader.ReadInt32();

                    long[] dataoffsets = new long[4];
                    dataoffsets[0] = Reader.ReadUInt32();
                    dataoffsets[1] = Reader.ReadUInt32();
                    dataoffsets[2] = Reader.ReadUInt32();
                    dataoffsets[3] = Reader.ReadUInt32();

                    Resource resource = null;

                    if (dataoffsets.All(o => o == 0))
                    {
                        foreach (var wad in wads)
                        {
                            resource = wad[name];
                            if (resource != null)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        resource = new Resource(new Size3i(width, height, 1), 4, 1, Format.R8G8B8A8UNorm);

                        byte[][] images = new byte[4][];

                        for (int mipSlice = 0; mipSlice < 4; ++mipSlice)
                        {
                            Reader.Seek(texturesOffset + offsets[i] + dataoffsets[mipSlice], SeekOrigin.Begin);

                            images[mipSlice] = Reader.ReadBytes(width * height);
                            width >>= 1; height >>= 1;
                        }

                        Reader.Seek(2, SeekOrigin.Current);
                        byte[] pallet = Reader.ReadBytes(256 * 3);

                        for (int mipSlice = 0; mipSlice < 4; ++mipSlice)
                        {
                            byte[] data = resource[mipSlice, 0];
                            byte[] image = images[mipSlice];

                            for (int j = 0; j < image.Length; ++j)
                            {
                                int palletIndex = image[j] * 3;
                                int dataIndex = j * 3;

                                data[dataIndex + 0] = pallet[palletIndex + 0];
                                data[dataIndex + 1] = pallet[palletIndex + 1];
                                data[dataIndex + 2] = pallet[palletIndex + 2];
                            }
                        }
                    }

                    Textures[i] = resource;
                }
            }

            //Vertices
            Reader.Seek(vertexesOffset, SeekOrigin.Begin);
            Vertices = new Vector3f[vertexesCount / 12];
            for (int i = 0; i < Vertices.Length; ++i)
            {
                Vertices[i] = new Vector3f(Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle());
            }

            //Visibility
            Reader.Seek(visibilityOffset, SeekOrigin.Begin);
            Visibility = Reader.ReadBytes((int)visibilityCount);

            //Nodes

            //Surfaces
            Reader.Seek(texinfoOffset, SeekOrigin.Begin);
            Surfaces = new Surface[texinfoCount / 24];
            for (int i = 0; i < Surfaces.Length; ++i)
            {
                Surfaces[i] = new Surface(
                    new Vector4f(Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle()),
                    new Vector4f(Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle()),
                    Reader.ReadInt32(), Reader.ReadInt32());
            }

            //Faces
            Reader.Seek(facesOffset, SeekOrigin.Begin);
            Faces = new Face[facesCount / 20];
            for (int i = 0; i < Faces.Length; ++i)
            {
                Faces[i] = new Face(
                    Reader.ReadUInt16(), Reader.ReadInt16(),
                    Reader.ReadInt32(), Reader.ReadInt16(), Reader.ReadInt16(),
                    Reader.ReadByte(), Reader.ReadByte(), Reader.ReadByte(), Reader.ReadByte(),
                    Reader.ReadInt32());
            }

            //Lighting
            Reader.Seek(facesOffset, SeekOrigin.Begin);
            Lighting = Reader.ReadBytes((int)lightingCount);

            //#define clipnodes     9
            //#define leafs        10
            //#define marksurfaces 11
            //#define edges        12
            //#define surfedges    13
            //#define models       14
            
            //Edges
            Reader.Seek(edgesOffset, SeekOrigin.Begin);
            Edges = new Edge[edgesCount / 4];
            for (int i = 0; i < Edges.Length; ++i)
            {
                Edges[i] = new Edge(Reader.ReadUInt16(), Reader.ReadUInt16());
            }

            //SurfaceEdges
            Reader.Seek(surfedgesOffset, SeekOrigin.Begin);
            SurfaceEdges = new int[surfedgesCount / 4];
            for (int i = 0; i < Planes.Length; ++i)
            {
                SurfaceEdges[i] = Reader.ReadInt32();
            }
        }
예제 #11
0
        private void ReadExtension(Ibasa.IO.BinaryReader reader)
        {
            int size = reader.ReadUInt16();

            if (size < 495) //size can grow with new versions
            {
                return;
            }

            Extension.AuthorName          = reader.ReadBytes(41);
            Extension.AuthorComments      = reader.ReadBytes(324);
            Extension.DateTimeStampMonth  = reader.ReadUInt16();
            Extension.DateTimeStampDay    = reader.ReadUInt16();
            Extension.DateTimeStampYear   = reader.ReadUInt16();
            Extension.DateTimeStampHour   = reader.ReadUInt16();
            Extension.DateTimeStampMinute = reader.ReadUInt16();
            Extension.DateTimeStampSecond = reader.ReadUInt16();
            Extension.JobId                 = reader.ReadBytes(41);
            Extension.JobTimeHours          = reader.ReadUInt16();
            Extension.JobTimeMinutes        = reader.ReadUInt16();
            Extension.JobTimeSeconds        = reader.ReadUInt16();
            Extension.SoftwareId            = reader.ReadBytes(41);
            Extension.SoftwareVersionNumber = reader.ReadUInt16();
            Extension.SoftwareVersionLetter = reader.ReadByte();
            Extension.KeyColor              = reader.ReadInt32();
            Extension.PixelAspectRatioN     = reader.ReadUInt16();
            Extension.PixelAspectRatioD     = reader.ReadUInt16();
            Extension.GammaValueN           = reader.ReadUInt16();
            Extension.GammaValueD           = reader.ReadUInt16();
            long colorCorrectionOffset = reader.ReadUInt32();
            long postageStampOffset    = reader.ReadUInt32();
            long scanLineOffset        = reader.ReadUInt32();

            Extension.Attributes = reader.ReadByte();

            //read color correction
            if (colorCorrectionOffset != 0)
            {
                reader.BaseStream.Seek(colorCorrectionOffset, SeekOrigin.Begin);
                Extension.ColorCorrection = new Vector4i[256];
                for (int i = 0; i < 256; ++i)
                {
                    int a = reader.ReadUInt16();
                    int r = reader.ReadUInt16();
                    int g = reader.ReadUInt16();
                    int b = reader.ReadUInt16();

                    Extension.ColorCorrection[i] = new Vector4i(r, g, b, a);
                }
            }
            //read scan lines
            if (scanLineOffset != 0)
            {
                reader.BaseStream.Seek(scanLineOffset, SeekOrigin.Begin);
                Extension.ScanLines = new long[Header.Height];
                for (int i = 0; i < Header.Height; ++i)
                {
                    Extension.ScanLines[i] = reader.ReadUInt32();
                }
            }
            //read postage stamp
            if (postageStampOffset != 0)
            {
                reader.BaseStream.Seek(postageStampOffset, SeekOrigin.Begin);

                int width  = reader.ReadByte();
                int height = reader.ReadByte();
                Extension.PostageStamp = ReadData(reader, width, height);
            }
        }
예제 #12
0
        private Resource ReadUncompressedColorData(Ibasa.IO.BinaryReader reader, int width, int height)
        {
            switch (Header.PixelDepth)
            {
            case 16:
            {
                Resource resource = new Resource(new Size3i(width, height, 1), 1, 1, SharpIL.Format.B8G8R8UNorm);
                byte[]   data     = resource[0, 0];
                for (int y = 0; y < resource.Size.Height; ++y)
                {
                    for (int x = 0; x < resource.Size.Width; ++x)
                    {
                        ushort color = reader.ReadUInt16();

                        byte r = (byte)(color & 0x1F);
                        byte g = (byte)((color >> 5) & 0x1F);
                        byte b = (byte)((color >> 10) & 0x1F);

                        int offset = x * 3 + y * 3 * resource.Size.Width;

                        data[offset + 0] = b;
                        data[offset + 1] = g;
                        data[offset + 2] = r;
                    }
                }
                return(resource);
            }

            case 24:
            {
                Resource resource = new Resource(new Size3i(width, height, 1), 1, 1, SharpIL.Format.B8G8R8UNorm);
                byte[]   data     = resource[0, 0];
                for (int y = 0; y < resource.Size.Height; ++y)
                {
                    for (int x = 0; x < resource.Size.Width; ++x)
                    {
                        byte b = reader.ReadByte();
                        byte g = reader.ReadByte();
                        byte r = reader.ReadByte();

                        int offset = x * 3 + y * 3 * resource.Size.Width;

                        data[offset + 0] = b;
                        data[offset + 1] = g;
                        data[offset + 2] = r;
                    }
                }
                return(resource);
            }

            case 32:
            {
                Resource resource = new Resource(new Size3i(width, height, 1), 1, 1, SharpIL.Format.B8G8R8A8UNorm);
                byte[]   data     = resource[0, 0];
                for (int y = 0; y < resource.Size.Height; ++y)
                {
                    for (int x = 0; x < resource.Size.Width; ++x)
                    {
                        byte b = reader.ReadByte();
                        byte g = reader.ReadByte();
                        byte r = reader.ReadByte();
                        byte a = reader.ReadByte();

                        int offset = x * 4 + y * 4 * resource.Size.Width;

                        data[offset + 0] = b;
                        data[offset + 1] = g;
                        data[offset + 2] = r;
                        data[offset + 3] = a;
                    }
                }
                return(resource);
            }

            default:
                throw new InvalidDataException("Unrecognized image depth.");
            }
        }
예제 #13
0
        public Bsp(Stream stream, IEnumerable <Package.Wad> wads)
        {
            if (!stream.CanSeek || !stream.CanRead)
            {
                throw new ArgumentException("stream must be seekable and readable.", "stream");
            }
            if (wads == null)
            {
                wads = System.Linq.Enumerable.Empty <Package.Wad>();
            }

            Reader = new Ibasa.IO.BinaryReader(stream, Encoding.ASCII);

            if (Reader.ReadUInt32() != 30)
            {
                throw new InvalidDataException("Version is not 30.");
            }

            long entitiesOffset     = Reader.ReadUInt32();
            long entitiesCount      = Reader.ReadUInt32();
            long planesOffset       = Reader.ReadUInt32();
            long planesCount        = Reader.ReadUInt32();
            long texturesOffset     = Reader.ReadUInt32();
            long texturesCount      = Reader.ReadUInt32();
            long vertexesOffset     = Reader.ReadUInt32();
            long vertexesCount      = Reader.ReadUInt32();
            long visibilityOffset   = Reader.ReadUInt32();
            long visibilityCount    = Reader.ReadUInt32();
            long nodesOffset        = Reader.ReadUInt32();
            long nodesCount         = Reader.ReadUInt32();
            long texinfoOffset      = Reader.ReadUInt32();
            long texinfoCount       = Reader.ReadUInt32();
            long facesOffset        = Reader.ReadUInt32();
            long facesCount         = Reader.ReadUInt32();
            long lightingOffset     = Reader.ReadUInt32();
            long lightingCount      = Reader.ReadUInt32();
            long clipnodesOffset    = Reader.ReadUInt32();
            long clipnodesCount     = Reader.ReadUInt32();
            long leafsOffset        = Reader.ReadUInt32();
            long leafsCount         = Reader.ReadUInt32();
            long marksurfacesOffset = Reader.ReadUInt32();
            long marksurfacesCount  = Reader.ReadUInt32();
            long edgesOffset        = Reader.ReadUInt32();
            long edgesCount         = Reader.ReadUInt32();
            long surfedgesOffset    = Reader.ReadUInt32();
            long surfedgesCount     = Reader.ReadUInt32();
            long modelsOffset       = Reader.ReadUInt32();
            long modelsCount        = Reader.ReadUInt32();

            //Entities
            Reader.Seek(entitiesOffset, SeekOrigin.Begin);
            Entities = Encoding.ASCII.GetString(Reader.ReadBytes((int)entitiesCount));

            //Planes
            Reader.Seek(planesOffset, SeekOrigin.Begin);
            Planes = new Planef[planesCount / 20];
            for (int i = 0; i < Planes.Length; ++i)
            {
                Planes[i] = new Planef(
                    Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle());

                uint type = Reader.ReadUInt32();
            }

            //Textures
            {
                Reader.Seek(texturesOffset, SeekOrigin.Begin);
                long[] offsets = new long[Reader.ReadUInt32()];
                for (int i = 0; i < offsets.Length; ++i)
                {
                    offsets[i] = Reader.ReadUInt32();
                }

                Textures = new Resource[offsets.Length];
                for (int i = 0; i < offsets.Length; ++i)
                {
                    Reader.Seek(texturesOffset + offsets[i], SeekOrigin.Begin);

                    string name     = Encoding.ASCII.GetString(Reader.ReadBytes(16));
                    int    nullbyte = name.IndexOf('\0');
                    name = nullbyte == -1 ? name : name.Substring(0, nullbyte);

                    int width  = Reader.ReadInt32();
                    int height = Reader.ReadInt32();

                    long[] dataoffsets = new long[4];
                    dataoffsets[0] = Reader.ReadUInt32();
                    dataoffsets[1] = Reader.ReadUInt32();
                    dataoffsets[2] = Reader.ReadUInt32();
                    dataoffsets[3] = Reader.ReadUInt32();

                    Resource resource = null;

                    if (dataoffsets.All(o => o == 0))
                    {
                        foreach (var wad in wads)
                        {
                            resource = wad[name];
                            if (resource != null)
                            {
                                break;
                            }
                        }
                    }
                    else
                    {
                        resource = new Resource(new Size3i(width, height, 1), 4, 1, Format.R8G8B8A8UNorm);

                        byte[][] images = new byte[4][];

                        for (int mipSlice = 0; mipSlice < 4; ++mipSlice)
                        {
                            Reader.Seek(texturesOffset + offsets[i] + dataoffsets[mipSlice], SeekOrigin.Begin);

                            images[mipSlice] = Reader.ReadBytes(width * height);
                            width          >>= 1; height >>= 1;
                        }

                        Reader.Seek(2, SeekOrigin.Current);
                        byte[] pallet = Reader.ReadBytes(256 * 3);

                        for (int mipSlice = 0; mipSlice < 4; ++mipSlice)
                        {
                            byte[] data  = resource[mipSlice, 0];
                            byte[] image = images[mipSlice];

                            for (int j = 0; j < image.Length; ++j)
                            {
                                int palletIndex = image[j] * 3;
                                int dataIndex   = j * 3;

                                data[dataIndex + 0] = pallet[palletIndex + 0];
                                data[dataIndex + 1] = pallet[palletIndex + 1];
                                data[dataIndex + 2] = pallet[palletIndex + 2];
                            }
                        }
                    }

                    Textures[i] = resource;
                }
            }

            //Vertices
            Reader.Seek(vertexesOffset, SeekOrigin.Begin);
            Vertices = new Vector3f[vertexesCount / 12];
            for (int i = 0; i < Vertices.Length; ++i)
            {
                Vertices[i] = new Vector3f(Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle());
            }

            //Visibility
            Reader.Seek(visibilityOffset, SeekOrigin.Begin);
            Visibility = Reader.ReadBytes((int)visibilityCount);

            //Nodes

            //Surfaces
            Reader.Seek(texinfoOffset, SeekOrigin.Begin);
            Surfaces = new Surface[texinfoCount / 24];
            for (int i = 0; i < Surfaces.Length; ++i)
            {
                Surfaces[i] = new Surface(
                    new Vector4f(Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle()),
                    new Vector4f(Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle(), Reader.ReadSingle()),
                    Reader.ReadInt32(), Reader.ReadInt32());
            }

            //Faces
            Reader.Seek(facesOffset, SeekOrigin.Begin);
            Faces = new Face[facesCount / 20];
            for (int i = 0; i < Faces.Length; ++i)
            {
                Faces[i] = new Face(
                    Reader.ReadUInt16(), Reader.ReadInt16(),
                    Reader.ReadInt32(), Reader.ReadInt16(), Reader.ReadInt16(),
                    Reader.ReadByte(), Reader.ReadByte(), Reader.ReadByte(), Reader.ReadByte(),
                    Reader.ReadInt32());
            }

            //Lighting
            Reader.Seek(facesOffset, SeekOrigin.Begin);
            Lighting = Reader.ReadBytes((int)lightingCount);

            //#define clipnodes     9
            //#define leafs        10
            //#define marksurfaces 11
            //#define edges        12
            //#define surfedges    13
            //#define models       14

            //Edges
            Reader.Seek(edgesOffset, SeekOrigin.Begin);
            Edges = new Edge[edgesCount / 4];
            for (int i = 0; i < Edges.Length; ++i)
            {
                Edges[i] = new Edge(Reader.ReadUInt16(), Reader.ReadUInt16());
            }

            //SurfaceEdges
            Reader.Seek(surfedgesOffset, SeekOrigin.Begin);
            SurfaceEdges = new int[surfedgesCount / 4];
            for (int i = 0; i < Planes.Length; ++i)
            {
                SurfaceEdges[i] = Reader.ReadInt32();
            }
        }