* Thin out models in memory by removing unused frames. This saves 200MB with DNE on Polymer.

* fix memory corruption when loading a Polymer savegame using another renderer and then change to Polymer
* fix possible crash in OSD_Exec() and uninitialized mem access in game config reader
* move makeasmwriteable() to baselayer.c


git-svn-id: https://svn.eduke32.com/eduke32@1910 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2011-06-19 18:30:32 +00:00
parent ef61e48c25
commit 51fb860650
9 changed files with 218 additions and 96 deletions

View file

@ -128,7 +128,7 @@ typedef struct
md3shader_t *shaders; md3shader_t *shaders;
md3uv_t *uv; md3uv_t *uv;
md3xyzn_t *xyzn; md3xyzn_t *xyzn;
float *geometry; float *geometry; // used by Polymer
} md3surf_t; } md3surf_t;
#define SIZEOF_MD3SURF_T (11*sizeof(int32_t) + 64*sizeof(char)) #define SIZEOF_MD3SURF_T (11*sizeof(int32_t) + 64*sizeof(char))
@ -244,5 +244,6 @@ voxmodel_t *voxload(const char *filnam);
int32_t voxdraw(voxmodel_t *m, spritetype *tspr); int32_t voxdraw(voxmodel_t *m, spritetype *tspr);
int md3postload_polymer(md3model_t* m); int md3postload_polymer(md3model_t* m);
int32_t md_thinoutmodel(int32_t modelid, uint8_t *usedframebitmap);
#endif // !_mdsprite_h_ #endif // !_mdsprite_h_

View file

@ -378,3 +378,42 @@ int32_t baselayer_init(void)
return 0; return 0;
} }
#if defined _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#elif defined __linux || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __APPLE__
# include <sys/mman.h>
#endif
void makeasmwriteable(void)
{
#ifndef ENGINE_USING_A_C
extern int32_t dep_begin, dep_end;
# if defined _WIN32
DWORD oldprot;
if (!VirtualProtect((LPVOID)&dep_begin, (SIZE_T)&dep_end - (SIZE_T)&dep_begin, PAGE_EXECUTE_READWRITE, &oldprot))
{
initprintf("Error making code writeable");
return;
}
# elif defined __linux || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __APPLE__
int32_t pagesize;
size_t dep_begin_page;
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1)
{
initprintf("Error getting system page size\n");
return;
}
dep_begin_page = ((size_t)&dep_begin) & ~(pagesize-1);
if (mprotect((void *)dep_begin_page, (size_t)&dep_end - dep_begin_page, PROT_READ|PROT_WRITE) < 0)
{
initprintf("Error making code writeable (errno=%d)\n", errno);
return;
}
# else
# error "Don't know how to unprotect the self-modifying assembly on this platform!"
# endif
#endif
}

View file

