ref: 41f0fca28c4087f9c3520c92f79d6e03334a7195
parent: d3fd0ce3fd223f7acfdba6ea650cba84f3d2db57
author: Sigrid Solveig Haflínudóttir <sigrid@ftrv.se>
date: Mon Oct 9 20:57:02 EDT 2023
normal quake: completely rewrite memory management; increase default limits "Zone" is no longer. Use malloc/free instead, with double-linked lists. This makes -m cmdline argument obsolete - memory is allocated dynamically and the engine no longer falls over on Arcane Dimensions entry map.
--- a/bspfile.h
+++ b/bspfile.h
@@ -10,7 +10,7 @@
#define MAX_MAP_PLANES 32767
#define MAX_MAP_NODES 32767 // because negative shorts are contents
#define MAX_MAP_CLIPNODES 32767 //
-#define MAX_MAP_LEAFS 8192
+#define MAX_MAP_LEAFS 65535
#define MAX_MAP_VERTS 65535
#define MAX_MAP_FACES 65535
#define MAX_MAP_MARKSURFACES 65535
--- a/cl_main.c
+++ b/cl_main.c
@@ -183,7 +183,6 @@
case 3:
MSG_WriteByte (&cls.message, clc_stringcmd);
MSG_WriteString (&cls.message, "begin");
- Cache_Report (); // print remaining memory
break;
case 4:
--- a/cl_parse.c
+++ b/cl_parse.c
@@ -213,7 +213,7 @@
Con_Printf("Bad maxclients (%d) from server\n", cl.maxclients);
return;
}
- cl.scores = Hunk_AllocName(cl.maxclients * sizeof *cl.scores, "scores");
+ cl.scores = Hunk_Alloc(cl.maxclients * sizeof *cl.scores);
// parse gametype
cl.gametype = MSG_ReadByte ();
@@ -291,8 +291,6 @@
R_NewMap ();
- Hunk_Check (); // make sure nothing is hurt
-
noclip_anglehack = false; // noclip is turned off at start
}
--- a/client.h
+++ b/client.h
@@ -65,7 +65,7 @@
vec3_t start, end;
} beam_t;
-#define MAX_EFRAGS 640
+#define MAX_EFRAGS 4096
#define MAX_MAPSTRING 2048
#define MAX_DEMOS 8
@@ -267,7 +267,7 @@
void CL_Disconnect_f (void);
void CL_NextDemo (void);
-#define MAX_VISEDICTS 256
+#define MAX_VISEDICTS 4096
extern int cl_numvisedicts;
extern entity_t *cl_visedicts[MAX_VISEDICTS];
--- a/cmd.c
+++ b/cmd.c
@@ -264,7 +264,7 @@
void Cmd_Exec_f (void)
{
char *f;
- int mark;
+ void *mark;
if (Cmd_Argc () != 2)
{
@@ -272,7 +272,7 @@
return;
}
- mark = Hunk_LowMark ();
+ mark = Hunk_Mark ();
f = loadhunklmp(Cmd_Argv(1), nil);
if(f == nil){
Con_Printf(va("exec: %r\n"));
@@ -281,7 +281,7 @@
Con_Printf ("execing %s\n",Cmd_Argv(1));
Cbuf_InsertText (f);
- Hunk_FreeToLowMark (mark);
+ Hunk_FreeToMark (mark);
}
--- a/common.c
+++ b/common.c
@@ -310,7 +310,7 @@
{
if(startsize < 256)
startsize = 256;
- buf->data = Hunk_AllocName(startsize, "sizebuf");
+ buf->data = Hunk_Alloc(startsize);
buf->maxsize = startsize;
buf->cursize = 0;
}
--- a/console.c
+++ b/console.c
@@ -175,7 +175,7 @@
*/
void Con_Init (void)
{
- con_text = Hunk_AllocName (CON_TEXTSIZE, "context");
+ con_text = Hunk_Alloc(CON_TEXTSIZE);
memset(con_text, ' ', CON_TEXTSIZE);
con_linewidth = -1;
Con_CheckResize ();
--- a/dat.h
+++ b/dat.h
@@ -1,8 +1,6 @@
typedef struct Sfx Sfx;
extern char *game;
-extern uchar *membase;
-extern int memsize;
enum{
Npath = 64,
--- a/draw.c
+++ b/draw.c
@@ -24,7 +24,7 @@
typedef struct cachepic_s
{
char name[Npath];
- cache_user_t cache;
+ mem_user_t cache;
} cachepic_t;
#define MAX_CACHED_PICS 128
--- a/fns.h
+++ b/fns.h
@@ -34,7 +34,7 @@
char* ext(char*, char*);
void radix(char*, char*);
void* loadhunklmp(char *, int *);
-void* loadcachelmp(char *, cache_user_t *);
+void* loadcachelmp(char *, mem_user_t *);
void* loadstklmp(char *, void *, int, int *);
void loadpoints(void);
void dumpcfg(void);
--- a/fs.c
+++ b/fs.c
@@ -104,7 +104,7 @@
static int notid1;
static int loadsize;
static uchar *loadbuf;
-static cache_user_t *loadcache;
+static mem_user_t *loadcache;
static Biobuf *demobf;
static vlong demoofs;
@@ -376,8 +376,8 @@
radix(f, r);
buf = nil;
switch(mth){
- case Fhunk: buf = Hunk_AllocName(m + 1, r); break;
- case Fcache: buf = Cache_Alloc(loadcache, m + 1, r); break;
+ case Fhunk: buf = Hunk_Alloc(m + 1); break;
+ case Fcache: buf = Cache_Alloc(loadcache, m + 1); break;
case Fstack: buf = m + 1 <= loadsize ? loadbuf : Hunk_TempAlloc(m + 1); break;
}
if(buf == nil)
@@ -397,7 +397,7 @@
}
void *
-loadcachelmp(char *f, cache_user_t *c)
+loadcachelmp(char *f, mem_user_t *c)
{
loadcache = c;
loadlmp(f, Fcache, nil);
@@ -828,7 +828,7 @@
fatal("pak %s: invalid lump number %d", f, nlmp);
if(nlmp != Npak0lmp)
notid1 = 1;
- l = Hunk_AllocName(nlmp * sizeof *l, "pak");
+ l = Hunk_Alloc(nlmp * sizeof *l);
p = Hunk_Alloc(sizeof *p);
strncpy(p->f, f, sizeof(p->f)-1);
p->bf = bf;
--- a/host.c
+++ b/host.c
@@ -24,7 +24,7 @@
double oldrealtime; // last frame run
int host_framecount;
-int host_hunklevel;
+void *host_hunklevel;
client_t *host_client; // current client
@@ -140,7 +140,7 @@
svs.maxclientslimit = svs.maxclients;
if (svs.maxclientslimit < 4)
svs.maxclientslimit = 4;
- svs.clients = Hunk_AllocName(svs.maxclientslimit * sizeof *svs.clients, "clients");
+ svs.clients = Hunk_Alloc(svs.maxclientslimit * sizeof *svs.clients);
if (svs.maxclients > 1)
setcvarv ("deathmatch", 1.0);
@@ -395,7 +395,7 @@
D_FlushCaches ();
Mod_ClearAll ();
if (host_hunklevel)
- Hunk_FreeToLowMark (host_hunklevel);
+ Hunk_FreeToMark (host_hunklevel);
cls.signon = 0;
memset(&sv, 0, sizeof sv);
@@ -597,7 +597,6 @@
Mod_Init ();
NET_Init ();
SV_Init ();
- dprint("%4.1f megabyte heap\n", memsize / (1024 * 1024.0));
R_InitTextures (); // needed even for dedicated servers
if (cls.state != ca_dedicated)
@@ -626,8 +625,7 @@
Cbuf_InsertText ("+mlook\n");
Cbuf_InsertText ("exec quake.rc\n");
- Hunk_AllocName (0, "-HOST_HUNKLEVEL-");
- host_hunklevel = Hunk_LowMark ();
+ host_hunklevel = Hunk_Mark ();
host_initialized = true;
}
--- a/model.c
+++ b/model.c
@@ -14,7 +14,7 @@
byte mod_novis[MAX_MAP_LEAFS/8];
-#define MAX_MOD_KNOWN 256
+#define MAX_MOD_KNOWN 4096
model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
@@ -339,7 +339,7 @@
m->nummiptex = LittleLong (m->nummiptex);
loadmodel->numtextures = m->nummiptex;
- loadmodel->textures = Hunk_AllocName(m->nummiptex * sizeof *loadmodel->textures, loadname);
+ loadmodel->textures = Hunk_Alloc(m->nummiptex * sizeof *loadmodel->textures);
for (i=0 ; i<m->nummiptex ; i++)
{
@@ -355,7 +355,7 @@
if ( (mt->width & 15) || (mt->height & 15) )
fatal ("Texture %s is not 16 aligned", mt->name);
pixels = mt->width*mt->height/64*85;
- tx = Hunk_AllocName(pixels + sizeof *tx, loadname);
+ tx = Hunk_Alloc(pixels + sizeof *tx);
loadmodel->textures[i] = tx;
memcpy(tx->name, mt->name, sizeof tx->name);
@@ -476,7 +476,7 @@
loadmodel->lightdata = nil;
return;
}
- loadmodel->lightdata = Hunk_AllocName(l->filelen, loadname);
+ loadmodel->lightdata = Hunk_Alloc(l->filelen);
memcpy(loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
}
@@ -493,7 +493,7 @@
loadmodel->visdata = nil;
return;
}
- loadmodel->visdata = Hunk_AllocName(l->filelen, loadname);
+ loadmodel->visdata = Hunk_Alloc(l->filelen);
memcpy(loadmodel->visdata, mod_base + l->fileofs, l->filelen);
}
@@ -510,7 +510,7 @@
loadmodel->entities = nil;
return;
}
- loadmodel->entities = Hunk_AllocName(l->filelen, loadname);
+ loadmodel->entities = Hunk_Alloc(l->filelen);
memcpy(loadmodel->entities, mod_base + l->fileofs, l->filelen);
}
@@ -530,7 +530,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadVertexes: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->vertexes = out;
loadmodel->numvertexes = count;
@@ -558,7 +558,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadSubmodels: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->submodels = out;
loadmodel->numsubmodels = count;
@@ -594,7 +594,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadEdges: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName((count+1) * sizeof *out, loadname);
+ out = Hunk_Alloc((count+1) * sizeof *out);
loadmodel->edges = out;
loadmodel->numedges = count;
@@ -623,7 +623,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadTexInfo: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->texinfo = out;
loadmodel->numtexinfo = count;
@@ -688,7 +688,7 @@
int bmins[2], bmaxs[2];
mins[0] = mins[1] = 999999;
- maxs[0] = maxs[1] = -99999;
+ maxs[0] = maxs[1] = -999999;
tex = s->texinfo;
@@ -742,7 +742,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadFaces: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->surfaces = out;
loadmodel->numsurfaces = count;
@@ -825,7 +825,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadNodes: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->nodes = out;
loadmodel->numnodes = count;
@@ -872,7 +872,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadLeafs: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->leafs = out;
loadmodel->numleafs = count;
@@ -919,7 +919,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadClipnodes: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->clipnodes = out;
loadmodel->numclipnodes = count;
@@ -974,7 +974,7 @@
in = loadmodel->nodes;
count = loadmodel->numnodes;
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
hull->clipnodes = out;
hull->firstclipnode = 0;
@@ -1010,7 +1010,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadMarksurfaces: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->marksurfaces = out;
loadmodel->nummarksurfaces = count;
@@ -1038,7 +1038,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadSurfedges: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * sizeof *out, loadname);
+ out = Hunk_Alloc(count * sizeof *out);
loadmodel->surfedges = out;
loadmodel->numsurfedges = count;
@@ -1064,7 +1064,7 @@
if (l->filelen % sizeof(*in))
fatal("Mod_LoadPlanes: funny lump size in %s", loadmodel->name);
count = l->filelen / sizeof(*in);
- out = Hunk_AllocName(count * 2 * sizeof *out, loadname);
+ out = Hunk_Alloc(count * 2 * sizeof *out);
loadmodel->planes = out;
loadmodel->numplanes = count;
@@ -1176,7 +1176,7 @@
if (i < mod->numsubmodels-1)
{ // duplicate the basic information
- char name[10];
+ char name[32];
sprint (name, "*%d", i+1);
loadmodel = Mod_FindName (name);
@@ -1220,10 +1220,9 @@
}
pinframe = (trivertx_t *)(pdaliasframe + 1);
- pframe = Hunk_AllocName(numv * sizeof *pframe, loadname);
+ *pframeindex = Hunk_From(pheader);
+ pframe = Hunk_Alloc(numv * sizeof *pframe);
- *pframeindex = (byte *)pframe - (byte *)pheader;
-
for (j=0 ; j<numv ; j++)
{
int k;
@@ -1262,8 +1261,9 @@
numframes = LittleLong (pingroup->numframes);
- paliasgroup = Hunk_AllocName(sizeof(*paliasgroup) +
- (numframes - 1) * sizeof paliasgroup->frames[0], loadname);
+ *pframeindex = Hunk_From(pheader);
+ paliasgroup = Hunk_Alloc(sizeof(*paliasgroup) +
+ (numframes - 1) * sizeof paliasgroup->frames[0]);
paliasgroup->numframes = numframes;
@@ -1274,14 +1274,11 @@
pbboxmax->v[i] = pingroup->bboxmax.v[i];
}
- *pframeindex = (byte *)paliasgroup - (byte *)pheader;
-
pin_intervals = (daliasinterval_t *)(pingroup + 1);
- poutintervals = Hunk_AllocName(numframes * sizeof *poutintervals, loadname);
+ paliasgroup->intervals = Hunk_From(pheader);
+ poutintervals = Hunk_Alloc(numframes * sizeof *poutintervals);
- paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader;
-
for (i=0 ; i<numframes ; i++)
{
*poutintervals = LittleFloat (pin_intervals->interval);
@@ -1312,9 +1309,9 @@
{
uchar *pskin, *pinskin;
- pskin = Hunk_AllocName(skinsize, loadname);
+ *pskinindex = Hunk_From(pheader);
+ pskin = Hunk_Alloc(skinsize);
pinskin = (uchar *)pin;
- *pskinindex = (uchar *)pskin - (uchar *)pheader;
memcpy(pskin, pinskin, skinsize);
pinskin += skinsize;
return (void *)pinskin;
@@ -1340,20 +1337,17 @@
numskins = LittleLong (pinskingroup->numskins);
- paliasskingroup = Hunk_AllocName(sizeof(*paliasskingroup) +
- (numskins - 1) * sizeof paliasskingroup->skindescs[0], loadname);
+ *pskinindex = Hunk_From(pheader);
+ paliasskingroup = Hunk_Alloc(sizeof(*paliasskingroup) +
+ (numskins - 1) * sizeof paliasskingroup->skindescs[0]);
paliasskingroup->numskins = numskins;
- *pskinindex = (byte *)paliasskingroup - (byte *)pheader;
-
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
- poutskinintervals = Hunk_AllocName(numskins * sizeof *poutskinintervals,
- loadname);
+ paliasskingroup->intervals = Hunk_From(pheader);
+ poutskinintervals = Hunk_Alloc(numskins * sizeof *poutskinintervals);
- paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader;
-
for (i=0 ; i<numskins ; i++)
{
*poutskinintervals = LittleFloat (pinskinintervals->interval);
@@ -1395,9 +1389,6 @@
daliasskintype_t *pskintype;
maliasskindesc_t *pskindesc;
int skinsize;
- int start, end, total;
-
- start = Hunk_LowMark ();
pinmodel = (mdl_t *)buffer;
@@ -1416,11 +1407,12 @@
LittleLong (pinmodel->numverts) * sizeof (stvert_t) +
LittleLong (pinmodel->numtris) * sizeof (mtriangle_t);
- pheader = Hunk_AllocName(size, loadname);
+ pheader = Hunk_Alloc(size);
pmodel = (mdl_t *) ((byte *)&pheader[1] +
(LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]));
-
+ pheader->model = (byte *)pmodel - (byte *)pheader;
+
// mod->cache.data = pheader;
mod->flags = LittleLong (pinmodel->flags);
@@ -1467,8 +1459,6 @@
if (pmodel->skinwidth & 0x03)
fatal ("Mod_LoadAliasModel: skinwidth not multiple of 4");
- pheader->model = (byte *)pmodel - (byte *)pheader;
-
//
// load the skins
//
@@ -1479,10 +1469,9 @@
pskintype = (daliasskintype_t *)&pinmodel[1];
- pskindesc = Hunk_AllocName(numskins * sizeof *pskindesc, loadname);
+ pheader->skindesc = Hunk_From(pheader);
+ pskindesc = Hunk_Alloc(numskins * sizeof *pskindesc);
- pheader->skindesc = (byte *)pskindesc - (byte *)pheader;
-
for (i=0 ; i<numskins ; i++)
{
aliasskintype_t skintype;
@@ -1589,15 +1578,8 @@
//
// move the complete, relocatable alias model to the cache
//
- end = Hunk_LowMark ();
- total = end - start;
-
- Cache_Alloc (&mod->cache, total, loadname);
- if (!mod->cache.data)
- return;
- memcpy(mod->cache.data, pheader, total);
- Hunk_FreeToLowMark (start);
+ Hunk_CacheFrom(&mod->cache, pheader);
}
void *
@@ -1613,7 +1595,7 @@
height = LittleLong(pinframe->height);
size = width * height;
- pspriteframe = Hunk_AllocName(size + sizeof *pspriteframe, loadname);
+ pspriteframe = Hunk_Alloc(size + sizeof *pspriteframe);
memset(pspriteframe, 0, size + sizeof *pspriteframe);
*ppframe = pspriteframe;
@@ -1651,8 +1633,8 @@
numframes = LittleLong (pingroup->numframes);
- pspritegroup = Hunk_AllocName(sizeof(*pspritegroup) +
- (numframes - 1) * sizeof pspritegroup->frames[0], loadname);
+ pspritegroup = Hunk_Alloc(sizeof(*pspritegroup) +
+ (numframes - 1) * sizeof pspritegroup->frames[0]);
pspritegroup->numframes = numframes;
@@ -1660,7 +1642,7 @@
pin_intervals = (dspriteinterval_t *)(pingroup + 1);
- poutintervals = Hunk_AllocName(numframes * sizeof *poutintervals, loadname);
+ poutintervals = Hunk_Alloc(numframes * sizeof *poutintervals);
pspritegroup->intervals = poutintervals;
@@ -1711,7 +1693,7 @@
size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames);
- psprite = Hunk_AllocName(size, loadname);
+ psprite = Hunk_Alloc(size);
mod->cache.data = psprite;
--- a/model.h
+++ b/model.h
@@ -343,7 +343,7 @@
//
// additional model data
//
- cache_user_t cache; // only access through Mod_Extradata
+ mem_user_t cache; // only access through Mod_Extradata
} model_t;
--- a/net_main.c
+++ b/net_main.c
@@ -524,7 +524,7 @@
for (i = 0; i < net_numsockets; i++)
{
- s = Hunk_AllocName(sizeof *s, "qsocket");
+ s = Hunk_Alloc(sizeof *s);
s->next = net_freeSockets;
net_freeSockets = s;
s->disconnected = true;
--- a/qk1.c
+++ b/qk1.c
@@ -5,18 +5,11 @@
#include "quakedef.h"
#include "fns.h"
-mainstacksize = 512*1024;
+mainstacksize = 4*1024*1024;
char *netmtpt = "/net";
-uchar *membase;
-int memsize;
char *game;
int debug;
-enum{
- KB = 1024*1024,
- Nmem = 64 * KB
-};
-
void
dprint(char *fmt, ...)
{
@@ -119,7 +112,6 @@
{
double t, t´, Δt;
- memsize = Nmem;
ARGBEGIN{
case 'D':
debug = 1;
@@ -130,17 +122,11 @@
case 'g':
game = EARGF(usage());
break;
- case 'm':
- memsize = strtol(EARGF(usage()), nil, 0) * KB;
- if(memsize <= 0)
- sysfatal("invalid memsize");
- break;
case 'x':
netmtpt = EARGF(usage());
break;
default: usage();
}ARGEND
- membase = emalloc(memsize);
srand(getpid());
/* ignore fp exceptions: rendering shit assumes they are */
setfcr(getfcr() & ~(FPOVFL|FPUNFL|FPINVAL|FPZDIV));
--- a/quakedef.h
+++ b/quakedef.h
@@ -31,10 +31,10 @@
//
// per-level limits
//
-#define MAX_EDICTS 600 // FIXME: ouch! ouch! ouch!
+#define MAX_EDICTS 32000 // FIXME: ouch! ouch! ouch!
#define Nlights 64
-#define MAX_MODELS 256 // these are sent over the net as bytes
-#define MAX_SOUNDS 256 // so they cannot be blindly increased
+#define MAX_MODELS 4096 // these are sent over the net as bytes
+#define MAX_SOUNDS 2048 // so they cannot be blindly increased
#define MAX_STYLESTRING 64
@@ -41,7 +41,7 @@
//
// stats are integers communicated to the client by the server
//
-#define MAX_CL_STATS 32
+#define MAX_CL_STATS 256
#define STAT_HEALTH 0
#define STAT_FRAGS 1
#define STAT_WEAPON 2
@@ -161,7 +161,7 @@
struct Sfx{
char s[Npath];
- cache_user_t cu;
+ mem_user_t cu;
};
extern cvar_t bgmvolume;
--- a/r_bsp.c
+++ b/r_bsp.c
@@ -23,8 +23,8 @@
typedef enum {touchessolid, drawnode, nodrawnode} solidstate_t;
-#define MAX_BMODEL_VERTS 500 // 6K
-#define MAX_BMODEL_EDGES 1000 // 12K
+#define MAX_BMODEL_VERTS 1000 // 6K
+#define MAX_BMODEL_EDGES 3000 // 12K
static mvertex_t *pbverts;
static bedge_t *pbedges;
--- a/r_edge.c
+++ b/r_edge.c
@@ -14,8 +14,6 @@
have a sentinal at both ends?
*/
-
-edge_t *auxedges;
edge_t *r_edges, *edge_p, *edge_max;
surf_t *surfaces, *surface_p, *surf_max;
@@ -628,12 +626,11 @@
void R_ScanEdges (void)
{
int iv, bottom;
- byte basespans[MAXSPANS*sizeof(espan_t)+CACHE_SIZE];
espan_t *basespan_p;
surf_t *s;
basespan_p = (espan_t *)
- ((uintptr)(basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
+ ((uintptr)(r_basespans + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
max_span_p = &basespan_p[MAXSPANS - r_refdef.vrect.width];
span_p = basespan_p;
--- a/r_main.c
+++ b/r_main.c
@@ -11,6 +11,8 @@
alight_t r_viewlighting = {128, 192, viewlightvec};
float r_time1;
int r_numallocatededges;
+int r_numallocatedbasespans;
+byte *r_basespans;
qboolean r_drawpolys;
qboolean r_drawculledpolys;
qboolean r_worldpolysbacktofront;
@@ -108,10 +110,8 @@
cvar_t r_drawflat = {"r_drawflat", "0"};
cvar_t r_ambient = {"r_ambient", "0"};
cvar_t r_reportsurfout = {"r_reportsurfout", "0"};
-cvar_t r_maxsurfs = {"r_maxsurfs", "0"};
cvar_t r_numsurfs = {"r_numsurfs", "0"};
cvar_t r_reportedgeout = {"r_reportedgeout", "0"};
-cvar_t r_maxedges = {"r_maxedges", "0"};
cvar_t r_numedges = {"r_numedges", "0"};
cvar_t r_aliastransbase = {"r_aliastransbase", "200"};
cvar_t r_aliastransadj = {"r_aliastransadj", "100"};
@@ -132,7 +132,7 @@
byte *dest;
// create a simple checkerboard texture for the default
- r_notexture_mip = Hunk_AllocName(16*16+8*8+4*4+2*2 + sizeof *r_notexture_mip, "notexture");
+ r_notexture_mip = Hunk_Alloc(16*16+8*8+4*4+2*2 + sizeof *r_notexture_mip);
r_notexture_mip->width = r_notexture_mip->height = 16;
r_notexture_mip->offsets[0] = sizeof *r_notexture_mip;
@@ -184,17 +184,12 @@
Cvar_RegisterVariable (&r_aliasstats);
Cvar_RegisterVariable (&r_dspeeds);
Cvar_RegisterVariable (&r_reportsurfout);
- Cvar_RegisterVariable (&r_maxsurfs);
Cvar_RegisterVariable (&r_numsurfs);
Cvar_RegisterVariable (&r_reportedgeout);
- Cvar_RegisterVariable (&r_maxedges);
Cvar_RegisterVariable (&r_numedges);
Cvar_RegisterVariable (&r_aliastransbase);
Cvar_RegisterVariable (&r_aliastransadj);
- setcvarv ("r_maxedges", (float)NUMSTACKEDGES);
- setcvarv ("r_maxsurfs", (float)NUMSTACKSURFACES);
-
view_clipplanes[0].leftedge = true;
view_clipplanes[1].rightedge = true;
view_clipplanes[1].leftedge = view_clipplanes[2].leftedge =
@@ -223,47 +218,26 @@
// FIXME: is this one short?
for (i=0 ; i<cl.worldmodel->numleafs ; i++)
cl.worldmodel->leafs[i].efrags = nil;
-
+
+ r_numallocatedbasespans = MAXSPANS;
+ r_basespans = Hunk_Alloc(r_numallocatedbasespans * sizeof(espan_t) + CACHE_SIZE);
r_viewleaf = nil;
R_ClearParticles ();
- r_cnumsurfs = r_maxsurfs.value;
-
- if (r_cnumsurfs <= MINSURFACES)
- r_cnumsurfs = MINSURFACES;
-
- if (r_cnumsurfs > NUMSTACKSURFACES)
- {
- surfaces = Hunk_AllocName(r_cnumsurfs * sizeof *surfaces, "surfaces");
- surface_p = surfaces;
- surf_max = &surfaces[r_cnumsurfs];
- r_surfsonstack = false;
+ r_cnumsurfs = MAXSURFACES;
+ surfaces = Hunk_Alloc(r_cnumsurfs * sizeof *surfaces);
+ surface_p = surfaces;
+ surf_max = &surfaces[r_cnumsurfs];
// surface 0 doesn't really exist; it's just a dummy because index 0
// is used to indicate no edge attached to surface
- surfaces--;
- }
- else
- {
- r_surfsonstack = true;
- }
+ surfaces--;
r_maxedgesseen = 0;
r_maxsurfsseen = 0;
- r_numallocatededges = r_maxedges.value;
+ r_numallocatededges = MAXEDGES;
+ r_edges = Hunk_Alloc(r_numallocatededges * sizeof *r_edges);
- if (r_numallocatededges < MINEDGES)
- r_numallocatededges = MINEDGES;
-
- if (r_numallocatededges <= NUMSTACKEDGES)
- {
- auxedges = nil;
- }
- else
- {
- auxedges = Hunk_AllocName(r_numallocatededges * sizeof *auxedges, "edges");
- }
-
r_dowarpold = false;
r_viewchanged = false;
#ifdef PASSAGES
@@ -814,31 +788,6 @@
*/
void R_EdgeDrawing (void)
{
- edge_t ledges[NUMSTACKEDGES +
- ((CACHE_SIZE - 1) / sizeof(edge_t)) + 1];
- surf_t lsurfs[NUMSTACKSURFACES +
- ((CACHE_SIZE - 1) / sizeof(surf_t)) + 1];
-
- if (auxedges)
- {
- r_edges = auxedges;
- }
- else
- {
- r_edges = (edge_t *)
- (((uintptr)&ledges[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
- }
-
- if (r_surfsonstack)
- {
- surfaces = (surf_t *)
- (((uintptr)&lsurfs[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
- surf_max = &surfaces[r_cnumsurfs];
- // surface 0 doesn't really exist; it's just a dummy because index 0
- // is used to indicate no edge attached to surface
- surfaces--;
- }
-
R_BeginEdgeFrame ();
if (r_dspeeds.value)
@@ -877,9 +826,9 @@
r_refdef must be set before the first call
================
*/
-void R_RenderView_ (void)
+void R_RenderView (void)
{
- byte warpbuffer[WARP_WIDTH * WARP_HEIGHT];
+ static byte warpbuffer[WARP_WIDTH * WARP_HEIGHT];
r_warpbuffer = warpbuffer;
@@ -958,27 +907,6 @@
// back to high floating-point precision
fppdbl ();
-}
-
-void R_RenderView (void)
-{
- int dummy;
- int delta;
-
- delta = (byte *)&dummy - r_stack_start;
- if (delta < -10000 || delta > 10000)
- fatal ("R_RenderView: called without enough stack");
-
- if ( Hunk_LowMark() & 3 )
- fatal ("Hunk is missaligned");
-
- if ( (uintptr)(&dummy) & 3 )
- fatal ("Stack is missaligned");
-
- if ( (uintptr)(&r_warpbuffer) & 3 )
- fatal ("Globals are missaligned");
-
- R_RenderView_ ();
}
/*
--- a/r_part.c
+++ b/r_part.c
@@ -4,7 +4,7 @@
#include "quakedef.h"
#include "fns.h"
-#define MAX_PARTICLES 2048 // default max # of particles at one
+#define MAX_PARTICLES 4096 // default max # of particles at one
// time
#define ABSOLUTE_MIN_PARTICLES 512 // no fewer than this no matter what's
// on the command line
@@ -25,7 +25,7 @@
R_InitParticles(void)
{
r_numparticles = MAX_PARTICLES;
- particles = Hunk_AllocName(r_numparticles * sizeof *particles, "particles");
+ particles = Hunk_Alloc(r_numparticles * sizeof *particles);
}
/*
--- a/r_shared.h
+++ b/r_shared.h
@@ -7,16 +7,12 @@
#define MAXWORKINGVERTS (MAXVERTS+4) // max points in an intermediate
// polygon (while processing)
// !!! if this is changed, it must be changed in d_ifacea.h too !!!
-#define MAXHEIGHT 2048
-#define MAXWIDTH 2048
+#define MAXHEIGHT 3840
+#define MAXWIDTH 2160
#define MAXDIMENSION ((MAXHEIGHT > MAXWIDTH) ? MAXHEIGHT : MAXWIDTH)
#define SIN_BUFFER_SIZE (MAXDIMENSION+CYCLE)
-#define INFINITE_DISTANCE 0x10000 // distance that's always guaranteed to
- // be farther away than anything in
- // the scene
-
//===================================================================
extern void R_DrawLine (polyvert_t *polyvert0, polyvert_t *polyvert1);
@@ -39,11 +35,10 @@
extern vec3_t vright, base_vright;
extern entity_t *currententity;
-#define NUMSTACKEDGES 2400
-#define MINEDGES NUMSTACKEDGES
-#define NUMSTACKSURFACES 800
-#define MINSURFACES NUMSTACKSURFACES
-#define MAXSPANS 3000
+// NOTE: these are only initial values. limits are supposed to scale up dynamically
+#define MAXEDGES 8192
+#define MAXSURFACES 8192
+#define MAXSPANS 8192
// !!! if this is changed, it must be changed in asm_draw.h too !!!
typedef struct espan_s
@@ -74,6 +69,9 @@
int pad[2]; // to 64 bytes
} surf_t;
+
+extern int r_numallocatedbasespans;
+extern byte *r_basespans;
extern surf_t *surfaces, *surface_p, *surf_max;
--- a/snd.c
+++ b/snd.c
@@ -311,7 +311,7 @@
stepscale = (float)info.rate / Srate;
len = info.samples / stepscale;
len *= info.width * info.channels;
- if(sc = Cache_Alloc(&sfx->cu, len + sizeof *sc, sfx->s), sc == nil)
+ if(sc = Cache_Alloc(&sfx->cu, len + sizeof *sc), sc == nil)
return nil;
sc->length = info.samples;
sc->loop = info.loopofs;
@@ -851,11 +851,7 @@
Cvar_RegisterVariable(&ambient_level);
Cvar_RegisterVariable(&ambient_fade);
- if(memsize < 0x800000){
- setcvar("loadas8bit", "1");
- fprint(2, "initsnd: forcing 8bit width\n");
- }
- known_sfx = Hunk_AllocName(MAX_SFX * sizeof *known_sfx, "Sfx");
+ known_sfx = Hunk_Alloc(MAX_SFX * sizeof *known_sfx);
num_sfx = 0;
ambsfx[Ambwater] = precachesfx("ambience/water1.wav");
ambsfx[Ambsky] = precachesfx("ambience/wind2.wav");
--- a/sv_main.c
+++ b/sv_main.c
@@ -1049,7 +1049,7 @@
// allocate server memory
sv.max_edicts = MAX_EDICTS;
- sv.edicts = Hunk_AllocName (sv.max_edicts*pr_edict_size, "edicts");
+ sv.edicts = Hunk_Alloc(sv.max_edicts*pr_edict_size);
sv.datagram.maxsize = sizeof sv.datagram_buf;
sv.datagram.cursize = 0;
--- a/vid.c
+++ b/vid.c
@@ -40,16 +40,15 @@
vid.height = 160;
if(d_pzbuffer != nil){
D_FlushCaches();
- Hunk_FreeToHighMark(highhunk);
+ free(d_pzbuffer);
d_pzbuffer = nil;
}
- highhunk = Hunk_HighMark();
// alloc an extra line in case we want to wrap, and allocate the z-buffer
hunkvbuf = vid.width * vid.height * sizeof *d_pzbuffer;
scachesz = D_SurfaceCacheForRes(vid.width, vid.height);
hunkvbuf += scachesz;
- if((d_pzbuffer = Hunk_HighAllocName(hunkvbuf, "video")) == nil)
+ if((d_pzbuffer = malloc(hunkvbuf)) == nil)
sysfatal("Not enough memory for video mode\n");
surfcache = (byte *)d_pzbuffer + vid.width * vid.height * sizeof *d_pzbuffer;
D_InitCaches(surfcache, scachesz);
--- a/zone.c
+++ b/zone.c
@@ -4,856 +4,175 @@
#include "quakedef.h"
#include "fns.h"
-#define DYNAMIC_SIZE 0xc000
+typedef struct mem_t mem_t;
-#define ZONEID 0x1d4a11
-#define MINFRAGMENT 64
-
-typedef struct memblock_s
+struct mem_t
{
- 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 boundary
-} memblock_t;
+ mem_t *prev, *next;
+ mem_user_t *user;
+ int size; // NOT including this header
+};
-typedef struct
-{
- int size; // total bytes malloced, including header
- memblock_t blocklist; // start / end cap for linked list
- memblock_t *rover;
-} memzone_t;
+static mem_t *hunk_head;
+static mem_t *cache_head;
-void Cache_FreeLow (int new_low_hunk);
-void Cache_FreeHigh (int new_high_hunk);
-
-
-/*
-==============================================================================
-
- 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
-
-The zone calls are pretty much only used for small strings and structures,
-all big things are allocated on the hunk.
-==============================================================================
-*/
-
-memzone_t *mainzone;
-
-void Z_ClearZone (memzone_t *zone, int size);
-
-
-/*
-========================
-Z_ClearZone
-========================
-*/
-void Z_ClearZone (memzone_t *zone, int size)
+int
+Hunk_From(void *p)
{
- memblock_t *block;
-
-// set the entire zone to one free block
+ mem_t *m;
+ int off;
- zone->blocklist.next = zone->blocklist.prev = block =
- (memblock_t *)((byte *)zone + sizeof(memzone_t));
- zone->blocklist.tag = 1; // in use block
- zone->blocklist.id = 0;
- zone->blocklist.size = 0;
- zone->rover = block;
-
- block->prev = block->next = &zone->blocklist;
- block->tag = 0; // free block
- block->id = ZONEID;
- block->size = size - sizeof(memzone_t);
-}
-
-
-/*
-========================
-Z_Free
-========================
-*/
-void Z_Free (void *ptr)
-{
- memblock_t *block, *other;
-
- if (!ptr)
- fatal ("Z_Free: NULL pointer");
-
- block = (memblock_t *)((uchar *)ptr - sizeof(memblock_t));
- if (block->id != ZONEID)
- fatal ("Z_Free: freed a pointer without ZONEID");
- if (block->tag == 0)
- fatal ("Z_Free: freed a freed pointer");
-
- 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 == mainzone->rover)
- mainzone->rover = other;
- block = other;
+ for(off = 0, m = hunk_head; m != nil; m = m->next){
+ off += m->size;
+ if((void*)(m+1) == p)
+ break;
}
-
- 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 == mainzone->rover)
- mainzone->rover = block;
- }
+ assert(m != nil || p == nil);
+ return off;
}
-void *
-Z_Malloc(int size)
+void
+Hunk_CacheFrom(mem_user_t *c, void *p)
{
- void *buf;
+ int size;
+ mem_t *n, *prev;
+ byte *data;
- Z_CheckHeap(); // DEBUG
- if((buf = Z_TagMalloc(size, 1)) == nil)
- fatal("Z_Malloc: failed on allocation of %d bytes", size);
- memset(buf, 0, size);
-
- return buf;
-}
-
-void *Z_TagMalloc (int size, int tag)
-{
- int extra;
- memblock_t *start, *rover, *new, *base;
-
- if (!tag)
- fatal ("Z_TagMalloc: tried to use a 0 tag");
-
-//
-// scan through the block list looking for the first free block
-// of sufficient size
-//
- size += sizeof(memblock_t); // account for size of block header
- size += 4; // space for memory trash tester
- size = (size + 7) & ~7; // align to 8-byte boundary
-
- base = rover = mainzone->rover;
- start = base->prev;
-
- do
- {
- if (rover == start) // scaned all the way around the list
- return nil;
- if (rover->tag)
- base = rover = rover->next;
- else
- rover = rover->next;
- } while (base->tag || base->size < size);
-
-//
-// found a block big enough
-//
- extra = base->size - size;
- if (extra > MINFRAGMENT)
- { // there will be a free fragment after the allocated block
- new = (memblock_t *) ((byte *)base + size );
- new->size = extra;
- new->tag = 0; // free block
- new->prev = base;
- new->id = ZONEID;
- new->next = base->next;
- new->next->prev = new;
- base->next = new;
- base->size = size;
+ for(size = 0, n = hunk_head; n != nil; n = n->next){
+ size += n->size;
+ if((void*)(n+1) == p)
+ break;
}
-
- base->tag = tag; // no longer a free block
-
- mainzone->rover = base->next; // next allocation will start looking here
-
- base->id = ZONEID;
+ assert((void*)(n+1) == p);
+ data = Cache_Alloc(c, size);
-// marker for memory trash testing
- *(int *)((byte *)base + base->size - 4) = ZONEID;
-
- return (void *) ((byte *)base + sizeof(memblock_t));
-}
-
-
-/*
-========================
-Z_Print
-========================
-*/
-void Z_Print (memzone_t *zone)
-{
- memblock_t *block;
-
- Con_Printf ("zone size: %d location: %p\n",mainzone->size,mainzone);
-
- for (block = zone->blocklist.next ; ; block = block->next)
- {
- Con_Printf ("block:%p size:%7d tag:%3d\n",
- block, block->size, block->tag);
-
- if (block->next == &zone->blocklist)
- break; // all blocks have been hit
- if ( (byte *)block + block->size != (byte *)block->next)
- Con_Printf ("ERROR: block size does not touch the next block\n");
- if ( block->next->prev != block)
- Con_Printf ("ERROR: next block doesn't have proper back link\n");
- if (!block->tag && !block->next->tag)
- Con_Printf ("ERROR: two consecutive free blocks\n");
+ hunk_head = n->next;
+ if(hunk_head != nil)
+ hunk_head->prev = nil;
+ for(size = 0; n != nil; n = prev){
+ memmove(data+size, n+1, n->size);
+ size += n->size;
+ prev = n->prev;
+ free(n);
}
}
-
-/*
-========================
-Z_CheckHeap
-========================
-*/
-void Z_CheckHeap (void)
+void *
+Hunk_Alloc(int size)
{
- memblock_t *block;
-
- for (block = mainzone->blocklist.next ; ; block = block->next)
- {
- if (block->next == &mainzone->blocklist)
- break; // all blocks have been hit
- if ( (byte *)block + block->size != (byte *)block->next)
- fatal ("Z_CheckHeap: block size does not touch the next block\n");
- if ( block->next->prev != block)
- fatal ("Z_CheckHeap: next block doesn't have proper back link\n");
- if (!block->tag && !block->next->tag)
- fatal ("Z_CheckHeap: two consecutive free blocks\n");
- }
-}
+ mem_t *m;
-//============================================================================
+ size = (size+15)&~15;
+ m = mallocz(sizeof(*m) + size, 1);
+ if(m == nil)
+ sysfatal("Hunk_Alloc: %r");
+ m->size = size;
+ m->next = hunk_head;
+ if(hunk_head != nil)
+ hunk_head->prev = m;
+ hunk_head = m;
-#define HUNK_SENTINAL 0x1df001ed
-
-typedef struct
-{
- int sentinal;
- int size; // including sizeof(hunk_t), -1 = not allocated
- char name[8];
-} hunk_t;
-
-int hunk_low_used;
-int hunk_high_used;
-
-qboolean hunk_tempactive;
-int hunk_tempmark;
-
-void R_FreeTextures (void);
-
-/*
-==============
-Hunk_Check
-
-Run consistancy and sentinal trahing checks
-==============
-*/
-void Hunk_Check (void)
-{
- hunk_t *h;
-
- for (h = (hunk_t *)membase ; (byte *)h != membase + hunk_low_used ; )
- {
- if (h->sentinal != HUNK_SENTINAL)
- fatal ("Hunk_Check: trahsed sentinal");
- if (h->size < 16 || h->size + (byte *)h - membase > memsize)
- fatal ("Hunk_Check: bad size");
- h = (hunk_t *)((byte *)h+h->size);
- }
+ return m+1;
}
-/*
-==============
-Hunk_Print
-
-If "all" is specified, every single allocation is printed.
-Otherwise, allocations with the same name will be totaled up before printing.
-==============
-*/
-void Hunk_Print (qboolean all)
+void *
+Hunk_Mark(void)
{
- hunk_t *h, *next, *endlow, *starthigh, *endhigh;
- int count, sum;
- int totalblocks;
- char name[9];
-
- name[8] = 0;
- count = 0;
- sum = 0;
- totalblocks = 0;
-
- h = (hunk_t *)membase;
- endlow = (hunk_t *)(membase + hunk_low_used);
- starthigh = (hunk_t *)(membase + memsize - hunk_high_used);
- endhigh = (hunk_t *)(membase + memsize);
-
- Con_Printf (" :%8d total hunk size\n", memsize);
- Con_Printf ("-------------------------\n");
-
- while (1)
- {
- //
- // skip to the high hunk if done with low hunk
- //
- if ( h == endlow )
- {
- Con_Printf ("-------------------------\n");
- Con_Printf (" :%8d REMAINING\n", memsize - hunk_low_used - hunk_high_used);
- Con_Printf ("-------------------------\n");
- h = starthigh;
- }
-
- //
- // if totally done, break
- //
- if ( h == endhigh )
- break;
-
- //
- // run consistancy checks
- //
- if (h->sentinal != HUNK_SENTINAL)
- fatal ("Hunk_Check: trahsed sentinal");
- if (h->size < 16 || h->size + (byte *)h - membase > memsize)
- fatal ("Hunk_Check: bad size");
-
- next = (hunk_t *)((byte *)h+h->size);
- count++;
- totalblocks++;
- sum += h->size;
-
- //
- // print the single block
- //
- memcpy(name, h->name, 8);
- if (all)
- Con_Printf ("%8p :%8d %8s\n",h, h->size, name);
-
- //
- // print the total
- //
- if (next == endlow || next == endhigh ||
- strncmp (h->name, next->name, 8) )
- {
- if (!all)
- Con_Printf (" :%8d %8s (TOTAL)\n",sum, name);
- count = 0;
- sum = 0;
- }
-
- h = next;
- }
-
- Con_Printf ("-------------------------\n");
- Con_Printf ("%8d total blocks\n", totalblocks);
-
+ return hunk_head;
}
-/*
-===================
-Hunk_AllocName
-===================
-*/
-void *Hunk_AllocName (int size, char *name)
+void
+Hunk_FreeToMark(void *mark)
{
- hunk_t *h;
-
-#ifdef PARANOID
- Hunk_Check ();
-#endif
+ mem_t *m;
- if (size < 0)
- fatal ("Hunk_Alloc: bad size: %d", size);
-
- size = sizeof(hunk_t) + ((size+15)&~15);
-
- if (memsize - hunk_low_used - hunk_high_used < size)
- fatal ("Hunk_Alloc: failed on %d bytes",size);
-
- h = (hunk_t *)(membase + hunk_low_used);
- hunk_low_used += size;
-
- Cache_FreeLow (hunk_low_used);
-
- memset(h, 0, size);
-
- h->size = size;
- h->sentinal = HUNK_SENTINAL;
- strncpy(h->name, name, 8);
-
- return (void *)(h+1);
-}
-
-/*
-===================
-Hunk_Alloc
-===================
-*/
-void *Hunk_Alloc (int size)
-{
- return Hunk_AllocName (size, "unknown");
-}
-
-int Hunk_LowMark (void)
-{
- return hunk_low_used;
-}
-
-void Hunk_FreeToLowMark (int mark)
-{
- if (mark < 0 || mark > hunk_low_used)
- fatal ("Hunk_FreeToLowMark: bad mark %d", mark);
- memset(membase + mark, 0, hunk_low_used - mark);
- hunk_low_used = mark;
-}
-
-int Hunk_HighMark (void)
-{
- if (hunk_tempactive)
- {
- hunk_tempactive = false;
- Hunk_FreeToHighMark (hunk_tempmark);
+ while(hunk_head != mark){
+ m = hunk_head->next;
+ free(hunk_head);
+ hunk_head = m;
}
-
- return hunk_high_used;
}
-void Hunk_FreeToHighMark (int mark)
+void *
+Hunk_TempAlloc(int size)
{
- if (hunk_tempactive)
- {
- hunk_tempactive = false;
- Hunk_FreeToHighMark (hunk_tempmark);
- }
- if (mark < 0 || mark > hunk_high_used)
- fatal ("Hunk_FreeToHighMark: bad mark %d", mark);
- memset(membase + memsize - hunk_high_used, 0, hunk_high_used - mark);
- hunk_high_used = mark;
-}
+ static void *buf;
+ static int bufsz;
+ if(bufsz > size)
+ return buf;
+ buf = realloc(buf, size);
+ if(buf == nil)
+ sysfatal("Hunk_TempAlloc: %r");
+ bufsz = size;
-/*
-===================
-Hunk_HighAllocName
-===================
-*/
-void *Hunk_HighAllocName (int size, char *name)
-{
- hunk_t *h;
-
- if (size < 0)
- fatal ("Hunk_HighAllocName: bad size: %d", size);
-
- if (hunk_tempactive)
- {
- Hunk_FreeToHighMark (hunk_tempmark);
- hunk_tempactive = false;
- }
-
-#ifdef PARANOID
- Hunk_Check ();
-#endif
-
- size = sizeof(hunk_t) + ((size+15)&~15);
-
- if (memsize - hunk_low_used - hunk_high_used < size)
- {
- Con_Printf ("Hunk_HighAlloc: failed on %d bytes\n",size);
- return nil;
- }
-
- hunk_high_used += size;
- Cache_FreeHigh (hunk_high_used);
-
- h = (hunk_t *)(membase + memsize - hunk_high_used);
-
- memset(h, 0, size);
- h->size = size;
- h->sentinal = HUNK_SENTINAL;
- strncpy(h->name, name, 8);
-
- return (void *)(h+1);
-}
-
-
-/*
-=================
-Hunk_TempAlloc
-
-Return space from the top of the hunk
-=================
-*/
-void *Hunk_TempAlloc (int size)
-{
- void *buf;
-
- size = (size+15)&~15;
-
- if (hunk_tempactive)
- {
- Hunk_FreeToHighMark (hunk_tempmark);
- hunk_tempactive = false;
- }
-
- hunk_tempmark = Hunk_HighMark ();
-
- buf = Hunk_HighAllocName (size, "temp");
-
- hunk_tempactive = true;
-
return buf;
}
-/*
-===============================================================================
-
-CACHE MEMORY
-
-===============================================================================
-*/
-
-typedef struct cache_system_s
+void *
+Cache_Check(mem_user_t *c)
{
- int size; // including this header
- cache_user_t *user;
- char name[16];
- struct cache_system_s *prev, *next;
- struct cache_system_s *lru_prev, *lru_next; // for LRU flushing
-} cache_system_t;
-
-cache_system_t *Cache_TryAlloc (int size, qboolean nobottom);
-
-cache_system_t cache_head;
-
-/*
-===========
-Cache_Move
-===========
-*/
-void Cache_Move ( cache_system_t *c)
-{
- cache_system_t *new;
-
-// we are clearing up space at the bottom, so only allocate it late
- new = Cache_TryAlloc (c->size, true);
- if (new)
- {
-// Con_Printf ("cache_move ok\n");
-
- memcpy(new+1, c+1, c->size - sizeof *new);
- new->user = c->user;
- memcpy(new->name, c->name, sizeof new->name);
- Cache_Free (c->user);
- new->user->data = (void *)(new+1);
- }
- else
- {
-// Con_Printf ("cache_move failed\n");
-
- Cache_Free (c->user); // tough luck...
- }
+ return c->data;
}
-/*
-============
-Cache_FreeLow
-
-Throw things out until the hunk can be expanded to the given point
-============
-*/
-void Cache_FreeLow (int new_low_hunk)
+static void
+Cache_Flush(void)
{
- cache_system_t *c;
-
- while (1)
- {
- c = cache_head.next;
- if (c == &cache_head)
- return; // nothing in cache at all
- if ((byte *)c >= membase + new_low_hunk)
- return; // there is space to grow the hunk
- Cache_Move ( c ); // reclaim the space
- }
-}
-
-/*
-============
-Cache_FreeHigh
-
-Throw things out until the hunk can be expanded to the given point
-============
-*/
-void Cache_FreeHigh (int new_high_hunk)
-{
- cache_system_t *c, *prev;
-
- prev = nil;
- while (1)
- {
- c = cache_head.prev;
- if (c == &cache_head)
- return; // nothing in cache at all
- if ( (byte *)c + c->size <= membase + memsize - new_high_hunk)
- return; // there is space to grow the hunk
- if (c == prev)
- Cache_Free (c->user); // didn't move out of the way
- else
- {
- Cache_Move (c); // try to move it
- prev = c;
- }
- }
-}
-
-void Cache_UnlinkLRU (cache_system_t *cs)
-{
- if (!cs->lru_next || !cs->lru_prev)
- fatal ("Cache_UnlinkLRU: NULL link");
-
- cs->lru_next->lru_prev = cs->lru_prev;
- cs->lru_prev->lru_next = cs->lru_next;
-
- cs->lru_prev = cs->lru_next = nil;
-}
-
-void Cache_MakeLRU (cache_system_t *cs)
-{
- if (cs->lru_next || cs->lru_prev)
- fatal ("Cache_MakeLRU: active link");
-
- cache_head.lru_next->lru_prev = cs;
- cs->lru_next = cache_head.lru_next;
- cs->lru_prev = &cache_head;
- cache_head.lru_next = cs;
-}
-
-/*
-============
-Cache_TryAlloc
-
-Looks for a free block of memory between the high and low hunk marks
-Size should already include the header and padding
-============
-*/
-cache_system_t *Cache_TryAlloc (int size, qboolean nobottom)
-{
- cache_system_t *cs, *new;
-
-// is the cache completely empty?
-
- if (!nobottom && cache_head.prev == &cache_head)
- {
- if (memsize - hunk_high_used - hunk_low_used < size)
- fatal ("Cache_TryAlloc: %d is greater then free hunk", size);
-
- new = (cache_system_t *) (membase + hunk_low_used);
- memset(new, 0, sizeof *new);
- new->size = size;
-
- cache_head.prev = cache_head.next = new;
- new->prev = new->next = &cache_head;
+ mem_t *s;
- Cache_MakeLRU (new);
- return new;
+ while(cache_head != nil){
+ s = cache_head->next;
+ cache_head->user->data = nil;
+ free(cache_head);
+ cache_head = s;
}
-
-// search from the bottom up for space
-
- new = (cache_system_t *) (membase + hunk_low_used);
- cs = cache_head.next;
-
- do
- {
- if (!nobottom || cs != cache_head.next)
- {
- if ( (byte *)cs - (byte *)new >= size)
- { // found space
- memset(new, 0, sizeof *new);
- new->size = size;
-
- new->next = cs;
- new->prev = cs->prev;
- cs->prev->next = new;
- cs->prev = new;
-
- Cache_MakeLRU (new);
-
- return new;
- }
- }
-
- // continue looking
- new = (cache_system_t *)((byte *)cs + cs->size);
- cs = cs->next;
-
- } while (cs != &cache_head);
-
-// try to allocate one at the very end
- if ( membase + memsize - hunk_high_used - (byte *)new >= size)
- {
- memset(new, 0, sizeof *new);
- new->size = size;
-
- new->next = &cache_head;
- new->prev = cache_head.prev;
- cache_head.prev->next = new;
- cache_head.prev = new;
-
- Cache_MakeLRU (new);
-
- return new;
- }
-
- return nil; // couldn't allocate
}
-/*
-============
-Cache_Flush
-
-Throw everything out, so new data will be demand cached
-============
-*/
-void Cache_Flush (void)
-{
- while (cache_head.next != &cache_head)
- Cache_Free ( cache_head.next->user ); // reclaim the space
-}
-
void
-Cache_Report(void)
+Cache_Free(mem_user_t *c)
{
- dprint("%4.1f megabyte data cache\n",
- (memsize - hunk_high_used - hunk_low_used)
- / (float)(1024*1024));
-}
+ mem_t *cs;
-/*
-============
-Cache_Init
+ if(!c->data)
+ fatal("Cache_Free: not allocated");
-============
-*/
-void Cache_Init (void)
-{
- cache_head.next = cache_head.prev = &cache_head;
- cache_head.lru_next = cache_head.lru_prev = &cache_head;
-
- Cmd_AddCommand ("flush", Cache_Flush);
-}
-
-/*
-==============
-Cache_Free
-
-Frees the memory and removes it from the LRU list
-==============
-*/
-void Cache_Free (cache_user_t *c)
-{
- cache_system_t *cs;
-
- if (!c->data)
- fatal ("Cache_Free: not allocated");
-
- cs = ((cache_system_t *)c->data) - 1;
-
+ cs = ((mem_t *)c->data) - 1;
+ if(cs == cache_head)
+ cache_head = cs->next;
cs->prev->next = cs->next;
cs->next->prev = cs->prev;
cs->next = cs->prev = nil;
c->data = nil;
-
- Cache_UnlinkLRU (cs);
+ free(cs);
}
-
-
-/*
-==============
-Cache_Check
-==============
-*/
-void *Cache_Check (cache_user_t *c)
+void *
+Cache_Alloc(mem_user_t *c, int size)
{
- cache_system_t *cs;
+ mem_t *cs;
- if (!c->data)
- return nil;
+ if(c->data)
+ fatal("Cache_Alloc: allready allocated");
+ if(size <= 0)
+ fatal("Cache_Alloc: size %d", size);
- cs = ((cache_system_t *)c->data) - 1;
-
-// move to head of LRU
- Cache_UnlinkLRU (cs);
- Cache_MakeLRU (cs);
+ cs = mallocz(sizeof(*cs) + size, 1);
+ if(cs == nil)
+ sysfatal("Cache_Alloc: %r");
+ cs->size = size;
+ cs->next = cache_head;
+ if(cache_head != nil)
+ cache_head->prev = cs;
+ cache_head = cs;
+ c->data = cs+1;
+ cs->user = c;
return c->data;
}
-
-/*
-==============
-Cache_Alloc
-==============
-*/
-void *Cache_Alloc (cache_user_t *c, int size, char *name)
+void
+Memory_Init(void)
{
- cache_system_t *cs;
-
- if (c->data)
- fatal ("Cache_Alloc: allready allocated");
-
- if (size <= 0)
- fatal ("Cache_Alloc: size %d", size);
-
- size = (size + sizeof(*cs) + 15) & ~15;
-
-// find memory for it
- while (1)
- {
- cs = Cache_TryAlloc (size, false);
- if (cs)
- {
- strncpy (cs->name, name, sizeof(cs->name)-1);
- c->data = (void *)(cs+1);
- cs->user = c;
- break;
- }
-
- // free the least recently used cahedat
- if (cache_head.lru_prev == &cache_head)
- fatal ("Cache_Alloc: out of memory");
- // not enough memory at all
- Cache_Free ( cache_head.lru_prev->user );
- }
-
- return Cache_Check (c);
-}
-
-void Memory_Init (void)
-{
- int zonesize = DYNAMIC_SIZE;
-
- hunk_low_used = 0;
- hunk_high_used = 0;
-
- Cache_Init ();
- mainzone = Hunk_AllocName (zonesize, "zone" );
- Z_ClearZone (mainzone, zonesize);
+ Cmd_AddCommand("flush", Cache_Flush);
}
--- a/zone.h
+++ b/zone.h
@@ -1,112 +1,20 @@
-/*
- memory allocation
-
-
-H_??? The hunk manages the entire memory block given to quake. It must be
-contiguous. Memory can be allocated from either the low or high end in a
-stack fashion. The only way memory is released is by resetting one of the
-pointers.
-
-Hunk allocations should be given a name, so the Hunk_Print () function
-can display usage.
-
-Hunk allocations are guaranteed to be 16 byte aligned.
-
-The video buffers are allocated high to avoid leaving a hole underneath
-server allocations when changing to a higher video mode.
-
-
-Z_??? Zone memory functions used for small, dynamic allocations like text
-strings from command input. There is only about 48K for it, allocated at
-the very bottom of the hunk.
-
-Cache_??? Cache memory is for objects that can be dynamically loaded and
-can usefully stay persistant between levels. The size of the cache
-fluctuates from level to level.
-
-To allocate a cachable object
-
-
-Temp_??? Temp memory is used for file loading and surface caching. The size
-of the cache memory is adjusted so that there is a minimum of 512k remaining
-for temp memory.
-
-
------- Top of Memory -------
-
-high hunk allocations
-
-<--- high hunk reset point held by vid
-
-video buffer
-
-z buffer
-
-surface cache
-
-<--- high hunk used
-
-cachable memory
-
-<--- low hunk used
-
-client and server low hunk allocations
-
-<-- low hunk reset point held by host
-
-startup hunk allocations
-
-Zone block
-
------ Bottom of Memory -----
-
-
-
-*/
-
-void Memory_Init (void);
-
-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);
-
-void *Hunk_Alloc (int size); // returns 0 filled memory
-void *Hunk_AllocName (int size, char *name);
-
-void *Hunk_HighAllocName (int size, char *name);
-
-int Hunk_LowMark (void);
-void Hunk_FreeToLowMark (int mark);
-
-int Hunk_HighMark (void);
-void Hunk_FreeToHighMark (int mark);
-
-void *Hunk_TempAlloc (int size);
-
-void Hunk_Check (void);
-
-typedef struct cache_user_s
+typedef struct
{
- void *data;
-} cache_user_t;
+ void *data;
+}mem_user_t;
-void Cache_Flush (void);
+#define Z_Free(p) free(p)
+#define Z_Malloc(sz) mallocz((sz), 1)
-void *Cache_Check (cache_user_t *c);
-// returns the cached data, and moves to the head of the LRU list
-// if present, otherwise returns NULL
+int Hunk_From(void *p);
+void Hunk_CacheFrom(mem_user_t *c, void *p);
+void *Hunk_Alloc(int size);
+void *Hunk_Mark(void);
+void Hunk_FreeToMark(void *mark);
+void *Hunk_TempAlloc(int size);
-void Cache_Free (cache_user_t *c);
+void *Cache_Alloc(mem_user_t *c, int size);
+void *Cache_Check(mem_user_t *c);
+void Cache_Free(mem_user_t *c);
-void *Cache_Alloc (cache_user_t *c, int size, char *name);
-// Returns NULL if all purgable data was tossed and there still
-// wasn't enough room.
-
-void Cache_Report (void);
-
-
-
+void Memory_Init(void);