@@ -275,6 +275,169 @@ IResourceBlock takeBestBlock(long maxSize, HashSet<IResourceBlock> blockset)
275
275
pageCount = ( int ) currentPageCount ;
276
276
}
277
277
278
+ public static void AssignPositions ( IList < IResourceBlock > blocks , uint basePosition , out RpfResourcePageFlags pageFlags )
279
+ {
280
+ var sys = ( basePosition == 0x50000000 ) ;
281
+
282
+ IResourceBlock getRootBlock ( )
283
+ {
284
+ if ( sys && ( blocks . Count > 0 ) )
285
+ {
286
+ return blocks [ 0 ] ;
287
+ }
288
+ return null ;
289
+ }
290
+ HashSet < IResourceBlock > getBlockSet ( )
291
+ {
292
+ var blockset = new HashSet < IResourceBlock > ( ) ;
293
+ int start = sys ? 1 : 0 ;
294
+ for ( int i = start ; i < blocks . Count ; i ++ )
295
+ {
296
+ blockset . Add ( blocks [ i ] ) ;
297
+ }
298
+ return blockset ;
299
+ }
300
+ IResourceBlock findBestBlock ( long maxSize , HashSet < IResourceBlock > blockset )
301
+ {
302
+ if ( maxSize <= 0 ) return null ;
303
+ IResourceBlock r = null ;
304
+ long rlen = 0 ;
305
+ foreach ( var block in blockset )
306
+ {
307
+ var blockLength = block . BlockLength ;
308
+ if ( ( blockLength <= maxSize ) && ( blockLength > rlen ) )
309
+ {
310
+ r = block ;
311
+ rlen = blockLength ;
312
+ }
313
+ }
314
+ return r ;
315
+ }
316
+ IResourceBlock takeBestBlock ( long maxSize , HashSet < IResourceBlock > blockset )
317
+ {
318
+ var r = findBestBlock ( maxSize , blockset ) ;
319
+ if ( r != null )
320
+ {
321
+ blockset . Remove ( r ) ;
322
+ }
323
+ return r ;
324
+ }
325
+ long pad ( long p )
326
+ {
327
+ return ( ( ALIGN_SIZE - ( p % ALIGN_SIZE ) ) % ALIGN_SIZE ) ;
328
+ }
329
+
330
+
331
+ long largestBlockSize = 0 ; // find largest structure
332
+ long startPageSize = BASE_SIZE ; // 0x2000; // find starting page size
333
+ long totalBlockSize = 0 ;
334
+ foreach ( var block in blocks )
335
+ {
336
+ var blockLength = block . BlockLength ;
337
+ totalBlockSize += blockLength ;
338
+ totalBlockSize += pad ( totalBlockSize ) ;
339
+ if ( largestBlockSize < blockLength )
340
+ {
341
+ largestBlockSize = blockLength ;
342
+ }
343
+ }
344
+ while ( startPageSize < largestBlockSize )
345
+ {
346
+ startPageSize *= 2 ;
347
+ }
348
+
349
+
350
+ pageFlags = new RpfResourcePageFlags ( ) ;
351
+
352
+ while ( true )
353
+ {
354
+ if ( blocks . Count == 0 ) break ;
355
+
356
+ var currentPosition = 0L ;
357
+ var currentPageSize = startPageSize ;
358
+ var currentPageStart = 0L ;
359
+ var currentPageSpace = startPageSize ;
360
+ var currentRemainder = totalBlockSize ;
361
+ var rootblock = getRootBlock ( ) ;
362
+ var blockset = getBlockSet ( ) ;
363
+
364
+ var pageCount = 1 ;
365
+ var pageCounts = new uint [ 9 ] ;
366
+ var pageCountIndex = 0 ;
367
+ var targetPageSize = Math . Max ( 65536 , startPageSize >> 5 ) ;
368
+ var minPageSize = Math . Max ( 512 , Math . Min ( targetPageSize , startPageSize ) >> 4 ) ;
369
+ var baseShift = 0u ;
370
+ var baseSize = 512 ;
371
+ while ( baseSize < minPageSize )
372
+ {
373
+ baseShift ++ ;
374
+ baseSize *= 2 ;
375
+ if ( baseShift >= 0xF ) break ;
376
+ }
377
+ var baseSizeMax = baseSize << 8 ;
378
+ var baseSizeMaxTest = startPageSize ;
379
+ while ( baseSizeMaxTest < baseSizeMax )
380
+ {
381
+ pageCountIndex ++ ;
382
+ baseSizeMaxTest *= 2 ;
383
+ }
384
+ pageCounts [ pageCountIndex ] = 1 ;
385
+
386
+ while ( true )
387
+ {
388
+ var isroot = sys && ( currentPosition == 0 ) ;
389
+ var block = isroot ? rootblock : takeBestBlock ( currentPageSpace , blockset ) ;
390
+ var blockLength = block ? . BlockLength ?? 0 ;
391
+ if ( block != null )
392
+ {
393
+ //add this block to the current page.
394
+ block . FilePosition = basePosition + currentPosition ;
395
+ var opos = currentPosition ;
396
+ currentPosition += blockLength ;
397
+ currentPosition += pad ( currentPosition ) ;
398
+ var usedspace = currentPosition - opos ;
399
+ currentPageSpace -= usedspace ;
400
+ currentRemainder -= usedspace ; //blockLength;//
401
+
402
+ }
403
+ else if ( blockset . Count > 0 )
404
+ {
405
+ //allocate a new page
406
+ currentPageStart += currentPageSize ;
407
+ currentPosition = currentPageStart ;
408
+ block = findBestBlock ( long . MaxValue , blockset ) ; //just find the biggest block
409
+ blockLength = block ? . BlockLength ?? 0 ;
410
+ while ( blockLength <= ( currentPageSize >> 1 ) ) //determine best new page size
411
+ {
412
+ if ( currentPageSize <= minPageSize ) break ;
413
+ if ( pageCountIndex >= 8 ) break ;
414
+ if ( ( currentPageSize <= targetPageSize ) && ( currentRemainder >= ( currentPageSize - minPageSize ) ) ) break ;
415
+
416
+ currentPageSize = currentPageSize >> 1 ;
417
+ pageCountIndex ++ ;
418
+ }
419
+ currentPageSpace = currentPageSize ;
420
+ pageCounts [ pageCountIndex ] ++ ;
421
+ pageCount ++ ;
422
+ }
423
+ else
424
+ {
425
+ break ;
426
+ }
427
+ }
428
+
429
+
430
+ pageFlags = new RpfResourcePageFlags ( pageCounts , baseShift ) ;
431
+
432
+ if ( ( pageCount == pageFlags . Count ) && ( pageFlags . Size >= currentPosition ) ) //make sure page counts fit in the flags value
433
+ {
434
+ break ;
435
+ }
436
+
437
+ startPageSize *= 2 ;
438
+ }
439
+
440
+ }
278
441
279
442
280
443
public static byte [ ] Build ( ResourceFileBase fileBase , int version , bool compress = true )
@@ -286,22 +449,29 @@ public static byte[] Build(ResourceFileBase fileBase, int version, bool compress
286
449
IList < IResourceBlock > graphicBlocks ;
287
450
GetBlocks ( fileBase , out systemBlocks , out graphicBlocks ) ;
288
451
289
- int systemPageSize = BASE_SIZE ; // *4;
290
- int systemPageCount ;
291
- AssignPositions ( systemBlocks , 0x50000000 , ref systemPageSize , out systemPageCount ) ;
452
+ //int systemPageSize = BASE_SIZE;// *4;
453
+ //int systemPageCount;
454
+ //AssignPositions(systemBlocks, 0x50000000, ref systemPageSize, out systemPageCount);
455
+
456
+ //int graphicsPageSize = BASE_SIZE;
457
+ //int graphicsPageCount;
458
+ //AssignPositions(graphicBlocks, 0x60000000, ref graphicsPageSize, out graphicsPageCount);
292
459
293
- int graphicsPageSize = BASE_SIZE ;
294
- int graphicsPageCount ;
295
- AssignPositions ( graphicBlocks , 0x60000000 , ref graphicsPageSize , out graphicsPageCount ) ;
460
+
461
+ RpfResourcePageFlags systemPageFlags ;
462
+ AssignPositions ( systemBlocks , 0x50000000 , out systemPageFlags ) ;
463
+
464
+ RpfResourcePageFlags graphicsPageFlags ;
465
+ AssignPositions ( graphicBlocks , 0x60000000 , out graphicsPageFlags ) ;
296
466
297
467
298
468
299
469
300
470
//fileBase.FilePagesInfo.SystemPagesCount = 0;
301
471
//if (systemPageCount > 0)
302
472
// fileBase.FilePagesInfo.SystemPagesCount = 1; // (byte)systemPageCount; //1
303
- fileBase . FilePagesInfo . SystemPagesCount = ( byte ) systemPageCount ;
304
- fileBase . FilePagesInfo . GraphicsPagesCount = ( byte ) graphicsPageCount ;
473
+ fileBase . FilePagesInfo . SystemPagesCount = ( byte ) systemPageFlags . Count ; // systemPageCount;
474
+ fileBase . FilePagesInfo . GraphicsPagesCount = ( byte ) graphicsPageFlags . Count ; // graphicsPageCount;
305
475
306
476
307
477
@@ -342,14 +512,14 @@ public static byte[] Build(ResourceFileBase fileBase, int version, bool compress
342
512
343
513
344
514
345
- var sysDataSize = systemPageCount * systemPageSize ;
515
+ var sysDataSize = ( int ) systemPageFlags . Size ; // systemPageCount * systemPageSize;
346
516
var sysData = new byte [ sysDataSize ] ;
347
517
systemStream . Flush ( ) ;
348
518
systemStream . Position = 0 ;
349
519
systemStream . Read ( sysData , 0 , ( int ) systemStream . Length ) ;
350
520
351
521
352
- var gfxDataSize = graphicsPageCount * graphicsPageSize ;
522
+ var gfxDataSize = ( int ) graphicsPageFlags . Size ; // graphicsPageCount * graphicsPageSize;
353
523
var gfxData = new byte [ gfxDataSize ] ;
354
524
graphicsStream . Flush ( ) ;
355
525
graphicsStream . Position = 0 ;
@@ -363,9 +533,11 @@ public static byte[] Build(ResourceFileBase fileBase, int version, bool compress
363
533
364
534
//uint sf = RpfResourceFileEntry.GetFlagsFromSize(sysDataSize, sv);
365
535
//uint gf = RpfResourceFileEntry.GetFlagsFromSize(gfxDataSize, gv); //TODO: might be broken...
536
+ //uint sf = RpfResourceFileEntry.GetFlagsFromBlocks((uint)systemPageCount, (uint)systemPageSize, sv);
537
+ //uint gf = RpfResourceFileEntry.GetFlagsFromBlocks((uint)graphicsPageCount, (uint)graphicsPageSize, gv);
538
+ uint sf = systemPageFlags . Value + ( sv << 28 ) ;
539
+ uint gf = graphicsPageFlags . Value + ( gv << 28 ) ;
366
540
367
- uint sf = RpfResourceFileEntry . GetFlagsFromBlocks ( ( uint ) systemPageCount , ( uint ) systemPageSize , sv ) ;
368
- uint gf = RpfResourceFileEntry . GetFlagsFromBlocks ( ( uint ) graphicsPageCount , ( uint ) graphicsPageSize , gv ) ;
369
541
370
542
var tdatasize = sysDataSize + gfxDataSize ;
371
543
var tdata = new byte [ tdatasize ] ;
0 commit comments