@ -730,6 +730,8 @@ static int32_t defsparser(scriptfile *script)
break; break;
} }
md_setmisc(lastmodelid,(float)scale, shadeoffs,0.0,0); md_setmisc(lastmodelid,(float)scale, shadeoffs,0.0,0);
if (glrendmode==4)
md3postload_polymer((md3model_t *)models[lastmodelid]);
#endif #endif
modelskin = lastmodelskin = 0; modelskin = lastmodelskin = 0;
seenframe = 0; seenframe = 0;
@ -764,8 +766,6 @@ static int32_t defsparser(scriptfile *script)
{ {
switch (md_defineframe(lastmodelid, framename, tilex, max(0,modelskin), 0.0f,0)) switch (md_defineframe(lastmodelid, framename, tilex, max(0,modelskin), 0.0f,0))
{ {
case 0:
break;
case -1: case -1:
happy = 0; break; // invalid model id!? happy = 0; break; // invalid model id!?
case -2: case -2:
@ -778,6 +778,8 @@ static int32_t defsparser(scriptfile *script)
script->filename, scriptfile_getlinum(script,cmdtokptr)); script->filename, scriptfile_getlinum(script,cmdtokptr));
happy = 0; happy = 0;
break; break;
default:
break;
} }
} }
#endif #endif
@ -934,6 +936,9 @@ static int32_t defsparser(scriptfile *script)
char *modelend, *modelfn; char *modelend, *modelfn;
double scale=1.0, mzadd=0.0; double scale=1.0, mzadd=0.0;
int32_t shadeoffs=0, pal=0, flags=0; int32_t shadeoffs=0, pal=0, flags=0;
uint8_t usedframebitmap[1024>>3];
Bmemset(usedframebitmap, 0, sizeof(usedframebitmap));
static const tokenlist modeltokens[] = static const tokenlist modeltokens[] =
{ {
@ -983,7 +988,7 @@ static int32_t defsparser(scriptfile *script)
{ {
char *frametokptr = script->ltextptr; char *frametokptr = script->ltextptr;
char *frameend, *framename = 0, happy=1; char *frameend, *framename = 0, happy=1;
int32_t ftilenume = -1, ltilenume = -1, tilex = 0; int32_t ftilenume = -1, ltilenume = -1, tilex = 0, framei;
double smoothduration = 0.1f; double smoothduration = 0.1f;
static const tokenlist modelframetokens[] = static const tokenlist modelframetokens[] =
@ -1037,10 +1042,9 @@ static int32_t defsparser(scriptfile *script)
#ifdef USE_OPENGL #ifdef USE_OPENGL
for (tilex = ftilenume; tilex <= ltilenume && happy; tilex++) for (tilex = ftilenume; tilex <= ltilenume && happy; tilex++)
{ {
switch (md_defineframe(lastmodelid, framename, tilex, max(0,modelskin), smoothduration,pal)) framei = md_defineframe(lastmodelid, framename, tilex, max(0,modelskin), smoothduration,pal);
switch (framei)
{ {
case 0:
break;
case -1: case -1:
happy = 0; break; // invalid model id!? happy = 0; break; // invalid model id!?
case -2: case -2:
@ -1053,6 +1057,9 @@ static int32_t defsparser(scriptfile *script)
script->filename, scriptfile_getlinum(script,frametokptr)); script->filename, scriptfile_getlinum(script,frametokptr));
happy = 0; happy = 0;
break; break;
default:
if (framei >= 0 && framei<1024)
usedframebitmap[framei>>3] |= (1<<(framei&7));
} }
} }
#endif #endif
@ -1312,6 +1319,24 @@ static int32_t defsparser(scriptfile *script)
#ifdef USE_OPENGL #ifdef USE_OPENGL
md_setmisc(lastmodelid,(float)scale,shadeoffs,(float)mzadd,flags); md_setmisc(lastmodelid,(float)scale,shadeoffs,(float)mzadd,flags);
// thin out the loaded model by throwing away unused frames
if (models[lastmodelid]->mdnum==3 && ((md3model_t *)models[lastmodelid])->numframes <= 1024)
{
md3model_t *m = (md3model_t *)models[lastmodelid];
int32_t i, onumframes;
onumframes = m->numframes;
i = md_thinoutmodel(lastmodelid, usedframebitmap);
#ifdef DEBUG_MODEL_MEM
if (i>=0 && i<onumframes)
initprintf("used %d/%d frames: %s\n", i, onumframes, modelfn);
else if (i<0)
initprintf("md_thinoutmodel returned %d: %s\n", i, modelfn);
#endif
}
if (glrendmode==4)
md3postload_polymer((md3model_t *)models[lastmodelid]);
#endif #endif
modelskin = lastmodelskin = 0; modelskin = lastmodelskin = 0;

View file

@ -291,7 +291,7 @@ int32_t md_defineframe(int32_t modelid, const char *framename, int32_t tilenume,
tile2model[tilenume].skinnum = skinnum; tile2model[tilenume].skinnum = skinnum;
tile2model[tilenume].smoothduration = smoothduration; tile2model[tilenume].smoothduration = smoothduration;
return 0; return i;
} }
int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend, int32_t fpssc, int32_t flags) int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *frameend, int32_t fpssc, int32_t flags)
@ -331,6 +331,108 @@ int32_t md_defineanimation(int32_t modelid, const char *framestart, const char *
return(0); return(0);
} }
int32_t md_thinoutmodel(int32_t modelid, uint8_t *usedframebitmap)
{
md3model_t *m;
md3surf_t *s;
mdanim_t *anm;
int32_t i, surfi, sub, usedframes;
static int16_t otonframe[1024];
if ((uint32_t)modelid >= (uint32_t)nextmodelid) return -1;
m = (md3model_t *)models[modelid];
if (m->mdnum != 3) return -2;
for (anm=m->animations; anm; anm=anm->next)
{
if (anm->endframe <= anm->startframe)
{
// initprintf("backward anim %d-%d\n", anm->startframe, anm->endframe);
return -3;
}
for (i=anm->startframe; i<anm->endframe; i++)
usedframebitmap[i>>3] |= (1<<(i&7));
}
sub = 0;
for (i=0; i<m->numframes; i++)
{
if (!(usedframebitmap[i>>3]&(1<<(i&7))))
{
sub++;
otonframe[i] = -1;
continue;
}
otonframe[i] = i-sub;
}
usedframes = m->numframes - sub;
if (usedframes==0 || usedframes==m->numframes)
return usedframes;
//// THIN OUT! ////
for (i=0; i<m->numframes; i++)
{
if (otonframe[i]>=0 && otonframe[i] != i)
{
if (m->muladdframes)
Bmemcpy(&m->muladdframes[2*otonframe[i]], &m->muladdframes[2*i], 2*sizeof(point3d));
Bmemcpy(&m->head.frames[otonframe[i]], &m->head.frames[i], sizeof(md3frame_t));
}
}
for (surfi=0; surfi < m->head.numsurfs; surfi++)
{
s = &m->head.surfs[surfi];
for (i=0; i<m->numframes; i++)
if (otonframe[i]>=0 && otonframe[i] != i)
Bmemcpy(&s->xyzn[otonframe[i]*s->numverts], &s->xyzn[i*s->numverts], s->numverts*sizeof(md3xyzn_t));
}
////// tweak frame indices in various places
for (anm=m->animations; anm; anm=anm->next)
{
if (otonframe[anm->startframe]==-1 || otonframe[anm->endframe-1]==-1)
initprintf("md %d WTF: anm %d %d\n", modelid, anm->startframe, anm->endframe);
anm->startframe = otonframe[anm->startframe];
anm->endframe = otonframe[anm->endframe-1];
}
for (i=0; i<MAXTILES+EXTRATILES; i++)
if (tile2model[i].modelid == modelid)
{
if (otonframe[tile2model[i].framenum]==-1)
initprintf("md %d WTF: tile %d, fr %d\n", modelid, i, tile2model[i].framenum);
tile2model[i].framenum = otonframe[tile2model[i].framenum];
}
////// realloc & change "numframes" everywhere
// TODO: check if NULL
if (m->muladdframes)
m->muladdframes = Brealloc(m->muladdframes, 2*sizeof(point3d)*usedframes);
m->head.frames = Brealloc(m->head.frames, sizeof(md3frame_t)*usedframes);
for (surfi=0; surfi < m->head.numsurfs; surfi++)
{
m->head.surfs[surfi].numframes = usedframes;
// CAN'T do that because xyzn is offset from a larger block when loaded from md3:
// m->head.surfs[surfi].xyzn = Brealloc(m->head.surfs[surfi].xyzn, s->numverts*usedframes*sizeof(md3xyzn_t));
}
m->head.numframes = usedframes;
m->numframes = usedframes;
////////////
return usedframes;
}
int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, int32_t surfnum, float param, float specpower, float specfactor) int32_t md_defineskin(int32_t modelid, const char *skinfn, int32_t palnum, int32_t skinnum, int32_t surfnum, float param, float specpower, float specfactor)
{ {
mdskinmap_t *sk, *skl; mdskinmap_t *sk, *skl;
@ -1685,13 +1787,23 @@ int md3postload_polymer(md3model_t *m)
int *numtris; int *numtris;
float lat, lng, vec1[5], vec2[5], mat[9], r; float lat, lng, vec1[5], vec2[5], mat[9], r;
if (m->head.surfs[0].geometry)
return -1; // already postprocessed
// let's also repack the geometry to more usable formats // let's also repack the geometry to more usable formats
surfi = 0; surfi = 0;
while (surfi < m->head.numsurfs) while (surfi < m->head.numsurfs)
{ {
s = &m->head.surfs[surfi]; s = &m->head.surfs[surfi];
#ifdef DEBUG_MODEL_MEM
i = (m->head.numframes * s->numverts * sizeof(float) * 15);
if (i > 1<<20)
initprintf("size %d (%d fr, %d v): md %s surf %d/%d\n", i, m->head.numframes, s->numverts,
m->indices?(char *)m->indices:"null", surfi, m->head.numsurfs);
if (m->indices)
Bfree(m->indices), m->indices=NULL;
#endif
s->geometry = Bcalloc(m->head.numframes * s->numverts * sizeof(float), 15); s->geometry = Bcalloc(m->head.numframes * s->numverts * sizeof(float), 15);
numtris = Bcalloc(s->numverts, sizeof(int)); numtris = Bcalloc(s->numverts, sizeof(int));
@ -3249,19 +3361,18 @@ mdmodel_t *mdload(const char *filnam)
if (vm) if (vm)
{ {
#ifdef DEBUG_MODEL_MEM
((md3model_t *)vm)->indices = (void *)Bstrdup(filnam);
#endif
md3postload_common((md3model_t *)vm); md3postload_common((md3model_t *)vm);
#ifdef POLYMER
// implies defined(POLYMOST) && defined(USE_OPENGL)?
if (glrendmode==4)
i = md3postload_polymer((md3model_t *)vm);
else
i = md3postload_polymer_check((md3model_t *)vm);
if (!i) #ifdef POLYMER
{ if (glrendmode!=4)
mdfree(vm); if (!md3postload_polymer_check((md3model_t *)vm))
vm = (mdmodel_t *)0; {
} mdfree(vm);
vm = (mdmodel_t *)0;
}
#endif #endif
} }

View file

@ -252,12 +252,16 @@ int32_t OSD_Exec(const char *szScript)
if (fp != NULL) if (fp != NULL)
{ {
char line[255]; char line[256], *cp;
OSD_Printf("Executing \"%s\"\n", szScript); OSD_Printf("Executing \"%s\"\n", szScript);
osdexecscript++; osdexecscript++;
while (fgets(line, sizeof(line)-1, fp) != NULL) while (fgets(line, sizeof(line), fp) != NULL)
OSD_Dispatch(strtok(line,"\r\n")); {
cp = strtok(line,"\r\n");
if (cp)
OSD_Dispatch(cp);
}
osdexecscript--; osdexecscript--;
fclose(fp); fclose(fp);
return 0; return 0;

View file

@ -2163,41 +2163,3 @@ static int32_t buildkeytranslationtable(void)
return 0; return 0;
} }
#endif #endif
#if defined _WIN32
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
#elif defined __linux || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __APPLE__
# include <sys/mman.h>
#endif
void makeasmwriteable(void)
{
#ifndef ENGINE_USING_A_C
extern int32_t dep_begin, dep_end;
# if defined _WIN32
DWORD oldprot;
if (!VirtualProtect((LPVOID)&dep_begin, (SIZE_T)&dep_end - (SIZE_T)&dep_begin, PAGE_EXECUTE_READWRITE, &oldprot))
{
initprint("Error making code writeable\n");
return;
}
# elif defined __linux || defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __APPLE__
int32_t pagesize;
size_t dep_begin_page;
pagesize = sysconf(_SC_PAGE_SIZE);
if (pagesize == -1)
{
initprintf("Error getting system page size\n");
return;
}
dep_begin_page = ((size_t)&dep_begin) & ~(pagesize-1);
if (mprotect((void *)dep_begin_page, (size_t)&dep_end - dep_begin_page, PROT_READ|PROT_WRITE) < 0)
{
initprintf("Error making code writeable (errno=%d)\n", errno);
return;
}
# else
# error "Don't know how to unprotect the self-modifying assembly on this platform!"
# endif
#endif
}

View file

@ -3771,20 +3771,3 @@ static LPTSTR GetWindowsErrorMsg(DWORD code)
return lpMsgBuf; return lpMsgBuf;
} }
//
// makeasmwriteable() -- removes write protection from the self-modifying assembly code
//
void makeasmwriteable(void)
{
#ifndef ENGINE_USING_A_C
extern int32_t dep_begin, dep_end;
DWORD oldprot;
if (!VirtualProtect((LPVOID)&dep_begin, (SIZE_T)&dep_end - (SIZE_T)&dep_begin, PAGE_EXECUTE_READWRITE, &oldprot))
{
ShowErrorBox("Problem making code writeable");
}
#endif
}

View file

@ -648,6 +648,8 @@ int32_t CONFIG_ReadSetup(void)
SCRIPT_GetString(ud.config.scripthandle, "Comm Setup",commmacro,&ud.ridecule[dummy][0]); SCRIPT_GetString(ud.config.scripthandle, "Comm Setup",commmacro,&ud.ridecule[dummy][0]);
} }
Bmemset(tempbuf, 0, sizeof(tempbuf));
// Bmemset(dummybuf, 0, sizeof(dummybuf));
SCRIPT_GetString(ud.config.scripthandle, "Comm Setup","PlayerName",&tempbuf[0]); SCRIPT_GetString(ud.config.scripthandle, "Comm Setup","PlayerName",&tempbuf[0]);
while (Bstrlen(OSD_StripColors(dummybuf,tempbuf)) > 10) while (Bstrlen(OSD_StripColors(dummybuf,tempbuf)) > 10)

