#---------------------------------------------------------------------------------
TARGET := ctru
BUILD := build
-SOURCES := source source/services source/gpu source/allocator
+SOURCES := source \
+ source/allocator \
+ source/gpu \
+ source/services \
+ source/util
DATA := data
INCLUDES := include
--- /dev/null
+#pragma once
+
+#include <stdint.h>
+#include <stddef.h>
+
+#define rbtree_item(ptr, type, member) \
+ ((type*)(((char*)ptr) - offsetof(type, member)))
+
+typedef struct rbtree rbtree_t;
+typedef struct rbtree_node rbtree_node_t;
+
+typedef void (*rbtree_node_destructor_t)(rbtree_node_t *Node);
+typedef int (*rbtree_node_comparator_t)(const rbtree_node_t *lhs,
+ const rbtree_node_t *rhs);
+struct rbtree_node
+{
+ uintptr_t parent_color;
+ rbtree_node_t *child[2];
+};
+
+struct rbtree
+{
+ rbtree_node_t *root;
+ rbtree_node_comparator_t comparator;
+ size_t size;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void
+rbtree_init(rbtree_t *tree,
+ rbtree_node_comparator_t comparator);
+
+int
+rbtree_empty(const rbtree_t *tree);
+
+size_t
+rbtree_size(const rbtree_t *tree);
+
+__attribute__((warn_unused_result))
+rbtree_node_t*
+rbtree_insert(rbtree_t *tree,
+ rbtree_node_t *node);
+
+void
+rbtree_insert_multi(rbtree_t *tree,
+ rbtree_node_t *node);
+
+rbtree_node_t*
+rbtree_find(const rbtree_t *tree,
+ const rbtree_node_t *node);
+
+rbtree_node_t*
+rbtree_min(const rbtree_t *tree);
+
+rbtree_node_t*
+rbtree_max(const rbtree_t *tree);
+
+rbtree_node_t*
+rbtree_node_next(const rbtree_node_t *node);
+
+rbtree_node_t*
+rbtree_node_prev(const rbtree_node_t *node);
+
+rbtree_node_t*
+rbtree_remove(rbtree_t *tree,
+ rbtree_node_t *node,
+ rbtree_node_destructor_t destructor);
+
+void
+rbtree_clear(rbtree_t *tree,
+ rbtree_node_destructor_t destructor);
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null
+#include <3ds/util/rbtree.h>
+#include "rbtree_internal.h"
+
+void
+rbtree_clear(rbtree_t *tree,
+ rbtree_node_destructor_t destructor)
+{
+ rbtree_node_t *node = tree->root;
+
+ while(tree->root != NULL)
+ {
+ while(node->child[LEFT] != NULL)
+ node = node->child[LEFT];
+
+ if(node->child[RIGHT] != NULL)
+ node = node->child[RIGHT];
+ else
+ {
+ rbtree_node_t *parent = get_parent(node);
+
+ if(parent == NULL)
+ tree->root = NULL;
+ else
+ parent->child[node != parent->child[LEFT]] = NULL;
+
+ if(destructor != NULL)
+ (*destructor)(node);
+
+ node = parent;
+ }
+ }
+
+ tree->size = 0;
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+
+int
+rbtree_empty(const rbtree_t *tree)
+{
+ return tree->root == NULL;
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+#include "rbtree_internal.h"
+
+rbtree_node_t*
+rbtree_find(const rbtree_t *tree,
+ const rbtree_node_t *node)
+{
+ rbtree_node_t *tmp = tree->root;
+ rbtree_node_t *save = NULL;
+
+ while(tmp != NULL)
+ {
+ int rc = (*tree->comparator)(node, tmp);
+ if(rc < 0)
+ {
+ tmp = tmp->child[LEFT];
+ }
+ else if(rc > 0)
+ {
+ tmp = tmp->child[RIGHT];
+ }
+ else
+ {
+ save = tmp;
+ tmp = tmp->child[LEFT];
+ }
+ }
+
+ return save;
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+
+void
+rbtree_init(rbtree_t *tree,
+ rbtree_node_comparator_t comparator)
+{
+ tree->root = NULL;
+ tree->comparator = comparator;
+ tree->size = 0;
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+#include "rbtree_internal.h"
+
+static rbtree_node_t*
+do_insert(rbtree_t *tree,
+ rbtree_node_t *node,
+ int multi)
+{
+ rbtree_node_t *original = node;
+ rbtree_node_t **tmp = &tree->root;
+ rbtree_node_t *parent = NULL;
+ rbtree_node_t *save = NULL;
+
+ while(*tmp != NULL)
+ {
+ int cmp = (*(tree->comparator))(node, *tmp);
+ parent = *tmp;
+
+ if(cmp < 0)
+ tmp = &((*tmp)->child[LEFT]);
+ else if(cmp > 0)
+ tmp = &((*tmp)->child[RIGHT]);
+ else
+ {
+ if(!multi)
+ save = *tmp;
+
+ tmp = &((*tmp)->child[LEFT]);
+ }
+ }
+
+ if(save != NULL)
+ {
+ return save;
+ }
+
+ *tmp = node;
+
+ node->child[LEFT] = node->child[RIGHT] = NULL;
+ set_parent(node, parent);
+
+ set_red(node);
+
+ while(is_red((parent = get_parent(node))))
+ {
+ rbtree_node_t *grandparent = get_parent(parent);
+ int left = (parent == grandparent->child[LEFT]);
+ rbtree_node_t *uncle = grandparent->child[left];
+
+ if(is_red(uncle))
+ {
+ set_black(uncle);
+ set_black(parent);
+ set_red(grandparent);
+
+ node = grandparent;
+ }
+ else
+ {
+ if(parent->child[left] == node)
+ {
+ rbtree_node_t *tmp;
+
+ rbtree_rotate(tree, parent, left);
+
+ tmp = parent;
+ parent = node;
+ node = tmp;
+ }
+
+ set_black(parent);
+ set_red(grandparent);
+ rbtree_rotate(tree, grandparent, !left);
+ }
+ }
+
+ set_black(tree->root);
+
+ tree->size += 1;
+
+ return original;
+}
+
+rbtree_node_t*
+rbtree_insert(rbtree_t *tree,
+ rbtree_node_t *node)
+{
+ return do_insert(tree, node, 0);
+}
+
+void
+rbtree_insert_multi(rbtree_t *tree,
+ rbtree_node_t *node)
+{
+ do_insert(tree, node, 1);
+}
--- /dev/null
+#pragma once
+
+#define LEFT 0
+#define RIGHT 1
+
+typedef enum rbtree_color
+{
+ RED = 0,
+ BLACK = 1,
+} rbtree_color_t;
+
+#define COLOR_MASK (RED|BLACK)
+
+static inline void
+set_black(rbtree_node_t *node)
+{
+ node->parent_color &= ~COLOR_MASK;
+ node->parent_color |= BLACK;
+}
+
+static inline void
+set_red(rbtree_node_t *node)
+{
+ node->parent_color &= ~COLOR_MASK;
+ node->parent_color |= RED;
+}
+
+static inline rbtree_color_t
+get_color(const rbtree_node_t *node)
+{
+ if(node == NULL)
+ return BLACK;
+ return (rbtree_color_t)(node->parent_color & COLOR_MASK);
+}
+
+static inline int
+is_black(const rbtree_node_t *node)
+{
+ return get_color(node) == BLACK;
+}
+
+static inline int
+is_red(const rbtree_node_t *node)
+{
+ return get_color(node) == RED;
+}
+
+static inline rbtree_node_t*
+get_parent(const rbtree_node_t *node)
+{
+ return (rbtree_node_t*)(node->parent_color & ~COLOR_MASK);
+}
+
+static inline void
+set_parent(rbtree_node_t *node,
+ const rbtree_node_t *parent)
+{
+ node->parent_color = (get_color(node)) | ((uintptr_t)parent);
+}
+
+void
+rbtree_rotate(rbtree_t *tree,
+ rbtree_node_t *node,
+ int left);
--- /dev/null
+#include <3ds/util/rbtree.h>
+#include "rbtree_internal.h"
+
+static inline rbtree_node_t*
+do_iterate(const rbtree_node_t *node,
+ int next)
+{
+ rbtree_node_t *it = (rbtree_node_t*)node;
+
+ if(it->child[next] != NULL)
+ {
+ it = it->child[next];
+ while(it->child[!next] != NULL)
+ it = it->child[!next];
+ }
+ else
+ {
+ rbtree_node_t *parent = get_parent(node);
+ while(parent != NULL && it == parent->child[next])
+ {
+ it = parent;
+ parent = get_parent(it);
+ }
+
+ it = parent;
+ }
+
+ return it;
+}
+
+rbtree_node_t*
+rbtree_node_next(const rbtree_node_t *node)
+{
+ return do_iterate(node, RIGHT);
+}
+
+rbtree_node_t*
+rbtree_node_prev(const rbtree_node_t *node)
+{
+ return do_iterate(node, LEFT);
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+#include "rbtree_internal.h"
+
+static inline rbtree_node_t*
+do_minmax(const rbtree_t *tree,
+ int max)
+{
+ rbtree_node_t *node = tree->root;
+
+ if(node == NULL)
+ return NULL;
+
+ while(node->child[max] != NULL)
+ node = node->child[max];
+
+ return node;
+}
+
+rbtree_node_t*
+rbtree_min(const rbtree_t *tree)
+{
+ rbtree_node_t *node;
+
+ node = do_minmax(tree, LEFT);
+
+ return node;
+}
+
+rbtree_node_t*
+rbtree_max(const rbtree_t *tree)
+{
+ rbtree_node_t *node;
+
+ node = do_minmax(tree, RIGHT);
+
+ return node;
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+#include "rbtree_internal.h"
+
+static void
+recolor(rbtree_t *tree,
+ rbtree_node_t *parent,
+ rbtree_node_t *node)
+{
+ rbtree_node_t *sibling;
+
+ while(is_black(node) && node != tree->root)
+ {
+ int left = (node == parent->child[LEFT]);
+
+ sibling = parent->child[left];
+
+ if(is_red(sibling))
+ {
+ set_black(sibling);
+ set_red(parent);
+ rbtree_rotate(tree, parent, left);
+ sibling = parent->child[left];
+ }
+
+ if(is_black(sibling->child[LEFT]) && is_black(sibling->child[RIGHT]))
+ {
+ set_red(sibling);
+ node = parent;
+ parent = get_parent(node);
+ }
+ else
+ {
+ if(is_black(sibling->child[left]))
+ {
+ set_black(sibling->child[!left]);
+ set_red(sibling);
+ rbtree_rotate(tree, sibling, !left);
+ sibling = parent->child[left];
+ }
+
+ if(is_black(parent))
+ set_black(sibling);
+ else
+ set_red(sibling);
+ set_black(parent);
+ set_black(sibling->child[left]);
+
+ rbtree_rotate(tree, parent, left);
+
+ node = tree->root;
+ }
+ }
+
+ if(node != NULL)
+ set_black(node);
+}
+
+rbtree_node_t*
+rbtree_remove(rbtree_t *tree,
+ rbtree_node_t *node,
+ rbtree_node_destructor_t destructor)
+{
+ rbtree_color_t color;
+ rbtree_node_t *child, *parent, *original = node;
+ rbtree_node_t *next;
+
+ next = rbtree_node_next(node);
+
+ if(node->child[LEFT] != NULL && node->child[RIGHT] != NULL)
+ {
+ rbtree_node_t *old = node;
+
+ node = node->child[RIGHT];
+ while(node->child[LEFT] != NULL)
+ node = node->child[LEFT];
+
+ parent = get_parent(old);
+ if(parent != NULL)
+ {
+ if(parent->child[LEFT] == old)
+ parent->child[LEFT] = node;
+ else
+ parent->child[RIGHT] = node;
+ }
+ else
+ tree->root = node;
+
+ child = node->child[RIGHT];
+ parent = get_parent(node);
+ color = get_color(node);
+
+ if(parent == old)
+ parent = node;
+ else
+ {
+ if(child != NULL)
+ set_parent(child, parent);
+ parent->child[LEFT] = child;
+
+ node->child[RIGHT] = old->child[RIGHT];
+ set_parent(old->child[RIGHT], node);
+ }
+
+ node->parent_color = old->parent_color;
+ node->child[LEFT] = old->child[LEFT];
+ set_parent(old->child[LEFT], node);
+ }
+ else
+ {
+ if(node->child[LEFT] == NULL)
+ child = node->child[RIGHT];
+ else
+ child = node->child[LEFT];
+
+ parent = get_parent(node);
+ color = get_color(node);
+
+ if(child != NULL)
+ set_parent(child, parent);
+ if(parent != NULL)
+ {
+ if(parent->child[LEFT] == node)
+ parent->child[LEFT] = child;
+ else
+ parent->child[RIGHT] = child;
+ }
+ else
+ tree->root = child;
+ }
+
+ if(color == BLACK)
+ recolor(tree, parent, child);
+
+ if(destructor != NULL)
+ (*destructor)(original);
+
+ tree->size -= 1;
+
+ return next;
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+#include "rbtree_internal.h"
+
+void
+rbtree_rotate(rbtree_t *tree,
+ rbtree_node_t *node,
+ int left)
+{
+ rbtree_node_t *tmp = node->child[left];
+ rbtree_node_t *parent = get_parent(node);
+
+ node->child[left] = tmp->child[!left];
+ if(tmp->child[!left] != NULL)
+ set_parent(tmp->child[!left], node);
+
+ tmp->child[!left] = node;
+ set_parent(tmp, parent);
+ if(parent != NULL)
+ {
+ if(node == parent->child[!left])
+ parent->child[!left] = tmp;
+ else
+ parent->child[left] = tmp;
+ }
+ else
+ tree->root = tmp;
+ set_parent(node, tmp);
+}
--- /dev/null
+#include <3ds/util/rbtree.h>
+
+size_t
+rbtree_size(const rbtree_t *tree)
+{
+ return tree->size;
+}