diff --git a/cgdoom/cgdoom.c b/cgdoom/cgdoom.c index b1ebd79..4349566 100644 --- a/cgdoom/cgdoom.c +++ b/cgdoom/cgdoom.c @@ -378,18 +378,13 @@ static FileMapping gWADMap; /* Index of most likely sectors for fragment search. (CGDOOM_WAD_MMAP) */ static SectorIndexInfo *gIndex = NULL; -/* Developer statistics */ -static int gDevFragments = 0; -static int gDevIndexHits = 0; -static const void *gDevLowestFragment = NULL; -int gDevUnalignedLumpLoads = 0; -int gDevUnalignedLumpSize = 0; - /* Global options */ int CGD_TrustUnalignedLumps = 0; /* Performance counters */ struct CGD_Perf CGD_Perf; +/* Developer statistics */ +struct CGD_Stats CGD_Stats; /* Read next sector from file, while caching into a buffer. */ const void *ReadNextSector(FileAccessCache *fc, int *size) @@ -451,7 +446,7 @@ int FindSectorInFlash(const void *buf, int size) typeof(&memcmp) memcmp_fun = &memcmp; if(size == FLASH_PAGE_SIZE) memcmp_fun = &CGD_sector_memcmp; - gDevFragments++; + CGD_Stats.WADFragments++; #ifdef FLASH_INDEX /* If an index has been built, search in it */ @@ -459,7 +454,7 @@ int FindSectorInFlash(const void *buf, int size) IndexSearchSector(gIndex, buf, &lo, &hi); for(int i = lo; i < hi; i++) { if(!memcmp_fun(buf, gIndex[i].sector, size)) { - gDevIndexHits++; + CGD_Stats.WADIndexHits++; return (gIndex[i].sector - FLASH_START) / FLASH_PAGE_SIZE; } } @@ -515,8 +510,8 @@ int CreateFileMapping(int fd, FileMapping *pMap) /* Look for consecutive sectors in the same fragment */ const void *pFragment = FLASH_START + (iSectorID * FLASH_PAGE_SIZE); - if(!gDevLowestFragment || pFragment < gDevLowestFragment) - gDevLowestFragment = pFragment; + if(!CGD_Stats.WADLowestFragment || pFragment> 10); + Layout_Spacing(&l, 12); + + Layout_Text(&l, "Lumps loaded:", "%d (%d kB)", + CGD_Stats.LumpsLoaded, + (int)(CGD_Stats.LumpsLoadedTotal >> 10)); + Layout_Text(&l, "... of which unaligned:", "%d (%d kB)", + CGD_Stats.UnalignedLumpsLoaded, + (int)(CGD_Stats.UnalignedLumpsLoadedTotal >> 10)); + Layout_Text(&l, "Lumps referenced:", "%d (%d kB)", + CGD_Stats.LumpsReferenced, + (int)(CGD_Stats.LumpsReferencedTotal >> 10)); Bdisp_FrameAndColor(3, 16); Bdisp_FrameAndColor(1, 0); Bdisp_PutDisp_DD(); diff --git a/cgdoom/cgdoom.h b/cgdoom/cgdoom.h index a3b0372..d3fcc2e 100644 --- a/cgdoom/cgdoom.h +++ b/cgdoom/cgdoom.h @@ -59,4 +59,28 @@ struct CGD_Perf prof_t UnalignedLumpLoading; }; +struct CGD_Stats +{ + /* Fragments in the WAD file */ + int WADFragments; + /* Lowest fragment address (hints at filesystem entry point) */ + void const *WADLowestFragment; + /* Number of index hits during fragment search */ + int WADIndexHits; + + /* Total memory allocated with Z_Malloc (bytes) */ + uint32_t MemoryAllocated; + + /* Number of lumps loaded, number of lumps not loaded (addressed directly in + ROM), number of unaligned lumps loaded */ + int LumpsLoaded; + int LumpsReferenced; + int UnalignedLumpsLoaded; + + /* The total size for these three catefories (bytes) */ + uint64_t LumpsLoadedTotal; + uint64_t LumpsReferencedTotal; + uint64_t UnalignedLumpsLoadedTotal; +}; + #endif /* CGDOOM_H */ diff --git a/cgdoom/dstrings.c b/cgdoom/dstrings.c index f41ed6c..77d289e 100644 --- a/cgdoom/dstrings.c +++ b/cgdoom/dstrings.c @@ -25,8 +25,7 @@ -const char* endmsg[NUM_QUITMESSAGES+1]= -{ +const char * const endmsg[NUM_QUITMESSAGES+1] = { // DOOM1 QUITMSG, "please don't leave, there's more\ndemons to toast!", diff --git a/cgdoom/dstrings.h b/cgdoom/dstrings.h index 3f5016a..4692ad3 100644 --- a/cgdoom/dstrings.h +++ b/cgdoom/dstrings.h @@ -46,7 +46,7 @@ // QuitDOOM messages #define NUM_QUITMESSAGES 22 -extern const char* endmsg[]; +extern const char * const endmsg[]; #endif diff --git a/cgdoom/info.c b/cgdoom/info.c index ce83063..e316d84 100644 --- a/cgdoom/info.c +++ b/cgdoom/info.c @@ -54,7 +54,7 @@ const char sprnames[NUMSPRITES][5] = { }; -state_t states[NUMSTATES] = { +state_t const states[NUMSTATES] = { {SPR_TROO,0,-1,0,S_NULL,0,0}, // S_NULL {SPR_SHTG,4,0,TA_Light0,S_NULL,0,0}, // S_LIGHTDONE {SPR_PUNG,0,1,TA_WeaponReady,S_PUNCH,0,0}, // S_PUNCH diff --git a/cgdoom/info.h b/cgdoom/info.h index 2463ce4..7269ede 100644 --- a/cgdoom/info.h +++ b/cgdoom/info.h @@ -1156,7 +1156,7 @@ typedef struct long misc1, misc2; } state_t; -extern state_t states[NUMSTATES]; +extern state_t const states[NUMSTATES]; extern const char sprnames[NUMSPRITES][5]; diff --git a/cgdoom/os.h b/cgdoom/os.h index 1724763..53fbf83 100644 --- a/cgdoom/os.h +++ b/cgdoom/os.h @@ -1,18 +1,15 @@ #include "platform.h" +#define SYSTEM_STACK_SAFE (64*1024) +#define USER_STACK_SAFE (32*1024) -//CGDOOM -#define SYSTEM_STACK_SAFE (90*1024) -#define USER_STACK_SAFE (40*1024) - -//memory mapping: -//0x880A2AD5..0x880CB2D5:SaveVRAMBuffer 165888 bytes +// SaveVRAMBuffer 165888 bytes #define SAVE_VRAM_SIZE (WIDTH*HEIGHT*2-3) -extern unsigned char *SaveVRAMBuffer;//[SAVE_VRAM_SIZE]; +extern unsigned char *SaveVRAMBuffer; -//0xA80F0000..0xA815FFFF: system stack (512 kB). +// system stack (512 kB). #define SYSTEM_STACK_SIZE (512*1024-SYSTEM_STACK_SAFE) -extern unsigned char *SystemStack;//[SYSTEM_STACK_SIZE]; +extern unsigned char *SystemStack; extern unsigned short *VRAM; void * CGDMalloc(int iSize); diff --git a/cgdoom/w_wad.c b/cgdoom/w_wad.c index 7962252..83b0444 100644 --- a/cgdoom/w_wad.c +++ b/cgdoom/w_wad.c @@ -302,7 +302,6 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash) { c = FindInFlash((const void **)&lumpcache[lump], lumpinfo[lump].size, lumpinfo[lump].position); } -// else ASSERT(lumpinfo[lump].size != 10240); int full = (c == lumpinfo[lump].size); int aligned = (((uint32_t)lumpcache[lump] & 1) == 0); @@ -311,11 +310,10 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash) aligned = 1; /* Record statistics on loading unaligned but full lumps */ - extern int gDevUnalignedLumpLoads; - extern int gDevUnalignedLumpSize; + extern struct CGD_Stats CGD_Stats; if(full && !aligned) { - gDevUnalignedLumpLoads++; - gDevUnalignedLumpSize += lumpinfo[lump].size; + CGD_Stats.UnalignedLumpsLoaded++; + CGD_Stats.UnalignedLumpsLoadedTotal += lumpinfo[lump].size; } /* Allocate only if the lump spans several fragments, or is misaligned; @@ -323,11 +321,13 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash) the heap would provide. */ if(!full || !aligned) { + CGD_Stats.LumpsLoaded++; + CGD_Stats.LumpsLoadedTotal += lumpinfo[lump].size; + prof_enter(CGD_Perf.LumpLoading); if(!aligned) prof_enter(CGD_Perf.UnalignedLumpLoading); - Z_Malloc (lumpinfo[lump].size, tag, &lumpcache[lump]); W_ReadLump (lump, lumpcache[lump]); @@ -335,6 +335,11 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash) prof_leave(CGD_Perf.UnalignedLumpLoading); prof_leave(CGD_Perf.LumpLoading); } + else + { + CGD_Stats.LumpsReferenced++; + CGD_Stats.LumpsReferencedTotal += lumpinfo[lump].size; + } return lumpcache[lump]; } @@ -345,29 +350,20 @@ void * W_ReadLumpWithZ_Malloc(int lump,int tag,int iEnableFlash) // static void* W_CacheLumpNumCommon( int lump, int tag,int iEnableFlash) { - if (lump >= numlumps) { I_Error ("W_CacheLumpNum: %i >= numlumps (%i)",lump,numlumps); } - - //printf("x"); - if (!lumpcache[lump]) { - // try to find in flash (may fail if the piece is in 2 fragments (file fragmentaion) W_ReadLumpWithZ_Malloc(lump,tag,iEnableFlash); } else { - //printf ("cache hit on lump %i\n",lump); Z_ChangeTag (lumpcache[lump],tag); } - /*if (lump==1203) - printf("sky access, returning %x \n",lumpcache[lump]);*/ - if(lumpcache[lump] == NULL) I_ErrorI("W_CacheLumpNumCommon", (int)lumpcache[lump], lump, 0, 0); diff --git a/cgdoom/z_zone.c b/cgdoom/z_zone.c index cc60aa5..2746488 100644 --- a/cgdoom/z_zone.c +++ b/cgdoom/z_zone.c @@ -51,7 +51,7 @@ typedef struct memblock_t* rover; } memzone_t; -/* CGDOOM: In order to increase available memory, we need to support multiple +/* CGDoom: In order to increase available memory, we need to support multiple zones. The code below is adapted to do that: * Z_ClearZone is already parameterized, nothing to do (it's never called) @@ -64,13 +64,16 @@ typedef struct * Z_FreeMemory is changed to iterate on one or all zones In addition to that, the next-fit strategy with a rover also runs over zones - since starting at the first zone when it's full loses *a lot* of time. */ -static memzone_t *zones[ZONE_MAX]; -static int zone_count; + since starting at the first zone when it's full loses *a lot* of time. + However, the next-fit strategy tends to produce *a lot* of fragmentation, + resulting in early allocation failures due to the lack of large spaces. For + this reason, the last region is not part of the zone rover rotation. */ + +static memzone_t *zones[ZONE_MAX]; /* static memzone_t *mainzone; */ +static int zone_count; static int zone_rover = 0; -// static memzone_t* mainzone; // @@ -225,6 +228,7 @@ void Z_Free (const void* ptr) void* Z_Malloc( int size, int tag, void* user ) { prof_enter(CGD_Perf.DynamicAllocation); + CGD_Stats.MemoryAllocated += size; static int iCalled = 0; int extra; @@ -308,15 +312,22 @@ void* Z_Malloc( int size, int tag, void* user ) if (failed) { - zone_no++; - if(zone_no == zone_count) - zone_no = 0; - if(zone_no == zone_start) + if (zone_no == zone_count - 1) { I_ErrorI ("Z_Malloc failure", size, 0, 0, 0); prof_leave(CGD_Perf.DynamicAllocation); return NULL; } + + /* When rotating, perform a full cycle before defaulting to the last + zone; this preserves the last zone to avoid fragmentation and absorb + occasional large chunks */ + zone_no++; + if(zone_no == zone_count - 1) + zone_no = 0; + if(zone_no == zone_start) + zone_no = zone_count - 1; + zone = zones[zone_no]; } else break; @@ -362,7 +373,8 @@ void* Z_Malloc( int size, int tag, void* user ) // next allocation will start looking here zone->rover = base->next; - zone_rover = zone_no; + if (zone_no != zone_count - 1) + zone_rover = zone_no; base->id = ZONEID; @@ -500,3 +512,37 @@ int Z_FreeMemory (int zone) return free; } + + +// +// Z_LargestFreeBlock +// +int Z_LargestFreeBlock (int zone) +{ + if (zone < 0) + { + int maxsize = 0; + for (int i = 0; i < zone_count; i++) { + int n = Z_LargestFreeBlock(i); + if (n > maxsize) + maxsize = n; + } + return maxsize; + } + + memblock_t* block; + int maxsize = 0; + + memzone_t* mainzone = zones[zone]; + + for(block = mainzone->blocklist.next;block != &mainzone->blocklist;block = block->next) + { + if (!block->user || block->tag >= PU_PURGELEVEL) + { + if (block->size > maxsize) + maxsize = block->size; + } + } + + return maxsize; +} diff --git a/cgdoom/z_zone.h b/cgdoom/z_zone.h index 03f2d02..8ff90ec 100644 --- a/cgdoom/z_zone.h +++ b/cgdoom/z_zone.h @@ -53,10 +53,12 @@ void Z_DumpHeap (int lowtag, int hightag); void Z_CheckHeap (void); void Z_ChangeTag2 (const void *ptr, int tag); -/* CGDOOM: Returns free memory in specified zone, or all zones if zone < 0 */ +/* CGDoom: Returns free memory in specified zone, or all zones if zone < 0 */ int Z_FreeMemory (int zone); +/* CGDoom: Returns largest free block in specified zone, or all if zone < 0 */ +int Z_LargestFreeBlock (int zone); -/* CGDOOM: Support for multiple zones is added; Z_Init() now does nothing, +/* CGDoom: Support for multiple zones is added; Z_Init() now does nothing, zones need to be added manually (see D_DoomMain()). */ void Z_AddZone (void *zone, int size); diff --git a/src-cg/platform.h b/src-cg/platform.h index 25652df..45dab2c 100644 --- a/src-cg/platform.h +++ b/src-cg/platform.h @@ -80,6 +80,7 @@ extern int CGD_TrustUnalignedLumps; #endif extern struct CGD_Perf CGD_Perf; +extern struct CGD_Stats CGD_Stats; //---