View file

@ -613,22 +613,16 @@ int32_t G_LoadPlayer(int32_t spot)
#ifdef POLYMER #ifdef POLYMER
if (getrendermode() == 4) if (getrendermode() == 4)
{
int32_t i = 0;
polymer_loadboard(); polymer_loadboard();
while (i < MAXSPRITES)
{
if (actor[i].lightptr)
{
actor[i].lightptr = NULL;
actor[i].lightId = -1;
}
i++;
}
}
#endif #endif
// this light pointer nulling needs to be outside the getrendermode check
// because we might be loading the savegame using another renderer but
// change to Polymer later
for (i=0; i<MAXSPRITES; i++)
{
actor[i].lightptr = NULL;
actor[i].lightId = -1;
}
return(0); return(0);
corrupt: corrupt:
@ -1930,8 +1924,8 @@ static void sv_preactordatasave()
Bmemset(savegame_bitmap, 0, sizeof(savegame_bitmap)); Bmemset(savegame_bitmap, 0, sizeof(savegame_bitmap));
for (i=0; i<MAXSPRITES; i++) for (i=0; i<MAXSPRITES; i++)
{ {
// Actor[i].lightptr = NULL; actor[i].lightptr = NULL;
// Actor[i].lightId = -1; actor[i].lightId = -1;
if (sprite[i].statnum==MAXSTATUS || actorscrptr[PN]==NULL) continue; if (sprite[i].statnum==MAXSTATUS || actorscrptr[PN]==NULL) continue;
if (T2 >= j && T2 < k) savegame_bitmap[i>>3][0] |= 1<<(i&7), T2 -= j; if (T2 >= j && T2 < k) savegame_bitmap[i>>3][0] |= 1<<(i&7), T2 -= j;
@ -1951,8 +1945,9 @@ static void sv_postactordata()
for (i=0; i<MAXSPRITES; i++) for (i=0; i<MAXSPRITES; i++)
{ {
// Actor[i].lightptr = NULL; actor[i].lightptr = NULL;
// Actor[i].lightId = -1; actor[i].lightId = -1;
actor[i].projectile = &SpriteProjectile[i]; actor[i].projectile = &SpriteProjectile[i];
if (sprite[i].statnum==MAXSTATUS || actorscrptr[PN]==NULL) continue; if (sprite[i].statnum==MAXSTATUS || actorscrptr[PN]==NULL) continue;