-
-
Save Erick194/2469d4bc1c04748b60e87235885c1977 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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