Ejemplo n.º 1
0
        public DATAField DATA; // Data

        public override bool CreateField(UnityBinaryReader r, GameFormatId format, string type, int dataSize)
        {
            if (format == GameFormatId.TES3)
            {
                switch (type)
                {
                case "NAME": EDID = r.ReadSTRV(dataSize); return(true);

                case "FNAM": FULL = r.ReadSTRV(dataSize); return(true);

                case "CLDT": r.SkipBytes(dataSize); return(true);

                case "DESC": DESC = r.ReadSTRV(dataSize); return(true);

                default: return(false);
                }
            }
            switch (type)
            {
            case "EDID": EDID = r.ReadSTRV(dataSize); return(true);

            case "FULL": FULL = r.ReadSTRV(dataSize); return(true);

            case "DESC": DESC = r.ReadSTRV(dataSize); return(true);

            case "ICON": ICON = r.ReadSTRV(dataSize); return(true);

            case "DATA": DATA = new DATAField(r, dataSize); return(true);

            default: return(false);
            }
        }
Ejemplo n.º 2
0
        public FMIDField <SOUNRecord> QNAM; // Close sound

        public override bool CreateField(UnityBinaryReader r, GameFormatId format, string type, int dataSize)
        {
            switch (type)
            {
            case "EDID":
            case "NAME": EDID = r.ReadSTRV(dataSize); return(true);

            case "MODL": MODL = new MODLGroup(r, dataSize); return(true);

            case "MODB": MODL.MODBField(r, dataSize); return(true);

            case "MODT": MODL.MODTField(r, dataSize); return(true);

            case "FULL":
            case "FNAM": FULL = r.ReadSTRV(dataSize); return(true);

            case "DATA":
            case "CNDT": DATA = new DATAField(r, dataSize, format); return(true);

            case "FLAG": DATA.FLAGField(r, dataSize); return(true);

            case "CNTO":
            case "NPCO": CNTOs.Add(new CNTOField(r, dataSize, format)); return(true);

            case "SCRI": SCRI = new FMIDField <SCPTRecord>(r, dataSize); return(true);

            case "SNAM": SNAM = new FMIDField <SOUNRecord>(r, dataSize); return(true);

            case "QNAM": QNAM = new FMIDField <SOUNRecord>(r, dataSize); return(true);

            default: return(false);
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Loads a DDS texture from an input stream.
        /// </summary>
        public static Texture2DInfo LoadDDSTexture(Stream inputStream, bool flipVertically = false)
        {
            using (var reader = new UnityBinaryReader(inputStream))
            {
                // Check the magic string.
                var magicString = reader.ReadBytes(4);
                if (!StringUtils.Equals(magicString, "DDS "))
                {
                    throw new FileFormatException("Invalid DDS file magic string: \"" + System.Text.Encoding.ASCII.GetString(magicString) + "\".");
                }

                // Deserialize the DDS file header.
                var header = new DDSHeader();
                header.Deserialize(reader);

                // Figure out the texture format and load the texture data.
                bool          hasMipmaps;
                uint          DDSMipmapLevelCount;
                TextureFormat textureFormat;
                int           bytesPerPixel;
                byte[]        textureData;
                ExtractDDSTextureFormatAndData(header, reader, out hasMipmaps, out DDSMipmapLevelCount, out textureFormat, out bytesPerPixel, out textureData);

                // Post-process the texture to generate missing mipmaps and possibly flip it vertically.
                PostProcessDDSTexture((int)header.dwWidth, (int)header.dwHeight, bytesPerPixel, hasMipmaps, (int)DDSMipmapLevelCount, textureData, flipVertically);

                return(new Texture2DInfo((int)header.dwWidth, (int)header.dwHeight, textureFormat, hasMipmaps, textureData));
            }
        }
Ejemplo n.º 4
0
 public RDATField(UnityBinaryReader r, int dataSize)
 {
     Type     = r.ReadLEUInt32();
     Flags    = (REGNType)r.ReadByte();
     Priority = r.ReadByte();
     r.SkipBytes(2); // Unused
 }
Ejemplo n.º 5
0
        public TNAMField TNAM;                                  // Timing

        public override bool CreateField(UnityBinaryReader r, GameFormatId format, string type, int dataSize)
        {
            switch (type)
            {
            case "EDID": EDID = r.ReadSTRV(dataSize); return(true);

            case "MODL": MODL = new MODLGroup(r, dataSize); return(true);

            case "MODB": MODL.MODBField(r, dataSize); return(true);

            case "FNAM": FNAM = r.ReadFILE(dataSize); return(true);

            case "GNAM": GNAM = r.ReadFILE(dataSize); return(true);

            case "WLST": for (var i = 0; i < dataSize >> 3; i++)
                {
                    WLSTs.Add(new WLSTField(r, dataSize));
                }
                return(true);

            case "TNAM": TNAM = new TNAMField(r, dataSize); return(true);

            default: return(false);
            }
        }
Ejemplo n.º 6
0
        public IN16Field?ANAM;              // Enchantment points (optional)

        public override bool CreateField(UnityBinaryReader r, GameFormatId format, string type, int dataSize)
        {
            switch (type)
            {
            case "EDID":
            case "NAME": EDID = r.ReadSTRV(dataSize); return(true);

            case "MODL": MODL = new MODLGroup(r, dataSize); return(true);

            case "MODB": MODL.MODBField(r, dataSize); return(true);

            case "MODT": MODL.MODTField(r, dataSize); return(true);

            case "FULL":
            case "FNAM": FULL = r.ReadSTRV(dataSize); return(true);

            case "DATA":
            case "BKDT": DATA = new DATAField(r, dataSize, format); return(true);

            case "ICON":
            case "ITEX": ICON = r.ReadFILE(dataSize); return(true);

            case "SCRI": SCRI = new FMIDField <SCPTRecord>(r, dataSize); return(true);

            case "DESC":
            case "TEXT": DESC = r.ReadSTRV(dataSize); return(true);

            case "ENAM": ENAM = new FMIDField <ENCHRecord>(r, dataSize); return(true);

            case "ANAM": ANAM = r.ReadT <IN16Field>(dataSize); return(true);

            default: return(false);
            }
        }
Ejemplo n.º 7
0
 public DATAField(UnityBinaryReader r, int dataSize)
 {
     Flags     = r.ReadLEUInt32();
     BaseCost  = r.ReadLESingle();
     AssocItem = r.ReadLEInt32();
     //wbUnion('Assoc. Item', wbMGEFFAssocItemDecider, [
     //  wbFormIDCk('Unused', [NULL]),
     //  wbFormIDCk('Assoc. Weapon', [WEAP]),
     //  wbFormIDCk('Assoc. Armor', [ARMO, NULL{?}]),
     //  wbFormIDCk('Assoc. Creature', [CREA, LVLC, NPC_]),
     //  wbInteger('Assoc. Actor Value', itS32, wbActorValueEnum)
     MagicSchool        = r.ReadLEInt32();
     ResistValue        = r.ReadLEInt32();
     CounterEffectCount = r.ReadLEUInt16();
     r.SkipBytes(2); // Unused
     Light           = new FormId <LIGHRecord>(r.ReadLEUInt32());
     ProjectileSpeed = r.ReadLESingle();
     EffectShader    = new FormId <EFSHRecord>(r.ReadLEUInt32());
     if (dataSize == 36)
     {
         return;
     }
     EnchantEffect = new FormId <EFSHRecord>(r.ReadLEUInt32());
     CastingSound  = new FormId <SOUNRecord>(r.ReadLEUInt32());
     BoltSound     = new FormId <SOUNRecord>(r.ReadLEUInt32());
     HitSound      = new FormId <SOUNRecord>(r.ReadLEUInt32());
     AreaSound     = new FormId <SOUNRecord>(r.ReadLEUInt32());
     ConstantEffectEnchantmentFactor = r.ReadLESingle();
     ConstantEffectBarterFactor      = r.ReadLESingle();
 }
Ejemplo n.º 8
0
        public BYTVField?XRGD;              // Ragdoll Data (optional)

        public override bool CreateField(UnityBinaryReader r, GameFormatId format, string type, int dataSize)
        {
            switch (type)
            {
            case "EDID": EDID = r.ReadSTRV(dataSize); return(true);

            case "NAME": NAME = new FMIDField <Record>(r, dataSize); return(true);

            case "DATA": DATA = new REFRRecord.DATAField(r, dataSize); return(true);

            case "XPCI": XPCI = new FMIDField <CELLRecord>(r, dataSize); return(true);

            case "FULL": XPCI.Value.AddName(r.ReadASCIIString(dataSize)); return(true);

            case "XLOD": XLOD = r.ReadBYTV(dataSize); return(true);

            case "XESP": XESP = new REFRRecord.XESPField(r, dataSize); return(true);

            case "XMRC": XMRC = new FMIDField <REFRRecord>(r, dataSize); return(true);

            case "XHRS": XHRS = new FMIDField <ACRERecord>(r, dataSize); return(true);

            case "XSCL": XSCL = r.ReadT <FLTVField>(dataSize); return(true);

            case "XRGD": XRGD = r.ReadBYTV(dataSize); return(true);

            default: return(false);
            }
        }
Ejemplo n.º 9
0
 public RecordGroup(UnityBinaryReader r, string filePath, GameFormatId format, int recordLevel)
 {
     _r           = r;
     _filePath    = filePath;
     _formatId    = format;
     _recordLevel = recordLevel;
 }
Ejemplo n.º 10
0
        public void ConstructTest_BinaryRange()
        {
            UnityBinaryReader reader = new UnityBinaryReader(TestData, 0, 8);

            Assert.ThrowsException <NullReferenceException>(delegate() { new UnityBinaryReader((byte[])null, 0, 8); });
            Assert.ThrowsException <ArgumentOutOfRangeException>(delegate() { new UnityBinaryReader(TestData, 0, 9); });
            Assert.ThrowsException <ArgumentOutOfRangeException>(delegate() { new UnityBinaryReader(TestData, 1, 8); });
        }
Ejemplo n.º 11
0
 public void Close()
 {
     if (_r != null)
     {
         _r.Close();
         _r = null;
     }
 }
Ejemplo n.º 12
0
 public HEDRField(UnityBinaryReader r, int dataSize)
 {
     Version         = r.ReadLESingle();
     FileType        = r.ReadLEUInt32();
     CompanyName     = r.ReadASCIIString(32, ASCIIFormat.ZeroPadded);
     FileDescription = r.ReadASCIIString(256, ASCIIFormat.ZeroPadded);
     NumRecords      = r.ReadLEUInt32();
 }
Ejemplo n.º 13
0
        public void ReadULongBE()
        {
            UnityBinaryReader r = new UnityBinaryReader(TestData);

            Assert.AreEqual <ulong>(0x0123456789ABCDEF, r.ReadULongBE());
            // Forward Test
            Assert.ThrowsException <IndexOutOfRangeException>(delegate() { r.ReadByte(); });
        }
Ejemplo n.º 14
0
 public AI_WField(UnityBinaryReader r, int dataSize)
 {
     Distance  = r.ReadLEInt16();
     Duration  = r.ReadLEInt16();
     TimeOfDay = r.ReadByte();
     Idle      = r.ReadBytes(8);
     Unknown   = r.ReadByte();
 }
Ejemplo n.º 15
0
 public override void DeserializeData(UnityBinaryReader reader, uint dataSize)
 {
     distance  = reader.ReadLEInt16();
     duration  = reader.ReadLEInt16();
     timeOfDay = reader.ReadByte();
     idle      = reader.ReadBytes(8);
     unknow    = reader.ReadByte();
 }
Ejemplo n.º 16
0
        public void ReadString()
        {
            UnityBinaryReader r = new UnityBinaryReader(TestStringBytes);

            Assert.AreEqual <string>(TestString, r.ReadString(TestStringBytes.Length));
            // Forward Test
            Assert.ThrowsException <IndexOutOfRangeException>(delegate() { r.ReadByte(); });
        }
Ejemplo n.º 17
0
 public XSEDField(UnityBinaryReader r, int dataSize)
 {
     Seed = r.ReadByte();
     if (dataSize == 4)
     {
         r.SkipBytes(3); // Unused
     }
 }
Ejemplo n.º 18
0
        public void ReadDouble()
        {
            UnityBinaryReader r = new UnityBinaryReader(TestDoubleBytes);

            Assert.AreEqual <double>(TestDouble, r.ReadDouble());
            // Forward Test
            Assert.ThrowsException <IndexOutOfRangeException>(delegate() { r.ReadByte(); });
        }
Ejemplo n.º 19
0
 public void RPLDField(UnityBinaryReader r, int dataSize)
 {
     Points = new Vector2[dataSize >> 3];
     for (var i = 0; i < Points.Length; i++)
     {
         Points[i] = new Vector2(r.ReadLESingle(), r.ReadLESingle());
     }
 }
Ejemplo n.º 20
0
        public void ReadSingle()
        {
            UnityBinaryReader r = new UnityBinaryReader(TestFloatBytes);

            Assert.AreEqual <float>(TestFloat, r.ReadFloat());
            // Forward Test
            Assert.ThrowsException <IndexOutOfRangeException>(delegate() { r.ReadByte(); });
        }
Ejemplo n.º 21
0
 public SNAMField(UnityBinaryReader r, int dataSize)
 {
     Values = new int[dataSize >> 2];
     for (var i = 0; i < Values.Length; i++)
     {
         Values[i] = r.ReadLEInt32();
     }
 }
Ejemplo n.º 22
0
 public DATAField(UnityBinaryReader r, int dataSize)
 {
     Speed  = r.ReadLESingle();
     Flags  = r.ReadLEUInt32();
     Value  = r.ReadLEUInt32();
     Weight = r.ReadLESingle();
     Damage = r.ReadLEUInt16();
 }
Ejemplo n.º 23
0
 public TRDTField(UnityBinaryReader r, int dataSize)
 {
     EmotionType  = r.ReadLEUInt32();
     EmotionValue = r.ReadLEInt32();
     r.SkipBytes(4); // Unused
     ResponseNumber = r.ReadByte();
     r.SkipBytes(3); // Unused
 }
Ejemplo n.º 24
0
        public void ReadULong()
        {
            UnityBinaryReader r = new UnityBinaryReader(TestData);

            Assert.AreEqual <ulong>(0xEFCDAB8967452301, r.ReadULong());
            // Forward Test
            Assert.ThrowsException <IndexOutOfRangeException>(delegate() { r.ReadByte(); });
        }
Ejemplo n.º 25
0
 public PSDTField(UnityBinaryReader r, int dataSize)
 {
     Month = r.ReadByte();
     DayOfWeek = r.ReadByte();
     Date = r.ReadByte();
     Time = (sbyte)r.ReadByte();
     Duration = r.ReadLEInt32();
 }
Ejemplo n.º 26
0
        public void ReadLong()
        {
            UnityBinaryReader r = new UnityBinaryReader(TestData);

            // r_bin
            Assert.AreEqual <long>(unchecked ((long)0xEFCDAB8967452301), r.ReadLong());
            // Forward Test
            Assert.ThrowsException <IndexOutOfRangeException>(delegate() { r.ReadByte(); });
        }
Ejemplo n.º 27
0
 public AI_FField(UnityBinaryReader r, int dataSize)
 {
     X        = r.ReadLESingle();
     Y        = r.ReadLESingle();
     Z        = r.ReadLESingle();
     Duration = r.ReadLEInt16();
     Id       = r.ReadASCIIString(32, ASCIIFormat.ZeroPadded);
     Unknown  = r.ReadLEInt16();
 }
Ejemplo n.º 28
0
    // TODO: Endianness?
    public static PCMAudioBuffer ReadWAV(string filePath)
    {
        using (var reader = new UnityBinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read)))
        {
            var chunkID = reader.ReadBytes(4);
            if (!StringUtils.Equals(chunkID, "RIFF"))
            {
                throw new FileFormatException("Invalid chunk ID.");
            }

            var chunkSize = reader.ReadLEUInt32(); // Size of the rest of the chunk after this number.

            var format = reader.ReadBytes(4);
            if (!StringUtils.Equals(format, "WAVE"))
            {
                throw new FileFormatException("Invalid chunk format.");
            }

            var subchunk1ID = reader.ReadBytes(4);
            if (!StringUtils.Equals(subchunk1ID, "fmt "))
            {
                throw new FileFormatException("Invalid subchunk ID.");
            }

            var subchunk1Size = reader.ReadLEUInt32(); // Size of rest of subchunk.

            var audioFormat = reader.ReadLEUInt16();
            if (audioFormat != 1) // 1 = PCM
            {
                throw new NotImplementedException("Unsupported audio format.");
            }

            var numChannels   = reader.ReadLEUInt16();
            var samplingRate  = reader.ReadLEUInt32(); // # of samples per second (not including all channels).
            var byteRate      = reader.ReadLEUInt32(); // # of bytes per second (including all channels).
            var blockAlign    = reader.ReadLEUInt16(); // # of bytes for one sample (including all channels).
            var bitsPerSample = reader.ReadLEUInt16(); // # of bits per sample (not including all channels).

            if (subchunk1Size == 18)
            {
                // Read any extra values.
                var subchunk1ExtraSize = reader.ReadLEUInt16();
                reader.ReadBytes(subchunk1ExtraSize);
            }

            var subchunk2ID = reader.ReadBytes(4); // "data"
            if (!StringUtils.Equals(subchunk2ID, "data"))
            {
                throw new FileFormatException("Invalid subchunk ID.");
            }

            var    subchunk2Size = reader.ReadLEUInt32(); // Size of rest of subchunk.
            byte[] audioData     = reader.ReadBytes((int)subchunk2Size);

            return(new PCMAudioBuffer((int)numChannels, (int)bitsPerSample, (int)samplingRate, audioData));
        }
    }
