Skip to content

Instantly share code, notes, and snippets.

@Erick194

Erick194/DOOM64 z_zone.c Secret

Created Jun 15, 2019
Embed
What would you like to do?
/* Z_zone.c */
#include "doomdef.h"
/*
==============================================================================
ZONE MEMORY ALLOCATION
There is never any space between memblocks, and there will never be two
contiguous free memblocks.
The rover can be left pointing at a non-empty block
It is of no value to free a cachable block, because it will get overwritten
automatically if needed
==============================================================================
*/
memzone_t *mainzone;
/*
========================
=
= Z_Init
=
========================
*/
void Z_Init (void)//L8002C8F0()
{
byte *mem;
int size;
mem = (byte *)(player_heap + 15 & ~15);//??
size = (byte *)audio_heap - (byte *)mem;
/* mars doesn't have a refzone */
mainzone = Z_InitZone(mem, size);
}
/*
========================
=
= Z_InitZone
=
========================
*/
memzone_t *Z_InitZone(byte *base, int size)//L8002C934()
{
memzone_t *zone;
zone = (memzone_t *)base;
zone->size = size;
zone->rover = &zone->blocklist;
zone->rover2 = &zone->blocklist;
zone->rover3 = zone->rover2;
zone->blocklist.size = size - (int)((byte *)&zone->blocklist - (byte *)zone);
zone->blocklist.user = NULL;
zone->blocklist.tag = 0;
zone->blocklist.id = ZONEID;
zone->blocklist.next = NULL;
zone->blocklist.prev = NULL;
return zone;
}
/*
========================
=
= Z_SetAllocBase -> appointed by Kaiser
=
= Exclusive Doom 64
========================
*/
void Z_SetAllocBase(byte *base)//L8002C970()
{
memzone_t *zone;
zone = (memzone_t *)base;
zone->rover2 = zone->rover;
}
/*
========================
=
= Z_Malloc2
=
= You can pass a NULL user if the tag is < PU_PURGELEVEL
========================
*/
#define MINFRAGMENT 64
void *Z_Malloc2 (memzone_t *mainzone, int size, int tag, void *user)//L8002C97C()
{
int extra;
memblock_t *start, *rover, *newblock, *base;
#if 0
Z_CheckHeap (mainzone); /* DEBUG */
#endif
/* */
/* scan through the block list looking for the first free block */
/* of sufficient size, throwing out any purgable blocks along the way */
/* */
size += sizeof(memblock_t); /* account for size of block header */
size = (size + 15) & ~15; /* phrase align everything */
start = base = mainzone->rover;
while (base->user || base->size < size)
{
if (base->user)
rover = base;
else
rover = base->next;
if (!rover)
goto backtostart;
if (rover->user)
{
if (!(rover->tag & PU_PURGELEVEL))
{
if (!(rover->tag & PU_CACHE) || rover->lockframe >= (*L8005A730 - 1))
{
/* hit an in use block, so move base past it */
base = rover->next;
if (!base)
{
backtostart:
base = mainzone->rover2;//base = &mainzone->blocklist;
}
if (base == start) /* scaned all the way around the list */
{
Z_DumpHeap(mainzone);
I_Error("Z_Malloc2: failed allocation on %i", size);
}
continue;
}
}
/* */
/* free the rover block (adding the size to base) */
/* */
Z_Free((byte *)rover + sizeof(memblock_t)); /* mark as free */
}
if (base != rover)
{ /* merge with base */
base->size += rover->size;
base->next = rover->next;
if (rover->next)
rover->next->prev = base;
else
mainzone->rover3 = base;
}
}
/* */
/* found a block big enough */
/* */
extra = base->size - size;
if (extra > MINFRAGMENT)
{ /* there will be a free fragment after the allocated block */
newblock = (memblock_t *)((byte *)base + size);
newblock->size = extra;
newblock->user = NULL; /* free block */
newblock->tag = 0;
newblock->id = ZONEID;
newblock->prev = base;
newblock->next = base->next;
if (newblock->next)
newblock->next->prev = newblock;
base->next = newblock;
base->size = size;
mainzone->rover3 = newblock;
}
if (user)
{
base->user = user; /* mark as an in use block */
*(void **)user = (void *) ((byte *)base + sizeof(memblock_t));
}
else
{
if (tag >= PU_PURGELEVEL)
I_Error ("Z_Malloc: an owner is required for purgable blocks");
base->user = (void *)1; /* mark as in use, but unowned */
}
base->tag = tag;
base->id = ZONEID;
base->lockframe = *L8005A730;
mainzone->rover = base->next; /* next allocation will start looking here */
if (!mainzone->rover)
{
mainzone->rover3 = base;
mainzone->rover = mainzone->rover2;//mainzone->rover = &mainzone->blocklist;
}
return (void *)((byte *)base + sizeof(memblock_t));
}
/*
========================
=
= Z_Alloc2
=
= You can pass a NULL user if the tag is < PU_PURGELEVEL
= Exclusive From Psx Doom
========================
*/
void *Z_Alloc2(memzone_t *mainzone, int size, int tag, void *user)//L8002CBE0()
{
int extra;
memblock_t *rover, *newblock, *base;
/* */
/* scan through the block list looking for the first free block */
/* of sufficient size, throwing out any purgable blocks along the way */
/* */
base = mainzone->rover3;//base = &mainzone->blocklist;
size += sizeof(memblock_t); /* account for size of block header */
size = (size + 15) & ~15; /* phrase align everything */
while (base->user || base->size < size)
{
if (base->user)
rover = base;
else
{
/* hit an in use block, so move base past it */
rover = base->prev;
if (!rover)
{
Z_DumpHeap(mainzone);
I_Error("Z_Alloc: failed allocation on %i", size);
}
}
if (rover->user)
{
if (!(rover->tag & PU_PURGELEVEL))
{
if (!(rover->tag & PU_CACHE) || rover->lockframe >= (L8005A730 - 1))
{
/* hit an in use block, so move base past it */
base = rover->prev;
if (!base)
{
Z_DumpHeap(mainzone);
I_Error("Z_Alloc: failed allocation on %i", size);
}
continue;
}
}
/* */
/* free the rover block (adding the size to base) */
/* */
Z_Free((byte *)rover + sizeof(memblock_t)); /* mark as free */
}
if (base != rover)
{ /* merge with base */
rover->size += base->size;
rover->next = base->next;
if (base->next)
base->next->prev = rover;
else
mainzone->rover3 = base;
base = rover;
}
}
/* */
/* found a block big enough */
/* */
extra = base->size - size;
if (extra > MINFRAGMENT)
{ /* there will be a free fragment after the allocated block */
newblock = base;
base = (memblock_t *)((byte *)base + extra);
base->prev = newblock;
base->next = newblock->next;
base->size = size;
if (base->next)
base->next->prev = base;
newblock->next = base;
newblock->size = extra;
newblock->user = NULL; // free block
newblock->tag = 0;
newblock->id = ZONEID;
}
if (user)
{
base->user = user; /* mark as an in use block */
*(void **)user = (void *)((byte *)base + sizeof(memblock_t));
}
else
{
if (tag >= PU_PURGELEVEL)
I_Error("Z_Alloc: an owner is required for purgable blocks");
base->user = (void *)1; /* mark as in use, but unowned */
}
base->tag = tag;
base->id = ZONEID;
base->lockframe = *L8005A730;
return (void *)((byte *)base + sizeof(memblock_t));
}
/*
========================
=
= Z_Free2
=
========================
*/
void Z_Free2(memzone_t *mainzone, void *ptr)//L8002CE28()
{
memblock_t *block;
block = (memblock_t *)((byte *)ptr - sizeof(memblock_t));
if (block->id != ZONEID)
I_Error("Z_Free: freed a pointer without ZONEID");
if (block->user > (void **)0x100) /* smaller values are not pointers */
*block->user = 0; /* clear the user's mark */
block->user = NULL; /* mark as free */
block->tag = 0;
}
/*
========================
=
= Z_FreeTags
=
========================
*/
void Z_FreeTags (memzone_t *mainzone, int tag)//L8002CE8C()
{
memblock_t *block, *next;
for (block = &mainzone->blocklist; block; block = next)
{
next = block->next; /* get link before freeing */
if (!block->user)
continue; /* free block */
if (block->tag & tag)
{
Z_Free(((byte *)block + sizeof(memblock_t)));
}
}
for (block = &mainzone->blocklist; block; block = next)
{
next = block->next; // get link before freeing
if (!block->user && next && !next->user)
{
block->size += next->size;
block->next = next->next;
if (next->next)
next->next->prev = block;
}
}
mainzone->rover = &mainzone->blocklist;
mainzone->rover2 = &mainzone->blocklist;
mainzone->rover3 = &mainzone->blocklist;
for (block = mainzone->blocklist.next; block; block = block->next)
{
mainzone->rover3 = block;
}
}
/*
========================
=
= Z_Touch
=
= Exclusive Doom 64
========================
*/
void Z_Touch(void *ptr)//L8002CF9C()
{
memblock_t *block;
block = (memblock_t *)((byte *)ptr - sizeof(memblock_t));
if (block->id != ZONEID)
I_Error("Z_Touch: touched a pointer without ZONEID");
block->lockframe = *L8005A730;
}
/*
========================
=
= Z_CheckZone
= Previously Named Z_CheckHeap
========================
*/
void Z_CheckHeap (memzone_t *mainzone)//L8002CFEC()
{
memblock_t *checkblock;
for (checkblock = &mainzone->blocklist ; checkblock; checkblock = checkblock->next)
{
if (checkblock->id != ZONEID)
I_Error("Z_CheckZone: block missing ZONEID");
if (!checkblock->next)
{
if ((byte *)checkblock + checkblock->size - (byte *)mainzone != mainzone->size)
I_Error ("Z_CheckZone: zone size changed\n");
continue;
}
if ( (byte *)checkblock + checkblock->size != (byte *)checkblock->next)
I_Error ("Z_CheckZone: block size does not touch the next block\n");
if ( checkblock->next->prev != checkblock)
I_Error ("Z_CheckZone: next block doesn't have proper back link\n");
}
}
/*
========================
=
= Z_ChangeTag
=
========================
*/
void Z_ChangeTag (void *ptr, int tag)//L8002D0F0()
{
memblock_t *block;
block = (memblock_t *)((byte *)ptr - sizeof(memblock_t));
if (block->id != ZONEID)
I_Error("Z_ChangeTag: freed a pointer without ZONEID");
if (tag >= PU_PURGELEVEL && (int)block->user < 0x100)
I_Error("Z_ChangeTag: an owner is required for purgable blocks");
block->tag = tag;
block->lockframe = *L8005A730;
}
/*
========================
=
= Z_FreeMemory
=
========================
*/
int Z_FreeMemory (memzone_t *mainzone)//L8002D188()
{
memblock_t *block;
int free;
free = 0;
for (block = &mainzone->blocklist; block; block = block->next)
{
if (!block->user)
free += block->size;
}
return free;
}
/*
========================
=
= Z_DumpHeap
=
========================
*/
void Z_DumpHeap(memzone_t *mainzone)//L8002D1C8()
{
#if 0
memblock_t *block;
printf("zone size: %i location: %p\n", mainzone->size, mainzone);
for (block = &mainzone->blocklist; block; block = block->next)
{
printf("block:%p size:%7i user:%p tag:%3i frame:%i\n",
block, block->size, block->user, block->tag, block->lockframe);
if (!block->next)
continue;
if ((byte *)block + block->size != (byte *)block->next)
printf("ERROR: block size does not touch the next block\n");
if (block->next->prev != block)
printf("ERROR: next block doesn't have proper back link\n");
}
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment