Clean up memory usage of XML loading
This commit is contained in:
parent
17cc6063a3
commit
aa8590d585
@ -451,7 +451,9 @@ void debug_drawUi(GameState *state, f32 dt)
|
|||||||
i32 debug_bAllocated = state->arena.bytesAllocated;
|
i32 debug_bAllocated = state->arena.bytesAllocated;
|
||||||
DEBUG_PUSH_VAR("TotalMemoryAllocated: %db", debug_bAllocated, "i32");
|
DEBUG_PUSH_VAR("TotalMemoryAllocated: %db", debug_bAllocated, "i32");
|
||||||
i32 debug_kbAllocated = state->arena.bytesAllocated / 1024;
|
i32 debug_kbAllocated = state->arena.bytesAllocated / 1024;
|
||||||
|
i32 debug_mbAllocated = debug_kbAllocated / 1024;
|
||||||
DEBUG_PUSH_VAR("TotalMemoryAllocated: %dkb", debug_kbAllocated, "i32");
|
DEBUG_PUSH_VAR("TotalMemoryAllocated: %dkb", debug_kbAllocated, "i32");
|
||||||
|
DEBUG_PUSH_VAR("TotalMemoryAllocated: %dmb", debug_mbAllocated, "i32");
|
||||||
DEBUG_PUSH_STRING("");
|
DEBUG_PUSH_STRING("");
|
||||||
|
|
||||||
AudioManager *audioManager = &state->audioManager;
|
AudioManager *audioManager = &state->audioManager;
|
||||||
|
@ -19,11 +19,10 @@ void entity_setActiveAnim(Entity *entity, char *animName)
|
|||||||
if (common_strcmp(anim->key, animName) == 0)
|
if (common_strcmp(anim->key, animName) == 0)
|
||||||
{
|
{
|
||||||
entity->currAnimId = i;
|
entity->currAnimId = i;
|
||||||
EntityAnim *currEntityAnim =
|
EntityAnim *newEntityAnim = &entity->animList[i];
|
||||||
&entity->animList[entity->currAnimId];
|
newEntityAnim->currDuration =
|
||||||
currEntityAnim->currDuration =
|
newEntityAnim->anim->frameDuration;
|
||||||
currEntityAnim->anim->frameDuration;
|
newEntityAnim->currFrame = 0;
|
||||||
currEntityAnim->currFrame = 0;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,38 +188,19 @@ INTERNAL void debug_recursivePrintXmlTree(XmlNode *root, i32 levelsDeep)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void assetInit(GameState *state)
|
INTERNAL XmlToken *tokeniseXmlBuffer(MemoryArena *arena, char *buffer,
|
||||||
|
i32 bufferSize, int *numTokens)
|
||||||
{
|
{
|
||||||
AssetManager *assetManager = &state->assetManager;
|
|
||||||
MemoryArena *arena = &state->arena;
|
|
||||||
|
|
||||||
/* Create empty 1x1 4bpp black texture */
|
|
||||||
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
|
|
||||||
Texture emptyTex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap));
|
|
||||||
assetManager->textures[texlist_empty] = emptyTex;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
**********************
|
**********************
|
||||||
* Tokenise XML Buffer
|
* Tokenise XML Buffer
|
||||||
**********************
|
**********************
|
||||||
*/
|
*/
|
||||||
PlatformFileRead xmlFileRead = {0};
|
|
||||||
|
|
||||||
i32 result = platform_readFileToBuffer(
|
|
||||||
arena, "data/textures/WorldTraveller/ClaudeSprite.xml",
|
|
||||||
&xmlFileRead);
|
|
||||||
|
|
||||||
XmlToken *xmlTokens = PLATFORM_MEM_ALLOC(arena, 8192, XmlToken);
|
XmlToken *xmlTokens = PLATFORM_MEM_ALLOC(arena, 8192, XmlToken);
|
||||||
i32 tokenIndex = 0;
|
i32 tokenIndex = 0;
|
||||||
if (result)
|
for (i32 i = 0; i < bufferSize; i++)
|
||||||
{
|
{
|
||||||
DEBUG_LOG("Failed to read sprite sheet xml");
|
char c = (CAST(char *) buffer)[i];
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i32 i = 0; i < xmlFileRead.size; i++)
|
|
||||||
{
|
|
||||||
char c = (CAST(char *)xmlFileRead.buffer)[i];
|
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case '<':
|
case '<':
|
||||||
@ -255,9 +236,9 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
case '"':
|
case '"':
|
||||||
{
|
{
|
||||||
xmlTokens[tokenIndex].type = xmltokentype_value;
|
xmlTokens[tokenIndex].type = xmltokentype_value;
|
||||||
for (i32 j = i + 1; j < xmlFileRead.size; j++)
|
for (i32 j = i + 1; j < bufferSize; j++)
|
||||||
{
|
{
|
||||||
char c = (CAST(char *) xmlFileRead.buffer)[j];
|
char c = (CAST(char *) buffer)[j];
|
||||||
|
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
{
|
{
|
||||||
@ -265,8 +246,8 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xmlTokens[tokenIndex]
|
xmlTokens[tokenIndex].string[xmlTokens[tokenIndex].len++] =
|
||||||
.string[xmlTokens[tokenIndex].len++] = c;
|
c;
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
ASSERT(xmlTokens[tokenIndex].len <
|
ASSERT(xmlTokens[tokenIndex].len <
|
||||||
ARRAY_COUNT(xmlTokens[tokenIndex].string));
|
ARRAY_COUNT(xmlTokens[tokenIndex].string));
|
||||||
@ -285,9 +266,9 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
if ((c >= 'a' && c <= 'z') || c >= 'A' && c <= 'Z')
|
if ((c >= 'a' && c <= 'z') || c >= 'A' && c <= 'Z')
|
||||||
{
|
{
|
||||||
xmlTokens[tokenIndex].type = xmltokentype_name;
|
xmlTokens[tokenIndex].type = xmltokentype_name;
|
||||||
for (i32 j = i; j < xmlFileRead.size; j++)
|
for (i32 j = i; j < bufferSize; j++)
|
||||||
{
|
{
|
||||||
char c = (CAST(char *) xmlFileRead.buffer)[j];
|
char c = (CAST(char *) buffer)[j];
|
||||||
|
|
||||||
if (c == ' ' || c == '=' || c == '>' || c == '<' ||
|
if (c == ' ' || c == '=' || c == '>' || c == '<' ||
|
||||||
c == '\\')
|
c == '\\')
|
||||||
@ -311,10 +292,17 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
XmlNode root = {0};
|
// TODO(doyle): Dynamic token allocation
|
||||||
XmlNode *node = &root;
|
*numTokens = 8192;
|
||||||
|
return xmlTokens;
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL XmlNode *buildXmlTree(MemoryArena *arena, XmlToken *xmlTokens,
|
||||||
|
i32 numTokens)
|
||||||
|
{
|
||||||
|
XmlNode *root = PLATFORM_MEM_ALLOC(arena, 1, XmlNode);
|
||||||
|
XmlNode *node = root;
|
||||||
node->parent = node;
|
node->parent = node;
|
||||||
|
|
||||||
// NOTE(doyle): Used for when closing a node with many children. We
|
// NOTE(doyle): Used for when closing a node with many children. We
|
||||||
@ -323,7 +311,7 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
// token indicates the group is closing- we need to set the last child's
|
// token indicates the group is closing- we need to set the last child's
|
||||||
// next reference to NULL
|
// next reference to NULL
|
||||||
XmlNode *prevNode = NULL;
|
XmlNode *prevNode = NULL;
|
||||||
for (i32 i = 0; i < tokenIndex; i++)
|
for (i32 i = 0; i < numTokens; i++)
|
||||||
{
|
{
|
||||||
XmlToken *token = &xmlTokens[i];
|
XmlToken *token = &xmlTokens[i];
|
||||||
|
|
||||||
@ -447,14 +435,16 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
return root;
|
||||||
DEBUG_RECURSIVE_PRINT_XML_TREE(&root);
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
node = &root;
|
INTERNAL void parseXmlTreeToGame(AssetManager *assetManager, MemoryArena *arena,
|
||||||
|
XmlNode *root)
|
||||||
|
{
|
||||||
|
XmlNode *node = root;
|
||||||
while (node)
|
while (node)
|
||||||
{
|
{
|
||||||
if(common_strcmp(node->name, "TextureAtlas") == 0)
|
if (common_strcmp(node->name, "TextureAtlas") == 0)
|
||||||
{
|
{
|
||||||
XmlNode *atlasXmlNode = node;
|
XmlNode *atlasXmlNode = node;
|
||||||
TexAtlas *atlasEntry = NULL;
|
TexAtlas *atlasEntry = NULL;
|
||||||
@ -470,8 +460,8 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
|
|
||||||
asset_loadTextureImage(assetManager, imagePath, texlist_claude);
|
asset_loadTextureImage(assetManager, imagePath, texlist_claude);
|
||||||
|
|
||||||
atlasEntry->key =
|
atlasEntry->key = PLATFORM_MEM_ALLOC(
|
||||||
PLATFORM_MEM_ALLOC(arena, common_strlen(imageName)+1, char);
|
arena, common_strlen(imageName) + 1, char);
|
||||||
common_strncpy(atlasEntry->key, imageName,
|
common_strncpy(atlasEntry->key, imageName,
|
||||||
common_strlen(imageName));
|
common_strlen(imageName));
|
||||||
|
|
||||||
@ -588,7 +578,7 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
i32 keyLen = common_strlen(newSubTexEntry.key);
|
i32 keyLen = common_strlen(newSubTexEntry.key);
|
||||||
|
|
||||||
subTexEntry->key =
|
subTexEntry->key =
|
||||||
PLATFORM_MEM_ALLOC(arena, keyLen+1, char);
|
PLATFORM_MEM_ALLOC(arena, keyLen + 1, char);
|
||||||
common_strncpy(subTexEntry->key, newSubTexEntry.key,
|
common_strncpy(subTexEntry->key, newSubTexEntry.key,
|
||||||
keyLen);
|
keyLen);
|
||||||
}
|
}
|
||||||
@ -617,20 +607,105 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
}
|
}
|
||||||
node = node->next;
|
node = node->next;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Load shaders */
|
INTERNAL void recursiveFreeXmlTree(MemoryArena *arena, XmlNode *node)
|
||||||
asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl",
|
{
|
||||||
"data/shaders/sprite.frag.glsl",
|
if (!node)
|
||||||
shaderlist_sprite);
|
{
|
||||||
|
return;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
// NOTE(doyle): First attribute is statically allocated, only if there's
|
||||||
|
// more attributes do we dynamically allocate
|
||||||
|
XmlAttribute *attrib = node->attribute.next;
|
||||||
|
|
||||||
result =
|
while (attrib)
|
||||||
asset_loadTTFont(assetManager, arena, "C:/Windows/Fonts/Arialbd.ttf");
|
{
|
||||||
|
XmlAttribute *next = attrib->next;
|
||||||
|
|
||||||
#ifdef DENGINE_DEBUG
|
attrib->name = NULL;
|
||||||
if (result) DEBUG_LOG("Font loading failed");
|
attrib->value = NULL;
|
||||||
GL_CHECK_ERROR();
|
PLATFORM_MEM_FREE(arena, attrib, sizeof(XmlAttribute));
|
||||||
DEBUG_LOG("Assets loaded");
|
attrib = next;
|
||||||
#endif
|
}
|
||||||
|
|
||||||
|
recursiveFreeXmlTree(arena, node->child);
|
||||||
|
recursiveFreeXmlTree(arena, node->next);
|
||||||
|
|
||||||
|
node->name = NULL;
|
||||||
|
node->isClosed = FALSE;
|
||||||
|
PLATFORM_MEM_FREE(arena, node, sizeof(XmlNode));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL void freeXmlData(MemoryArena *arena, XmlToken *tokens, i32 numTokens,
|
||||||
|
XmlNode *tree)
|
||||||
|
{
|
||||||
|
if (tree) recursiveFreeXmlTree(arena, tree);
|
||||||
|
if (tokens) PLATFORM_MEM_FREE(arena, tokens, numTokens * sizeof(XmlToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL void assetInit(GameState *state)
|
||||||
|
{
|
||||||
|
AssetManager *assetManager = &state->assetManager;
|
||||||
|
MemoryArena *arena = &state->arena;
|
||||||
|
|
||||||
|
/* Create empty 1x1 4bpp black texture */
|
||||||
|
u32 bitmap = (0xFF << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF << 0);
|
||||||
|
Texture emptyTex = texture_gen(1, 1, 4, CAST(u8 *)(&bitmap));
|
||||||
|
assetManager->textures[texlist_empty] = emptyTex;
|
||||||
|
|
||||||
|
PlatformFileRead terrainXml = {0};
|
||||||
|
i32 result = platform_readFileToBuffer(
|
||||||
|
arena, "data/textures/WorldTraveller/terrain.xml", &terrainXml);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
DEBUG_LOG("Failed to read sprite sheet xml");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Tokenise buffer */
|
||||||
|
i32 numTokens = 0;
|
||||||
|
XmlToken *xmlTokens = tokeniseXmlBuffer(arena, terrainXml.buffer,
|
||||||
|
terrainXml.size, &numTokens);
|
||||||
|
|
||||||
|
/* Build XML tree from tokens */
|
||||||
|
XmlNode *xmlTree = buildXmlTree(arena, xmlTokens, numTokens);
|
||||||
|
|
||||||
|
/* Parse XML tree to game structures */
|
||||||
|
parseXmlTreeToGame(assetManager, arena, xmlTree);
|
||||||
|
|
||||||
|
/* Free data */
|
||||||
|
freeXmlData(arena, xmlTokens, numTokens, xmlTree);
|
||||||
|
platform_closeFileRead(arena, &terrainXml);
|
||||||
|
}
|
||||||
|
|
||||||
|
PlatformFileRead claudeXml = {0};
|
||||||
|
result = platform_readFileToBuffer(
|
||||||
|
arena, "data/textures/WorldTraveller/ClaudeSprite.xml", &claudeXml);
|
||||||
|
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
DEBUG_LOG("Failed to read sprite sheet xml");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Tokenise buffer */
|
||||||
|
i32 numTokens = 0;
|
||||||
|
XmlToken *xmlTokens = tokeniseXmlBuffer(arena, claudeXml.buffer,
|
||||||
|
claudeXml.size, &numTokens);
|
||||||
|
|
||||||
|
/* Build XML tree from tokens */
|
||||||
|
XmlNode *xmlTree = buildXmlTree(arena, xmlTokens, numTokens);
|
||||||
|
|
||||||
|
/* Parse XML tree to game structures */
|
||||||
|
parseXmlTreeToGame(assetManager, arena, xmlTree);
|
||||||
|
|
||||||
|
/* Free data */
|
||||||
|
freeXmlData(arena, xmlTokens, numTokens, xmlTree);
|
||||||
|
platform_closeFileRead(arena, &claudeXml);
|
||||||
|
|
||||||
TexAtlas *claudeAtlas =
|
TexAtlas *claudeAtlas =
|
||||||
asset_getTexAtlas(assetManager, "ClaudeSprite.png");
|
asset_getTexAtlas(assetManager, "ClaudeSprite.png");
|
||||||
@ -684,6 +759,21 @@ INTERNAL void assetInit(GameState *state)
|
|||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
DEBUG_LOG("Animations created");
|
DEBUG_LOG("Animations created");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load shaders */
|
||||||
|
asset_loadShaderFiles(assetManager, arena, "data/shaders/sprite.vert.glsl",
|
||||||
|
"data/shaders/sprite.frag.glsl",
|
||||||
|
shaderlist_sprite);
|
||||||
|
|
||||||
|
result =
|
||||||
|
asset_loadTTFont(assetManager, arena, "C:/Windows/Fonts/Arialbd.ttf");
|
||||||
|
|
||||||
|
#ifdef DENGINE_DEBUG
|
||||||
|
if (result) DEBUG_LOG("Font loading failed");
|
||||||
|
GL_CHECK_ERROR();
|
||||||
|
DEBUG_LOG("Assets loaded");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Load sound */
|
/* Load sound */
|
||||||
|
|
||||||
@ -874,7 +964,7 @@ INTERNAL v2 getPosRelativeToRect(Rect rect, v2 offset,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL void unitTest()
|
INTERNAL void unitTest(MemoryArena *arena)
|
||||||
{
|
{
|
||||||
ASSERT(common_atoi("-2", common_strlen("-2")) == -2);
|
ASSERT(common_atoi("-2", common_strlen("-2")) == -2);
|
||||||
ASSERT(common_atoi("100", common_strlen("100")) == 100);
|
ASSERT(common_atoi("100", common_strlen("100")) == 100);
|
||||||
@ -886,6 +976,29 @@ INTERNAL void unitTest()
|
|||||||
ASSERT(common_atoi("+32", common_strlen("+32")) == 32);
|
ASSERT(common_atoi("+32", common_strlen("+32")) == 32);
|
||||||
ASSERT(common_atoi("+ 32", common_strlen("+ 32")) == 0);
|
ASSERT(common_atoi("+ 32", common_strlen("+ 32")) == 0);
|
||||||
|
|
||||||
|
|
||||||
|
PlatformFileRead xmlFileRead = {0};
|
||||||
|
i32 result = platform_readFileToBuffer(
|
||||||
|
arena, "data/textures/WorldTraveller/ClaudeSprite.xml", &xmlFileRead);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
DEBUG_LOG(
|
||||||
|
"unitTest() error: Could not load XML file for memory free test");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Tokenise buffer */
|
||||||
|
i32 memBefore = arena->bytesAllocated;
|
||||||
|
i32 numTokens = 0;
|
||||||
|
XmlToken *xmlTokens = tokeniseXmlBuffer(arena, xmlFileRead.buffer,
|
||||||
|
xmlFileRead.size, &numTokens);
|
||||||
|
/* Build XML tree from tokens */
|
||||||
|
XmlNode *xmlTree = buildXmlTree(arena, xmlTokens, numTokens);
|
||||||
|
freeXmlData(arena, xmlTokens, numTokens, xmlTree);
|
||||||
|
i32 memAfter = arena->bytesAllocated;
|
||||||
|
|
||||||
|
ASSERT(memBefore == memAfter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(doyle): Remove and implement own random generator!
|
// TODO(doyle): Remove and implement own random generator!
|
||||||
@ -894,7 +1007,7 @@ INTERNAL void unitTest()
|
|||||||
void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
void worldTraveller_gameInit(GameState *state, v2 windowSize)
|
||||||
{
|
{
|
||||||
#ifdef DENGINE_DEBUG
|
#ifdef DENGINE_DEBUG
|
||||||
unitTest();
|
unitTest(&state->arena);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
i32 result = audio_init(&state->audioManager);
|
i32 result = audio_init(&state->audioManager);
|
||||||
@ -1290,11 +1403,12 @@ INTERNAL void beginAttack(EventQueue *eventQueue, World *world,
|
|||||||
switch (attacker->stats->queuedAttack)
|
switch (attacker->stats->queuedAttack)
|
||||||
{
|
{
|
||||||
case entityattack_tackle:
|
case entityattack_tackle:
|
||||||
|
entity_setActiveAnim(attacker, "claudeAttack");
|
||||||
EntityAnim attackAnim = attacker->animList[attacker->currAnimId];
|
EntityAnim attackAnim = attacker->animList[attacker->currAnimId];
|
||||||
f32 busyDuration = attackAnim.anim->frameDuration *
|
f32 busyDuration = attackAnim.anim->frameDuration *
|
||||||
CAST(f32) attackAnim.anim->numFrames;
|
CAST(f32) attackAnim.anim->numFrames;
|
||||||
attacker->stats->busyDuration = busyDuration;
|
attacker->stats->busyDuration = busyDuration;
|
||||||
entity_setActiveAnim(attacker, "claudeAttack");
|
|
||||||
if (attacker->direction == direction_east)
|
if (attacker->direction == direction_east)
|
||||||
attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
|
attacker->dPos.x += (1.0f * METERS_TO_PIXEL);
|
||||||
else
|
else
|
||||||
|
@ -32,21 +32,6 @@ enum TerrainRects
|
|||||||
terrainrects_count,
|
terrainrects_count,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum HeroRects
|
|
||||||
{
|
|
||||||
herorects_idle,
|
|
||||||
herorects_walkA,
|
|
||||||
herorects_walkB,
|
|
||||||
herorects_head,
|
|
||||||
herorects_waveA,
|
|
||||||
herorects_waveB,
|
|
||||||
herorects_battlePose,
|
|
||||||
herorects_castA,
|
|
||||||
herorects_castB,
|
|
||||||
herorects_castC,
|
|
||||||
herorects_count,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum AnimList
|
enum AnimList
|
||||||
{
|
{
|
||||||
animlist_hero_idle,
|
animlist_hero_idle,
|
||||||
|
Loading…
Reference in New Issue
Block a user