Ejemplo n.º 29
0
 public LNAMField(UnityBinaryReader r, int dataSize)
 {
     Direct = new FormId <Record>(r.ReadLEUInt32());
     //if (dataSize == 0)
     IndirectWorld = new FormId <WRLDRecord>(r.ReadLEUInt32());
     //if (dataSize == 0)
     IndirectGridX = r.ReadLEInt16();
     IndirectGridY = r.ReadLEInt16();
 }
Ejemplo n.º 30
0
        }                                   // Editor ID

        public override bool CreateField(UnityBinaryReader r, GameFormatId format, string type, int dataSize)
        {
            switch (type)
            {
            case "EDID": EDID = r.ReadSTRV(dataSize); return(true);

            default: return(false);
            }
        }
Ejemplo n.º 31
0
		public void Deserialize(UnityBinaryReader reader)
		{
			dwSize = reader.ReadLEUInt32();
			if(dwSize != 124)
			{
				throw new FileFormatException("Invalid DDS file header size: " + dwSize.ToString() + '.');
			}

			dwFlags = reader.ReadLEUInt32();
			if(!Utils.ContainsBitFlags(dwFlags, (uint)DDSFlags.Height, (uint)DDSFlags.Width))
			{
				throw new FileFormatException("Invalid DDS file flags: " + dwFlags.ToString() + '.');
			}

			dwHeight = reader.ReadLEUInt32();
			dwWidth = reader.ReadLEUInt32();
			dwPitchOrLinearSize = reader.ReadLEUInt32();
			dwDepth = reader.ReadLEUInt32();
			dwMipMapCount = reader.ReadLEUInt32();

			dwReserved1 = new uint[11];
			for(int i = 0; i < dwReserved1.Length; i++)
			{
				dwReserved1[i] = reader.ReadLEUInt32();
			}

			pixelFormat = new DDSPixelFormat();
			pixelFormat.Deserialize(reader);

			dwCaps = reader.ReadLEUInt32();
			if(!Utils.ContainsBitFlags(dwCaps, (uint)DDSCaps.Texture))
			{
				throw new FileFormatException("Invalid DDS file caps: " + dwCaps.ToString() + '.');
			}

			dwCaps2 = reader.ReadLEUInt32();
			dwCaps3 = reader.ReadLEUInt32();
			dwCaps4 = reader.ReadLEUInt32();
			dwReserved2 = reader.ReadLEUInt32();
		}
