mirror of
https://gitlab.com/dosowisko.net/libsuperderpy.git
synced 2025-02-08 06:06:43 +01:00
fix memory leaks and other mem-bugs
This commit is contained in:
parent
51b08cee76
commit
686514fba5
5 changed files with 109 additions and 74 deletions
|
@ -23,7 +23,7 @@
|
|||
#include "gamestate.h"
|
||||
#include "internal.h"
|
||||
|
||||
SYMBOL_INTERNAL struct Gamestate* AddNewGamestate(struct Game *game) {
|
||||
SYMBOL_INTERNAL struct Gamestate* AddNewGamestate(struct Game *game, const char* name) {
|
||||
struct Gamestate *tmp = game->_priv.gamestates;
|
||||
if (!tmp) {
|
||||
game->_priv.gamestates = malloc(sizeof(struct Gamestate));
|
||||
|
@ -35,7 +35,7 @@ SYMBOL_INTERNAL struct Gamestate* AddNewGamestate(struct Game *game) {
|
|||
tmp->next = malloc(sizeof(struct Gamestate));
|
||||
tmp = tmp->next;
|
||||
}
|
||||
tmp->name = NULL;
|
||||
tmp->name = strdup(name);
|
||||
tmp->handle = NULL;
|
||||
tmp->loaded = false;
|
||||
tmp->paused = false;
|
||||
|
@ -68,8 +68,7 @@ SYMBOL_EXPORT void LoadGamestate(struct Game *game, const char* name) {
|
|||
}
|
||||
gs->pending_load = true;
|
||||
} else {
|
||||
gs = AddNewGamestate(game);
|
||||
gs->name = strdup(name);
|
||||
gs = AddNewGamestate(game, name);
|
||||
gs->pending_load = true;
|
||||
gs->showLoading = true;
|
||||
}
|
||||
|
|
|
@ -137,23 +137,55 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game *game) {
|
|||
}
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL void* AddGarbage(struct Game *game, void* data) {
|
||||
if (!game->_priv.garbage) {
|
||||
game->_priv.garbage = malloc(sizeof(struct libsuperderpy_list));
|
||||
game->_priv.garbage->data = data;
|
||||
game->_priv.garbage->next = NULL;
|
||||
SYMBOL_INTERNAL struct libsuperderpy_list* AddToList(struct libsuperderpy_list *list, void* data) {
|
||||
if (!list) {
|
||||
list = malloc(sizeof(struct libsuperderpy_list));
|
||||
list->data = data;
|
||||
list->next = NULL;
|
||||
} else {
|
||||
struct libsuperderpy_list *garbage = malloc(sizeof(struct libsuperderpy_list));
|
||||
garbage->next = game->_priv.garbage;
|
||||
garbage->data = data;
|
||||
game->_priv.garbage = garbage;
|
||||
struct libsuperderpy_list *elem = malloc(sizeof(struct libsuperderpy_list));
|
||||
elem->next = list;
|
||||
elem->data = data;
|
||||
list = elem;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL struct libsuperderpy_list* RemoveFromList(struct libsuperderpy_list **list, bool (*identity)(struct libsuperderpy_list* elem, void* data), void* data) {
|
||||
struct libsuperderpy_list *prev = NULL, *tmp = *list, *start = *list;
|
||||
void* d = NULL;
|
||||
while (tmp) {
|
||||
if (identity(tmp, data)) {
|
||||
if (prev) {
|
||||
prev->next = tmp->next;
|
||||
d = tmp->data;
|
||||
free(tmp);
|
||||
return d;
|
||||
} else {
|
||||
start = tmp->next;
|
||||
d = tmp->data;
|
||||
free(tmp);
|
||||
*list = start;
|
||||
return d;
|
||||
}
|
||||
}
|
||||
prev = tmp;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL void* AddGarbage(struct Game *game, void* data) {
|
||||
game->_priv.garbage = AddToList(game->_priv.garbage, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
SYMBOL_INTERNAL void ClearGarbage(struct Game *game) {
|
||||
struct libsuperderpy_list *tmp;
|
||||
while (game->_priv.garbage) {
|
||||
free(game->_priv.garbage->data);
|
||||
game->_priv.garbage = game->_priv.garbage->next;
|
||||
tmp = game->_priv.garbage->next;
|
||||
free(game->_priv.garbage);
|
||||
game->_priv.garbage = tmp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,8 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
|||
game->config.height = atoi(GetConfigOptionDefault(game, "SuperDerpy", "height", "720"));
|
||||
if (game->config.height<180) game->config.height=180;
|
||||
|
||||
game->_priv.showconsole = game->config.debug;
|
||||
|
||||
if(!al_init_image_addon()) {
|
||||
fprintf(stderr, "failed to initialize image addon!\n");
|
||||
/*al_show_native_message_box(display, "Error", "Error", "Failed to initialize al_init_image_addon!",
|
||||
|
@ -167,8 +169,6 @@ SYMBOL_EXPORT struct Game* libsuperderpy_init(int argc, char** argv, const char*
|
|||
al_set_mixer_gain(game->audio.music, game->config.music/10.0);
|
||||
al_set_mixer_gain(game->audio.voice, game->config.voice/10.0);
|
||||
|
||||
game->_priv.showconsole = game->config.debug;
|
||||
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
|
||||
game->_priv.argc = argc;
|
||||
|
@ -328,7 +328,6 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
|
|||
tmp=game->_priv.gamestates;
|
||||
|
||||
while (tmp) {
|
||||
|
||||
if ((tmp->pending_start) && (tmp->loaded)) {
|
||||
PrintConsole(game, "Starting gamestate \"%s\"...", tmp->name);
|
||||
al_stop_timer(game->_priv.timer);
|
||||
|
@ -415,8 +414,10 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) {
|
|||
SYMBOL_EXPORT void libsuperderpy_destroy(struct Game *game) {
|
||||
game->shuttingdown = true;
|
||||
|
||||
ClearGarbage(game);
|
||||
|
||||
// in case of restart
|
||||
struct Gamestate *tmp = game->_priv.gamestates;
|
||||
struct Gamestate *tmp = game->_priv.gamestates, *pom;
|
||||
while (tmp) {
|
||||
if (tmp->started) {
|
||||
PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name);
|
||||
|
@ -429,14 +430,20 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game *game) {
|
|||
dlclose(tmp->handle);
|
||||
tmp->loaded = false;
|
||||
}
|
||||
tmp=tmp->next;
|
||||
free(tmp->name);
|
||||
pom = tmp->next;
|
||||
free(tmp);
|
||||
tmp=pom;
|
||||
}
|
||||
|
||||
al_clear_to_color(al_map_rgb(0,0,0));
|
||||
PrintConsole(game, "Shutting down...");
|
||||
DrawConsole(game);
|
||||
al_flip_display();
|
||||
al_rest(0.1);
|
||||
while (game->_priv.garbage) {
|
||||
free(game->_priv.garbage->data);
|
||||
game->_priv.garbage = game->_priv.garbage->next;
|
||||
}
|
||||
(*game->_priv.loading.Unload)(game, game->_priv.loading.data);
|
||||
al_destroy_timer(game->_priv.timer);
|
||||
Console_Unload(game);
|
||||
|
@ -452,8 +459,9 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game *game) {
|
|||
al_shutdown_ttf_addon();
|
||||
al_shutdown_font_addon();
|
||||
char** argv = game->_priv.argv;
|
||||
bool restart = game->restart;
|
||||
free(game);
|
||||
if (game->restart) {
|
||||
if (restart) {
|
||||
execv(argv[0], argv); // FIXME: on OSX there's chdir called which might break it
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ SYMBOL_EXPORT void TM_Process(struct Timeline* timeline) {
|
|||
struct TM_Action *tmp = timeline->queue;
|
||||
timeline->queue = timeline->queue->next;
|
||||
(*tmp->function)(timeline->game, tmp, TM_ACTIONSTATE_DESTROY);
|
||||
TM_DestroyArgs(tmp->arguments);
|
||||
free(tmp->name);
|
||||
free(tmp);
|
||||
}
|
||||
|
@ -101,6 +102,7 @@ SYMBOL_EXPORT void TM_Process(struct Timeline* timeline) {
|
|||
tmp = pom;
|
||||
pom = pom->next;
|
||||
} else {
|
||||
TM_DestroyArgs(pom->arguments);
|
||||
free(pom->name);
|
||||
free(pom);
|
||||
tmp2 = tmp;
|
||||
|
@ -264,19 +266,30 @@ SYMBOL_EXPORT struct TM_Action* TM_AddBackgroundAction(struct Timeline* timeline
|
|||
|
||||
/*! \brief Predefined action used by TM_AddQueuedBackgroundAction */
|
||||
SYMBOL_INTERNAL bool runinbackground(struct Game* game, struct TM_Action* action, enum TM_ActionState state) {
|
||||
if (state != TM_ACTIONSTATE_RUNNING) return false;
|
||||
int* delay = (int*) action->arguments->next->value;
|
||||
char* name = (char*) action->arguments->next->next->value;
|
||||
struct Timeline *timeline = (struct Timeline*) action->arguments->next->next->next->value;
|
||||
TM_AddBackgroundAction(timeline, action->arguments->value, action->arguments->next->next->next->next, *delay, name);
|
||||
int* delay = (int*) TM_GetArg(action->arguments, 1);
|
||||
char* name = (char*) TM_GetArg(action->arguments, 2);
|
||||
struct Timeline *timeline = (struct Timeline*) TM_GetArg(action->arguments, 3);
|
||||
struct TM_Arguments *arguments = (struct TM_Arguments*) TM_GetArg(action->arguments, 4);
|
||||
bool *used = (bool*) TM_GetArg(action->arguments, 5);
|
||||
if (state == TM_ACTIONSTATE_START) {
|
||||
TM_AddBackgroundAction(timeline, TM_GetArg(action->arguments, 0), arguments, *delay, name);
|
||||
*used = true;
|
||||
}
|
||||
if (state == TM_ACTIONSTATE_DESTROY) {
|
||||
free(name);
|
||||
free(delay);
|
||||
if (!(*used)) {
|
||||
TM_DestroyArgs(arguments);
|
||||
}
|
||||
free(used);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
SYMBOL_EXPORT struct TM_Action* TM_AddQueuedBackgroundAction(struct Timeline* timeline, bool (*func)(struct Game*, struct TM_Action*, enum TM_ActionState), struct TM_Arguments* args, int delay, char* name) {
|
||||
TM_WrapArg(int, del, delay);
|
||||
struct TM_Arguments* arguments = TM_AddToArgs(NULL, 4, (void*) func, del, strdup(name), (void*) timeline);
|
||||
arguments->next->next->next->next = args;
|
||||
TM_WrapArg(bool, used, false);
|
||||
struct TM_Arguments* arguments = TM_AddToArgs(NULL, 6, (void*) func, del, strdup(name), (void*) timeline, args, used);
|
||||
return TM_AddAction(timeline, *runinbackground, arguments, "TM_BackgroundAction");
|
||||
}
|
||||
|
||||
|
@ -294,63 +307,37 @@ SYMBOL_EXPORT void TM_AddDelay(struct Timeline* timeline, int delay) {
|
|||
|
||||
SYMBOL_EXPORT void TM_CleanQueue(struct Timeline* timeline) {
|
||||
PrintConsole(timeline->game, "Timeline Manager[%s]: cleaning queue", timeline->name);
|
||||
struct TM_Action *tmp, *tmp2, *pom = timeline->queue;
|
||||
tmp = NULL;
|
||||
struct TM_Action *tmp, *pom = timeline->queue;
|
||||
while (pom!=NULL) {
|
||||
if (pom->active) {
|
||||
if (*pom->function) (*pom->function)(timeline->game, pom, TM_ACTIONSTATE_DESTROY);
|
||||
if (pom->timer) {
|
||||
al_stop_timer(pom->timer);
|
||||
al_destroy_timer(pom->timer);
|
||||
}
|
||||
} else {
|
||||
TM_DestroyArgs(pom->arguments);
|
||||
pom->arguments = NULL;
|
||||
}
|
||||
if ((!tmp) || (tmp->next==pom)) {
|
||||
tmp = pom;
|
||||
pom = pom->next;
|
||||
} else {
|
||||
tmp = pom->next;
|
||||
free(pom->name);
|
||||
free(pom);
|
||||
tmp2 = tmp;
|
||||
if (!tmp) pom=timeline->queue->next;
|
||||
else pom=tmp->next;
|
||||
tmp = tmp2;
|
||||
pom = tmp;
|
||||
}
|
||||
}
|
||||
// TODO: it shouldn't be needed, but is. Debug!
|
||||
timeline->queue = NULL;
|
||||
}
|
||||
|
||||
SYMBOL_EXPORT void TM_CleanBackgroundQueue(struct Timeline* timeline) {
|
||||
PrintConsole(timeline->game, "Timeline Manager[%s]: cleaning background queue", timeline->name);
|
||||
struct TM_Action *tmp, *tmp2, *pom = timeline->background;
|
||||
tmp = NULL;
|
||||
struct TM_Action *tmp, *pom = timeline->background;
|
||||
while (pom!=NULL) {
|
||||
if (pom->active) {
|
||||
if (*pom->function) (*pom->function)(timeline->game, pom, TM_ACTIONSTATE_DESTROY);
|
||||
if (pom->timer) {
|
||||
al_stop_timer(pom->timer);
|
||||
al_destroy_timer(pom->timer);
|
||||
}
|
||||
} else {
|
||||
TM_DestroyArgs(pom->arguments);
|
||||
pom->arguments = NULL;
|
||||
}
|
||||
if ((!tmp) || (tmp->next==pom)) {
|
||||
tmp = pom;
|
||||
pom = pom->next;
|
||||
} else {
|
||||
tmp = pom->next;
|
||||
free(pom->name);
|
||||
free(pom);
|
||||
tmp2 = tmp;
|
||||
if (!tmp) pom=timeline->background->next;
|
||||
else pom=tmp->next;
|
||||
tmp = tmp2;
|
||||
pom = tmp;
|
||||
}
|
||||
}
|
||||
// TODO: it shouldn't be needed, but is. Debug!
|
||||
timeline->background = NULL;
|
||||
}
|
||||
|
||||
|
@ -389,6 +376,13 @@ SYMBOL_EXPORT struct TM_Arguments* TM_AddToArgs(struct TM_Arguments* args, int n
|
|||
return args;
|
||||
}
|
||||
|
||||
SYMBOL_EXPORT void* TM_GetArg(struct TM_Arguments *args, int num) {
|
||||
for (int i=0; i<num; i++) {
|
||||
args = args->next;
|
||||
}
|
||||
return args->value;
|
||||
}
|
||||
|
||||
SYMBOL_EXPORT void TM_DestroyArgs(struct TM_Arguments* args) {
|
||||
struct TM_Arguments *pom;
|
||||
while (args) {
|
||||
|
|
|
@ -92,6 +92,8 @@ void TM_CleanBackgroundQueue(struct Timeline*);
|
|||
void TM_Destroy(struct Timeline*);
|
||||
/*! \brief Add data to TM_Arguments queue. */
|
||||
struct TM_Arguments* TM_AddToArgs(struct TM_Arguments* args, int num, ...);
|
||||
/*! \brief Get nth argument from TM_Arguments queue (counted from 0). */
|
||||
void* TM_GetArg(struct TM_Arguments *args, int num);
|
||||
/*! \brief Destroy TM_Arguments queue. */
|
||||
void TM_DestroyArgs(struct TM_Arguments* args);
|
||||
|
||||
|
|
Loading…
Reference in a new issue