private static void GlueFreeBlocks(CPpmd7 p) { CPpmd7_Node_Ref head = new CPpmd7_Node_Ref(p.AlignOffset + p.Size); CPpmd7_Node_Ref n = head; uint i; p.GlueCount = 255; /* create doubly-linked list of free blocks */ for (i = 0; i < PPMD_NUM_INDEXES; i++) { ushort nu = I2U(p, i); CPpmd7_Node_Ref next = (CPpmd7_Node_Ref)p.FreeList[i]; p.FreeList[i] = default(CPpmd_Void_Ref); while (next.Value != 0) { CPpmd7_Node *node = NODE(p, next); node->Next = n; n = NODE(p, n)->Prev = next; next = *(CPpmd7_Node_Ref *)node; node->Stamp = 0; node->NU = (ushort)nu; } } NODE(p, head)->Stamp = 1; NODE(p, head)->Next = n; NODE(p, n)->Prev = head; if (p.LoUnit != p.HiUnit) { ((CPpmd7_Node *)p.LoUnit)->Stamp = 1; } /* Glue free blocks */ while (n != head) { CPpmd7_Node *node = NODE(p, n); uint nu = (uint)node->NU; for (;;) { CPpmd7_Node *node2 = NODE(p, n) + nu; nu += node2->NU; if (node2->Stamp != 0 || nu >= 0x10000) { break; } NODE(p, node2->Prev)->Next = node2->Next; NODE(p, node2->Next)->Prev = node2->Prev; node->NU = (ushort)nu; } n = node->Next; } /* Fill lists of free blocks */ for (n = NODE(p, head)->Next; n != head;) { CPpmd7_Node * node = NODE(p, n); uint nu; CPpmd7_Node_Ref next = node->Next; for (nu = node->NU; nu > 128; nu -= 128, node += 128) { InsertNode(p, node, PPMD_NUM_INDEXES - 1); } if (I2U(p, i = U2I(p, nu)) != nu) { uint k = I2U(p, --i); InsertNode(p, node + k, nu - k - 1); } InsertNode(p, node, i); n = next; } }
private static CPpmd7_Node *NODE(CPpmd7 p, CPpmd7_Node_Ref offs) => (CPpmd7_Node *)(p.Base + offs.Value);