Ejemplo n.º 32
0
		/// <summary>
		/// Extracts a DDS file's texture format and pixel data.
		/// </summary>
		private static void ExtractDDSTextureFormatAndData(DDSHeader header, UnityBinaryReader reader, out bool hasMipmaps, out uint DDSMipmapLevelCount, out TextureFormat textureFormat, out int bytesPerPixel, out byte[] textureData)
		{
			hasMipmaps = Utils.ContainsBitFlags(header.dwCaps, (uint)DDSCaps.Mipmap);

			// Non-mipmapped textures still have one mipmap level: the texture itself.
			DDSMipmapLevelCount = hasMipmaps ? header.dwMipMapCount : 1;

			// If the DDS file contains uncompressed data.
			if(Utils.ContainsBitFlags(header.pixelFormat.flags, (uint)DDSPixelFormatFlags.RGB))
			{
				// some permutation of RGB
				if(!Utils.ContainsBitFlags(header.pixelFormat.flags, (uint)DDSPixelFormatFlags.AlphaPixels))
				{
					throw new NotImplementedException("Unsupported DDS file pixel format.");
				}
				// some permutation of RGBA
				else
				{
					// There should be 32 bits per pixel.
					if(header.pixelFormat.RGBBitCount != 32)
					{
						throw new FileFormatException("Invalid DDS file pixel format.");
					}

					// BGRA32
					if((header.pixelFormat.BBitMask == 0x000000FF) && (header.pixelFormat.GBitMask == 0x0000FF00) && (header.pixelFormat.RBitMask == 0x00FF0000) && (header.pixelFormat.ABitMask == 0xFF000000))
					{
						textureFormat = TextureFormat.BGRA32;
						bytesPerPixel = 4;
					}
					// ARGB32
					else if((header.pixelFormat.ABitMask == 0x000000FF) && (header.pixelFormat.RBitMask == 0x0000FF00) && (header.pixelFormat.GBitMask == 0x00FF0000) && (header.pixelFormat.BBitMask == 0xFF000000))
					{
						textureFormat = TextureFormat.ARGB32;
						bytesPerPixel = 4;
					}
					else
					{
						throw new NotImplementedException("Unsupported DDS file pixel format.");
					}

					if(!hasMipmaps)
					{
						textureData = new byte[header.dwPitchOrLinearSize * header.dwHeight];
					}
					else
					{
						// Create a data buffer to hold all mipmap levels down to 1x1.
						textureData = new byte[TextureUtils.CalculateMipMappedTextureDataSize((int)header.dwWidth, (int)header.dwHeight, bytesPerPixel)];
					}
					
					reader.ReadRestOfBytes(textureData, 0);
				}
			}
			else if(StringUtils.Equals(header.pixelFormat.fourCC, "DXT1"))
			{
				textureFormat = TextureFormat.ARGB32;
				bytesPerPixel = 4;

				var compressedTextureData = reader.ReadRestOfBytes();
				textureData = DecodeDXT1ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.pixelFormat, DDSMipmapLevelCount);
			}
			else if(StringUtils.Equals(header.pixelFormat.fourCC, "DXT3"))
			{
				textureFormat = TextureFormat.ARGB32;
				bytesPerPixel = 4;

				var compressedTextureData = reader.ReadRestOfBytes();
				textureData = DecodeDXT3ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.pixelFormat, DDSMipmapLevelCount);
			}
			else if(StringUtils.Equals(header.pixelFormat.fourCC, "DXT5"))
			{
				textureFormat = TextureFormat.ARGB32;
				bytesPerPixel = 4;

				var compressedTextureData = reader.ReadRestOfBytes();
				textureData = DecodeDXT5ToARGB(compressedTextureData, header.dwWidth, header.dwHeight, header.pixelFormat, DDSMipmapLevelCount);
			}
			else
			{
				throw new NotImplementedException("Unsupported DDS file pixel format.");
			}
		}
