aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/glulxe/heap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/glulxe/heap.cpp')
-rw-r--r--engines/glk/glulxe/heap.cpp499
1 files changed, 247 insertions, 252 deletions
diff --git a/engines/glk/glulxe/heap.cpp b/engines/glk/glulxe/heap.cpp
index 00b8dcb74c..86cd4439b8 100644
--- a/engines/glk/glulxe/heap.cpp
+++ b/engines/glk/glulxe/heap.cpp
@@ -26,295 +26,290 @@ namespace Glk {
namespace Glulxe {
void Glulxe::heap_clear() {
- while (heap_head) {
- heapblock_t *blo = heap_head;
- heap_head = blo->next;
- blo->next = nullptr;
- blo->prev = nullptr;
- glulx_free(blo);
- }
- heap_tail = nullptr;
-
- if (heap_start) {
- uint res = change_memsize(heap_start, true);
- if (res)
- fatal_error_i("Unable to revert memory size when deactivating heap.",
- heap_start);
- }
-
- heap_start = 0;
- alloc_count = 0;
- /* heap_sanity_check(); */
+ while (heap_head) {
+ heapblock_t *blo = heap_head;
+ heap_head = blo->next;
+ blo->next = nullptr;
+ blo->prev = nullptr;
+ glulx_free(blo);
+ }
+ heap_tail = nullptr;
+
+ if (heap_start) {
+ uint res = change_memsize(heap_start, true);
+ if (res)
+ fatal_error_i("Unable to revert memory size when deactivating heap.",
+ heap_start);
+ }
+
+ heap_start = 0;
+ alloc_count = 0;
+ /* heap_sanity_check(); */
}
int Glulxe::heap_is_active() const {
- return (heap_start != 0);
+ return (heap_start != 0);
}
uint Glulxe::heap_get_start() const {
- return heap_start;
+ return heap_start;
}
uint Glulxe::heap_alloc(uint len) {
- heapblock_t *blo, *newblo;
+ heapblock_t *blo, *newblo;
#ifdef FIXED_MEMSIZE
- return 0;
+ return 0;
#else /* FIXED_MEMSIZE */
- if (len <= 0)
- fatal_error("Heap allocation length must be positive.");
-
- blo = heap_head;
- while (blo) {
- if (blo->isfree && blo->len >= len)
- break;
-
- if (!blo->isfree) {
- blo = blo->next;
- continue;
- }
-
- if (!blo->next || !blo->next->isfree) {
- blo = blo->next;
- continue;
- }
-
- /* This is a free block, but the next block in the list is also
- free, so we "advance" by merging rather than by going to
- blo->next. */
- newblo = blo->next;
- blo->len += newblo->len;
- if (newblo->next) {
- blo->next = newblo->next;
- newblo->next->prev = blo;
- }
- else {
- blo->next = nullptr;
- heap_tail = blo;
- }
- newblo->next = nullptr;
- newblo->prev = nullptr;
- glulx_free(newblo);
- newblo = nullptr;
- continue;
- }
-
- if (!blo) {
- /* No free area is visible on the list. Try extending memory. How
- much? Double the heap size, or by 256 bytes, or by the memory
- length requested -- whichever is greatest. */
- uint res;
- uint extension;
- uint oldendmem = endmem;
-
- extension = 0;
- if (heap_start)
- extension = endmem - heap_start;
- if (extension < len)
- extension = len;
- if (extension < 256)
- extension = 256;
- /* And it must be rounded up to a multiple of 256. */
- extension = (extension + 0xFF) & (~(uint)0xFF);
-
- res = change_memsize(endmem+extension, true);
- if (res)
- return 0;
-
- /* If we just started the heap, note that. */
- if (heap_start == 0)
- heap_start = oldendmem;
-
- if (heap_tail && heap_tail->isfree) {
- /* Append the new space to the last block. */
- blo = heap_tail;
- blo->len += extension;
- }
- else {
- /* Append the new space to the block list, as a new block. */
- newblo = (heapblock_t *)glulx_malloc(sizeof(heapblock_t));
- if (!newblo)
- fatal_error("Unable to allocate record for heap block.");
- newblo->addr = oldendmem;
- newblo->len = extension;
- newblo->isfree = true;
- newblo->next = nullptr;
- newblo->prev = nullptr;
-
- if (!heap_tail) {
- heap_head = newblo;
- heap_tail = newblo;
- }
- else {
- blo = heap_tail;
- heap_tail = newblo;
- blo->next = newblo;
- newblo->prev = blo;
- }
-
- blo = newblo;
- newblo = nullptr;
- }
-
- /* and continue forwards, using this new block (blo). */
- }
-
- /* Something strange happened. */
- if (!blo || !blo->isfree || blo->len < len)
- return 0;
-
- /* We now have a free block of size len or longer. */
-
- if (blo->len == len) {
- blo->isfree = false;
- }
- else {
- newblo = (heapblock_t *)glulx_malloc(sizeof(heapblock_t));
- if (!newblo)
- fatal_error("Unable to allocate record for heap block.");
- newblo->isfree = true;
- newblo->addr = blo->addr + len;
- newblo->len = blo->len - len;
- blo->len = len;
- blo->isfree = false;
- newblo->next = blo->next;
- if (newblo->next)
- newblo->next->prev = newblo;
- newblo->prev = blo;
- blo->next = newblo;
- if (heap_tail == blo)
- heap_tail = newblo;
- }
-
- alloc_count++;
- /* heap_sanity_check(); */
- return blo->addr;
+ if (len <= 0)
+ fatal_error("Heap allocation length must be positive.");
+
+ blo = heap_head;
+ while (blo) {
+ if (blo->isfree && blo->len >= len)
+ break;
+
+ if (!blo->isfree) {
+ blo = blo->next;
+ continue;
+ }
+
+ if (!blo->next || !blo->next->isfree) {
+ blo = blo->next;
+ continue;
+ }
+
+ /* This is a free block, but the next block in the list is also
+ free, so we "advance" by merging rather than by going to
+ blo->next. */
+ newblo = blo->next;
+ blo->len += newblo->len;
+ if (newblo->next) {
+ blo->next = newblo->next;
+ newblo->next->prev = blo;
+ } else {
+ blo->next = nullptr;
+ heap_tail = blo;
+ }
+ newblo->next = nullptr;
+ newblo->prev = nullptr;
+ glulx_free(newblo);
+ newblo = nullptr;
+ continue;
+ }
+
+ if (!blo) {
+ /* No free area is visible on the list. Try extending memory. How
+ much? Double the heap size, or by 256 bytes, or by the memory
+ length requested -- whichever is greatest. */
+ uint res;
+ uint extension;
+ uint oldendmem = endmem;
+
+ extension = 0;
+ if (heap_start)
+ extension = endmem - heap_start;
+ if (extension < len)
+ extension = len;
+ if (extension < 256)
+ extension = 256;
+ /* And it must be rounded up to a multiple of 256. */
+ extension = (extension + 0xFF) & (~(uint)0xFF);
+
+ res = change_memsize(endmem + extension, true);
+ if (res)
+ return 0;
+
+ /* If we just started the heap, note that. */
+ if (heap_start == 0)
+ heap_start = oldendmem;
+
+ if (heap_tail && heap_tail->isfree) {
+ /* Append the new space to the last block. */
+ blo = heap_tail;
+ blo->len += extension;
+ } else {
+ /* Append the new space to the block list, as a new block. */
+ newblo = (heapblock_t *)glulx_malloc(sizeof(heapblock_t));
+ if (!newblo)
+ fatal_error("Unable to allocate record for heap block.");
+ newblo->addr = oldendmem;
+ newblo->len = extension;
+ newblo->isfree = true;
+ newblo->next = nullptr;
+ newblo->prev = nullptr;
+
+ if (!heap_tail) {
+ heap_head = newblo;
+ heap_tail = newblo;
+ } else {
+ blo = heap_tail;
+ heap_tail = newblo;
+ blo->next = newblo;
+ newblo->prev = blo;
+ }
+
+ blo = newblo;
+ newblo = nullptr;
+ }
+
+ /* and continue forwards, using this new block (blo). */
+ }
+
+ /* Something strange happened. */
+ if (!blo || !blo->isfree || blo->len < len)
+ return 0;
+
+ /* We now have a free block of size len or longer. */
+
+ if (blo->len == len) {
+ blo->isfree = false;
+ } else {
+ newblo = (heapblock_t *)glulx_malloc(sizeof(heapblock_t));
+ if (!newblo)
+ fatal_error("Unable to allocate record for heap block.");
+ newblo->isfree = true;
+ newblo->addr = blo->addr + len;
+ newblo->len = blo->len - len;
+ blo->len = len;
+ blo->isfree = false;
+ newblo->next = blo->next;
+ if (newblo->next)
+ newblo->next->prev = newblo;
+ newblo->prev = blo;
+ blo->next = newblo;
+ if (heap_tail == blo)
+ heap_tail = newblo;
+ }
+
+ alloc_count++;
+ /* heap_sanity_check(); */
+ return blo->addr;
#endif /* FIXED_MEMSIZE */
}
void Glulxe::heap_free(uint addr) {
- heapblock_t *blo;
-
- for (blo = heap_head; blo; blo = blo->next) {
- if (blo->addr == addr)
- break;
- };
- if (!blo || blo->isfree)
- fatal_error_i("Attempt to free unallocated address from heap.", addr);
-
- blo->isfree = true;
- alloc_count--;
- if (alloc_count <= 0) {
- heap_clear();
- }
-
- /* heap_sanity_check(); */
+ heapblock_t *blo;
+
+ for (blo = heap_head; blo; blo = blo->next) {
+ if (blo->addr == addr)
+ break;
+ };
+ if (!blo || blo->isfree)
+ fatal_error_i("Attempt to free unallocated address from heap.", addr);
+
+ blo->isfree = true;
+ alloc_count--;
+ if (alloc_count <= 0) {
+ heap_clear();
+ }
+
+ /* heap_sanity_check(); */
}
int Glulxe::heap_get_summary(uint *valcount, uint **summary) {
- uint *arr, len, pos;
- heapblock_t *blo;
+ uint *arr, len, pos;
+ heapblock_t *blo;
- *valcount = 0;
- *summary = nullptr;
+ *valcount = 0;
+ *summary = nullptr;
- if (heap_start == 0)
- return 0;
+ if (heap_start == 0)
+ return 0;
- len = 2 + 2*alloc_count;
- arr = (uint *)glulx_malloc(len * sizeof(uint));
- if (!arr)
- return 1;
+ len = 2 + 2 * alloc_count;
+ arr = (uint *)glulx_malloc(len * sizeof(uint));
+ if (!arr)
+ return 1;
- pos = 0;
- arr[pos++] = heap_start;
- arr[pos++] = alloc_count;
+ pos = 0;
+ arr[pos++] = heap_start;
+ arr[pos++] = alloc_count;
- for (blo = heap_head; blo; blo = blo->next) {
- if (blo->isfree)
- continue;
- arr[pos++] = blo->addr;
- arr[pos++] = blo->len;
- }
+ for (blo = heap_head; blo; blo = blo->next) {
+ if (blo->isfree)
+ continue;
+ arr[pos++] = blo->addr;
+ arr[pos++] = blo->len;
+ }
- if (pos != len)
- fatal_error("Wrong number of active blocks in heap");
+ if (pos != len)
+ fatal_error("Wrong number of active blocks in heap");
- *valcount = len;
- *summary = arr;
- return 0;
+ *valcount = len;
+ *summary = arr;
+ return 0;
}
int Glulxe::heap_apply_summary(uint valcount, uint *summary) {
- uint lx, jx, lastend;
+ uint lx, jx, lastend;
- if (heap_start)
- fatal_error("Heap active when heap_apply_summary called");
+ if (heap_start)
+ fatal_error("Heap active when heap_apply_summary called");
- if (valcount == 0 || summary == nullptr)
- return 0;
- if (valcount == 2 && summary[0] == 0 && summary[1] == 0)
- return 0;
+ if (valcount == 0 || summary == nullptr)
+ return 0;
+ if (valcount == 2 && summary[0] == 0 && summary[1] == 0)
+ return 0;
#ifdef FIXED_MEMSIZE
- return 1;
+ return 1;
#else /* FIXED_MEMSIZE */
- lx = 0;
- heap_start = summary[lx++];
- alloc_count = summary[lx++];
-
- for (jx=lx; jx+2<valcount; jx+=2) {
- if (summary[jx] >= summary[jx+2])
- fatal_error("Heap block summary is out of order.");
- }
-
- lastend = heap_start;
-
- while (lx < valcount || lastend < endmem) {
- heapblock_t *blo;
-
- blo = (heapblock_t *)glulx_malloc(sizeof(heapblock_t));
- if (!blo)
- fatal_error("Unable to allocate record for heap block.");
-
- if (lx >= valcount) {
- blo->addr = lastend;
- blo->len = endmem - lastend;
- blo->isfree = true;
- } else {
- if (lastend < summary[lx]) {
- blo->addr = lastend;
- blo->len = summary[lx] - lastend;
- blo->isfree = true;
- } else {
- blo->addr = summary[lx++];
- blo->len = summary[lx++];
- blo->isfree = false;
- }
- }
-
- blo->prev = nullptr;
- blo->next = nullptr;
-
- if (!heap_head) {
- heap_head = blo;
- heap_tail = blo;
- }
- else {
- heap_tail->next = blo;
- blo->prev = heap_tail;
- heap_tail = blo;
- }
-
- lastend = blo->addr + blo->len;
- }
-
- /* heap_sanity_check(); */
-
- return 0;
+ lx = 0;
+ heap_start = summary[lx++];
+ alloc_count = summary[lx++];
+
+ for (jx = lx; jx + 2 < valcount; jx += 2) {
+ if (summary[jx] >= summary[jx + 2])
+ fatal_error("Heap block summary is out of order.");
+ }
+
+ lastend = heap_start;
+
+ while (lx < valcount || lastend < endmem) {
+ heapblock_t *blo;
+
+ blo = (heapblock_t *)glulx_malloc(sizeof(heapblock_t));
+ if (!blo)
+ fatal_error("Unable to allocate record for heap block.");
+
+ if (lx >= valcount) {
+ blo->addr = lastend;
+ blo->len = endmem - lastend;
+ blo->isfree = true;
+ } else {
+ if (lastend < summary[lx]) {
+ blo->addr = lastend;
+ blo->len = summary[lx] - lastend;
+ blo->isfree = true;
+ } else {
+ blo->addr = summary[lx++];
+ blo->len = summary[lx++];
+ blo->isfree = false;
+ }
+ }
+
+ blo->prev = nullptr;
+ blo->next = nullptr;
+
+ if (!heap_head) {
+ heap_head = blo;
+ heap_tail = blo;
+ } else {
+ heap_tail->next = blo;
+ blo->prev = heap_tail;
+ heap_tail = blo;
+ }
+
+ lastend = blo->addr + blo->len;
+ }
+
+ /* heap_sanity_check(); */
+
+ return 0;
#endif /* FIXED_MEMSIZE */
}