void templateAppInit(int width, int height) { GFX_start(); glViewport(0.0f, 0.0f, width, height); GFX_set_matrix_mode(PROJECTION_MATRIX); GFX_load_identity(); GFX_set_perspective(45.0f, (float)width / (float)height, 0.1f, 100.0f, -90.0f); obj = OBJ_load(OBJ_FILE, 1); unsigned int i = 0; while (i != obj->n_objmesh) { OBJ_build_mesh(obj, i); OBJ_free_mesh_vertex_data(obj, i); ++i; } i = 0; while (i != obj->n_texture) { OBJ_build_texture(obj, i, obj->texture_path, TEXTURE_MIPMAP, TEXTURE_FILTER_2X, 0.0f); ++i; } i = 0; while (i != obj->n_objmaterial) { MEMORY *fragment_shader = mopen((char *)"fragment.glsl", 1); MEMORY *vertex_shader = mopen((char *)"vertex.glsl", 1); OBJMATERIAL *objmaterial = &obj->objmaterial[i]; OBJ_build_material(obj, i, NULL); if (objmaterial->dissolve == 1.0f) minsert(fragment_shader, (char *)"#define SOLID_OBJECT\n", 0); else if (!objmaterial->dissolve) minsert(fragment_shader, (char *)"#define ALPHA_TESTED_OBJECT\n", 0); else minsert(fragment_shader, (char *)"#define TRANSPARENT_OBJECT\n", 0); if (objmaterial->illumination_model) { minsert(vertex_shader, (char *)"#define LIGHTING_SHADER\n", 0); minsert(fragment_shader, (char *)"#define LIGHTING_SHADER\n", 0); } objmaterial->program = PROGRAM_init(objmaterial->name); objmaterial->program->vertex_shader = SHADER_init((char *)"vertex", GL_VERTEX_SHADER); objmaterial->program->fragment_shader = SHADER_init((char *)"fragment", GL_FRAGMENT_SHADER); SHADER_compile(objmaterial->program->vertex_shader, (char *)vertex_shader->buffer, 1); SHADER_compile(objmaterial->program->fragment_shader, (char *)fragment_shader->buffer, 1); PROGRAM_set_bind_attrib_location_callback(objmaterial->program, program_bind_attrib_location); PROGRAM_link(objmaterial->program, 1); OBJ_set_draw_callback_material(obj, i, material_draw_callback); mclose(fragment_shader); mclose(vertex_shader); ++i; } }
void *malloc(size_t size) { register PACKET *current; register size_t newsize; register size_t oldsize; if (size <= 0) return NULL; if (check_alloc_size(size) == 0) return 0; if (need_mem_init) minit(); _lock(); /*-----------------------------------------------------------------------*/ /* SIZE IS CALCULATED BY FIRST ALIGNING (SIZE + BLOCK OVERHEAD) TO THE */ /* REQUIRED MINIMUM ALIGNMENT AND THEN SUBTRACTING THE BLOCK OVERHEAD. */ /*-----------------------------------------------------------------------*/ newsize = _M_RNDUP((size + _M_BLOCK_OVERHEAD), _M_MIN_ALN) - _M_BLOCK_OVERHEAD; current = sys_free; /*-----------------------------------------------------------------------*/ /* SCAN THROUGH FREE LIST FOR PACKET LARGE ENOUGH TO CONTAIN PACKET */ /*-----------------------------------------------------------------------*/ while (current && current->packet_size < newsize) current = current->size_ptr; if (!current) { _unlock(); return NULL; } oldsize = current->packet_size; /* REMEMBER OLD SIZE */ mremove(current); /* REMOVE PACKET FROM FREE LIST */ /*-----------------------------------------------------------------------*/ /* IF PACKET IS LARGER THAN NEEDED, FREE EXTRA SPACE AT END */ /* BY INSERTING REMAINING SPACE INTO FREE LIST. */ /*-----------------------------------------------------------------------*/ if (oldsize - newsize >= (_M_MIN_BLOCK + _M_BLOCK_OVERHEAD)) { register PACKET *next = (PACKET *) ((char *) current + _M_BLOCK_OVERHEAD + newsize); next->packet_size = oldsize - newsize - _M_BLOCK_OVERHEAD; minsert(next); current->packet_size = newsize; } current->packet_size |= _M_BLOCK_USED; _unlock(); return (char *)current + _M_BLOCK_OVERHEAD; }
/* * Takes the value "val" and inserts it into the tree. * Grows at the root if necessary. */ void insert(float val, tree * root) { node * n = root->root; if (n->left || n->right) { //If I am a 2 or 3 node w/ children. if (val < n->ldata) { minsert(val, n->left, left); } else if (n->middle != NULL && val < n->rdata) { minsert(val, n->middle, middle); } else { minsert(val, n->right, right); } } //The root is a temp-4 node w/children, grow a new root and right node. if (n->is4node && n->mid_right) { //Create new root, have old root's parent ptr point to it. //Make sure to clear out the middle data as well. node * new_root = modmem(GET, NULL); n->parent = new_root; new_root->ldata = n->mdata; new_root->is2node = true; n->mdata = 0; //Have the new root point to the old one. new_root->left = n; //Create the new right branch of the tree as well. Migrate //the proper pointers over (including the parent pointers!) node * new_right = modmem(GET, NULL); new_root->right = new_right; new_right->parent = new_root; new_right->ldata = n->rdata; new_right->is2node = true; n->rdata = 0; n->is4node = false; n->is3node = false; n->is2node = true; new_right->left = n->mid_right; new_right->right = n->right; n->right = n->middle; n->middle = NULL; n->mid_right = NULL; //Have grandchild parent pointers point to new right node. new_right->left->parent = new_right; new_right->right->parent = new_right; root->root = new_root; } //Initial case of inserting data: a full root node with no children. else if (n->is3node && n->left == NULL) { node * new_root = modmem(GET, NULL); new_root->left = n; swapsort(val, n); node * new_right = modmem(GET, NULL); n->parent = new_root; new_right->parent = new_root; new_root->ldata = n->mdata; new_root->is2node = true; n->mdata = 0; new_root->right = new_right; new_right->ldata = n->rdata; new_right->is2node = true; n->rdata = 0; n->is3node = false; n->is2node = true; root->root = new_root; } else if (n->is2node != true && n->left == NULL) { n->ldata = val; n->is2node = true; } else if (n->is2node && n->left == NULL) { simpleswap(val, n); } }
//Helper function for insert. Does all the heavy lifting save for growth //at the root node, which is reserved for insert itself. static void minsert(float val, node * n, direction dir) { //Shameless copy from insert. The logic is identical... if (n->left || n->right) { //If I am a 2 or 3 node w/ children. if (val < n->ldata) { minsert(val, n->left, left); } else if (n->middle != NULL && val < n->rdata) { minsert(val, n->middle, middle); } else { minsert(val, n->right, right); } } else if (n->is2node && n->left == NULL) { //I am a leaf 2-node simpleswap(val, n); } else { //I am a leaf 3-node and I'm ready to overflow! swapsort(val, n); n->is4node = true; } //The node has overflowed! Split accordingly. if (n->is4node) { node * parent = n->parent; float promoted_val = n->mdata; if (parent->is2node) { //Parent is a 2-node simpleswap(promoted_val, parent); node * new_node = modmem(GET, NULL); new_node->parent = parent; parent->middle = new_node; switch(dir) { case left: new_node->ldata = n->rdata; //Transfer pointers unconditionally, since it wouldn't hurt //either way new_node->left = n->mid_right; new_node->right = n->right; if (new_node->left != NULL) { new_node->left->parent = new_node; new_node->right->parent = new_node; } n->right = n->middle; break; case right: new_node->ldata = n->ldata; n->ldata = n->rdata; //As above, unconditional pointer xfer. new_node->left = n->left; new_node->right = n->middle; if (new_node->left != NULL) { new_node->left->parent = new_node; new_node->right->parent = new_node; } n->left = n->mid_right; break; } n->mid_right = NULL; n->middle = NULL; n->rdata = 0; new_node->is2node = true; } else { //Parent is a 3-node. swapsort(promoted_val, parent); parent->is4node = true; node * new_node = modmem(GET, NULL); new_node->parent = parent; switch(dir) { case left: //Rearrange for left parent->mid_right = parent->middle; parent->middle = new_node; new_node->ldata = n->rdata; new_node->left = n->mid_right; new_node->right = n->right; if (new_node->left != NULL) { new_node->left->parent = new_node; new_node->right->parent = new_node; } n->right = n->middle; break; case middle: //Rearrange for middle parent->mid_right = new_node; new_node->ldata = n->rdata; new_node->left = n->mid_right; new_node->right = n->right; if (new_node->left != NULL) { new_node->left->parent = new_node; new_node->right->parent = new_node; } n->right = n->middle; break; case right: //Rearrange for right parent->mid_right = new_node; new_node->ldata = n->ldata; n->ldata = n->rdata; new_node->left = n->left; new_node->right = n->middle; if (new_node->left != NULL) { new_node->left->parent = new_node; new_node->right->parent = new_node; } n->left = n->mid_right; break; } n->rdata = 0; n->middle = NULL; n->mid_right = NULL; new_node->is2node = true; } n->mdata = 0; //Clean up temp value storage. n->is2node = true; n->is3node = false; n->is4node = false; } }
void *memalign(size_t alignment, size_t size) { PACKET *aln_packet; PACKET *current; size_t newsize; size_t aln_mask = alignment - 1; int leftover = -1; char *aln_start; char *un_aln_start; if (size <= 0) return NULL; if (check_alloc_size(size) == 0) return NULL; /*--------------------------------------------------------------------*/ /* IF ALIGNMENT IS NOT A POWER OF TWO OR IS LESS THAN THE DEFAULT */ /* ALIGNMENT OF MALLOC, THEN SIMPLY RETURN WHAT MALLOC RETURNS. */ /*--------------------------------------------------------------------*/ if (alignment <= _M_MIN_ALN || (alignment & (alignment-1))) return malloc(size); if (need_mem_init) minit(); _lock(); newsize = _M_RNDUP((size + _M_BLOCK_OVERHEAD), _M_MIN_ALN) - _M_BLOCK_OVERHEAD; current = sys_free; /*-----------------------------------------------------------------------*/ /* SCAN THROUGH FREE LIST FOR PACKET LARGE ENOUGH TO CONTAIN ALIGNED */ /* PACKET */ /*-----------------------------------------------------------------------*/ for ( ; current ; current = current->size_ptr) { un_aln_start = (char *) current + _M_BLOCK_OVERHEAD; /*--------------------------------------------------------------------*/ /* IT IS POSSIBLE THAT WE COULD OVERFLOW THE size_t TYPE BELOW, BUT */ /* ADDING A CHECK HERE WOULD LIKELY BE A SIGNIFICANT PERFORMANCE HIT. */ /*--------------------------------------------------------------------*/ aln_start = (char *)(((size_t) un_aln_start + aln_mask) & ~aln_mask); leftover = un_aln_start + current->packet_size - aln_start -newsize; /*--------------------------------------------------------------------*/ /* MAKE SURE THAT THE PRE BLOCK SPACE IS LARGE ENOUGH TO BE A BLOCK */ /* OF ITS OWN. */ /*--------------------------------------------------------------------*/ for ( ; (char *)current+sizeof(PACKET) > aln_start-_M_BLOCK_OVERHEAD ; aln_start += alignment, leftover -= alignment); if (leftover >= 0) break; } if (!current) { _unlock(); return NULL; } /*-----------------------------------------------------------------------*/ /* SETUP NEW PACKET FOR ALIGNED MEMORY. */ /*-----------------------------------------------------------------------*/ mremove(current); aln_packet = (PACKET *) (aln_start - _M_BLOCK_OVERHEAD); aln_packet->packet_size = newsize | _M_BLOCK_USED; /*-----------------------------------------------------------------------*/ /* HANDLE THE FREE SPACE BEFORE THE ALIGNED BLOCK. IF THE ORIGINAL */ /* BLOCK WAS ALIGNED, THERE WON'T BE FREE SPACE BEFORE THE ALIGNED BLOCK.*/ /*-----------------------------------------------------------------------*/ if (aln_start != un_aln_start) { current->packet_size = (char *)aln_packet - un_aln_start; minsert(current); } /*-----------------------------------------------------------------------*/ /* HANDLE THE FREE SPACE AFTER THE ALIGNED BLOCK. IF IT IS LARGE ENOUGH */ /* TO BE A BLOCK OF ITS OWN, THEN MAKE IT ONE, OTHERWISE ADD THE */ /* LEFTOVER SIZE TO THE ALIGNED BLOCK. */ /*-----------------------------------------------------------------------*/ if (leftover >= _M_BLOCK_OVERHEAD + _M_MIN_BLOCK) { register PACKET *next = (PACKET *) (aln_start + newsize); next->packet_size = leftover - _M_BLOCK_OVERHEAD; minsert(next); } else aln_packet->packet_size += leftover; _unlock(); return aln_start; }
void free(void *packet) { register char *ptr = (char *)packet; register PACKET *last; /* POINT TO PREVIOUS PACKET */ register PACKET *current; /* POINTER TO THIS PACKET */ register PACKET *next; /* POINTER TO NEXT PACKET */ if (ptr == NULL) return; last = next = NULL; /* INITIALIZE POINTERS */ ptr -= _M_BLOCK_OVERHEAD; /* ADJUST POINT TO BEGINNING OF PACKET */ if (need_mem_init) minit(); _lock(); current = _M_SYS_FIRST; /*-----------------------------------------------------------------------*/ /* SEARCH FOR THE POINTER IN THE PACKET POINTED TO */ /*-----------------------------------------------------------------------*/ while (current < (PACKET *) ptr) { last = current; current = (PACKET *)((char *)current + (current->packet_size & ~_M_BLOCK_USED) + _M_BLOCK_OVERHEAD); } /*-----------------------------------------------------------------------*/ /* CHECK FOR POINTER OR PACKET ERRORS. */ /*-----------------------------------------------------------------------*/ if ((current != (PACKET *)ptr) || (!(current->packet_size & _M_BLOCK_USED))) { _unlock(); return; } current->packet_size &= ~_M_BLOCK_USED; /* MARK PACKET AS FREE */ /*-----------------------------------------------------------------------*/ /* GET POINTER TO NEXT PACKET IN MEMORY, IF ANY. */ /*-----------------------------------------------------------------------*/ next = (PACKET *)((char *)current + _M_BLOCK_OVERHEAD + current->packet_size); if (next > (PACKET *) &heap_mem[_memory_size - _M_BLOCK_OVERHEAD]) next = NULL; if (last && last->packet_size & _M_BLOCK_USED) last = NULL; if (next && next->packet_size & _M_BLOCK_USED) next = NULL; /*-----------------------------------------------------------------------*/ /* ATTEMPT TO COLLESCE THE THREE PACKETS (PREVIOUS, CURRENT, NEXT) */ /*-----------------------------------------------------------------------*/ if (last && next) { mremove(last); mremove(next); last->packet_size += current->packet_size + next->packet_size + _M_BLOCK_OVERHEAD + _M_BLOCK_OVERHEAD; minsert(last); _unlock(); return; } /*-----------------------------------------------------------------------*/ /* ATTEMPT TO COLLESCE THE CURRENT WITH LAST PACKET. (LAST, CURRENT) */ /*-----------------------------------------------------------------------*/ if (last) { mremove(last); last->packet_size += current->packet_size + _M_BLOCK_OVERHEAD; minsert(last); _unlock(); return; } /*-----------------------------------------------------------------------*/ /* ATTEMPT TO COLLESCE THE CURRENT WITH NEXT PACKET. (CURRENT, NEXT) */ /*-----------------------------------------------------------------------*/ if (next) { mremove(next); current->packet_size += next->packet_size + _M_BLOCK_OVERHEAD; minsert(current); _unlock(); return; } /*-----------------------------------------------------------------------*/ /* NO COLLESCENCE POSSIBLE, JUST INSERT THIS PACKET INTO LIST */ /*-----------------------------------------------------------------------*/ minsert(current); _unlock(); }
void *realloc(void *packet, size_t size) { register char *pptr = (char *) packet - _M_BLOCK_OVERHEAD; register size_t newsize; register size_t oldsize; if (packet == 0) return malloc(size); if (size == 0) { free(packet); return NULL; } if (check_alloc_size(size) == 0) return 0; if (need_mem_init) minit(); _lock(); /*-----------------------------------------------------------------------*/ /* NEW SIZE IS CALCULATED BY FIRST ALIGNING (SIZE+BLOCK OVERHEAD) TO THE */ /* REQUIRED MINIMUM ALIGNMENT AND THEN SUBTRACTING THE BLOCK OVERHEAD. */ /*-----------------------------------------------------------------------*/ newsize = _M_RNDUP((size + _M_BLOCK_OVERHEAD), _M_MIN_ALN) - _M_BLOCK_OVERHEAD; oldsize = ((PACKET *)pptr)->packet_size; if (!(oldsize & _M_BLOCK_USED)) { _unlock(); return NULL; } if (newsize == --oldsize) { _unlock(); return packet; } /*-----------------------------------------------------------------------*/ /* IF NEW SIZE IS LESS THAN CURRENT SIZE, TRUNCATE PACKET AND RETURN END */ /* TO FREE LIST */ /*-----------------------------------------------------------------------*/ if (newsize < oldsize) { if (oldsize - newsize < (_M_MIN_BLOCK + _M_BLOCK_OVERHEAD)) { _unlock(); return packet; } ((PACKET *)pptr)->packet_size = newsize | _M_BLOCK_USED; oldsize -= newsize + _M_BLOCK_OVERHEAD; pptr += newsize + _M_BLOCK_OVERHEAD; ((PACKET *)pptr)->packet_size = oldsize | _M_BLOCK_USED; free(pptr + _M_BLOCK_OVERHEAD); _unlock(); return packet; } /*-----------------------------------------------------------------------*/ /* IF NEW SIZE IS BIGGER THAN CURRENT PACKET, */ /* 1) CHECK NEXT PACKET IN LIST, SEE IF PACKET CAN BE EXPANDED */ /* 2) IF NOT, MOVE PACKET TO NEW LOCATION. */ /*-----------------------------------------------------------------------*/ else { PACKET *next = (PACKET *)(pptr + oldsize + _M_BLOCK_OVERHEAD); int temp; if (((char *)next < &heap_mem[_memory_size - _M_BLOCK_OVERHEAD]) && (!(next->packet_size & _M_BLOCK_USED)) && ((temp = oldsize + next->packet_size +_M_BLOCK_OVERHEAD - newsize) >= 0)) { mremove(next); if (temp < _M_MIN_BLOCK + _M_BLOCK_OVERHEAD) { ((PACKET *)pptr)->packet_size = newsize + temp | _M_BLOCK_USED; _unlock(); return packet; } ((PACKET *)pptr)->packet_size = newsize | _M_BLOCK_USED; pptr += newsize + _M_BLOCK_OVERHEAD; ((PACKET *)pptr)->packet_size = temp - _M_BLOCK_OVERHEAD; minsert((PACKET *)pptr); _unlock(); return packet; } else { /*---------------------------------------------------------------*/ /* ALLOCATE NEW PACKET AND MOVE DATA INTO IT. */ /*---------------------------------------------------------------*/ register char *new_packet = (char *)malloc(size); if (new_packet == 0) { _unlock(); return NULL; } memcpy(new_packet, packet, oldsize); free(packet); _unlock(); return new_packet; } } }