Ejemplo n.º 33
0
		public void Deserialize(UnityBinaryReader reader)
		{
			size = reader.ReadLEUInt32();
			if(size != 32)
			{
				throw new FileFormatException("Invalid DDS file pixel format size: " + size.ToString() + '.');
			}

			flags = reader.ReadLEUInt32();
			fourCC = reader.ReadBytes(4);
			RGBBitCount = reader.ReadLEUInt32();
			RBitMask = reader.ReadLEUInt32();
			GBitMask = reader.ReadLEUInt32();
			BBitMask = reader.ReadLEUInt32();
			ABitMask = reader.ReadLEUInt32();
		}
Ejemplo n.º 34
0
		/// <summary>
		/// Loads a DDS texture from an input stream.
		/// </summary>
		public static Texture2DInfo LoadDDSTexture(Stream inputStream, bool flipVertically = false)
		{
			using(var reader = new UnityBinaryReader(inputStream))
			{
				// Check the magic string.
				var magicString = reader.ReadBytes(4);
				if(!StringUtils.Equals(magicString, "DDS "))
				{
					throw new FileFormatException("Invalid DDS file magic string: \"" + System.Text.Encoding.ASCII.GetString(magicString) + "\".");
				}

				// Deserialize the DDS file header.
				var header = new DDSHeader();
				header.Deserialize(reader);

				// Figure out the texture format and load the texture data.
				bool hasMipmaps;
				uint DDSMipmapLevelCount;
				TextureFormat textureFormat;
				int bytesPerPixel;
				byte[] textureData;
				ExtractDDSTextureFormatAndData(header, reader, out hasMipmaps, out DDSMipmapLevelCount, out textureFormat, out bytesPerPixel, out textureData);

				// Post-process the texture to generate missing mipmaps and possibly flip it vertically.
				PostProcessDDSTexture((int)header.dwWidth, (int)header.dwHeight, bytesPerPixel, hasMipmaps, (int)DDSMipmapLevelCount, textureData, flipVertically);

				return new Texture2DInfo((int)header.dwWidth, (int)header.dwHeight, textureFormat, hasMipmaps, textureData);
			}
		}
