From db34bd9e2ded86ecca330e4169480176536f8627 Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Sat, 21 Mar 2026 13:10:08 +1000 Subject: [PATCH 1/3] memory.c cleanup and optimisation --- src/game/memory.c | 111 ++++++++++++++++++++++++++++++---------------- src/game/memory.h | 2 +- 2 files changed, 74 insertions(+), 39 deletions(-) diff --git a/src/game/memory.c b/src/game/memory.c index feca24fd1..da800b996 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -5,7 +5,8 @@ #include "print.h" #include "pc/debuglog.h" -#define ALIGN16(val) (((val) + 0xF) & ~0xF) +// Alignment to a data size +#define ALIGN_UP(val, align) (((val) + ((align) - 1)) & ~((align) - 1)) ////////////////// // dynamic pool // @@ -14,7 +15,8 @@ struct DynamicPool *gLevelPool = NULL; struct DynamicPool* dynamic_pool_init(void) { - struct DynamicPool* pool = calloc(1, sizeof(struct DynamicPool)); + struct DynamicPool* pool = malloc(sizeof(struct DynamicPool)); + if (!pool) { return NULL; } pool->usedSpace = 0; pool->tail = NULL; pool->nextFree = NULL; @@ -24,14 +26,17 @@ struct DynamicPool* dynamic_pool_init(void) { void* dynamic_pool_alloc(struct DynamicPool *pool, u32 size) { if (!pool) { return NULL; } - struct DynamicPoolNode* node = calloc(1, sizeof(struct DynamicPoolNode)); - node->ptr = calloc(1, size); + size_t header = ALIGN_UP(sizeof(struct DynamicPoolNode), sizeof(void*)); + struct DynamicPoolNode* node = malloc(header + size); + if (!node) { return NULL; } + node->ptr = (u8*)node + header; node->prev = pool->tail; node->size = size; pool->tail = node; pool->usedSpace += size; + memset(node->ptr, 0, size); return node->ptr; } @@ -50,8 +55,7 @@ void dynamic_pool_free(struct DynamicPool *pool, void* ptr) { next->prev = prev; } pool->usedSpace -= node->size; - free(node->ptr); - free(node); + free(node); // node->ptr is freed here too; it's part of the same allocation return; } next = node; @@ -81,8 +85,7 @@ void dynamic_pool_free_pool(struct DynamicPool *pool) { struct DynamicPoolNode* node = pool->nextFree; while (node) { struct DynamicPoolNode* prev = node->prev; - free(node->ptr); - free(node); + free(node); // node->ptr is freed here too; it's part of the same allocation node = prev; } @@ -107,7 +110,8 @@ struct GrowingPool* growing_pool_init(struct GrowingPool* pool, u32 nodeSize) { pool->usedSpace = 0; } else { // allocate a new pool - pool = calloc(1, sizeof(struct GrowingPool)); + pool = malloc(sizeof(struct GrowingPool)); + if (!pool) { return NULL; } pool->usedSpace = 0; pool->nodeSize = nodeSize; pool->tail = NULL; @@ -119,19 +123,22 @@ void* growing_pool_alloc(struct GrowingPool *pool, u32 size) { if (!pool) { return NULL; } // maintain alignment - size = ALIGN16(size); + size = ALIGN_UP(size, sizeof(void*)); // check if it's too big for a node if (size >= pool->nodeSize) { // create a node just for this - struct GrowingPoolNode* node = calloc(1, sizeof(struct GrowingPoolNode)); - node->ptr = calloc(1, size); + size_t header = ALIGN_UP(sizeof(struct GrowingPoolNode), sizeof(void*)); + struct GrowingPoolNode* node = malloc(header + size); + if (!node) { return NULL; } + node->ptr = (u8*) node + header; node->prev = pool->tail; node->usedSpace = size; pool->tail = node; pool->usedSpace += size; + memset(node->ptr, 0, size); return node->ptr; } @@ -143,7 +150,7 @@ void* growing_pool_alloc(struct GrowingPool *pool, u32 size) { while (node && depth < 128) { depth++; s64 freeSpace = (s64)pool->nodeSize - (s64)node->usedSpace; - if (freeSpace > size) { break; } + if (freeSpace >= (s64) size) { break; } node = node->prev; } if (depth >= 128) { @@ -153,9 +160,11 @@ void* growing_pool_alloc(struct GrowingPool *pool, u32 size) { // allocate new node if (!node) { - node = calloc(1, sizeof(struct GrowingPoolNode)); + size_t header = ALIGN_UP(sizeof(struct GrowingPoolNode), sizeof(void*)); + node = malloc(header + pool->nodeSize); + if (!node) { return NULL; } node->usedSpace = 0; - node->ptr = calloc(1, pool->nodeSize); + node->ptr = (u8*) node + header; node->prev = pool->tail; pool->tail = node; } @@ -174,8 +183,7 @@ void growing_pool_free_pool(struct GrowingPool *pool) { struct GrowingPoolNode* node = pool->tail; while (node) { struct GrowingPoolNode* prev = node->prev; - free(node->ptr); - free(node); + free(node); // node->ptr is freed here too; it's part of the same allocation node = prev; } free(pool); @@ -187,8 +195,13 @@ void growing_pool_free_pool(struct GrowingPool *pool) { struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free) { growing_array_free(&array); - array = calloc(1, sizeof(struct GrowingArray)); + array = malloc(sizeof(struct GrowingArray)); + if (!array) { return NULL; } array->buffer = calloc(capacity, sizeof(void *)); + if (!array->buffer) { + free(array); + return NULL; + } array->capacity = capacity; array->count = 0; array->alloc = alloc; @@ -200,11 +213,11 @@ void *growing_array_alloc(struct GrowingArray *array, u32 size) { if (array && array->buffer) { // Increase capacity if needed - while (array->count >= array->capacity) { + if (array->count >= array->capacity) { u32 newCapacity = array->capacity * 2; - void **newBuffer = calloc(newCapacity, sizeof(void *)); - memcpy(newBuffer, array->buffer, array->capacity * sizeof(void *)); - free(array->buffer); + void **newBuffer = realloc(array->buffer, newCapacity * sizeof(void *)); + if (!newBuffer) { return NULL; } + memset(newBuffer + array->capacity, 0, (newCapacity - array->capacity) * sizeof(void *)); array->buffer = newBuffer; array->capacity = newCapacity; } @@ -220,30 +233,52 @@ void *growing_array_alloc(struct GrowingArray *array, u32 size) { return NULL; } -void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count) { - if (array && array->buffer && count > 0 && - (to < from || to > from + count) && - (from + count) <= array->count && to <= array->count) { +// This function can move elements to an overlapping region +// `to` is the destination index in the array before any operations +// Does not expand the array if `to + count` exceeds capacity +bool growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count) { + if (!array || !array->buffer) { return false; } + if (count == 0) { return true; } + if (from >= array->count) { return false; } + if (from + count > array->count) { return false; } + if (to > array->count) { return false; } + if (to + count > array->count) { return false; } + if (from == to) { return true; } - void **temp = malloc(sizeof(void *) * count); - if (!temp) { return; } + // Use stack memory for small moves (faster) + // Use heap memory for large moves (dynamic size) + void **temp; + void *stackTemp[64]; + if (count <= 64) { + temp = stackTemp; + } else { + temp = (void **) malloc(sizeof(void *) * count); + if (!temp) { return false; } + } - // Copy elements to move to temporary buffer - memcpy(temp, array->buffer + from, sizeof(void *) * count); + // Copy elements to move to temporary buffer + memcpy(temp, array->buffer + from, sizeof(void *) * count); - // Remove copied elements from the array - memmove(array->buffer + from, array->buffer + (from + count), sizeof(void *) * (array->count - (from + count))); + // Remove copied elements from the array + u32 tailCount = array->count - (from + count); + if (tailCount > 0) { + memmove(array->buffer + from, array->buffer + from + count, sizeof(void *) * tailCount); + } - // Make place for the copied elements - // If moving left to right, account for the removed elements - if (to > from) { to -= count; } - memmove(array->buffer + (to + count), array->buffer + to, sizeof(void *) * (array->count - (to + count))); + // Make place for the copied elements + u32 numToShift = (array->count - count) - to; + if (numToShift > 0) { + memmove(array->buffer + to + count, array->buffer + to, sizeof(void *) * numToShift); + } - // Insert copied elements - memcpy(array->buffer + to, temp, sizeof(void *) * count); + // Insert copied elements + memcpy(array->buffer + to, temp, sizeof(void *) * count); + if (count > 64) { free(temp); } + + return true; } void growing_array_free(struct GrowingArray **array) { diff --git a/src/game/memory.h b/src/game/memory.h index d8f469814..62bd5c7eb 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -77,7 +77,7 @@ void growing_pool_free_pool(struct GrowingPool *pool); struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free); void *growing_array_alloc(struct GrowingArray *array, u32 size); -void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count); +bool growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count); void growing_array_free(struct GrowingArray **array); void growing_array_debug_print(struct GrowingArray *array, const char *name, s32 x, s32 y); From cf283b6d99971bb933af63fc8106e6af1a573c51 Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Mon, 23 Mar 2026 09:55:59 +1000 Subject: [PATCH 2/3] revert growing_array_move revision --- src/game/memory.c | 54 ++++++++++++++--------------------------------- src/game/memory.h | 2 +- 2 files changed, 17 insertions(+), 39 deletions(-) diff --git a/src/game/memory.c b/src/game/memory.c index da800b996..11b98317e 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -233,52 +233,30 @@ void *growing_array_alloc(struct GrowingArray *array, u32 size) { return NULL; } -// This function can move elements to an overlapping region -// `to` is the destination index in the array before any operations -// Does not expand the array if `to + count` exceeds capacity -bool growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count) { - if (!array || !array->buffer) { return false; } - if (count == 0) { return true; } - if (from >= array->count) { return false; } - if (from + count > array->count) { return false; } - if (to > array->count) { return false; } - if (to + count > array->count) { return false; } - if (from == to) { return true; } +void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count) { + if (array && array->buffer && count > 0 && + (to < from || to > from + count) && + (from + count) <= array->count && to <= array->count) { - // Use stack memory for small moves (faster) - // Use heap memory for large moves (dynamic size) - void **temp; - void *stackTemp[64]; - if (count <= 64) { - temp = stackTemp; - } else { - temp = (void **) malloc(sizeof(void *) * count); - if (!temp) { return false; } - } + void **temp = malloc(sizeof(void *) * count); + if (!temp) { return; } - // Copy elements to move to temporary buffer - memcpy(temp, array->buffer + from, sizeof(void *) * count); + // Copy elements to move to temporary buffer + memcpy(temp, array->buffer + from, sizeof(void *) * count); - // Remove copied elements from the array - u32 tailCount = array->count - (from + count); - if (tailCount > 0) { - memmove(array->buffer + from, array->buffer + from + count, sizeof(void *) * tailCount); - } + // Remove copied elements from the array + memmove(array->buffer + from, array->buffer + (from + count), sizeof(void *) * (array->count - (from + count))); - // Make place for the copied elements - u32 numToShift = (array->count - count) - to; - if (numToShift > 0) { - memmove(array->buffer + to + count, array->buffer + to, sizeof(void *) * numToShift); - } + // Make place for the copied elements + // If moving left to right, account for the removed elements + if (to > from) { to -= count; } + memmove(array->buffer + (to + count), array->buffer + to, sizeof(void *) * (array->count - (to + count))); - // Insert copied elements - memcpy(array->buffer + to, temp, sizeof(void *) * count); + // Insert copied elements + memcpy(array->buffer + to, temp, sizeof(void *) * count); - if (count > 64) { free(temp); } - - return true; } void growing_array_free(struct GrowingArray **array) { diff --git a/src/game/memory.h b/src/game/memory.h index 62bd5c7eb..d8f469814 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -77,7 +77,7 @@ void growing_pool_free_pool(struct GrowingPool *pool); struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free); void *growing_array_alloc(struct GrowingArray *array, u32 size); -bool growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count); +void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count); void growing_array_free(struct GrowingArray **array); void growing_array_debug_print(struct GrowingArray *array, const char *name, s32 x, s32 y); From ea4f23be0e4db7fcc0a11a1a4d947f26622d56d8 Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Fri, 27 Mar 2026 07:09:04 +1000 Subject: [PATCH 3/3] bring back the while loop --- src/game/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/game/memory.c b/src/game/memory.c index 11b98317e..f0e1f670f 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -213,7 +213,7 @@ void *growing_array_alloc(struct GrowingArray *array, u32 size) { if (array && array->buffer) { // Increase capacity if needed - if (array->count >= array->capacity) { + while (array->count >= array->capacity) { u32 newCapacity = array->capacity * 2; void **newBuffer = realloc(array->buffer, newCapacity * sizeof(void *)); if (!newBuffer) { return NULL; }