public static void AssignPositions(IList <IResourceBlock> blocks, uint basePosition, out ResourceChunkFlags flags, uint usedPages) { flags = new ResourceChunkFlags(); if (blocks.Count <= 0) { return; } long largestBlockSize = 0; // find largest structure long startPageSize = BASE_SIZE; // 0x2000; // find starting page size long totalBlockSize = 0; foreach (var block in blocks) { // Get size of all blocks padded var blockLength = block.BlockLength; totalBlockSize += blockLength; totalBlockSize += Pad(totalBlockSize); // Get biggest block if (largestBlockSize < blockLength) { largestBlockSize = blockLength; } } // Get minimum page size to contain biggest block while (startPageSize < largestBlockSize) { startPageSize *= 2; } var pageSizeMult = 1; long currentPosition; var sys = (basePosition == 0x50000000); bool invalidLayout; do { invalidLayout = false; var blockset = new ResourceBuilderBlockSet(blocks, sys); var rootblock = blockset.RootBlock; currentPosition = 0L; var currentPageSize = startPageSize; var currentPageStart = 0L; var currentPageSpace = startPageSize; long currentRemainder = totalBlockSize; var bucketIndex = 0; var targetPageSize = Math.Max(65536 * pageSizeMult, startPageSize >> (sys ? 5 : 2)); var minPageSize = Math.Max(512 * pageSizeMult, Math.Min(targetPageSize, startPageSize) >> 4); var baseShift = 0u; var baseSize = 512; while (baseSize < minPageSize) { baseShift++; baseSize *= 2; if (baseShift >= 0xF) { break; } } flags = new ResourceChunkFlags(new uint[9], baseShift); var baseSizeMax = baseSize << 8; var baseSizeMaxTest = startPageSize; while (baseSizeMaxTest < baseSizeMax) { bucketIndex++; baseSizeMaxTest *= 2; } if (!flags.TryAddChunk(bucketIndex)) { break; } while (blockset.Count > 0) { var isroot = sys && (currentPosition == 0); var block = isroot ? rootblock : blockset.GetBestBlock(currentPageSpace); // If there is no block to fit in space left if (block == null) { //allocate a new page currentPageStart += currentPageSize; currentPosition = currentPageStart; // Get the biggest block block = blockset.GetBestBlock(long.MaxValue); var blockLength = block?.BlockLength ?? 0; // Get the smallest page which can contain the block while (blockLength <= (currentPageSize >> 1)) { if (currentPageSize <= minPageSize) { break; } if (bucketIndex >= 8) { break; } if ((currentPageSize <= targetPageSize) && (currentRemainder >= (currentPageSize - minPageSize))) { break; } currentPageSize = currentPageSize >> 1; bucketIndex++; } currentPageSpace = currentPageSize; // Try adding another chunk to this bucket if (!flags.TryAddChunk(bucketIndex)) { invalidLayout = true; break; } } //add this block to the current page. block.BlockPosition = basePosition + currentPosition; var opos = currentPosition; currentPosition += block.BlockLength; currentPosition += Pad(currentPosition); var usedspace = currentPosition - opos; currentPageSpace -= usedspace; currentRemainder -= usedspace; } startPageSize *= 2; pageSizeMult *= 2; }while ((invalidLayout) || (flags.Size < totalBlockSize) || (flags.Count + usedPages > 128)); }