Ejemplo n.º 35
0
		/// <summary>
		/// Decodes a DXT1-compressed 4x4 block of texels using a prebuilt 4-color color table.
		/// </summary>
		/// <remarks>See https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC1 </remarks>
		private static Color32[] DecodeDXT1TexelBlock(UnityBinaryReader reader, Color[] colorTable)
		{
			Debug.Assert(colorTable.Length == 4);

			// Read pixel color indices.
			var colorIndices = new uint[16];

			var colorIndexBytes = new byte[4];
			reader.Read(colorIndexBytes, 0, colorIndexBytes.Length);

			const uint bitsPerColorIndex = 2;

			for(uint rowIndex = 0; rowIndex < 4; rowIndex++)
			{
				var rowBaseColorIndexIndex = 4 * rowIndex;
				var rowBaseBitOffset = 8 * rowIndex;

				for(uint columnIndex = 0; columnIndex < 4; columnIndex++)
				{
					// Color indices are arranged from right to left.
					var bitOffset = rowBaseBitOffset + (bitsPerColorIndex * (3 - columnIndex));

					colorIndices[rowBaseColorIndexIndex + columnIndex] = (uint)Utils.GetBits(bitOffset, bitsPerColorIndex, colorIndexBytes);
				}
			}

			// Calculate pixel colors.
			var colors = new Color32[16];

			for(int i = 0; i < 16; i++)
			{
				colors[i] = colorTable[colorIndices[i]];
			}

			return colors;
		}
