diff arena.c @ 883:9f149f0e98b7

It is now possible to switch back and forth between the menu ROM and the game
author Michael Pavone <pavone@retrodev.com>
date Fri, 13 Nov 2015 19:15:37 -0800
parents
children c7c573f0229e
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/arena.c	Fri Nov 13 19:15:37 2015 -0800
@@ -0,0 +1,81 @@
+/*
+ Copyright 2015 Michael Pavone
+ This file is part of BlastEm.
+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
+*/
+#include <stdlib.h>
+#include <stdint.h>
+#include "arena.h"
+
+struct arena {
+	void **used_blocks;
+	void **free_blocks;
+
+	size_t used_count;
+	size_t used_storage;
+	size_t free_count;
+	size_t free_storage;
+};
+
+static arena *current_arena;
+
+arena *get_current_arena()
+{
+	if (!current_arena) {
+		current_arena = calloc(1, sizeof(arena));
+	}
+	return current_arena;
+}
+
+arena *set_current_arena(arena *a)
+{
+	arena *tmp = current_arena;
+	current_arena = a;
+	return tmp;
+}
+
+arena *start_new_arena()
+{
+	arena *tmp = current_arena;
+	current_arena = NULL;
+	return tmp;
+}
+
+void track_block(void *block)
+{
+	arena *cur = get_current_arena();
+	if (cur->used_count == cur->used_storage) {
+		cur->used_storage *= 2;
+		cur->used_blocks = realloc(cur->used_blocks, cur->used_storage * sizeof(void *));
+	}
+	cur->used_blocks[cur->used_count++] = block;
+}
+
+void mark_all_free()
+{
+	arena *cur = get_current_arena();
+	if (!cur->free_blocks) {
+		cur->free_blocks = cur->used_blocks;
+		cur->free_storage = cur->used_storage;
+		cur->free_count = cur->used_count;
+		cur->used_count = cur->used_storage = 0;
+		cur->used_blocks = NULL;
+	} else {
+		if (cur->free_storage < cur->used_count + cur->free_count) {
+			cur->free_storage = cur->used_count + cur->free_count;
+			cur->free_blocks = realloc(cur->free_blocks, cur->free_storage * sizeof(void*));
+		}
+		for (; cur->used_count > 0; cur->used_count--)
+		{
+			cur->free_blocks[cur->free_count++] = cur->used_blocks[cur->used_count-1];
+		}
+	}
+}
+
+void *try_alloc_arena()
+{
+	if (!current_arena || !current_arena->free_count) {
+		return NULL;
+	}
+	return current_arena->free_blocks[--current_arena->free_count];
+}