@@ -380,7 +380,7 @@ public bool Unpack(AssetsFileReader reader, AssetsFileWriter writer)
380380 }
381381 return false ;
382382 }
383- public bool Pack ( AssetsFileReader reader , AssetsFileWriter writer , AssetBundleCompressionType compType )
383+ public bool Pack ( AssetsFileReader reader , AssetsFileWriter writer , AssetBundleCompressionType compType , bool blockDirAtEnd = true )
384384 {
385385 reader . Position = 0 ;
386386 writer . Position = 0 ;
@@ -395,7 +395,7 @@ public bool Pack(AssetsFileReader reader, AssetsFileWriter writer, AssetBundleCo
395395 totalFileSize = 0 ,
396396 compressedSize = 0 ,
397397 decompressedSize = 0 ,
398- flags = 0x43
398+ flags = ( uint ) ( 0x43 | ( blockDirAtEnd ? 0x80 : 0x00 ) )
399399 } ;
400400
401401 AssetBundleBlockAndDirectoryList06 newBlockAndDirList = new AssetBundleBlockAndDirectoryList06 ( )
@@ -408,128 +408,164 @@ public bool Pack(AssetsFileReader reader, AssetsFileWriter writer, AssetBundleCo
408408 dirInf = bundleInf6 . dirInf
409409 } ;
410410
411+ //write header now and overwrite it later
412+ long startPos = writer . Position ;
413+
414+ newHeader . Write ( writer ) ;
415+ if ( newHeader . fileVersion >= 7 )
416+ writer . Align16 ( ) ;
417+
418+ int headerSize = ( int ) ( writer . Position - startPos ) ;
419+
420+ long totalCompressedSize = 0 ;
411421 List < AssetBundleBlockInfo06 > newBlocks = new List < AssetBundleBlockInfo06 > ( ) ;
422+ List < Stream > newStreams = new List < Stream > ( ) ; //used if blockDirAtEnd == false
412423
413- reader . Position = bundleHeader6 . GetFileDataOffset ( ) ;
414- int fileDataLength = ( int ) ( bundleHeader6 . totalFileSize - reader . Position ) ;
415- byte [ ] fileData = reader . ReadBytes ( fileDataLength ) ;
424+ long fileDataOffset = bundleHeader6 . GetFileDataOffset ( ) ;
425+ int fileDataLength = ( int ) ( bundleHeader6 . totalFileSize - fileDataOffset ) ;
426+
427+ SegmentStream bundleDataStream = new SegmentStream ( reader . BaseStream , fileDataOffset , fileDataLength ) ;
416428
417- //todo, we just write everything to memory and then write to file
418- //we could calculate the blocks we need ahead of time and correctly
419- //size the block listing before this so we can write directly to file
420- byte [ ] compressedFileData ;
421429 switch ( compType )
422430 {
423431 case AssetBundleCompressionType . LZMA :
424432 {
425- compressedFileData = SevenZipHelper . Compress ( fileData ) ;
426- newBlocks . Add ( new AssetBundleBlockInfo06 ( )
433+ Stream writeStream ;
434+ if ( blockDirAtEnd )
435+ writeStream = writer . BaseStream ;
436+ else
437+ writeStream = GetTempFileStream ( ) ;
438+
439+ long writeStreamStart = writeStream . Position ;
440+ SevenZipHelper . Compress ( bundleDataStream , writeStream ) ;
441+ uint writeStreamLength = ( uint ) ( writeStream . Position - writeStreamStart ) ;
442+
443+ AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06 ( )
427444 {
428- compressedSize = ( uint ) compressedFileData . Length ,
429- decompressedSize = ( uint ) fileData . Length ,
445+ compressedSize = writeStreamLength ,
446+ decompressedSize = ( uint ) fileDataLength ,
430447 flags = 0x41
431- } ) ;
448+ } ;
449+
450+ totalCompressedSize += blockInfo . compressedSize ;
451+ newBlocks . Add ( blockInfo ) ;
452+
453+ if ( blockDirAtEnd )
454+ bundleDataStream . CopyToCompat ( writer . BaseStream ) ;
455+ else
456+ newStreams . Add ( writeStream ) ;
457+
432458 break ;
433459 }
434460 case AssetBundleCompressionType . LZ4 :
435461 {
436- using ( var memStreamCom = new MemoryStream ( ) )
437- using ( var binaryWriter = new BinaryWriter ( memStreamCom ) )
462+ //compress into 0x20000 blocks
463+ BinaryReader bundleDataReader = new BinaryReader ( bundleDataStream ) ;
464+ byte [ ] uncompressedBlock = bundleDataReader . ReadBytes ( 0x20000 ) ;
465+ while ( uncompressedBlock . Length != 0 )
438466 {
439- using ( var memStreamUnc = new MemoryStream ( fileData ) )
440- using ( var binaryReader = new BinaryReader ( memStreamUnc ) )
467+ Stream writeStream ;
468+ if ( blockDirAtEnd )
469+ writeStream = writer . BaseStream ;
470+ else
471+ writeStream = GetTempFileStream ( ) ;
472+
473+ byte [ ] compressedBlock = LZ4Codec . Encode32HC ( uncompressedBlock , 0 , uncompressedBlock . Length ) ;
474+ writeStream . Write ( compressedBlock , 0 , compressedBlock . Length ) ;
475+
476+ if ( compressedBlock . Length > uncompressedBlock . Length )
441477 {
442- //compress into 0x20000 blocks
443- byte [ ] uncompressedBlock = binaryReader . ReadBytes ( 131072 ) ;
444- while ( uncompressedBlock . Length != 0 )
478+ AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06 ( )
445479 {
446- byte [ ] compressedBlock = LZ4Codec . Encode32HC ( uncompressedBlock , 0 , uncompressedBlock . Length ) ;
447-
448- if ( compressedBlock . Length > uncompressedBlock . Length )
449- {
450- newBlocks . Add ( new AssetBundleBlockInfo06 ( )
451- {
452- compressedSize = ( uint ) uncompressedBlock . Length ,
453- decompressedSize = ( uint ) uncompressedBlock . Length ,
454- flags = 0x0
455- } ) ;
456- binaryWriter . Write ( uncompressedBlock ) ;
457- }
458- else
459- {
460- newBlocks . Add ( new AssetBundleBlockInfo06 ( )
461- {
462- compressedSize = ( uint ) compressedBlock . Length ,
463- decompressedSize = ( uint ) uncompressedBlock . Length ,
464- flags = 0x3
465- } ) ;
466- binaryWriter . Write ( compressedBlock ) ;
467- }
468-
469- uncompressedBlock = binaryReader . ReadBytes ( 131072 ) ;
470- }
480+ compressedSize = ( uint ) uncompressedBlock . Length ,
481+ decompressedSize = ( uint ) uncompressedBlock . Length ,
482+ flags = 0x0
483+ } ;
484+
485+ totalCompressedSize += blockInfo . compressedSize ;
486+
487+ newBlocks . Add ( blockInfo ) ;
471488 }
489+ else
490+ {
491+ AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06 ( )
492+ {
493+ compressedSize = ( uint ) compressedBlock . Length ,
494+ decompressedSize = ( uint ) uncompressedBlock . Length ,
495+ flags = 0x3
496+ } ;
497+
498+ totalCompressedSize += blockInfo . compressedSize ;
499+
500+ newBlocks . Add ( blockInfo ) ;
501+ }
502+
503+ if ( blockDirAtEnd )
504+ bundleDataStream . CopyToCompat ( writer . BaseStream ) ;
505+ else
506+ newStreams . Add ( writeStream ) ;
472507
473- compressedFileData = memStreamCom . ToArray ( ) ;
508+ uncompressedBlock = bundleDataReader . ReadBytes ( 0x20000 ) ;
474509 }
475510 break ;
476511 }
477512 case AssetBundleCompressionType . NONE :
478513 {
479- compressedFileData = fileData ;
480- newBlocks . Add ( new AssetBundleBlockInfo06 ( )
514+ AssetBundleBlockInfo06 blockInfo = new AssetBundleBlockInfo06 ( )
481515 {
482- compressedSize = ( uint ) fileData . Length ,
483- decompressedSize = ( uint ) fileData . Length ,
516+ compressedSize = ( uint ) fileDataLength ,
517+ decompressedSize = ( uint ) fileDataLength ,
484518 flags = 0x00
485- } ) ;
519+ } ;
520+
521+ totalCompressedSize += blockInfo . compressedSize ;
522+
523+ newBlocks . Add ( blockInfo ) ;
524+
525+ if ( blockDirAtEnd )
526+ bundleDataStream . CopyToCompat ( writer . BaseStream ) ;
527+ else
528+ newStreams . Add ( bundleDataStream ) ;
529+
486530 break ;
487531 }
488- default :
489- {
490- return false ;
491- }
492532 }
493533
494534 newBlockAndDirList . blockInf = newBlocks . ToArray ( ) ;
495535
496536 byte [ ] bundleInfoBytes ;
497- using ( var memStream = new MemoryStream ( ) )
537+ using ( MemoryStream memStream = new MemoryStream ( ) )
498538 {
499- var afw = new AssetsFileWriter ( memStream ) ;
500- newBlockAndDirList . Write ( afw ) ;
539+ AssetsFileWriter infoWriter = new AssetsFileWriter ( memStream ) ;
540+ newBlockAndDirList . Write ( infoWriter ) ;
501541 bundleInfoBytes = memStream . ToArray ( ) ;
502542 }
503543
504- if ( bundleInfoBytes == null || bundleInfoBytes . Length == 0 )
505- return false ;
506-
507544 //listing is usually lz4 even if the data blocks are lzma
508545 byte [ ] bundleInfoBytesCom = LZ4Codec . Encode32HC ( bundleInfoBytes , 0 , bundleInfoBytes . Length ) ;
509546
510- byte [ ] bundleHeaderBytes = null ;
511- using ( var memStream = new MemoryStream ( ) )
512- {
513- var afw = new AssetsFileWriter ( memStream ) ;
514- newHeader . Write ( afw ) ;
515- bundleHeaderBytes = memStream . ToArray ( ) ;
516- }
517-
518- if ( bundleHeaderBytes == null || bundleHeaderBytes . Length == 0 )
519- return false ;
520-
521- uint totalFileSize = ( uint ) ( bundleHeaderBytes . Length + bundleInfoBytesCom . Length + compressedFileData . Length ) ;
547+ uint totalFileSize = ( uint ) ( headerSize + bundleInfoBytesCom . Length + totalCompressedSize ) ;
522548 newHeader . totalFileSize = totalFileSize ;
523549 newHeader . decompressedSize = ( uint ) bundleInfoBytes . Length ;
524550 newHeader . compressedSize = ( uint ) bundleInfoBytesCom . Length ;
525551
552+ writer . Write ( bundleInfoBytesCom ) ;
553+
554+ if ( ! blockDirAtEnd )
555+ {
556+ foreach ( Stream newStream in newStreams )
557+ {
558+ newStream . Position = 0 ;
559+ newStream . CopyToCompat ( writer . BaseStream ) ;
560+ newStream . Close ( ) ;
561+ }
562+ }
563+
564+ writer . Position = 0 ;
526565 newHeader . Write ( writer ) ;
527566 if ( newHeader . fileVersion >= 7 )
528567 writer . Align16 ( ) ;
529568
530- writer . Write ( bundleInfoBytesCom ) ;
531- writer . Write ( compressedFileData ) ;
532-
533569 return true ;
534570 }
535571 return false ;
@@ -614,6 +650,13 @@ internal void GetFileRange(int index, out long offset, out long length)
614650 throw new NotSupportedException ( ) ;
615651 }
616652 }
653+
654+ private FileStream GetTempFileStream ( )
655+ {
656+ string tempFilePath = Path . GetTempFileName ( ) ;
657+ FileStream tempFileStream = new FileStream ( tempFilePath , FileMode . OpenOrCreate , FileAccess . ReadWrite , FileShare . Read , 4096 , FileOptions . DeleteOnClose ) ;
658+ return tempFileStream ;
659+ }
617660 }
618661
619662 public enum AssetBundleCompressionType
0 commit comments