Ejemplo n.º 36
0
		/// <summary>
		/// Builds a 4-color color table for a DXT1-compressed 4x4 block of texels and then decodes the texels.
		/// </summary>
		/// <remarks>See https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC1 </remarks>
		private static Color32[] DecodeDXT1TexelBlock(UnityBinaryReader reader, bool containsAlpha)
		{
			// Create the color table.
			var colorTable = new Color[4];
			colorTable[0] = ColorUtils.R5G6B5ToColor(reader.ReadLEUInt16());
			colorTable[1] = ColorUtils.R5G6B5ToColor(reader.ReadLEUInt16());

			if(!containsAlpha)
			{
				colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 3);
				colorTable[3] = Color.Lerp(colorTable[0], colorTable[1], 2.0f / 3);
			}
			else
			{
				colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 2);
				colorTable[3] = new Color(0, 0, 0, 0);
			}

			// Calculate pixel colors.
			return DecodeDXT1TexelBlock(reader, colorTable);
		}
Ejemplo n.º 37
0
		/// <summary>
		/// Decodes a DXT3-compressed 4x4 block of texels.
		/// </summary>
		/// <remarks>See https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC2 </remarks>
		private static Color32[] DecodeDXT3TexelBlock(UnityBinaryReader reader)
		{
			// Read compressed pixel alphas.
			var compressedAlphas = new byte[16];

			for(int rowIndex = 0; rowIndex < 4; rowIndex++)
			{
				var compressedAlphaRow = reader.ReadLEUInt16();

				for(int columnIndex = 0; columnIndex < 4; columnIndex++)
				{
					// Each compressed alpha is 4 bits.
					compressedAlphas[(4 * rowIndex) + columnIndex] = (byte)((compressedAlphaRow >> (columnIndex * 4)) & 0xF);
				}
			}

			// Calculate pixel alphas.
			var alphas = new byte[16];

			for(int i = 0; i < 16; i++)
			{
				var alphaPercent = (float)compressedAlphas[i] / 15;
				alphas[i] = (byte)Mathf.RoundToInt(alphaPercent * 255);
			}

			// Create the color table.
			var colorTable = new Color[4];
			colorTable[0] = ColorUtils.R5G6B5ToColor(reader.ReadLEUInt16());
			colorTable[1] = ColorUtils.R5G6B5ToColor(reader.ReadLEUInt16());
			colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 3);
			colorTable[3] = Color.Lerp(colorTable[0], colorTable[1], 2.0f / 3);

			// Calculate pixel colors.
			var colors = DecodeDXT1TexelBlock(reader, colorTable);

			for(int i = 0; i < 16; i++)
			{
				colors[i].a = alphas[i];
			}

			return colors;
		}
