⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 enhanced_zone_handling.txt

📁 quake1 dos源代码最新版本
💻 TXT
字号:
================================================================
Title         : Tutorial: Implementing the Enhanced Zone Handling into the Quake engine
Date          : 2001-09-20
Filename      : ENHANCED_ZONE_HANDLING.TXT
Author        : Matthias "Maddes" Buecher
Email Address : maddes@go.to
Homepage      : Quake Info Pool
                http://www.quake-info-pool.net/
                Quake Standards Group (short QSG)
                http://www.quakesrc.org/
Complexity    : Moderate
================================================================

On some occassions you can see that id wanted to use different zones, but the
implementation in the original source only deals with "mainzone".

This tutorial will enhance the zone handling of the Quake engine to handle many
different zones. To accomplish this all zone handling functions will get a zone
pointer as a new parameter, which tells them the zone to process.



But first we will increase the default/minimum size for the mainzone.

At top of ZONE.C remove the definition of DYNAMIC_SIZE and place the new
definition ZONE_MIN_SIZE at top of ZONE.H. This way you can access it in the
whole source code.

#define	ZONE_MIN_SIZE	128*1024	// 128K	// 2001-09-20 Increased default zone by Maddes

In ZONE.C change all occurences of DYNAMIC_SIZE into ZONE_MIN_SIZE.

At the end of ZONE.C in Memory_Init() change...

	p = COM_CheckParm ("-zone");
	if (p)
	{
		if (p < com_argc-1)
			zonesize = Q_atoi (com_argv[p+1]) * 1024;
		else
			Sys_Error ("Memory_Init: you must specify a size in KB after -zone");
	}

    ... into ...

	p = COM_CheckParm ("-zone");
	if (p)
	{
		if (p < com_argc-1)
		{	// 2001-09-20 Increased default zone by Maddes
			zonesize = Q_atoi (com_argv[p+1]) * 1024;
// 2001-09-20 Increased default zone by Maddes  start
			if (zonesize < ZONE_MIN_SIZE)
			{
				zonesize = ZONE_MIN_SIZE;
			}
		}
// 2001-09-20 Increased default zone by Maddes  end
		else
			Sys_Error ("Memory_Init: you must specify a size in KB after -zone");
	}



Now we will add the new parameter "memzone_t *zone" to all Z_* functions in ZONE.C.
Just add it as the first parameter like it already is for Z_ClearZone() and
Z_Print(), for example the definition of Z_Free() will look like this...

void Z_Free (memzone_t *zone, void *ptr)	// 2001-09-20 Enhanced zone handling by Maddes

Also change Z_Malloc(), Z_TagMalloc() and Z_CheckHeap() accordingly.


To make the functions work as we want to, you have to replace the usage of
"mainzone" with the "zone" parameter in all Z_* functions of ZONE.C. This is
necessary in Z_Free(), Z_Malloc(), Z_TagMalloc(), Z_Print() and Z_CheckHeap().

Note that Z_Malloc() also calls Z_CheckHeap() and Z_TagMalloc(), and you have to
pass the "zone" parameter too.


As the functions have changed, we have to change their declarations in ZONE.H.
The structure definitions of "memblock_t" and "memzone_t" have to be moved from
ZONE.C to ZONE.H too, as "mainzone" has to be declared in ZONE.H, so we can use
it throughout the engine for the Z_Malloc() and Z_Free() calls.

Add the definitions at the top of ZONE.H ...

// 2001-09-20 Enhanced zone handling by Maddes  start
typedef struct memblock_s
{
	int		size;           // including the header and possibly tiny fragments
	int     tag;            // a tag of 0 is a free block
	int     id;        		// should be ZONEID
	struct	memblock_s	*next, *prev;
//	int		pad;			// pad to 64-bit / 8-byte boundary
	struct	memzone_s	*zone;
} memblock_t;

typedef struct memzone_s
{
	int		size;		// total bytes malloced, including header
	memblock_t	blocklist;		// start / end cap for linked list
	memblock_t	*rover;
} memzone_t;

extern	memzone_t	*mainzone;
// 2001-09-20 Enhanced zone handling by Maddes  end

    ... and delete those lines from the top of ZONE.C.

Change the function declarations in ZONE.H from ...

void Z_Free (void *ptr);
void *Z_Malloc (int size);			// returns 0 filled memory
void *Z_TagMalloc (int size, int tag);

void Z_DumpHeap (void);
void Z_CheckHeap (void);
int Z_FreeMemory (void);

   ... into ...

// 2001-09-20 Enhanced zone handling by Maddes  start
void Z_ClearZone (memzone_t *zone, int size);
void Z_Free (memzone_t *zone, void *ptr);
void *Z_Malloc (memzone_t *zone, int size);			// returns 0 filled memory
void *Z_TagMalloc (memzone_t *zone, int size, int tag);

void Z_Print (memzone_t *zone);
void Z_CheckHeap (memzone_t *zone);
// 2001-09-20 Enhanced zone handling by Maddes  end

    ... which also removes the declarations of unexisting functions.


To make the engine compile again, add "mainzone" as the first parameter to all
calls of Z_Free() and Z_Malloc() throughout the engine.


The engine can now handle different zones, but if something goes wrong while
allocating or freeing memory then we don't know in which zone the error occured.

Move the structure definition of "hunk_t" to the top of ZONE.C and change Z_Free() to...

