- replaced the leaky hash table that was used to handle the animations.

Just replaced with a linear array - for a hash table indexed with a string to be efficient, a much larger amount of data is needed than 20 or 30 entries.
This is also hardly the kind of data where losing a microsecond for performing the search matters.
This commit is contained in:
Christoph Oelckers 2019-12-25 09:51:44 +01:00
parent 4a31447702
commit 5e821de481
6 changed files with 79 additions and 123 deletions

View file

@ -26,6 +26,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "renderlayer.h"
#include "duke3d.h"
#include "animlib.h"
#include "cmdlib.h"
#include "compat.h"
@ -38,43 +39,35 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
BEGIN_DUKE_NS
// animsound_t.sound
EDUKE32_STATIC_ASSERT(INT16_MAX >= MAXSOUNDS);
dukeanim_t* g_animPtr;
TArray<dukeanim_t> g_Animations;
hashtable_t h_dukeanim = { 8, NULL };
dukeanim_t * g_animPtr;
dukeanim_t *Anim_Find(const char *s)
dukeanim_t* Anim_Find(const char* s)
{
intptr_t ptr = hash_findcase(&h_dukeanim, s);
if (ptr == -1)
auto index = g_Animations.FindEx([=](dukeanim_t& anm) { return !anm.name.CompareNoCase(s); });
if (index == g_Animations.Size())
{
int const siz = Bstrlen(s) + 5;
char * const str = (char *)Xcalloc(1, siz);
maybe_append_ext(str, siz, s, ".anm");
ptr = hash_findcase(&h_dukeanim, str);
if (ptr == -1)
FString fname = s;
DefaultExtension(fname, ".anm");
index = g_Animations.FindEx([=](dukeanim_t& anm) { return !anm.name.CompareNoCase(fname); });
if (index == g_Animations.Size())
{
maybe_append_ext(str, siz, s, ".ivf");
ptr = hash_findcase(&h_dukeanim, str);
fname = s;
DefaultExtension(fname, ".ivf");
index = g_Animations.FindEx([=](dukeanim_t& anm) { return !anm.name.CompareNoCase(fname); });
if (index == g_Animations.Size()) return nullptr;
}
Xfree(str);
}
return (dukeanim_t *)(ptr == -1 ? NULL : (dukeanim_t *)ptr);
return &g_Animations[index];
}
dukeanim_t * Anim_Create(char const * fn)
{
dukeanim_t * anim = (dukeanim_t *)Xcalloc(1, sizeof(dukeanim_t));
hash_add(&h_dukeanim, fn, (intptr_t)anim, 0);
return anim;
g_Animations.Reserve(1);
auto p = &g_Animations.Last();
p->name = fn;
return p;
}
#ifndef EDUKE32_STANDALONE
@ -87,9 +80,6 @@ static int32_t const StopAllSounds = -1;
void Anim_Init(void)
{
hash_init(&h_dukeanim);
struct defaultanmsound {
#ifdef DYNSOUNDREMAP_ENABLE
int32_t const & sound;
@ -208,17 +198,16 @@ void Anim_Init(void)
if (anm.numsounds)
{
anim->sounds = (animsound_t *)dump.Alloc(anm.numsounds * sizeof(animsound_t));
anim->Sounds.Resize(anm.numsounds);
int const numsounds = anm.numsounds;
for (int i = 0; i < numsounds; ++i)
{
defaultanmsound const & src = anm.sounds[i];
animsound_t & dst = anim->sounds[i];
animsound_t & dst = anim->Sounds[i];
dst.sound = src.sound;
dst.frame = src.frame;
}
anim->numsounds = numsounds;
}
anim->frameflags = 0;
@ -358,9 +347,9 @@ int32_t Anim_Play(const char *fn)
framenum++;
if (anim)
{
while (soundidx < anim->numsounds && anim->sounds[soundidx].frame <= framenum)
while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= framenum)
{
int16_t sound = anim->sounds[soundidx].sound;
int16_t sound = anim->Sounds[soundidx].sound;
if (sound == -1)
FX_StopAllSounds();
else
@ -372,9 +361,9 @@ int32_t Anim_Play(const char *fn)
else
{
uint16_t convframenum = scale(framenum, convnumer, convdenom);
while (soundidx < origanim->numsounds && origanim->sounds[soundidx].frame <= convframenum)
while (soundidx < origanim->Sounds.Size() && origanim->Sounds[soundidx].frame <= convframenum)
{
int16_t sound = origanim->sounds[soundidx].sound;
int16_t sound = origanim->Sounds[soundidx].sound;
if (sound == -1)
FX_StopAllSounds();
else
@ -518,7 +507,6 @@ int32_t Anim_Play(const char *fn)
z = divscale16(200, tilesiz[TILE_ANIM].x);
rotatesprite_fs(160<<16, 100<<16, z, 512, TILE_ANIM, 0, 0, 2|4|8|64);
}
g_animPtr = anim;
i = VM_OnEventWithReturn(EVENT_CUTSCENE, g_player[screenpeek].ps->i, screenpeek, i);
g_animPtr = NULL;
@ -529,9 +517,9 @@ int32_t Anim_Play(const char *fn)
ototalclock += anim->framedelay;
while (soundidx < anim->numsounds && anim->sounds[soundidx].frame <= (uint16_t)i)
while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= (uint16_t)i)
{
int16_t sound = anim->sounds[soundidx].sound;
int16_t sound = anim->Sounds[soundidx].sound;
if (sound == -1)
FX_StopAllSounds();
else
@ -539,7 +527,6 @@ int32_t Anim_Play(const char *fn)
soundidx++;
}
++i;
} while (i < numframes);
@ -555,8 +542,6 @@ end_anim:
tileDelete(TILE_ANIM);
// this is the lock for anim->animbuf
return !running;
}

View file

@ -25,6 +25,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "compat.h"
#include "hash.h"
#include "tarray.h"
#include "zstring.h"
BEGIN_DUKE_NS
@ -35,16 +37,17 @@ typedef struct {
typedef struct
{
FString name;
double frameaspect1, frameaspect2;
uint8_t* animbuf;
animsound_t *sounds;
uint16_t numsounds;
TArray<animsound_t> Sounds;
uint8_t framedelay;
uint8_t frameflags;
} dukeanim_t;
extern dukeanim_t * g_animPtr;
extern hashtable_t h_dukeanim;
extern dukeanim_t* g_animPtr;
extern TArray<dukeanim_t> g_Animations;
extern dukeanim_t * Anim_Find(const char *s);
extern dukeanim_t * Anim_Create(const char *fn);
int32_t Anim_Play(const char *fn);

View file

@ -4756,12 +4756,9 @@ static void parsedefinitions_game_include(const char *fileName, scriptfile *pScr
static void parsedefinitions_game_animsounds(scriptfile *pScript, const char * blockEnd, char const * fileName, dukeanim_t * animPtr)
{
Xfree(animPtr->sounds);
size_t numPairs = 0;
size_t numPairs = 0, allocSize = 4;
animPtr->sounds = (animsound_t *)Xmalloc(allocSize * sizeof(animsound_t));
animPtr->numsounds = 0;
animPtr->Sounds.Clear();
int defError = 1;
uint16_t lastFrameNum = 1;
@ -4812,32 +4809,27 @@ static void parsedefinitions_game_animsounds(scriptfile *pScript, const char * b
break;
}
if (numPairs >= allocSize)
{
allocSize *= 2;
animPtr->sounds = (animsound_t *)Xrealloc(animPtr->sounds, allocSize * sizeof(animsound_t));
}
defError = 0;
animsound_t & sound = animPtr->sounds[numPairs];
animsound_t sound;
sound.frame = frameNum;
sound.sound = soundNum;
animPtr->Sounds.Push(sound);
++numPairs;
}
if (!defError)
{
animPtr->numsounds = numPairs;
// initprintf("Defined sound sequence for hi-anim \"%s\" with %d frame/sound pairs\n",
// hardcoded_anim_tokens[animnum].text, numpairs);
}
else
{
DO_FREE_AND_NULL(animPtr->sounds);
initprintf("Failed defining sound sequence for anim \"%s\".\n", fileName);
}
animPtr->Sounds.ShrinkToFit();
}
static int parsedefinitions_game(scriptfile *pScript, int firstPass)
@ -5323,9 +5315,6 @@ static void G_Cleanup(void)
hash_free(&h_arrays);
hash_free(&h_labels);
#endif
hash_loop(&h_dukeanim, G_FreeHashAnim);
hash_free(&h_dukeanim);
}
/*

View file

@ -27,6 +27,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "duke3d.h"
#include "animlib.h"
#include "compat.h"
#include "cmdlib.h"
#include "anim.h"
@ -40,40 +41,34 @@ BEGIN_RR_NS
// animsound_t.sound
EDUKE32_STATIC_ASSERT(INT16_MAX >= MAXSOUNDS);
hashtable_t h_dukeanim = { 8, NULL };
TArray<dukeanim_t> g_Animations;
dukeanim_t * g_animPtr;
dukeanim_t *Anim_Find(const char *s)
dukeanim_t* Anim_Find(const char* s)
{
intptr_t ptr = hash_findcase(&h_dukeanim, s);
if (ptr == -1)
auto index = g_Animations.FindEx([=](dukeanim_t& anm) { return !anm.name.CompareNoCase(s); });
if (index == g_Animations.Size())
{
int const siz = Bstrlen(s) + 5;
char * const str = (char *)Xcalloc(1, siz);
maybe_append_ext(str, siz, s, ".anm");
ptr = hash_findcase(&h_dukeanim, str);
if (ptr == -1)
FString fname = s;
DefaultExtension(fname, ".anm");
index = g_Animations.FindEx([=](dukeanim_t& anm) { return !anm.name.CompareNoCase(fname); });
if (index == g_Animations.Size())
{
maybe_append_ext(str, siz, s, ".ivf");
ptr = hash_findcase(&h_dukeanim, str);
fname = s;
DefaultExtension(fname, ".ivf");
index = g_Animations.FindEx([=](dukeanim_t& anm) { return !anm.name.CompareNoCase(fname); });
if (index == g_Animations.Size()) return nullptr;
}
Bfree(str);
}
return (dukeanim_t *)(ptr == -1 ? NULL : (dukeanim_t *)ptr);
return &g_Animations[index];
}
dukeanim_t * Anim_Create(char const * fn)
{
dukeanim_t * anim = (dukeanim_t *)Xcalloc(1, sizeof(dukeanim_t));
hash_add(&h_dukeanim, fn, (intptr_t)anim, 0);
return anim;
g_Animations.Reserve(1);
auto p = &g_Animations.Last();
p->name = fn;
return p;
}
#ifdef DYNSOUNDREMAP_ENABLE
@ -84,9 +79,6 @@ static int32_t const StopAllSounds = -1;
void Anim_Init(void)
{
hash_init(&h_dukeanim);
struct defaultanmsound {
#ifdef DYNSOUNDREMAP_ENABLE
int32_t const & sound;
@ -237,24 +229,23 @@ void Anim_Init(void)
};
#undef anmsnd
for (defaultanm const & anm : anms)
for (defaultanm const& anm : anms)
{
dukeanim_t * anim = Anim_Create(anm.fn);
dukeanim_t* anim = Anim_Create(anm.fn);
anim->framedelay = anm.fdelay;
if (anm.numsounds)
{
anim->sounds = (animsound_t *)Xmalloc(anm.numsounds * sizeof(animsound_t));
size_t const numsounds = anm.numsounds;
for (size_t i = 0; i < numsounds; ++i)
anim->Sounds.Resize(anm.numsounds);
int const numsounds = anm.numsounds;
for (int i = 0; i < numsounds; ++i)
{
defaultanmsound const & src = anm.sounds[i];
animsound_t & dst = anim->sounds[i];
defaultanmsound const& src = anm.sounds[i];
animsound_t& dst = anim->Sounds[i];
dst.sound = src.sound;
dst.frame = src.frame;
}
anim->numsounds = numsounds;
}
anim->frameflags = 0;
@ -390,9 +381,9 @@ int32_t Anim_Play(const char *fn)
framenum++;
if (anim)
{
while (soundidx < anim->numsounds && anim->sounds[soundidx].frame <= framenum)
while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= framenum)
{
int16_t sound = anim->sounds[soundidx].sound;
int16_t sound = anim->Sounds[soundidx].sound;
if (sound == -1)
FX_StopAllSounds();
else
@ -404,9 +395,9 @@ int32_t Anim_Play(const char *fn)
else
{
uint16_t convframenum = scale(framenum, convnumer, convdenom);
while (soundidx < origanim->numsounds && origanim->sounds[soundidx].frame <= convframenum)
while (soundidx < origanim->Sounds.Size() && origanim->Sounds[soundidx].frame <= convframenum)
{
int16_t sound = origanim->sounds[soundidx].sound;
int16_t sound = origanim->Sounds[soundidx].sound;
if (sound == -1)
FX_StopAllSounds();
else
@ -560,9 +551,9 @@ int32_t Anim_Play(const char *fn)
ototalclock += anim->framedelay;
while (soundidx < anim->numsounds && anim->sounds[soundidx].frame <= (uint16_t)i)
while (soundidx < anim->Sounds.Size() && anim->Sounds[soundidx].frame <= (uint16_t)i)
{
int16_t sound = anim->sounds[soundidx].sound;
int16_t sound = anim->Sounds[soundidx].sound;
if (sound == -1)
FX_StopAllSounds();
else

View file

@ -32,16 +32,16 @@ typedef struct {
typedef struct
{
FString name;
double frameaspect1, frameaspect2;
uint8_t* animbuf;
animsound_t *sounds;
uint16_t numsounds;
TArray<animsound_t> Sounds;
uint8_t framedelay;
uint8_t frameflags;
} dukeanim_t;
extern dukeanim_t * g_animPtr;
extern hashtable_t h_dukeanim;
extern dukeanim_t* g_animPtr;
extern TArray<dukeanim_t> g_Animations;
extern dukeanim_t * Anim_Find(const char *s);
extern dukeanim_t * Anim_Create(const char *fn);
int32_t Anim_Play(const char *fn);

View file

@ -6317,12 +6317,9 @@ static void parsedefinitions_game_include(const char *fileName, scriptfile *pScr
static void parsedefinitions_game_animsounds(scriptfile *pScript, const char * blockEnd, char const * fileName, dukeanim_t * animPtr)
{
Bfree(animPtr->sounds);
size_t numPairs = 0, allocSize = 4;
animPtr->sounds = (animsound_t *)Xmalloc(allocSize * sizeof(animsound_t));
animPtr->numsounds = 0;
animPtr->Sounds.Clear();
int defError = 1;
uint16_t lastFrameNum = 1;
@ -6373,32 +6370,26 @@ static void parsedefinitions_game_animsounds(scriptfile *pScript, const char * b
break;
}
if (numPairs >= allocSize)
{
allocSize *= 2;
animPtr->sounds = (animsound_t *)Xrealloc(animPtr->sounds, allocSize * sizeof(animsound_t));
}
defError = 0;
animsound_t & sound = animPtr->sounds[numPairs];
animsound_t sound;
sound.frame = frameNum;
sound.sound = soundNum;
animPtr->Sounds.Push(sound);
++numPairs;
}
if (!defError)
{
animPtr->numsounds = numPairs;
// initprintf("Defined sound sequence for hi-anim \"%s\" with %d frame/sound pairs\n",
// hardcoded_anim_tokens[animnum].text, numpairs);
}
else
{
DO_FREE_AND_NULL(animPtr->sounds);
initprintf("Failed defining sound sequence for anim \"%s\".\n", fileName);
}
animPtr->Sounds.ShrinkToFit();
}
static int parsedefinitions_game(scriptfile *pScript, int firstPass)
@ -6734,9 +6725,6 @@ static void G_Cleanup(void)
// Bfree(MusicPtr);
hash_free(&h_labels);
hash_loop(&h_dukeanim, G_FreeHashAnim);
hash_free(&h_dukeanim);
}
/*