Ejemplo n.º 38
0
		/// <summary>
		/// Decodes a DXT5-compressed 4x4 block of texels.
		/// </summary>
		/// <remarks>See https://msdn.microsoft.com/en-us/library/windows/desktop/bb694531(v=vs.85).aspx#BC3 </remarks>
		private static Color32[] DecodeDXT5TexelBlock(UnityBinaryReader reader)
		{
			// Create the alpha table.
			var alphaTable = new float[8];
			alphaTable[0] = reader.ReadByte();
			alphaTable[1] = reader.ReadByte();

			if(alphaTable[0] > alphaTable[1])
			{
				for(int i = 0; i < 6; i++)
				{
					alphaTable[2 + i] = Mathf.Lerp(alphaTable[0], alphaTable[1], (float)(1 + i) / 7);
				}
			}
			else
			{
				for(int i = 0; i < 4; i++)
				{
					alphaTable[2 + i] = Mathf.Lerp(alphaTable[0], alphaTable[1], (float)(1 + i) / 5);
				}

				alphaTable[6] = 0;
				alphaTable[7] = 255;
			}

			// Read pixel alpha indices.
			var alphaIndices = new uint[16];

			var alphaIndexBytesRow0 = new byte[3];
			reader.Read(alphaIndexBytesRow0, 0, alphaIndexBytesRow0.Length);
			Array.Reverse(alphaIndexBytesRow0); // Take care of little-endianness.

			var alphaIndexBytesRow1 = new byte[3];
			reader.Read(alphaIndexBytesRow1, 0, alphaIndexBytesRow1.Length);
			Array.Reverse(alphaIndexBytesRow1); // Take care of little-endianness.

			const uint bitsPerAlphaIndex = 3;

			alphaIndices[0] = (uint)Utils.GetBits(21, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[1] = (uint)Utils.GetBits(18, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[2] = (uint)Utils.GetBits(15, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[3] = (uint)Utils.GetBits(12, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[4] = (uint)Utils.GetBits(9, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[5] = (uint)Utils.GetBits(6, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[6] = (uint)Utils.GetBits(3, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[7] = (uint)Utils.GetBits(0, bitsPerAlphaIndex, alphaIndexBytesRow0);
			alphaIndices[8] = (uint)Utils.GetBits(21, bitsPerAlphaIndex, alphaIndexBytesRow1);
			alphaIndices[9] = (uint)Utils.GetBits(18, bitsPerAlphaIndex, alphaIndexBytesRow1);
			alphaIndices[10] = (uint)Utils.GetBits(15, bitsPerAlphaIndex, alphaIndexBytesRow1);
			alphaIndices[11] = (uint)Utils.GetBits(12, bitsPerAlphaIndex, alphaIndexBytesRow1);
			alphaIndices[12] = (uint)Utils.GetBits(9, bitsPerAlphaIndex, alphaIndexBytesRow1);
			alphaIndices[13] = (uint)Utils.GetBits(6, bitsPerAlphaIndex, alphaIndexBytesRow1);
			alphaIndices[14] = (uint)Utils.GetBits(3, bitsPerAlphaIndex, alphaIndexBytesRow1);
			alphaIndices[15] = (uint)Utils.GetBits(0, bitsPerAlphaIndex, alphaIndexBytesRow1);

			// Create the color table.
			var colorTable = new Color[4];
			colorTable[0] = ColorUtils.R5G6B5ToColor(reader.ReadLEUInt16());
			colorTable[1] = ColorUtils.R5G6B5ToColor(reader.ReadLEUInt16());
			colorTable[2] = Color.Lerp(colorTable[0], colorTable[1], 1.0f / 3);
			colorTable[3] = Color.Lerp(colorTable[0], colorTable[1], 2.0f / 3);

			// Calculate pixel colors.
			var colors = DecodeDXT1TexelBlock(reader, colorTable);

			for(int i = 0; i < 16; i++)
			{
				colors[i].a = (byte)Mathf.Round(alphaTable[alphaIndices[i]]);
			}

			return colors;
		}
Ejemplo n.º 39
0
		/// <summary>
		/// Decodes DXT data to ARGB.
		/// </summary>
		private static byte[] DecodeDXTToARGB(int DXTVersion, byte[] compressedData, uint width, uint height, DDSPixelFormat pixelFormat, uint mipmapCount)
		{
			bool alphaFlag = Utils.ContainsBitFlags(pixelFormat.flags, (uint)DDSPixelFormatFlags.AlphaPixels);
			bool containsAlpha = alphaFlag || ((pixelFormat.RGBBitCount == 32) && (pixelFormat.ABitMask != 0));

			var reader = new UnityBinaryReader(new MemoryStream(compressedData));
			var argb = new byte[TextureUtils.CalculateMipMappedTextureDataSize((int)width, (int)height, 4)];

			int mipMapWidth = (int)width;
			int mipMapHeight = (int)height;
			int baseARGBIndex = 0;

			for(int mipMapIndex = 0; mipMapIndex < mipmapCount; mipMapIndex++)
			{
				for(int rowIndex = 0; rowIndex < mipMapHeight; rowIndex += 4)
				{
					for(int columnIndex = 0; columnIndex < mipMapWidth; columnIndex += 4)
					{
						Color32[] colors = null;

						// Doing a switch instead of using a delegate for speed.
						switch(DXTVersion)
						{
							case 1:
								colors = DecodeDXT1TexelBlock(reader, containsAlpha);
								break;
							case 3:
								colors = DecodeDXT3TexelBlock(reader);
								break;
							case 5:
								colors = DecodeDXT5TexelBlock(reader);
								break;
							default:
								throw new NotImplementedException("Tried decoding a DDS file using an unsupported DXT format: DXT" + DXTVersion.ToString());
						}

						CopyDecodedTexelBlock(colors, argb, baseARGBIndex, rowIndex, columnIndex, mipMapWidth, mipMapHeight);
					}
				}

				baseARGBIndex += (mipMapWidth * mipMapHeight * 4);

				mipMapWidth /= 2;
				mipMapHeight /= 2;
			}

			return argb;
		}