@@ -56,7 +56,7 @@ private static BinaryWriter OpenOutput(string path)
5656 //
5757 // MUL -> UOP
5858 //
59- public static void ToUop ( string inFile , string inFileIdx , string outFile , FileType type , int typeIndex , CompressionFlag compressionFlag = CompressionFlag . None , string housingBinFile = "" )
59+ public static void ToUop ( string inFile , string inFileIdx , string outFile , FileType type , int typeIndex , CompressionFlag compressionFlag = CompressionFlag . None , string housingBinFile = "" , IProgress < int > progress = null )
6060 {
6161 // Same for all UOP files
6262 const long firstTable = 0x200 ;
@@ -163,6 +163,10 @@ public static void ToUop(string inFile, string inFileIdx, string outFile, FileTy
163163
164164 string [ ] hashFormat = GetHashFormat ( type , typeIndex , out int _ ) ;
165165
166+ int totalEntries = idxEntries . Count ;
167+ int lastReportedPct = - 1 ;
168+ progress ? . Report ( 0 ) ;
169+
166170 for ( int i = 0 ; i < tableCount ; ++ i )
167171 {
168172 long thisTable = writer . BaseStream . Position ;
@@ -308,6 +312,16 @@ public static void ToUop(string inFile, string inFileIdx, string outFile, FileTy
308312 tableEntries [ tableIdx ] . Hash = HashAdler32 ( data ) ;
309313 writer . Write ( data ) ;
310314 }
315+
316+ if ( totalEntries > 0 )
317+ {
318+ int pct = ( j + 1 ) * 100 / totalEntries ;
319+ if ( pct != lastReportedPct )
320+ {
321+ lastReportedPct = pct ;
322+ progress ? . Report ( pct ) ;
323+ }
324+ }
311325 }
312326
313327 long nextTable = writer . BaseStream . Position ;
@@ -354,7 +368,7 @@ public static void ToUop(string inFile, string inFileIdx, string outFile, FileTy
354368 //
355369 // UOP -> MUL
356370 //
357- public void FromUop ( string inFile , string outFile , string outFileIdx , FileType type , int typeIndex , string housingBinFile = "" )
371+ public void FromUop ( string inFile , string outFile , string outFileIdx , FileType type , int typeIndex , string housingBinFile = "" , IProgress < int > progress = null )
358372 {
359373 Dictionary < ulong , int > chunkIds = new Dictionary < ulong , int > ( ) ;
360374 Dictionary < ulong , int > chunkIds2 = new Dictionary < ulong , int > ( ) ;
@@ -391,6 +405,11 @@ public void FromUop(string inFile, string outFile, string outFileIdx, FileType t
391405 reader . ReadInt32 ( ) ; // format timestamp? 0xFD23EC43
392406
393407 long nextTable = reader . ReadInt64 ( ) ;
408+ reader . ReadInt32 ( ) ; // table size (unused)
409+ int totalFileCount = reader . ReadInt32 ( ) ;
410+ int processedCount = 0 ;
411+ int lastReportedPct = - 1 ;
412+ progress ? . Report ( 0 ) ;
394413
395414 do
396415 {
@@ -414,7 +433,8 @@ public void FromUop(string inFile, string outFile, string outFileIdx, FileType t
414433 offsets [ i ] . DecompressedSize = reader . ReadInt32 ( ) ; // decompressed size
415434 offsets [ i ] . Identifier = reader . ReadUInt64 ( ) ; // filename hash (HashLittle2)
416435 offsets [ i ] . Hash = reader . ReadUInt32 ( ) ; // data hash (Adler32)
417- offsets [ i ] . Compressed = reader . ReadInt16 ( ) != 0 ; // compression method (0 = none, 1 = zlib)
436+ offsets [ i ] . CompressionFlag = reader . ReadInt16 ( ) ; // compression method (0 = none, 1 = zlib, 3 = mythic)
437+ offsets [ i ] . Compressed = offsets [ i ] . CompressionFlag != 0 ;
418438 }
419439
420440 // Copy chunks
@@ -452,6 +472,17 @@ public void FromUop(string inFile, string outFile, string outFileIdx, FileType t
452472 writerBin . Write ( binDataToWrite , 0 , binDataToWrite . Length ) ;
453473 }
454474
475+ if ( totalFileCount > 0 )
476+ {
477+ ++ processedCount ;
478+ int pct = processedCount * 100 / totalFileCount ;
479+ if ( pct != lastReportedPct )
480+ {
481+ lastReportedPct = pct ;
482+ progress ? . Report ( pct ) ;
483+ }
484+ }
485+
455486 continue ;
456487 }
457488
@@ -480,6 +511,11 @@ public void FromUop(string inFile, string outFile, string outFileIdx, FileType t
480511 chunkData = decompressed ;
481512 }
482513
514+ if ( offsets [ i ] . CompressionFlag == ( short ) CompressionFlag . Mythic )
515+ {
516+ chunkData = MythicDecompress . Decompress ( chunkData ) ;
517+ }
518+
483519 if ( type == FileType . MapLegacyMul )
484520 {
485521 // Write this chunk on the right position (no IDX file to point to it)
@@ -541,6 +577,17 @@ public void FromUop(string inFile, string outFile, string outFileIdx, FileType t
541577 mulWriter . Write ( chunkData , dataOffset , chunkData . Length - dataOffset ) ;
542578 }
543579 }
580+
581+ if ( totalFileCount > 0 )
582+ {
583+ ++ processedCount ;
584+ int pct = processedCount * 100 / totalFileCount ;
585+ if ( pct != lastReportedPct )
586+ {
587+ lastReportedPct = pct ;
588+ progress ? . Report ( pct ) ;
589+ }
590+ }
544591 }
545592
546593 // Move to next table
@@ -551,10 +598,22 @@ public void FromUop(string inFile, string outFile, string outFileIdx, FileType t
551598 }
552599 while ( nextTable != 0 ) ;
553600
554- // Fix index
601+ // Fix index. Only pad up to the highest used entry — `used.Length` is the hash-lookup
602+ // upper bound (often 0x7FFFF), which would otherwise produce a multi-megabyte idx file
603+ // padded with sentinel rows beyond any real entry.
555604 if ( idxWriter != null )
556605 {
557- for ( int i = 0 ; i < used . Length ; ++ i )
606+ int padCount = 0 ;
607+ for ( int i = used . Length - 1 ; i >= 0 ; -- i )
608+ {
609+ if ( used [ i ] )
610+ {
611+ padCount = i + 1 ;
612+ break ;
613+ }
614+ }
615+
616+ for ( int i = 0 ; i < padCount ; ++ i )
558617 {
559618 if ( used [ i ] )
560619 {
0 commit comments