@@ -23,6 +23,9 @@ namespace Microsoft.Xna.Framework.Content
2323{
2424 public partial class ContentManager : IDisposable
2525 {
26+ const byte ContentCompressedLzx = 0x80 ;
27+ const byte ContentCompressedLz4 = 0x40 ;
28+
2629 #region Public ServiceProvider Property
2730
2831 public IServiceProvider ServiceProvider
@@ -463,99 +466,31 @@ private ContentReader GetContentReaderFromXnb(string originalAssetName, ref Stre
463466 {
464467 byte version = xnbReader . ReadByte ( ) ;
465468 byte flags = xnbReader . ReadByte ( ) ;
466- bool compressed = ( flags & 0x80 ) != 0 ;
469+
470+ bool compressedLzx = ( flags & ContentCompressedLzx ) != 0 ;
471+ bool compressedLz4 = ( flags & ContentCompressedLz4 ) != 0 ;
467472 if ( version != 5 && version != 4 )
468473 {
469474 throw new ContentLoadException ( "Invalid XNB version" ) ;
470475 }
471476 // The next int32 is the length of the XNB file
472477 int xnbLength = xnbReader . ReadInt32 ( ) ;
473478 ContentReader reader ;
474- if ( compressed )
479+ if ( compressedLzx || compressedLz4 )
475480 {
476- /* Decompress the XNB
477- * Thanks to ShinAli (https://bitbucket.org/alisci01/xnbdecompressor)
478- */
479- int compressedSize = xnbLength - 14 ;
481+ // Decompress the xnb
480482 int decompressedSize = xnbReader . ReadInt32 ( ) ;
481483
482- // This will replace the XNB stream at the end
483- MemoryStream decompressedStream = new MemoryStream (
484- new byte [ decompressedSize ] ,
485- 0 ,
486- decompressedSize ,
487- true ,
488- true // This MUST be true! Readers may need GetBuffer()!
489- ) ;
490-
491- /* Read in the whole XNB file at once, into a temp buffer.
492- * For slow disks, the extra malloc is more than worth the
493- * performance improvement from not constantly fread()ing!
494- */
495- MemoryStream compressedStream = new MemoryStream (
496- new byte [ compressedSize ] ,
497- 0 ,
498- compressedSize ,
499- true ,
500- true
501- ) ;
502- stream . Read ( compressedStream . GetBuffer ( ) , 0 , compressedSize ) ;
503-
504- // Default window size for XNB encoded files is 64Kb (need 16 bits to represent it)
505- LzxDecoder dec = new LzxDecoder ( 16 ) ;
506- int decodedBytes = 0 ;
507- long pos = 0 ;
508-
509- while ( pos < compressedSize )
484+ Stream decompressedStream = null ;
485+ if ( compressedLzx )
510486 {
511- /* The compressed stream is separated into blocks that will
512- * decompress into 32kB or some other size if specified.
513- * Normal, 32kB output blocks will have a short indicating
514- * the size of the block before the block starts. Blocks
515- * that have a defined output will be preceded by a byte of
516- * value 0xFF (255), then a short indicating the output size
517- * and another for the block size. All shorts for these
518- * cases are encoded in big endian order.
519- */
520- int hi = compressedStream . ReadByte ( ) ;
521- int lo = compressedStream . ReadByte ( ) ;
522- int block_size = ( hi << 8 ) | lo ;
523- int frame_size = 0x8000 ; // Frame size is 32kB by default
524- // Does this block define a frame size?
525- if ( hi == 0xFF )
526- {
527- hi = lo ;
528- lo = ( byte ) compressedStream . ReadByte ( ) ;
529- frame_size = ( hi << 8 ) | lo ;
530- hi = ( byte ) compressedStream . ReadByte ( ) ;
531- lo = ( byte ) compressedStream . ReadByte ( ) ;
532- block_size = ( hi << 8 ) | lo ;
533- pos += 5 ;
534- }
535- else
536- {
537- pos += 2 ;
538- }
539- // Either says there is nothing to decode
540- if ( block_size == 0 || frame_size == 0 )
541- {
542- break ;
543- }
544- dec . Decompress ( compressedStream , block_size , decompressedStream , frame_size ) ;
545- pos += block_size ;
546- decodedBytes += frame_size ;
547- /* Reset the position of the input just in case the bit
548- * buffer read in some unused bytes.
549- */
550- compressedStream . Seek ( pos , SeekOrigin . Begin ) ;
487+ int compressedSize = xnbLength - 14 ;
488+ decompressedStream = new LzxDecoderStream ( stream , decompressedSize , compressedSize ) ;
551489 }
552- if ( decompressedStream . Position != decompressedSize )
490+ else if ( compressedLz4 )
553491 {
554- throw new ContentLoadException (
555- "Decompression of " + originalAssetName + " failed. "
556- ) ;
492+ decompressedStream = new Lz4DecoderStream ( stream ) ;
557493 }
558- decompressedStream . Seek ( 0 , SeekOrigin . Begin ) ;
559494 reader = new ContentReader (
560495 this ,
561496 decompressedStream ,
@@ -599,13 +534,13 @@ private Stream CheckRawExtensions(string assetName, string[] extensions)
599534 }
600535 }
601536
602- // If we got here, we need to try the slower path :(
537+ // If we got here, we need to try the slower path :(. We load android raw assets here :)
603538 fileName = MonoGame . Utilities . FileHelpers . NormalizeFilePathSeparators (
604- assetName
539+ Path . Combine ( RootDirectory , assetName )
605540 ) ;
606541 try
607542 {
608- return OpenStream ( fileName ) ;
543+ return TitleContainer . OpenStream ( fileName ) ;
609544 }
610545 catch
611546 {
@@ -615,7 +550,7 @@ private Stream CheckRawExtensions(string assetName, string[] extensions)
615550 string fileNamePlusExt = fileName + ext ;
616551 try
617552 {
618- return OpenStream ( fileNamePlusExt ) ;
553+ return TitleContainer . OpenStream ( fileNamePlusExt ) ;
619554 }
620555 catch
621556 {
@@ -708,4 +643,4 @@ private static void RemoveContentManager(ContentManager contentManager)
708643
709644 #endregion
710645 }
711- }
646+ }
0 commit comments