From 4a881682df5e472319c4f5e1b984e21ddd25fbd0 Mon Sep 17 00:00:00 2001 From: alufolie91 Date: Tue, 1 Aug 2023 11:11:58 +0200 Subject: [PATCH 1/2] "Clean up and simplify zone memory allocation" more like, port zone memory stuff from srb2, idk may fix some stutter issues and give better performance in some cases still, see: https://git.do.srb2.org/STJr/SRB2/-/merge_requests/2059 --- src/z_zone.c | 513 ++++++++++++++++++++++++++------------------------- src/z_zone.h | 136 ++++++++------ 2 files changed, 340 insertions(+), 309 deletions(-) diff --git a/src/z_zone.c b/src/z_zone.c index 2214fb21f..740c28ac8 100644 --- a/src/z_zone.c +++ b/src/z_zone.c @@ -1,7 +1,7 @@ // SONIC ROBO BLAST 2 //----------------------------------------------------------------------------- // Copyright (C) 2006 by Graue. -// Copyright (C) 2006-2018 by Sonic Team Junior. +// Copyright (C) 2006-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -27,6 +27,7 @@ #include "doomdef.h" #include "doomstat.h" +#include "r_patch.h" #include "i_system.h" // I_GetFreeMem #include "i_video.h" // rendermode #include "z_zone.h" @@ -49,27 +50,11 @@ static boolean Z_calloc = false; //#define ZDEBUG2 #endif -struct memblock_s; - -typedef struct -{ - struct memblock_s *block; // Describing this memory - UINT32 id; // Should be ZONEID -} ATTRPACK memhdr_t; - -// Some code might want aligned memory. Assume it wants memory n bytes -// aligned -- then we allocate n-1 extra bytes and return a pointer to -// the first byte aligned as requested. -// Thus, "real" is the pointer we get from malloc() and will free() -// later, but "hdr" is where the memhdr_t starts. -// For non-aligned allocations they will be the same. typedef struct memblock_s { - void *real; - memhdr_t *hdr; - void **user; INT32 tag; // purgelevel + UINT32 id; // Should be ZONEID size_t size; // including the header and blocks size_t realsize; // size of real data only @@ -80,74 +65,41 @@ typedef struct memblock_s #endif struct memblock_s *next, *prev; -} ATTRPACK memblock_t; +} memblock_t; -#ifdef ZDEBUG -#define Ptr2Memblock(s, f) Ptr2Memblock2(s, f, __FILE__, __LINE__) -static memblock_t *Ptr2Memblock2(void *ptr, const char* func, const char *file, INT32 line) -#else -static memblock_t *Ptr2Memblock(void *ptr, const char* func) -#endif -{ - memhdr_t *hdr; - memblock_t *block; - - if (ptr == NULL) - return NULL; - -#ifdef ZDEBUG2 - CONS_Printf("%s %s:%d\n", func, file, line); -#endif - - hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr); - -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif - -#ifdef VALGRIND_MEMPOOL_EXISTS - if (!VALGRIND_MEMPOOL_EXISTS(hdr->block)) - { -#ifdef ZDEBUG - I_Error("%s: bad memblock from %s:%d", func, file, line); -#else - I_Error("%s: bad memblock", func); -#endif - } -#endif - if (hdr->id != ZONEID) - { -#ifdef ZDEBUG - I_Error("%s: wrong id from %s:%d", func, file, line); -#else - I_Error("%s: wrong id", func); -#endif - } - block = hdr->block; -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); -#endif - return block; - -} +#define MEMORY(x) (void *)((uintptr_t)(x) + sizeof(memblock_t)) +#define MEMBLOCK(x) (memblock_t *)((uintptr_t)(x) - sizeof(memblock_t)) +// both the head and tail of the zone memory block list static memblock_t head; +// +// Function prototypes +// static void Command_Memfree_f(void); #ifdef ZDEBUG static void Command_Memdump_f(void); #endif +// -------------------------- +// Zone memory initialisation +// -------------------------- + +/** Initialises zone memory. + * Used at game startup. + * + * \sa I_GetFreeMem, Command_Memfree_f, Command_Memdump_f + */ void Z_Init(void) { - UINT32 total, memfree; + size_t total, memfree; memset(&head, 0x00, sizeof(head)); head.next = head.prev = &head; memfree = I_GetFreeMem(&total)>>20; - CONS_Printf("System memory: %uMB - Free: %uMB\n", total>>20, memfree); + CONS_Printf("System memory: %sMB - Free: %sMB\n", sizeu1(total>>20), sizeu2(memfree)); // Note: This allocates memory. Watch out. COM_AddCommand("memfree", Command_Memfree_f); @@ -157,6 +109,17 @@ void Z_Init(void) #endif } + +// ---------------------- +// Zone memory allocation +// ---------------------- + +/** Frees allocated memory. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * \sa Z_FreeTags + */ #ifdef ZDEBUG void Z_Free2(void *ptr, const char *file, INT32 line) #else @@ -172,10 +135,14 @@ void Z_Free(void *ptr) CONS_Debug(DBG_MEMORY, "Z_Free %s:%d\n", file, line); #endif + block = MEMBLOCK(ptr); +#ifdef PARANOIA + if (block->id != ZONEID) #ifdef ZDEBUG - block = Ptr2Memblock2(ptr, "Z_Free", file, line); + I_Error("Z_Free at %s:%d: wrong id", file, line); #else - block = Ptr2Memblock(ptr, "Z_Free"); + I_Error("Z_Free: wrong id"); +#endif #endif #ifdef ZDEBUG @@ -183,11 +150,9 @@ void Z_Free(void *ptr) CONS_Debug(DBG_MEMORY, "Z_Free at %s:%d\n", file, line); #endif -#ifdef HAVE_BLUA // anything that isn't by lua gets passed to lua just in case. if (block->tag != PU_LUA) LUA_InvalidateUserdata(ptr); -#endif // TODO: if zdebugging, make sure no other block has a user // that is about to be freed. @@ -196,21 +161,27 @@ void Z_Free(void *ptr) if (block->user != NULL) *block->user = NULL; - // Free the memory and get rid of the block. - free(block->real); - block->prev->next = block->next; - block->next->prev = block->prev; - free(block); #ifdef VALGRIND_DESTROY_MEMPOOL VALGRIND_DESTROY_MEMPOOL(block); #endif + block->prev->next = block->next; + block->next->prev = block->prev; + free(block); } -// malloc() that doesn't accept failure. +/** malloc() that doesn't accept failure. + * + * \param size Amount of memory to be allocated, in bytes. + * \return A pointer to the allocated memory. + */ static void *xm(size_t size) { const size_t padedsize = size+sizeof (size_t); - void *p = malloc(padedsize); + void *p; + + if (padedsize < size)/* overflow check */ + I_Error("You are allocating memory too large!"); + p = malloc(padedsize); if (p == NULL) { @@ -220,10 +191,6 @@ static void *xm(size_t size) if (p == NULL) { -#if defined (_NDS) | defined (_PSP) - // Temporary-ish debugging measure - Command_Memfree_f(); -#endif I_Error("Out of memory allocating %s bytes", sizeu1(size)); } } @@ -231,10 +198,18 @@ static void *xm(size_t size) return p; } -// Z_Malloc -// You can pass Z_Malloc() a NULL user if the tag is less than -// PU_PURGELEVEL. - +/** The Z_MallocAlign function. + * Allocates a block of memory, adds it to a linked list so we can keep track of it. + * + * \param size Amount of memory to be allocated, in bytes. + * \param tag Purge tag. + * \param user The address of a pointer to the memory to be allocated. + * When the memory is freed by Z_Free later, + * the pointer at this address will then be automatically set to NULL. + * \param alignbits The alignment of the memory to be allocated, in bits. Can be 0. + * \note You can pass Z_Malloc() a NULL user if the tag is less than PU_PURGELEVEL. + * \sa Z_CallocAlign, Z_ReallocAlign + */ #ifdef ZDEBUG void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) @@ -242,81 +217,67 @@ void *Z_Malloc2(size_t size, INT32 tag, void *user, INT32 alignbits, void *Z_MallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) #endif { - // I have 0 knowledge about memory alignment but maybe if alignbits is - // something like 32 that would require too much BYTES, so bits amount - // should be divided by 8? Idk, maybe this would break alignment, but at - // least game wouldn't crash with "error allocating 2^32-1 bytes" - INT32 alignbytes = alignbits/8; - I_Assert(alignbytes >= 0 && alignbytes < (INT32)(sizeof(size_t) * 8)); - size_t extrabytes = ((size_t)1<<(alignbytes)) - 1; - size_t padsize = 0; memblock_t *block; void *ptr; - memhdr_t *hdr; - void *given; - size_t blocksize = extrabytes + sizeof *hdr + size; + (void)(alignbits); // no longer used, so silence warnings. #ifdef ZDEBUG2 CONS_Debug(DBG_MEMORY, "Z_Malloc %s:%d\n", file, line); #endif - block = xm(sizeof *block); + block = xm(sizeof (memblock_t) + size); + ptr = MEMORY(block); + I_Assert((intptr_t)ptr % sizeof (void *) == 0); + #ifdef HAVE_VALGRIND - padsize += (1<next = head.next; block->prev = &head; head.next = block; block->next->prev = block; - block->real = ptr; - block->hdr = hdr; block->tag = tag; block->user = NULL; #ifdef ZDEBUG block->ownerline = line; block->ownerfile = file; #endif - block->size = blocksize; + block->size = sizeof (memblock_t) + size; block->realsize = size; - hdr->id = ZONEID; - hdr->block = block; - -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); +#ifdef VALGRIND_CREATE_MEMPOOL + VALGRIND_CREATE_MEMPOOL(block, size, Z_calloc); #endif + block->id = ZONEID; + if (user != NULL) { block->user = user; - *(void **)user = given; + *(void **)user = ptr; } else if (tag >= PU_PURGELEVEL) I_Error("Z_Malloc: attempted to allocate purgable block " "(size %s) with no user", sizeu1(size)); - return given; + return ptr; } +/** The Z_CallocAlign function. + * Allocates a block of memory, adds it to a linked list so we can keep track of it. + * Unlike Z_MallocAlign, this also initialises the bytes to zero. + * + * \param size Amount of memory to be allocated, in bytes. + * \param tag Purge tag. + * \param user The address of a pointer to the memory to be allocated. + * When the memory is freed by Z_Free later, + * the pointer at this address will then be automatically set to NULL. + * \param alignbits The alignment of the memory to be allocated, in bits. Can be 0. + * \note You can pass Z_Calloc() a NULL user if the tag is less than PU_PURGELEVEL. + * \sa Z_MallocAlign, Z_ReallocAlign + */ #ifdef ZDEBUG void *Z_Calloc2(size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) #else @@ -333,10 +294,26 @@ void *Z_CallocAlign(size_t size, INT32 tag, void *user, INT32 alignbits) #endif } +/** The Z_ReallocAlign function. + * Reallocates a block of memory with a new size. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * If NULL, this function instead acts as a wrapper for Z_CallocAlign. + * \param size New size of memory block, in bytes. + * If zero, then the memory is freed and NULL is returned. + * \param tag New purge tag. + * \param user The address of a pointer to the memory to be reallocated. + * This can be a different user to the one originally assigned to the memory block. + * \param alignbits The alignment of the memory to be allocated, in bits. Can be 0. + * \return A pointer to the reallocated memory. Can be NULL if memory was freed. + * \note You can pass Z_Realloc() a NULL user if the tag is less than PU_PURGELEVEL. + * \sa Z_MallocAlign, Z_CallocAlign + */ #ifdef ZDEBUG void *Z_Realloc2(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits, const char *file, INT32 line) #else -void *Z_ReallocAlign(void *ptr, size_t size,INT32 tag, void *user, INT32 alignbits) +void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignbits) #endif { void *rez; @@ -362,10 +339,14 @@ void *Z_ReallocAlign(void *ptr, size_t size,INT32 tag, void *user, INT32 alignb #endif } + block = MEMBLOCK(ptr); +#ifdef PARANOIA + if (block->id != ZONEID) #ifdef ZDEBUG - block = Ptr2Memblock2(ptr, "Z_Realloc", file, line); + I_Error("Z_ReallocAlign at %s:%d: wrong id", file, line); #else - block = Ptr2Memblock(ptr, "Z_Realloc"); + I_Error("Z_ReallocAlign: wrong id"); +#endif #endif if (block == NULL) @@ -403,6 +384,11 @@ void *Z_ReallocAlign(void *ptr, size_t size,INT32 tag, void *user, INT32 alignb return rez; } +/** Frees all memory for a given set of tags. + * + * \param lowtag The lowest tag to consider. + * \param hightag The highest tag to consider. + */ void Z_FreeTags(INT32 lowtag, INT32 hightag) { memblock_t *block, *next; @@ -411,28 +397,57 @@ void Z_FreeTags(INT32 lowtag, INT32 hightag) for (block = head.next; block != &head; block = next) { next = block->next; // get link before freeing - if (block->tag >= lowtag && block->tag <= hightag) - Z_Free((UINT8 *)block->hdr + sizeof *block->hdr); + Z_Free(MEMORY(block)); } } -// -// Z_CheckMemCleanup -// -// TODO: Currently blocks >= PU_PURGELEVEL are freed every -// CLEANUPCOUNT. It might be better to keep track of -// the total size of all purgable memory and free it when the -// size exceeds some value. -// -// This was in Z_Malloc, but was freeing data at -// unsafe times. Now it is only called when it is safe -// to cleanup memory. +/** Iterates through all memory for a given set of tags. + * + * \param lowtag The lowest tag to consider. + * \param hightag The highest tag to consider. + * \param iterfunc The iterator function. + */ +void Z_IterateTags(INT32 lowtag, INT32 hightag, boolean (*iterfunc)(void *)) +{ + memblock_t *block, *next; + if (!iterfunc) + I_Error("Z_IterateTags: no iterator function was given"); + + for (block = head.next; block != &head; block = next) + { + next = block->next; // get link before possibly freeing + + if (block->tag >= lowtag && block->tag <= hightag) + { + void *mem = MEMORY(block); + boolean free = iterfunc(mem); + if (free) + Z_Free(mem); + } + } +} + +// ----------------- +// Utility functions +// ----------------- + +// starting value of nextcleanup #define CLEANUPCOUNT 2000 +// number of function calls left before next cleanup static INT32 nextcleanup = CLEANUPCOUNT; +/** This was in Z_Malloc, but was freeing data at + * unsafe times. Now it is only called when it is safe + * to cleanup memory. + * + * \todo Currently blocks >= PU_PURGELEVEL are freed every + * CLEANUPCOUNT. It might be better to keep track of + * the total size of all purgable memory and free it when the + * size exceeds some value. + */ void Z_CheckMemCleanup(void) { if (nextcleanup-- == 0) @@ -451,15 +466,13 @@ void Z_CheckMemCleanup(void) void Z_CheckHeap(INT32 i) { memblock_t *block; - memhdr_t *hdr; UINT32 blocknumon = 0; void *given; for (block = head.next; block != &head; block = block->next) { blocknumon++; - hdr = block->hdr; - given = (UINT8 *)hdr + sizeof *hdr; + given = MEMORY(block); #ifdef ZDEBUG2 CONS_Debug(DBG_MEMORY, "block %u owned by %s:%d\n", blocknumon, block->ownerfile, block->ownerline); @@ -475,7 +488,7 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } #endif if (block->user != NULL && *(block->user) != given) @@ -488,7 +501,7 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } if (block->next->prev != block) { @@ -500,7 +513,7 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } if (block->prev->next != block) { @@ -512,25 +525,9 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif - if (hdr->block != block) - { - I_Error("Z_CheckHeap %d: block %u" -#ifdef ZDEBUG - "(owned by %s:%d)" -#endif - " doesn't have linkback from allocated memory", - i, blocknumon -#ifdef ZDEBUG - , block->ownerfile, block->ownerline -#endif - ); - } - if (hdr->id != ZONEID) + if (block->id != ZONEID) { I_Error("Z_CheckHeap %d: block %u" #ifdef ZDEBUG @@ -540,50 +537,37 @@ void Z_CheckHeap(INT32 i) #ifdef ZDEBUG , block->ownerfile, block->ownerline #endif - ); + ); } -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); -#endif } } +// ------------------------ +// Zone memory modification +// ------------------------ + +/** Changes a memory block's purge tag. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * \param tag The new tag. + * \sa Z_SetUser + */ #ifdef PARANOIA void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line) #else -void Z_ChangeTag2(void *ptr, INT32 tag) +void Z_ChangeTag(void *ptr, INT32 tag) #endif { memblock_t *block; - memhdr_t *hdr; if (ptr == NULL) return; - hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr); + block = MEMBLOCK(ptr); -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif - -#ifdef VALGRIND_MEMPOOL_EXISTS - if (!VALGRIND_MEMPOOL_EXISTS(hdr->block)) - { #ifdef PARANOIA - I_Error("Z_CT at %s:%d: bad memblock", file, line); -#else - I_Error("Z_CT: bad memblock"); -#endif - } -#endif -#ifdef PARANOIA - if (hdr->id != ZONEID) I_Error("Z_CT at %s:%d: wrong id", file, line); -#endif - - block = hdr->block; - -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); + if (block->id != ZONEID) I_Error("Z_ChangeTag at %s:%d: wrong id", file, line); #endif if (tag >= PU_PURGELEVEL && block->user == NULL) @@ -593,12 +577,48 @@ void Z_ChangeTag2(void *ptr, INT32 tag) block->tag = tag; } +/** Changes a memory block's user. + * + * \param ptr A pointer to allocated memory, + * assumed to have been allocated with Z_Malloc/Z_Calloc. + * \param newuser The new user for the memory block. + * \sa Z_ChangeTag + */ +#ifdef PARANOIA +void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line) +#else +void Z_SetUser(void *ptr, void **newuser) +#endif +{ + memblock_t *block; + + if (ptr == NULL) + return; + + block = MEMBLOCK(ptr); + +#ifdef PARANOIA + if (block->id != ZONEID) I_Error("Z_SetUser at %s:%d: wrong id", file, line); +#endif + + if (block->tag >= PU_PURGELEVEL && newuser == NULL) + I_Error("Internal memory management error: " + "tried to make block purgable but it has no owner"); + + block->user = (void*)newuser; + *newuser = ptr; +} + +// ----------------- +// Zone memory usage +// ----------------- + /** Calculates memory usage for a given set of tags. + * * \param lowtag The lowest tag to consider. * \param hightag The highest tag to consider. * \return Number of bytes currently allocated in the heap for the * given tags. - * \sa Z_TagUsage */ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag) { @@ -615,44 +635,60 @@ size_t Z_TagsUsage(INT32 lowtag, INT32 hightag) return cnt; } -size_t Z_TagUsage(INT32 tagnum) -{ - return Z_TagsUsage(tagnum, tagnum); -} +// ----------------------- +// Miscellaneous functions +// ----------------------- -void Command_Memfree_f(void) +/** The function called by the "memfree" console command. + * Prints the memory being used by each part of the game to the console. + */ +static void Command_Memfree_f(void) { - UINT32 freebytes, totalbytes; + size_t freebytes, totalbytes; Z_CheckHeap(-1); CONS_Printf("\x82%s", M_GetText("Memory Info\n")); - CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TagsUsage(0, INT32_MAX)>>10)); - CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10)); - CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10)); - CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10)); - CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10)); - CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10)); - CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10)); - CONS_Printf(M_GetText("All purgable : %7s KB\n"), + CONS_Printf(M_GetText("Total heap used : %7s KB\n"), sizeu1(Z_TotalUsage()>>10)); + CONS_Printf(M_GetText("Static : %7s KB\n"), sizeu1(Z_TagUsage(PU_STATIC)>>10)); + CONS_Printf(M_GetText("Static (sound) : %7s KB\n"), sizeu1(Z_TagUsage(PU_SOUND)>>10)); + CONS_Printf(M_GetText("Static (music) : %7s KB\n"), sizeu1(Z_TagUsage(PU_MUSIC)>>10)); + CONS_Printf(M_GetText("Patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH)>>10)); + CONS_Printf(M_GetText("Patches (low priority) : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH_LOWPRIORITY)>>10)); + CONS_Printf(M_GetText("Patches (rotated) : %7s KB\n"), sizeu1(Z_TagUsage(PU_PATCH_ROTATED)>>10)); + CONS_Printf(M_GetText("Sprites : %7s KB\n"), sizeu1(Z_TagUsage(PU_SPRITE)>>10)); + CONS_Printf(M_GetText("HUD graphics : %7s KB\n"), sizeu1(Z_TagUsage(PU_HUDGFX)>>10)); + CONS_Printf(M_GetText("Locked cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_CACHE)>>10)); + CONS_Printf(M_GetText("Level : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVEL)>>10)); + CONS_Printf(M_GetText("Special thinker : %7s KB\n"), sizeu1(Z_TagUsage(PU_LEVSPEC)>>10)); + CONS_Printf(M_GetText("All purgable : %7s KB\n"), sizeu1(Z_TagsUsage(PU_PURGELEVEL, INT32_MAX)>>10)); #ifdef HWRENDER - if (rendermode != render_soft && rendermode != render_none) + if (rendermode == render_opengl) { - CONS_Printf(M_GetText("Patch info headers: %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); - CONS_Printf(M_GetText("Mipmap patches : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); - CONS_Printf(M_GetText("HW Texture cache : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); - CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); + CONS_Printf(M_GetText("Patch info headers : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHINFO)>>10)); + CONS_Printf(M_GetText("Cached textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRCACHE)>>10)); + CONS_Printf(M_GetText("Texture colormaps : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPATCHCOLMIPMAP)>>10)); + CONS_Printf(M_GetText("Model textures : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRMODELTEXTURE)>>10)); + CONS_Printf(M_GetText("Plane polygons : %7s KB\n"), sizeu1(Z_TagUsage(PU_HWRPLANE)>>10)); + //CONS_Printf(M_GetText("All GPU textures : %7d KB\n"), HWR_GetTextureUsed()>>10); } #endif CONS_Printf("\x82%s", M_GetText("System Memory Info\n")); freebytes = I_GetFreeMem(&totalbytes); - CONS_Printf(M_GetText(" Total physical memory: %7u KB\n"), totalbytes>>10); - CONS_Printf(M_GetText("Available physical memory: %7u KB\n"), freebytes>>10); + CONS_Printf(M_GetText(" Total physical memory: %s KB\n"), sizeu1(totalbytes>>10)); + CONS_Printf(M_GetText("Available physical memory: %s KB\n"), sizeu1(freebytes>>10)); } + + #ifdef ZDEBUG +/** The function called by the "memdump" console command. + * Prints zone memory debugging information (i.e. tag, size, location in code allocated). + * Can be all memory allocated in game, or between a set of tags (if -min/-max args used). + * This command is available only if ZDEBUG is enabled. + */ static void Command_Memdump_f(void) { memblock_t *block; @@ -674,45 +710,12 @@ static void Command_Memdump_f(void) } #endif -// Creates a copy of a string. +/** Creates a copy of a string. + * + * \param s The string to be copied. + * \return A copy of the string, allocated in zone memory. + */ char *Z_StrDup(const char *s) { return strcpy(ZZ_Alloc(strlen(s) + 1), s); } - - -#ifdef PARANOIA -void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line) -#else -void Z_SetUser2(void *ptr, void **newuser) -#endif -{ - memblock_t *block; - memhdr_t *hdr; - - if (ptr == NULL) - return; - - hdr = (memhdr_t *)((UINT8 *)ptr - sizeof *hdr); - -#ifdef VALGRIND_MAKE_MEM_DEFINED - VALGRIND_MAKE_MEM_DEFINED(hdr, sizeof *hdr); -#endif - -#ifdef PARANOIA - if (hdr->id != ZONEID) I_Error("Z_CT at %s:%d: wrong id", file, line); -#endif - - block = hdr->block; - -#ifdef VALGRIND_MAKE_MEM_NOACCESS - VALGRIND_MAKE_MEM_NOACCESS(hdr, sizeof *hdr); -#endif - - if (block->tag >= PU_PURGELEVEL && newuser == NULL) - I_Error("Internal memory management error: " - "tried to make block purgable but it has no owner"); - - block->user = (void*)newuser; - *newuser = ptr; -} diff --git a/src/z_zone.h b/src/z_zone.h index 9466f0338..36894e996 100644 --- a/src/z_zone.h +++ b/src/z_zone.h @@ -2,7 +2,7 @@ //----------------------------------------------------------------------------- // Copyright (C) 1993-1996 by id Software, Inc. // Copyright (C) 1998-2000 by DooM Legacy Team. -// Copyright (C) 1999-2018 by Sonic Team Junior. +// Copyright (C) 1999-2023 by Sonic Team Junior. // // This program is free software distributed under the // terms of the GNU General Public License, version 2. @@ -15,6 +15,7 @@ #define __Z_ZONE__ #include +#include "doomdef.h" #include "doomtype.h" #ifdef __GNUC__ // __attribute__ ((X)) @@ -30,52 +31,59 @@ //#define ZDEBUG // -// ZONE MEMORY -// PU - purge tags. -// Tags < PU_LEVEL are not purged until freed explicitly. -#define PU_STATIC 1 // static entire execution time -#define PU_LUA 2 // static entire execution time -- used by lua so it doesn't get caught in loops forever +// Purge tags +// +// Now they are an enum! -- Monster Iestyn 15/02/18 +// +enum +{ + // Tags < PU_LEVEL are not purged until freed explicitly. + PU_STATIC = 1, // static entire execution time + PU_LUA = 2, // static entire execution time -- used by lua so it doesn't get caught in loops forever + PU_PERFSTATS = 3, // static between changes to ps_samplesize cvar -#define PU_PERFSTATS 3 // static between changes to ps_samplesize cvar + PU_SOUND = 11, // static while playing + PU_MUSIC = 12, // static while playing -#define PU_SOUND 11 // static while playing -#define PU_MUSIC 12 // static while playing -#define PU_HUDGFX 13 // static until WAD added + PU_PATCH = 14, // static entire execution time + PU_PATCH_LOWPRIORITY = 15, // lower priority patch, static until level exited + PU_PATCH_ROTATED = 16, // rotated patch, static until level exited or WAD added + PU_PATCH_DATA = 17, // patch data, lifetime depends on the patch that owns it + PU_SPRITE = 18, // sprite patch, static until WAD added + PU_HUDGFX = 19, // HUD patch, static until WAD added -#define PU_HWRPATCHINFO 21 // Hardware GLPatch_t struct for OpenGL texture cache -#define PU_HWRPATCHCOLMIPMAP 22 // Hardware GLMipmap_t struct colromap variation of patch + PU_HWRPATCHINFO = 21, // Hardware GLPatch_t struct for OpenGL texture cache + PU_HWRPATCHCOLMIPMAP = 22, // Hardware GLMipmap_t struct colormap variation of patch + PU_HWRMODELTEXTURE = 23, // Hardware model texture -#define PU_HWRCACHE 48 // static until unlocked -#define PU_CACHE 49 // static until unlocked + PU_HWRCACHE = 48, // static until unlocked + PU_CACHE = 49, // static until unlocked -// Tags s.t. PU_LEVEL <= tag < PU_PURGELEVEL are purged at level start -#define PU_LEVEL 50 // static until level exited -#define PU_LEVSPEC 51 // a special thinker in a level -#define PU_HWRPLANE 52 + // Tags s.t. PU_LEVEL <= tag < PU_PURGELEVEL are purged at level start + PU_LEVEL = 50, // static until level exited + PU_LEVSPEC = 51, // a special thinker in a level + PU_HWRPLANE = 52, // if ZPLANALLOC is enabled in hw_bsp.c, this is used to alloc polygons for OpenGL -// Tags >= PU_PURGELEVEL are purgable whenever needed -#define PU_PURGELEVEL 100 -#define PU_CACHE_UNLOCKED 101 -#define PU_HWRCACHE_UNLOCKED 102 // 'second-level' cache for graphics - // stored in hardware format and downloaded as needed -#define PU_HWRPATCHINFO_UNLOCKED 103 + // Tags >= PU_PURGELEVEL are purgable whenever needed + PU_PURGELEVEL = 100, // Note: this is never actually used as a tag + PU_CACHE_UNLOCKED = 101, // Note: unused + PU_HWRCACHE_UNLOCKED = 102, // 'unlocked' PU_HWRCACHE memory: + // 'second-level' cache for graphics + // stored in hardware format and downloaded as needed + PU_HWRPATCHINFO_UNLOCKED = 103, // 'unlocked' PU_HWRMODELTEXTURE memory +}; +// +// Zone memory initialisation +// void Z_Init(void); -void Z_FreeTags(INT32 lowtag, INT32 hightag); -void Z_CheckMemCleanup(void); -void Z_CheckHeap(INT32 i); -#ifdef PARANOIA -void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line); -#else -void Z_ChangeTag2(void *ptr, INT32 tag); -#endif - -#ifdef PARANOIA -void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line); -#else -void Z_SetUser2(void *ptr, void **newuser); -#endif +// +// Zone memory allocation +// +// enable ZDEBUG to get the file + line the functions were called from +// for ZZ_Alloc, see doomdef.h +// // Z_Free and alloc with alignment #ifdef ZDEBUG @@ -99,31 +107,51 @@ void *Z_ReallocAlign(void *ptr, size_t size, INT32 tag, void *user, INT32 alignb #define Z_Calloc(s,t,u) Z_CallocAlign(s, t, u, sizeof(void *)) #define Z_Realloc(p,s,t,u) Z_ReallocAlign(p, s, t, u, sizeof(void *)) +// Free all memory by tag +// these don't give line numbers for ZDEBUG currently though +// (perhaps this should be changed in future?) +#define Z_FreeTag(tagnum) Z_FreeTags(tagnum, tagnum) +void Z_FreeTags(INT32 lowtag, INT32 hightag); -size_t Z_TagUsage(INT32 tagnum); -size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); +// Iterate memory by tag +#define Z_IterateTag(tagnum, func) Z_IterateTags(tagnum, tagnum, func) +void Z_IterateTags(INT32 lowtag, INT32 hightag, boolean (*iterfunc)(void *)); -char *Z_StrDup(const char *in); +// +// Utility functions +// +void Z_CheckMemCleanup(void); +void Z_CheckHeap(INT32 i); -// This is used to get the local FILE : LINE info from CPP -// prior to really call the function in question. +// +// Zone memory modification +// +// enable PARANOIA to get the file + line the functions were called from // #ifdef PARANOIA #define Z_ChangeTag(p,t) Z_ChangeTag2(p, t, __FILE__, __LINE__) +#define Z_SetUser(p,u) Z_SetUser2(p, u, __FILE__, __LINE__) +void Z_ChangeTag2(void *ptr, INT32 tag, const char *file, INT32 line); +void Z_SetUser2(void *ptr, void **newuser, const char *file, INT32 line); #else -#define Z_ChangeTag(p,t) Z_ChangeTag2(p, t) +void Z_ChangeTag(void *ptr, INT32 tag); +void Z_SetUser(void *ptr, void **newuser); #endif -#ifdef PARANOIA -#define Z_SetUser(p,u) Z_SetUser2(p, u, __FILE__, __LINE__) -#else -#define Z_SetUser(p,u) Z_SetUser2(p, u) -#endif +// +// Zone memory usage +// +// Note: These give the memory used in bytes, +// shift down by 10 to convert to KB +// +#define Z_TagUsage(tagnum) Z_TagsUsage(tagnum, tagnum) +size_t Z_TagsUsage(INT32 lowtag, INT32 hightag); +#define Z_TotalUsage() Z_TagsUsage(0, INT32_MAX) -#ifdef _NDS ///TODO: need a lock reference system -#define Z_Unlock(p) Z_ChangeTag(p, PU_CACHE_UNLOCKED) -#else -#define Z_Unlock(p) (void)p -#endif +// +// Miscellaneous functions +// +char *Z_StrDup(const char *in); +#define Z_Unlock(p) (void)p // TODO: remove this now that NDS code has been removed #endif -- 2.54.0 From a9c1e50cf88abd1792eb22299d4af8fcf153b654 Mon Sep 17 00:00:00 2001 From: xyzzy Date: Wed, 2 Aug 2023 15:12:53 +0300 Subject: [PATCH 2/2] Add missing files to .gitignore --- .gitignore | 4 +++- assets/.gitignore | 1 + src/CMakeLists.txt | 8 ++++++++ src/sdl/CMakeLists.txt | 20 ++++++++++---------- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index 797ea03df..8b73f04f5 100644 --- a/.gitignore +++ b/.gitignore @@ -23,4 +23,6 @@ Win32_LIB_ASM_Release /assets/debian compile.sh *.gz -.vscode/ \ No newline at end of file +.vscode/ +out +build diff --git a/assets/.gitignore b/assets/.gitignore index b9dc7c70d..52c1d72f4 100644 --- a/assets/.gitignore +++ b/assets/.gitignore @@ -10,3 +10,4 @@ !LICENSE-3RD-PARTY.txt !CMakeLists.txt !debian-template/* +installer diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index db19cbe81..e4eb9f134 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -12,6 +12,7 @@ set(SRB2_CORE_SOURCES d_net.c d_netcmd.c d_netfil.c + d_protocol.c dehacked.c f_finale.c f_wipe.c @@ -31,6 +32,7 @@ set(SRB2_CORE_SOURCES m_fixed.c m_menu.c m_misc.c + m_perfstats.c m_queue.c m_random.c md5.c @@ -61,6 +63,7 @@ set(SRB2_CORE_HEADERS d_netcmd.h d_netfil.h d_player.h + d_protocol.h d_think.h d_ticcmd.h dehacked.h @@ -97,6 +100,7 @@ set(SRB2_CORE_HEADERS m_menu.h m_misc.h m_queue.h + m_perfstats.h m_random.h m_swap.h md5.h @@ -121,6 +125,7 @@ set(SRB2_CORE_RENDER_SOURCES r_draw.c r_fps.c r_main.c + r_patch.c r_plane.c r_segs.c r_sky.c @@ -134,6 +139,7 @@ set(SRB2_CORE_RENDER_SOURCES r_fps.h r_local.h r_main.h + r_patch r_plane.h r_segs.h r_sky.h @@ -261,6 +267,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) lua_script.c lua_skinlib.c lua_thinkerlib.c + lua_udatalib.c ) set(SRB2_LUA_HEADERS lua_hook.h @@ -268,6 +275,7 @@ if(${SRB2_CONFIG_HAVE_BLUA}) lua_hudlib_drawlist.h lua_libs.h lua_script.h + lua_udatalib.h ) prepend_sources(SRB2_LUA_SOURCES) diff --git a/src/sdl/CMakeLists.txt b/src/sdl/CMakeLists.txt index b20adb096..67df4a646 100644 --- a/src/sdl/CMakeLists.txt +++ b/src/sdl/CMakeLists.txt @@ -274,16 +274,16 @@ if(${SDL2_FOUND}) ) ## strip debug symbols into separate file when using gcc - if(CMAKE_COMPILER_IS_GNUCC) - if(${CMAKE_BUILD_TYPE} MATCHES Debug) - message(STATUS "Will make separate debug symbols in *.debug") - add_custom_command(TARGET SRB2SDL2 POST_BUILD - COMMAND ${OBJCOPY} --only-keep-debug $ $.debug - COMMAND ${OBJCOPY} --strip-debug $ - COMMAND ${OBJCOPY} --add-gnu-debuglink=$.debug $ - ) - endif() - endif() + # if(CMAKE_COMPILER_IS_GNUCC) + # if(${CMAKE_BUILD_TYPE} MATCHES Debug) + # message(STATUS "Will make separate debug symbols in *.debug") + # add_custom_command(TARGET SRB2SDL2 POST_BUILD + # COMMAND ${OBJCOPY} --only-keep-debug $ $.debug + # COMMAND ${OBJCOPY} --strip-debug $ + # COMMAND ${OBJCOPY} --add-gnu-debuglink=$.debug $ + # ) + # endif() + # endif() #### Installation #### if(${CMAKE_SYSTEM} MATCHES Darwin) -- 2.54.0