private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stream stream, BinaryReader xnbReader, char platform, Action <IDisposable> recordDisposableObject) { byte version = xnbReader.ReadByte(); byte flags = xnbReader.ReadByte(); bool compressed = (flags & 0x80) != 0; if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressed) { /* Decompress the XNB * Thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) */ int compressedSize = xnbLength - 14; int decompressedSize = xnbReader.ReadInt32(); // This will replace the XNB stream at the end MemoryStream decompressedStream = new MemoryStream( new byte[decompressedSize], 0, decompressedSize, true, true // This MUST be true! Readers may need GetBuffer()! ); /* Read in the whole XNB file at once, into a temp buffer. * For slow disks, the extra malloc is more than worth the * performance improvement from not constantly fread()ing! */ MemoryStream compressedStream = new MemoryStream( new byte[compressedSize], 0, compressedSize, true, true ); stream.Read(compressedStream.GetBuffer(), 0, compressedSize); // Default window size for XNB encoded files is 64Kb (need 16 bits to represent it) LzxDecoder dec = new LzxDecoder(16); int decodedBytes = 0; long pos = 0; while (pos < compressedSize) { /* The compressed stream is separated into blocks that will * decompress into 32kB or some other size if specified. * Normal, 32kB output blocks will have a short indicating * the size of the block before the block starts. Blocks * that have a defined output will be preceded by a byte of * value 0xFF (255), then a short indicating the output size * and another for the block size. All shorts for these * cases are encoded in big endian order. */ int hi = compressedStream.ReadByte(); int lo = compressedStream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; // Frame size is 32kB by default // Does this block define a frame size? if (hi == 0xFF) { hi = lo; lo = (byte)compressedStream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)compressedStream.ReadByte(); lo = (byte)compressedStream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } // Either says there is nothing to decode if (block_size == 0 || frame_size == 0) { break; } dec.Decompress(compressedStream, block_size, decompressedStream, frame_size); pos += block_size; decodedBytes += frame_size; /* Reset the position of the input just in case the bit * buffer read in some unused bytes. */ compressedStream.Seek(pos, SeekOrigin.Begin); } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException( "Decompression of " + originalAssetName + " failed. " ); } decompressedStream.Seek(0, SeekOrigin.Begin); reader = new ContentReader( this, decompressedStream, originalAssetName, version, platform, recordDisposableObject ); } else { reader = new ContentReader( this, stream, originalAssetName, version, platform, recordDisposableObject ); } return(reader); }
private static Stream PrepareStream(Stream input, string assetName) { Stream stream; try { bool flag; //Compressionflag BinaryReader reader = new BinaryReader(input); if (((reader.ReadByte() != 0x58) || (reader.ReadByte() != 0x4e)) || (reader.ReadByte() != 0x42)) //First three bytes have to be "XNB" { throw new ContentLoadException("Bad XNB Magic"); } if (reader.ReadByte() != 0x77) //Platform have to be "w" -> stands for windows { throw new ContentLoadException("Bad XNB Platform"); } switch (reader.ReadUInt16()) //Version { case 3: case 4: flag = false; //Not compressed Stream break; case 0x8003: case 0x8004: flag = true; //Compressed Stream break; default: throw new ContentLoadException("Bad XNB Version"); } int num = reader.ReadInt32(); //Number of bytes if (input.CanSeek && ((num - 10) > (input.Length - input.Position))) //Check if we can read the expected number of bytes { throw new ContentLoadException("Bad XNB Size"); } // is the stream compressed? if (flag) { // ... let's decompress it! // get the decompressed size (num is our compressed size) int decompressedSize = reader.ReadInt32(); // create a memory stream of that size MemoryStream output = new MemoryStream(decompressedSize); // save our initial position long pos = input.Position; // default window size for XNB encoded files is 64Kb (need 16 bits to represent it) LzxDecoder decoder = new LzxDecoder(16); // start our decode process while (pos < num) { // the compressed stream is seperated into blocks that will decompress // into 32Kb or some other size if specified. // normal, 32Kb output blocks will have a short indicating the size // of the block before the block starts // blocks that have a defined output will be preceded by a byte of value // 0xFF (255), then a short indicating the output size and another // for the block size // all shorts for these cases are encoded in big endian order int hi, lo, block_size, frame_size; // let's get the first byte hi = reader.ReadByte(); // does this block define a frame size? if (hi == 0xFF) { // get our bytes hi = reader.ReadByte(); lo = reader.ReadByte(); // make a beautiful short baby together frame_size = (hi << 8) | lo; // let's read the block size hi = reader.ReadByte(); lo = reader.ReadByte(); block_size = (hi << 8) | lo; // add the read in bytes to the position pos += 5; } else { // just block size, so let's read the rest lo = reader.ReadByte(); block_size = (hi << 8) | lo; // frame size is 32Kb by default frame_size = 32768; // add the read in bytes to the position pos += 2; } // either says there is nothing to decode if (block_size == 0 || frame_size == 0) { break; } // let's decompress the sucker decoder.Decompress(input, block_size, output, frame_size); // let's increment the input position by the block size pos += block_size; // reset the position of the input just incase the bit buffer // read in some unused bytes input.Seek(pos, SeekOrigin.Begin); } // finished decoding everything, let's set the decompressed buffer // to the beginning and return that output.Seek(0, SeekOrigin.Begin); stream = output; } else // if not, return the input stream untouched { stream = input; } } catch (IOException exception) { throw new ContentLoadException("Bad XNB", exception); } return(stream); }
private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stream stream, BinaryReader xnbReader, Action <IDisposable> recordDisposableObject) { // The first 4 bytes should be the "XNB" header. i use that to detect an invalid file byte x = xnbReader.ReadByte(); byte n = xnbReader.ReadByte(); byte b = xnbReader.ReadByte(); byte platform = xnbReader.ReadByte(); if (x != 'X' || n != 'N' || b != 'B' || !(targetPlatformIdentifiers.Contains((char)platform))) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } byte version = xnbReader.ReadByte(); byte flags = xnbReader.ReadByte(); bool compressedLzx = (flags & ContentCompressedLzx) != 0; bool compressedLz4 = (flags & ContentCompressedLz4) != 0; if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressedLzx || compressedLz4) { // Decompress the xnb int decompressedSize = xnbReader.ReadInt32(); MemoryStream decompressedStream = null; if (compressedLzx) { //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) // default window size for XNB encoded files is 64Kb (need 16 bits to represent it) LzxDecoder dec = new LzxDecoder(16); decompressedStream = new MemoryStream(decompressedSize); int compressedSize = xnbLength - 14; long startPos = stream.Position; long pos = startPos; while (pos - startPos < compressedSize) { // the compressed stream is seperated into blocks that will decompress // into 32Kb or some other size if specified. // normal, 32Kb output blocks will have a short indicating the size // of the block before the block starts // blocks that have a defined output will be preceded by a byte of value // 0xFF (255), then a short indicating the output size and another // for the block size // all shorts for these cases are encoded in big endian order int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; // frame size is 32Kb by default // does this block define a frame size? if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } // either says there is nothing to decode if (block_size == 0 || frame_size == 0) { break; } dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; // reset the position of the input just incase the bit buffer // read in some unused bytes stream.Seek(pos, SeekOrigin.Begin); } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + " failed. "); } decompressedStream.Seek(0, SeekOrigin.Begin); } else if (compressedLz4) { // Decompress to a byte[] because Windows 8 doesn't support MemoryStream.GetBuffer() var buffer = new byte[decompressedSize]; using (var decoderStream = new Lz4DecoderStream(stream)) { if (decoderStream.Read(buffer, 0, buffer.Length) != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + " failed. "); } } // Creating the MemoryStream with a byte[] shares the buffer so it doesn't allocate any more memory decompressedStream = new MemoryStream(buffer); } reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject); } else { reader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject); } return(reader); }
private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stream stream, BinaryReader xnbReader, Action <IDisposable> recordDisposableObject) { // The first 4 bytes should be the "XNB" header. byte x = xnbReader.ReadByte(); byte n = xnbReader.ReadByte(); byte b = xnbReader.ReadByte(); byte platform = xnbReader.ReadByte(); if (x != 'X' || n != 'N' || b != 'B' || !(targetPlatformIdentifiers.Contains((char)platform))) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } byte version = xnbReader.ReadByte(); byte flags = xnbReader.ReadByte(); bool compressed = (flags & 0x80) != 0; if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressed) { /* Decompress the XNB * Thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) */ int compressedSize = xnbLength - 14; int decompressedSize = xnbReader.ReadInt32(); MemoryStream decompressedStream = new MemoryStream(decompressedSize); // Default window size for XNB encoded files is 64Kb (need 16 bits to represent it) LzxDecoder dec = new LzxDecoder(16); int decodedBytes = 0; long startPos = stream.Position; long pos = startPos; while (pos - startPos < compressedSize) { /* The compressed stream is separated into blocks that will * decompress into 32kB or some other size if specified. * Normal, 32kB output blocks will have a short indicating * the size of the block before the block starts. Blocks * that have a defined output will be preceded by a byte of * value 0xFF (255), then a short indicating the output size * and another for the block size. All shorts for these * cases are encoded in big endian order. */ int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; // Frame size is 32kB by default // Does this block define a frame size? if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } // Either says there is nothing to decode if (block_size == 0 || frame_size == 0) { break; } dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; decodedBytes += frame_size; /* Reset the position of the input just in case the bit * buffer read in some unused bytes. */ stream.Seek(pos, SeekOrigin.Begin); } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException( "Decompression of " + originalAssetName + " failed. " ); } decompressedStream.Seek(0, SeekOrigin.Begin); reader = new ContentReader( this, decompressedStream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject ); } else { reader = new ContentReader( this, stream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject ); } return(reader); }
private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stream stream, BinaryReader xnbReader, Action <IDisposable> recordDisposableObject) { // The first 4 bytes should be the "XNB" header. i use that to detect an invalid file byte x = xnbReader.ReadByte(); byte n = xnbReader.ReadByte(); byte b = xnbReader.ReadByte(); byte platform = xnbReader.ReadByte(); if (x != 'X' || n != 'N' || b != 'B' || !(targetPlatformIdentifiers.Contains((char)platform))) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } byte version = xnbReader.ReadByte(); byte flags = xnbReader.ReadByte(); bool compressed = (flags & 0x80) != 0; if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressed) { //decompress the xnb //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) int compressedSize = xnbLength - 14; int decompressedSize = xnbReader.ReadInt32(); MemoryStream decompressedStream = new MemoryStream(decompressedSize); // default window size for XNB encoded files is 64Kb (need 16 bits to represent it) LzxDecoder dec = new LzxDecoder(16); int decodedBytes = 0; long startPos = stream.Position; long pos = startPos; #if ANDROID // Android native stream does not support the Position property. LzxDecoder.Decompress also uses // Seek. So we read the entirity of the stream into a memory stream and replace stream with the // memory stream. MemoryStream memStream = new MemoryStream(); stream.CopyTo(memStream); memStream.Seek(0, SeekOrigin.Begin); stream.Dispose(); stream = memStream; // Position is at the start of the MemoryStream as Stream.CopyTo copies from current position pos = 0; #endif while (pos - startPos < compressedSize) { // the compressed stream is seperated into blocks that will decompress // into 32Kb or some other size if specified. // normal, 32Kb output blocks will have a short indicating the size // of the block before the block starts // blocks that have a defined output will be preceded by a byte of value // 0xFF (255), then a short indicating the output size and another // for the block size // all shorts for these cases are encoded in big endian order int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; // frame size is 32Kb by default // does this block define a frame size? if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } // either says there is nothing to decode if (block_size == 0 || frame_size == 0) { break; } dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; decodedBytes += frame_size; // reset the position of the input just incase the bit buffer // read in some unused bytes stream.Seek(pos, SeekOrigin.Begin); } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + " failed. "); } decompressedStream.Seek(0, SeekOrigin.Begin); reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject); } else { reader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, version, recordDisposableObject); } return(reader); }
private uint ReadHuffSym(ushort[] table, byte[] lengths, uint nsyms, uint nbits, LzxDecoder.BitBuffer bitbuf) { bitbuf.EnsureBits((byte) 16); uint num1; if ((num1 = (uint) table[(IntPtr) bitbuf.PeekBits((byte) nbits)]) >= nsyms) { uint num2 = (uint) (1 << 32 - (int) nbits); uint num3; do { num2 >>= 1; num3 = num1 << 1 | (((int) bitbuf.GetBuffer() & (int) num2) != 0 ? 1U : 0U); if ((int) num2 == 0) return 0U; } while ((num1 = (uint) table[(IntPtr) num3]) >= nsyms); } uint num4 = (uint) lengths[(IntPtr) num1]; bitbuf.RemoveBits((byte) num4); return num1; }
private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stream stream, BinaryReader xnbReader, Action <IDisposable> recordDisposableObject) { byte num1 = xnbReader.ReadByte(); byte num2 = xnbReader.ReadByte(); byte num3 = xnbReader.ReadByte(); byte num4 = xnbReader.ReadByte(); if ((int)num1 != 88 || (int)num2 != 78 || (int)num3 != 66 || (int)num4 != 119 && (int)num4 != 120 && (int)num4 != 109) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } byte num5 = xnbReader.ReadByte(); bool flag = ((int)xnbReader.ReadByte() & 128) != 0; if ((int)num5 != 5 && (int)num5 != 4) { throw new ContentLoadException("Invalid XNB version"); } int num6 = xnbReader.ReadInt32(); ContentReader contentReader; if (flag) { int num7 = num6 - 14; int capacity = xnbReader.ReadInt32(); MemoryStream memoryStream = new MemoryStream(capacity); LzxDecoder lzxDecoder = new LzxDecoder(16); int num8 = 0; long position = stream.Position; long offset = position; while (offset - position < (long)num7) { int num9 = stream.ReadByte(); int num10 = stream.ReadByte(); int inLen = num9 << 8 | num10; int outLen = 32768; long num11; if (num9 == (int)byte.MaxValue) { outLen = num10 << 8 | (int)(byte)stream.ReadByte(); inLen = (int)(byte)stream.ReadByte() << 8 | (int)(byte)stream.ReadByte(); num11 = offset + 5L; } else { num11 = offset + 2L; } if (inLen != 0 && outLen != 0) { lzxDecoder.Decompress(stream, inLen, (Stream)memoryStream, outLen); offset = num11 + (long)inLen; num8 += outLen; stream.Seek(offset, SeekOrigin.Begin); } else { break; } } if (memoryStream.Position != (long)capacity) { throw new ContentLoadException("Decompression of " + originalAssetName + " failed. "); } memoryStream.Seek(0L, SeekOrigin.Begin); contentReader = new ContentReader(this, (Stream)memoryStream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, (int)num5, recordDisposableObject); } else { contentReader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice, originalAssetName, (int)num5, recordDisposableObject); } return(contentReader); }
private void ReadLengths(byte[] lens, uint first, uint last, LzxDecoder.BitBuffer bitbuf) { for (uint index = 0U; index < 20U; ++index) { uint num = bitbuf.ReadBits((byte) 4); this.m_state.PRETREE_len[(IntPtr) index] = (byte) num; } this.MakeDecodeTable(20U, 6U, this.m_state.PRETREE_len, this.m_state.PRETREE_table); uint num1 = first; while (num1 < last) { int num2 = (int) this.ReadHuffSym(this.m_state.PRETREE_table, this.m_state.PRETREE_len, 20U, 6U, bitbuf); switch (num2) { case 17: uint num3 = bitbuf.ReadBits((byte) 4) + 4U; while ((int) num3-- != 0) lens[(IntPtr) num1++] = (byte) 0; continue; case 18: uint num4 = bitbuf.ReadBits((byte) 5) + 20U; while ((int) num4-- != 0) lens[(IntPtr) num1++] = (byte) 0; continue; case 19: uint num5 = bitbuf.ReadBits((byte) 1) + 4U; int num6 = (int) this.ReadHuffSym(this.m_state.PRETREE_table, this.m_state.PRETREE_len, 20U, 6U, bitbuf); int num7 = (int) lens[(IntPtr) num1] - num6; if (num7 < 0) num7 += 17; while ((int) num5-- != 0) lens[(IntPtr) num1++] = (byte) num7; continue; default: int num8 = (int) lens[(IntPtr) num1] - num2; if (num8 < 0) num8 += 17; lens[(IntPtr) num1++] = (byte) num8; continue; } } }
protected T ReadAsset <T>(string assetName, Action <IDisposable> recordDisposableObject) { if (string.IsNullOrEmpty(assetName)) { throw new ArgumentNullException(); } if (disposed) { throw new ObjectDisposedException("ContentManager"); } string originalAssetName = assetName; object result = null; if (this.graphicsDeviceService == null) { this.graphicsDeviceService = serviceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService; if (this.graphicsDeviceService == null) { throw new InvalidOperationException("No Graphics Device Service"); } } // Replace Windows path separators with local path separators assetName = Path.Combine(_rootDirectory, assetName.Replace('\\', Path.DirectorySeparatorChar)); // Get the real file name if ((typeof(T) == typeof(Texture2D))) { assetName = Texture2DReader.Normalize(assetName); } else if ((typeof(T) == typeof(SpriteFont))) { assetName = SpriteFontReader.Normalize(assetName); } else if ((typeof(T) == typeof(Effect))) { assetName = Effect.Normalize(assetName); } else if ((typeof(T) == typeof(Song))) { assetName = SongReader.Normalize(assetName); } else if ((typeof(T) == typeof(SoundEffect))) { assetName = SoundEffectReader.Normalize(assetName); } else if ((typeof(T) == typeof(Video))) { assetName = Video.Normalize(assetName); } else { throw new NotSupportedException("Format not supported"); } if (string.IsNullOrEmpty(assetName)) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } if (!Path.HasExtension(assetName)) { assetName = string.Format("{0}.xnb", assetName); } if (Path.GetExtension(assetName).ToUpper() == ".XNB") { // Load a XNB file //Loads from Assets directory + /assetName Stream stream = OpenStream(assetName); BinaryReader xnbReader = new BinaryReader(stream); // The first 4 bytes should be the "XNB" header. i use that to detect an invalid file byte[] headerBuffer = new byte[3]; xnbReader.Read(headerBuffer, 0, 3); string headerString = Encoding.UTF8.GetString(headerBuffer, 0, 3); byte platform = xnbReader.ReadByte(); if (string.Compare(headerString, "XNB") != 0 || !(platform == 'w' || platform == 'x' || platform == 'm')) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } ushort version = xnbReader.ReadUInt16(); int graphicsProfile = version & 0x7f00; version &= 0x80ff; bool compressed = false; if (version == 0x8005 || version == 0x8004) { compressed = true; } else if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressed) { //decompress the xnb //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) int compressedSize = xnbLength - 14; int decompressedSize = xnbReader.ReadInt32(); int newFileSize = decompressedSize + 10; MemoryStream decompressedStream = new MemoryStream(decompressedSize); LzxDecoder dec = new LzxDecoder(16); int decodedBytes = 0; int pos = 0; while (pos < compressedSize) { // let's seek to the correct position stream.Seek(pos + 14, SeekOrigin.Begin); int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } if (block_size == 0 || frame_size == 0) { break; } int lzxRet = dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; decodedBytes += frame_size; } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + "failed. " + " Try decompressing with nativeDecompressXnb first."); } decompressedStream.Seek(0, SeekOrigin.Begin); reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice); } else { reader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice); } ContentTypeReaderManager typeManager = new ContentTypeReaderManager(reader); reader.TypeReaders = typeManager.LoadAssetReaders(reader); foreach (ContentTypeReader r in reader.TypeReaders) { r.Initialize(typeManager); } // we need to read a byte here for things to work out, not sure why reader.ReadByte(); // Get the 1-based index of the typereader we should use to start decoding with int index = reader.ReadByte(); ContentTypeReader contentReader = reader.TypeReaders[index - 1]; result = reader.ReadObject <T>(contentReader); reader.Close(); stream.Close(); } else { if ((typeof(T) == typeof(Texture2D))) { //Basically the same as Texture2D.FromFile but loading from the assets instead of a filePath Stream assetStream = OpenStream(assetName); Bitmap image = BitmapFactory.DecodeStream(assetStream); ESImage theTexture = new ESImage(image, graphicsDeviceService.GraphicsDevice.PreferedFilter); result = new Texture2D(theTexture) { Name = Path.GetFileNameWithoutExtension(assetName) }; } if ((typeof(T) == typeof(SpriteFont))) { //result = new SpriteFont(Texture2D.FromFile(graphicsDeviceService.GraphicsDevice,assetName), null, null, null, 0, 0.0f, null, null); throw new NotImplementedException(); } if ((typeof(T) == typeof(Song))) { result = new Song(assetName); } if ((typeof(T) == typeof(SoundEffect))) { result = new SoundEffect(assetName); } if ((typeof(T) == typeof(Video))) { result = new Video(assetName); } } /*else * { * // Load a XNB file * //Loads from Assets directory + /assetName * Stream assetStream = OpenStream(assetName); * * ContentReader reader = new ContentReader(this, assetStream, this.graphicsDeviceService.GraphicsDevice); * ContentTypeReaderManager typeManager = new ContentTypeReaderManager(reader); * reader.TypeReaders = typeManager.LoadAssetReaders(reader); * foreach (ContentTypeReader r in reader.TypeReaders) * { * r.Initialize(typeManager); * } * // we need to read a byte here for things to work out, not sure why * reader.ReadByte(); * * // Get the 1-based index of the typereader we should use to start decoding with * int index = reader.ReadByte(); * ContentTypeReader contentReader = reader.TypeReaders[index - 1]; * result = reader.ReadObject<T>(contentReader); * * reader.Close(); * assetStream.Close(); * }*/ if (result == null) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } // Store references to the asset for later use T asset = (T)result; if (asset is IDisposable && recordDisposableObject != null) { recordDisposableObject(asset as IDisposable); } else { disposableAssets.Add(asset as IDisposable); } loadedAssets.Add(originalAssetName, asset); return((T)result); }
public T Load <T>(string assetName) { string originalAssetName = assetName; object result = null; if (this.graphicsDeviceService == null) { this.graphicsDeviceService = serviceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService; if (this.graphicsDeviceService == null) { throw new InvalidOperationException("No Graphics Device Service"); } } if (string.IsNullOrEmpty(assetName)) { throw new ArgumentException("assetname"); } if (!string.IsNullOrEmpty(_rootDirectory)) { assetName = _rootDirectory + Path.DirectorySeparatorChar + assetName; } // Check for windows-style directory separator character assetName = assetName.Replace('\\', Path.DirectorySeparatorChar); // Get the real file name if ((typeof(T) == typeof(Texture2D))) { assetName = Texture2DReader.Normalize(assetName); } if ((typeof(T) == typeof(SpriteFont))) { assetName = SpriteFontReader.Normalize(assetName); } if ((typeof(T) == typeof(Song))) { assetName = SongReader.Normalize(assetName); } if ((typeof(T) == typeof(SoundEffect))) { assetName = SoundEffectReader.Normalize(assetName); } if ((typeof(T) == typeof(Video))) { assetName = Video.Normalize(assetName); } if ((typeof(T) == typeof(Effect))) { assetName = Effect.Normalize(assetName); } if (string.IsNullOrEmpty(assetName)) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } if (!Path.HasExtension(assetName)) { assetName = string.Format("{0}.xnb", assetName); } if (Path.GetExtension(assetName).ToUpper() == ".XNB") { // Load a XNB file FileStream stream = new FileStream(assetName, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader xnbReader = new BinaryReader(stream); // The first 4 bytes should be the "XNB" header. i use that to detect an invalid file byte[] headerBuffer = new byte[3]; xnbReader.Read(headerBuffer, 0, 3); string headerString = Encoding.UTF8.GetString(headerBuffer, 0, 3); byte platform = xnbReader.ReadByte(); if (string.Compare(headerString, "XNB") != 0 || !(platform == 'w' || platform == 'x' || platform == 'm')) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } ushort version = xnbReader.ReadUInt16(); int graphicsProfile = version & 0x7f00; version &= 0x80ff; bool compressed = false; if (version == 0x8005 || version == 0x8004) { compressed = true; } else if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressed) { //decompress the xnb //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) int compressedSize = xnbLength - 14; int decompressedSize = xnbReader.ReadInt32(); int newFileSize = decompressedSize + 10; MemoryStream decompressedStream = new MemoryStream(decompressedSize); LzxDecoder dec = new LzxDecoder(16); int decodedBytes = 0; int pos = 0; while (pos < compressedSize) { // let's seek to the correct position stream.Seek(pos + 14, SeekOrigin.Begin); int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } if (block_size == 0 || frame_size == 0) { break; } int lzxRet = dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; decodedBytes += frame_size; } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + "failed. " + " Try decompressing with nativeDecompressXnb first."); } decompressedStream.Seek(0, SeekOrigin.Begin); reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice); } else { reader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice); } ContentTypeReaderManager typeManager = new ContentTypeReaderManager(reader); reader.TypeReaders = typeManager.LoadAssetReaders(reader); foreach (ContentTypeReader r in reader.TypeReaders) { r.Initialize(typeManager); } // we need to read a byte here for things to work out, not sure why reader.ReadByte(); // Get the 1-based index of the typereader we should use to start decoding with int index = reader.ReadByte(); ContentTypeReader contentReader = reader.TypeReaders[index - 1]; result = reader.ReadObject <T>(contentReader); reader.Close(); stream.Close(); } else { if ((typeof(T) == typeof(Texture2D))) { result = Texture2D.FromFile(graphicsDeviceService.GraphicsDevice, assetName); } if ((typeof(T) == typeof(SpriteFont))) { //result = new SpriteFont(Texture2D.FromFile(graphicsDeviceService.GraphicsDevice,assetName), null, null, null, 0, 0.0f, null, null); throw new NotImplementedException(); } if ((typeof(T) == typeof(Song))) { result = new Song(assetName); } if ((typeof(T) == typeof(SoundEffect))) { result = new SoundEffect(assetName); } if ((typeof(T) == typeof(Video))) { result = new Video(assetName); } if ((typeof(T) == typeof(Effect))) { result = new Effect(graphicsDeviceService.GraphicsDevice, assetName); } } if (result == null) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } return((T)result); }
protected T ReadAsset <T>(string assetName, Action <IDisposable> recordDisposableObject, int lod = 0) { if (string.IsNullOrEmpty(assetName)) { throw new ArgumentNullException("assetName"); } if (disposed) { throw new ObjectDisposedException("ContentManager"); } //GC.GetTotalMemory(true); //Process currentProcess = System.Diagnostics.Process.GetCurrentProcess(); //long memstart = currentProcess.WorkingSet64; string originalAssetName = assetName; object result = null; if (this.graphicsDeviceService == null) { this.graphicsDeviceService = serviceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService; if (this.graphicsDeviceService == null) { throw new InvalidOperationException("No Graphics Device Service"); } } // Replace Windows path separators with local path separators assetName = GetRealFilename <T>(assetName); if (string.IsNullOrEmpty(assetName)) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } if (!Path.HasExtension(assetName)) { assetName = string.Format("{0}.xnb", assetName); } if (Path.GetExtension(assetName).ToLower() == ".xnb") { // Load a XNB file using (Stream stream = OpenStream(assetName)) { using (BinaryReader xnbReader = new BinaryReader(stream)) { // The first 4 bytes should be the "XNB" header. i use that to detect an invalid file byte[] headerBuffer = new byte[3]; xnbReader.Read(headerBuffer, 0, 3); string headerString = Encoding.UTF8.GetString(headerBuffer, 0, 3); byte platform = xnbReader.ReadByte(); if (string.Compare(headerString, "XNB") != 0 || !(platform == 'w' || platform == 'x' || platform == 'm')) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } ushort version = xnbReader.ReadUInt16(); int graphicsProfile = version & 0x7f00; version &= 0x80ff; bool compressed = false; if (version == 0x8005 || version == 0x8004) { compressed = true; } else if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressed) { //decompress the xnb //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) int compressedSize = xnbLength - 14; int decompressedSize = xnbReader.ReadInt32(); int newFileSize = decompressedSize + 10; MemoryStream decompressedStream = new MemoryStream(decompressedSize); LzxDecoder dec = new LzxDecoder(16); int decodedBytes = 0; int pos = 0; while (pos < compressedSize) { // let's seek to the correct position stream.Seek(pos + 14, SeekOrigin.Begin); int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else { pos += 2; } if (block_size == 0 || frame_size == 0) { break; } int lzxRet = dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; decodedBytes += frame_size; } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + "failed. " + " Try decompressing with nativeDecompressXnb first."); } decompressedStream.Seek(0, SeekOrigin.Begin); reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice); } else { reader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice); } using (reader) { ContentTypeReaderManager typeManager = new ContentTypeReaderManager(reader); reader.TypeReaders = typeManager.LoadAssetReaders(reader); foreach (ContentTypeReader r in reader.TypeReaders) { r.Initialize(typeManager); } // we need to read a byte here for things to work out, not sure why reader.ReadByte(); // Get the 1-based index of the typereader we should use to start decoding with int index = reader.ReadByte(); ContentTypeReader contentReader = reader.TypeReaders[index - 1]; result = reader.ReadObject <T>(contentReader); } } } } else { if ((typeof(T) == typeof(Texture2D))) { using (Stream assetStream = OpenStream(assetName)) { Texture2D texture = Texture2D.FromFile(graphicsDeviceService.GraphicsDevice, assetStream, lod); texture.Name = originalAssetName; result = texture; } } else if ((typeof(T) == typeof(SpriteFont))) { //result = new SpriteFont(Texture2D.FromFile(graphicsDeviceService.GraphicsDevice,assetName), null, null, null, 0, 0.0f, null, null); throw new NotImplementedException(); } else if ((typeof(T) == typeof(Song))) { result = new Song(assetName); } else if ((typeof(T) == typeof(SoundEffect))) { result = new SoundEffect(assetName); } else if ((typeof(T) == typeof(Video))) { result = new Video(assetName); } else if ((typeof(T) == typeof(Effect))) { result = new Effect(graphicsDeviceService.GraphicsDevice, assetName); } } if (result == null) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } // Store references to the asset for later use T asset = (T)result; if (asset is IDisposable) { if (recordDisposableObject != null) { recordDisposableObject(asset as IDisposable); } else { disposableAssets.Add(asset as IDisposable); } } loadedAssets.Add(originalAssetName, asset); //GC.GetTotalMemory(true); //var memend = currentProcess.WorkingSet64; //Console.WriteLine("mem: " + assetName + ", " + (memend -memstart).ToString()); return((T)result); }
protected T ReadAsset<T>(string assetName, Action<IDisposable> recordDisposableObject) { if (string.IsNullOrEmpty(assetName)) { throw new ArgumentNullException("assetName"); } if (disposed) { throw new ObjectDisposedException("ContentManager"); } string originalAssetName = assetName; object result = null; if (this.graphicsDeviceService == null) { this.graphicsDeviceService = serviceProvider.GetService(typeof(IGraphicsDeviceService)) as IGraphicsDeviceService; if (this.graphicsDeviceService == null) { throw new InvalidOperationException("No Graphics Device Service"); } } // Replace Windows path separators with local path separators assetName = GetFilename(assetName); // Get the real file name if ((typeof(T) == typeof(Curve))) { assetName = CurveReader.Normalize(assetName); } else if ((typeof(T) == typeof(Texture2D))) { assetName = Texture2DReader.Normalize(assetName); } else if ((typeof(T) == typeof(SpriteFont))) { assetName = SpriteFontReader.Normalize(assetName); } else if ((typeof(T) == typeof(Effect))) { assetName = Effect.Normalize(assetName); } else if ((typeof(T) == typeof(Song))) { assetName = SongReader.Normalize(assetName); } else if ((typeof(T) == typeof(SoundEffect))) { assetName = SoundEffectReader.Normalize(assetName); } else if ((typeof(T) == typeof(Video))) { assetName = Video.Normalize(assetName); } if (string.IsNullOrEmpty(assetName)) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } if (!Path.HasExtension(assetName)) assetName = string.Format("{0}.xnb", assetName); if (Path.GetExtension(assetName).ToLower() == ".xnb") { // Load a XNB file Stream stream = OpenStream(assetName); try { using (BinaryReader xnbReader = new BinaryReader(stream)) { // The first 4 bytes should be the "XNB" header. i use that to detect an invalid file byte x = xnbReader.ReadByte(); byte n = xnbReader.ReadByte(); byte b = xnbReader.ReadByte(); byte platform = xnbReader.ReadByte(); if (x != 'X' || n != 'N' || b != 'B' || !(platform == 'w' || platform == 'x' || platform == 'm')) { throw new ContentLoadException("Asset does not appear to be a valid XNB file. Did you process your content for Windows?"); } byte version = xnbReader.ReadByte(); byte flags = xnbReader.ReadByte(); bool compressed = (flags & 0x80) != 0; if (version != 5 && version != 4) { throw new ContentLoadException("Invalid XNB version"); } // The next int32 is the length of the XNB file int xnbLength = xnbReader.ReadInt32(); ContentReader reader; if (compressed) { LzxDecoder dec = new LzxDecoder(16); //decompress the xnb //thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor) int compressedSize = xnbLength - 14; int decompressedSize = xnbReader.ReadInt32(); int newFileSize = decompressedSize + 10; MemoryStream decompressedStream = new MemoryStream(decompressedSize); int decodedBytes = 0; int pos = 0; #if ANDROID // Android native stream does not support the Position property. LzxDecoder.Decompress also uses // Seek. So we read the entirity of the stream into a memory stream and replace stream with the // memory stream. MemoryStream memStream = new MemoryStream(); stream.CopyTo(memStream); memStream.Seek(0, SeekOrigin.Begin); stream.Dispose(); stream = memStream; pos = -14; #endif while (pos < compressedSize) { // let's seek to the correct position // The stream should already be in the correct position, and seeking can be slow stream.Seek(pos + 14, SeekOrigin.Begin); int hi = stream.ReadByte(); int lo = stream.ReadByte(); int block_size = (hi << 8) | lo; int frame_size = 0x8000; if (hi == 0xFF) { hi = lo; lo = (byte)stream.ReadByte(); frame_size = (hi << 8) | lo; hi = (byte)stream.ReadByte(); lo = (byte)stream.ReadByte(); block_size = (hi << 8) | lo; pos += 5; } else pos += 2; if (block_size == 0 || frame_size == 0) break; int lzxRet = dec.Decompress(stream, block_size, decompressedStream, frame_size); pos += block_size; decodedBytes += frame_size; } if (decompressedStream.Position != decompressedSize) { throw new ContentLoadException("Decompression of " + originalAssetName + "failed. " + " Try decompressing with nativeDecompressXnb first."); } decompressedStream.Seek(0, SeekOrigin.Begin); reader = new ContentReader(this, decompressedStream, this.graphicsDeviceService.GraphicsDevice, originalAssetName); } else { reader = new ContentReader(this, stream, this.graphicsDeviceService.GraphicsDevice, originalAssetName); } using (reader) { result = reader.ReadAsset<T>(); } } } finally { if (stream != null) { stream.Dispose(); } } } else { if ((typeof(T) == typeof(Texture2D))) { #if IPHONE Texture2D texture = Texture2D.FromFile(graphicsDeviceService.GraphicsDevice, assetName); texture.Name = originalAssetName; result = texture; #else using (Stream assetStream = OpenStream(assetName)) { Texture2D texture = Texture2D.FromFile(graphicsDeviceService.GraphicsDevice, assetStream); texture.Name = originalAssetName; result = texture; } #endif } else if ((typeof(T) == typeof(SpriteFont))) { //result = new SpriteFont(Texture2D.FromFile(graphicsDeviceService.GraphicsDevice,assetName), null, null, null, 0, 0.0f, null, null); throw new NotImplementedException(); } else if ((typeof(T) == typeof(Song))) { result = new Song(assetName); } else if ((typeof(T) == typeof(SoundEffect))) { result = new SoundEffect(assetName); } else if ((typeof(T) == typeof(Video))) { result = new Video(assetName); } else if ((typeof(T) == typeof(Effect))) { result = new Effect(graphicsDeviceService.GraphicsDevice, assetName); } } if (result == null) { throw new ContentLoadException("Could not load " + originalAssetName + " asset!"); } if ( recordDisposableObject != null && result is IDisposable ) recordDisposableObject(result as IDisposable); return (T)result; }