void Z_Free (memzone_t *zone, void *ptr)	// 2001-09-20 Enhanced zone handling by Maddes
{
	memblock_t	*block, *other;
// 2001-09-20 Enhanced zone handling by Maddes  start
	hunk_t	*h;

	h = (hunk_t *)zone;
	h--;
// 2001-09-20 Enhanced zone handling by Maddes  end

	if (!ptr)
		Sys_Error ("Z_Free: NULL pointer");

	block = (memblock_t *) ( (byte *)ptr - sizeof(memblock_t));
	if (block->id != ZONEID)
// 2001-09-20 Enhanced zone handling by Maddes  start
	{
//		Sys_Error ("Z_Free: freed a pointer without ZONEID");
		Sys_Error ("Z_Free: freed a pointer without ZONEID in \"%s\"", h->name);
	}
// 2001-09-20 Enhanced zone handling by Maddes  end
	if (block->tag == 0)
// 2001-09-20 Enhanced zone handling by Maddes  start
	{
//		Sys_Error ("Z_Free: freed a freed pointer");
		Sys_Error ("Z_Free: freed a freed pointer in \"%s\"", h->name);
	}
// 2001-09-20 Enhanced zone handling by Maddes  end

// 2001-09-20 Enhanced zone handling by Maddes  start
	if (block->zone != zone)
	{
		Sys_Error ("Z_Free: freed a foreign pointer in \"%s\"\n", h->name);
	}
// 2001-09-20 Enhanced zone handling by Maddes  end

	block->tag = 0;		// mark as free

	other = block->prev;
	if (!other->tag)
	{	// merge with previous free block
		other->size += block->size;
		other->next = block->next;
		other->next->prev = other;
		if (block == zone->rover)	// 2001-09-20 Enhanced zone handling by Maddes
			zone->rover = other;	// 2001-09-20 Enhanced zone handling by Maddes
		block = other;
	}

	other = block->next;
	if (!other->tag)
	{	// merge the next free block onto the end
		block->size += other->size;
		block->next = other->next;
		block->next->prev = block;
		if (other == zone->rover)	// 2001-09-20 Enhanced zone handling by Maddes
			zone->rover = block;	// 2001-09-20 Enhanced zone handling by Maddes
	}
}

    ... and do a similar change to Z_Malloc() ...

void *Z_Malloc (memzone_t *zone, int size)	// 2001-09-20 Enhanced zone handling by Maddes
{
	void	*buf;

	Z_CheckHeap (zone);	// DEBUG	// 2001-09-20 Enhanced zone handling by Maddes
	buf = Z_TagMalloc (zone, size, 1);	// 2001-09-20 Enhanced zone handling by Maddes
	if (!buf)
// 2001-09-20 Enhanced zone handling by Maddes  start
	{
		hunk_t	*h;

		h = (hunk_t *)zone;
		h--;

//		Sys_Error ("Z_Malloc: failed on allocation of %i bytes",size);
		Sys_Error ("Z_Malloc: failed on allocation of %i bytes in \"%s\"", size, h->name);
	}
// 2001-09-20 Enhanced zone handling by Maddes  end

	Q_memset (buf, 0, size);

	return buf;
}

    ... at last we have to set the original zone of the block in Z_TagMalloc after 
    the id of the block is set...

	base->id = ZONEID;

	base->zone = zone;		// 2001-09-20 Enhanced zone handling by Maddes

Done.



When you add a new zone to the engine, define a zone pointer at top of ZONE.C...

// 2001-09-20 New tutorial zone by Maddes  start
memzone_t	*zone_sample;
int			zonesize_sample;
// 2001-09-20 New tutorial zone by Maddes  end

    ... declare it in ZONE.H for other source files ...

// 2001-09-20 New tutorial zone by Maddes  start
extern memzone_t	*zone_sample;
extern int			zonesize_sample;
// 2001-09-20 New tutorial zone by Maddes  end

    ... and allocate the zone memory at the end of Z_MemoryInit() in ZONE.C ...

// 2001-09-20 New tutorial zone by Maddes  start
	zonesize_sample = ZONE_MIN_SIZE;
	p = COM_CheckParm ("-samplezone");
	if (p)
	{
		if (p < com_argc-1)
		{
			zonesize_sample = Q_atoi (com_argv[p+1]) * 1024;
			if (zonesize_sample < ZONE_MIN_SIZE)
			{
				zonesize_sample = ZONE_MIN_SIZE;
			}
		}
		else
			Sys_Error ("Memory_Init: you must specify a size in KB after -samplezone");
	}
	zone_sample = Hunk_AllocName (zonesize_sample, "sample");
	Z_ClearZone (zone_sample, zonesize_sample);
// 2001-09-20 New tutorial zone by Maddes  end

Note that the zone name should only have 7 characters.

Now you can use the new zone throughout the engine in the following way...

	void	*ptr;

	Z_ClearZone (zone_sample, zonesize_sample);
	...
	ptr = Z_Malloc (zone_sample, 1024);
	...
	Z_Free (zone_sample, ptr);

That's it for the zone handling.


At last I show you how to add two new commands which help you to determine how
much mem is allocated for all the hunks and caches.

The first is "cachelist", just add the following line at the end of Memory_Init()...

	Cmd_AddCommand ("cachelist", Cache_Print);	// 2001-09-20 Cachelist command by Maddes

The second is "hunklist", add the following function behind Hunk_Print()...

// 2001-09-20 Hunklist command by Maddes  start
/*
===================
Hunk_Print_f
===================
*/
void Hunk_Print_f(void)
{
	qboolean	showall;

	showall = 0;
	if (Cmd_Argc() > 1)
	{
		showall = Q_atoi(Cmd_Argv(1));
	}

	Hunk_Print(showall);
}
// 2001-09-20 Hunklist command by Maddes  end

...and again add the following line at the end of Memory_Init()...

	Cmd_AddCommand ("hunklist", Hunk_Print_f);	// 2001-09-20 Hunklist command by Maddes

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -