diff --git a/src/gamestate.c b/src/gamestate.c index 819d057..6929ecd 100644 --- a/src/gamestate.c +++ b/src/gamestate.c @@ -45,6 +45,7 @@ SYMBOL_INTERNAL struct Gamestate* AddNewGamestate(struct Game *game, const char* tmp->pending_stop = false; tmp->pending_unload = false; tmp->next = NULL; + tmp->api = NULL; return tmp; } @@ -59,6 +60,19 @@ SYMBOL_INTERNAL struct Gamestate* FindGamestate(struct Game *game, const char* n return NULL; } +SYMBOL_EXPORT void RegisterGamestate(struct Game *game, const char* name, struct Gamestate_API *api) { + struct Gamestate *gs = FindGamestate(game, name); + if (!gs) { + gs = AddNewGamestate(game, name); + } + if (gs->api) { + PrintConsole(game, "Trying to register already registered gamestate \"%s\"!", name); + return; + } + gs->api = api; + PrintConsole(game, "Gamestate \"%s\" registered.", name); +} + SYMBOL_EXPORT void LoadGamestate(struct Game *game, const char* name) { struct Gamestate *gs = FindGamestate(game, name); if (gs) { diff --git a/src/gamestate.h b/src/gamestate.h index 0bee9e2..d391a91 100644 --- a/src/gamestate.h +++ b/src/gamestate.h @@ -25,6 +25,23 @@ struct Game; +struct Gamestate_API { + void (*Gamestate_Draw)(struct Game *game, void* data); + void (*Gamestate_Logic)(struct Game *game, void* data); + + void* (*Gamestate_Load)(struct Game *game, void (*progress)(struct Game *game)); + void (*Gamestate_Start)(struct Game *game, void* data); + void (*Gamestate_Pause)(struct Game *game, void* data); + void (*Gamestate_Resume)(struct Game *game, void* data); + void (*Gamestate_Stop)(struct Game *game, void* data); + void (*Gamestate_Unload)(struct Game *game, void* data); + + void (*Gamestate_ProcessEvent)(struct Game *game, void* data, ALLEGRO_EVENT *ev); + void (*Gamestate_Reload)(struct Game *game, void* data); + + int *Gamestate_ProgressCount; +}; + struct Gamestate { char* name; void* handle; @@ -32,28 +49,14 @@ struct Gamestate { bool started, pending_start, pending_stop; bool showLoading; bool paused; - struct Gamestate* next; + struct Gamestate *next; void* data; - struct { - void (*Gamestate_Draw)(struct Game *game, void* data); - void (*Gamestate_Logic)(struct Game *game, void* data); - - void* (*Gamestate_Load)(struct Game *game, void (*progress)(struct Game *game)); - void (*Gamestate_Start)(struct Game *game, void* data); - void (*Gamestate_Pause)(struct Game *game, void* data); - void (*Gamestate_Resume)(struct Game *game, void* data); - void (*Gamestate_Stop)(struct Game *game, void* data); - void (*Gamestate_Unload)(struct Game *game, void* data); - - void (*Gamestate_ProcessEvent)(struct Game *game, void* data, ALLEGRO_EVENT *ev); - void (*Gamestate_Reload)(struct Game *game, void* data); - - int *Gamestate_ProgressCount; - } api; + struct Gamestate_API *api; }; void LoadGamestate(struct Game *game, const char* name); void UnloadGamestate(struct Game *game, const char* name); +void RegisterGamestate(struct Game *game, const char* name, struct Gamestate_API *api); void StartGamestate(struct Game *game, const char* name); void StopGamestate(struct Game *game, const char* name); void PauseGamestate(struct Game *game, const char* name); diff --git a/src/internal.c b/src/internal.c index b5b873a..4174bdf 100644 --- a/src/internal.c +++ b/src/internal.c @@ -30,7 +30,7 @@ SYMBOL_INTERNAL void DrawGamestates(struct Game *game) { while (tmp) { if ((tmp->loaded) && (tmp->started)) { game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Draw)(game, tmp->data); + (*tmp->api->Gamestate_Draw)(game, tmp->data); } tmp = tmp->next; } @@ -41,7 +41,7 @@ SYMBOL_INTERNAL void LogicGamestates(struct Game *game) { while (tmp) { if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) { game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Logic)(game, tmp->data); + (*tmp->api->Gamestate_Logic)(game, tmp->data); } tmp = tmp->next; } @@ -52,7 +52,7 @@ SYMBOL_INTERNAL void EventGamestates(struct Game *game, ALLEGRO_EVENT *ev) { while (tmp) { if ((tmp->loaded) && (tmp->started) && (!tmp->paused)) { game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_ProcessEvent)(game, tmp->data, ev); + (*tmp->api->Gamestate_ProcessEvent)(game, tmp->data, ev); } tmp = tmp->next; } @@ -63,7 +63,7 @@ SYMBOL_INTERNAL void PauseGamestates(struct Game *game) { while (tmp) { if ((tmp->loaded) && (tmp->started)) { game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Pause)(game, tmp->data); + (*tmp->api->Gamestate_Pause)(game, tmp->data); } tmp = tmp->next; } @@ -75,7 +75,7 @@ SYMBOL_INTERNAL void ResumeGamestates(struct Game *game) { while (tmp) { if ((tmp->loaded) && (tmp->started)) { game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Resume)(game, tmp->data); + (*tmp->api->Gamestate_Resume)(game, tmp->data); } tmp = tmp->next; } @@ -131,9 +131,9 @@ SYMBOL_INTERNAL void GamestateProgress(struct Game *game) { struct Gamestate *tmp = game->_priv.tmp_gamestate.tmp; game->_priv.tmp_gamestate.p++; DrawGamestates(game); - float progressCount = *(tmp->api.Gamestate_ProgressCount) ? (float)*(tmp->api.Gamestate_ProgressCount) : 1; + float progressCount = *(tmp->api->Gamestate_ProgressCount) ? (float)*(tmp->api->Gamestate_ProgressCount) : 1; float progress = ((game->_priv.tmp_gamestate.p / progressCount) / (float)game->_priv.tmp_gamestate.toLoad) + (game->_priv.tmp_gamestate.loaded/(float)game->_priv.tmp_gamestate.toLoad); - if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), game->_priv.tmp_gamestate.p, *(tmp->api.Gamestate_ProgressCount)); + if (game->config.debug) PrintConsole(game, "[%s] Progress: %d% (%d/%d)", tmp->name, (int)(progress*100), game->_priv.tmp_gamestate.p, *(tmp->api->Gamestate_ProgressCount)); if (tmp->showLoading) (*game->_priv.loading.Draw)(game, game->_priv.loading.data, progress); DrawConsole(game); if (al_get_time() - game->_priv.tmp_gamestate.t >= 1/60.0) { diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c index 9a8a1dc..d6f02e2 100644 --- a/src/libsuperderpy.c +++ b/src/libsuperderpy.c @@ -246,7 +246,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { if (tmp->pending_stop) { PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name); game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Stop)(game, tmp->data); + (*tmp->api->Gamestate_Stop)(game, tmp->data); tmp->started = false; tmp->pending_stop = false; } @@ -268,43 +268,46 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { tmp->loaded = false; tmp->pending_unload = false; game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Unload)(game, tmp->data); - dlclose(tmp->handle); - tmp->handle = NULL; + (*tmp->api->Gamestate_Unload)(game, tmp->data); al_start_timer(game->_priv.timer); } if (tmp->pending_load) { - PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name); al_stop_timer(game->_priv.timer); - // TODO: take proper game name - char libname[1024]; - snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->name, tmp->name); - tmp->handle = dlopen(libname,RTLD_NOW); - if (!tmp->handle) { - //PrintConsole(&game, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror()); - FatalError(game, false, "Error while loading gamestate \"%s\": %s", tmp->name, dlerror()); - tmp->pending_load = false; - tmp->pending_start = false; - } else { + if (!tmp->api) { + PrintConsole(game, "Opening gamestate \"%s\"...", tmp->name); + char libname[1024]; + snprintf(libname, 1024, "libsuperderpy-%s-%s" LIBRARY_EXTENSION, game->name, tmp->name); + tmp->handle = dlopen(libname,RTLD_NOW); + if (!tmp->handle) { + FatalError(game, false, "Error while opening gamestate \"%s\": %s", tmp->name, dlerror()); + + tmp->pending_load = false; + tmp->pending_start = false; + } else { + + tmp->api = malloc(sizeof(struct Gamestate_API)); #define GS_ERROR FatalError(game, false, "Error on resolving gamestate symbol: %s", dlerror()); tmp->pending_load = false; tmp->pending_start = false; tmp=tmp->next; continue; - if (!(tmp->api.Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Draw = dlsym(tmp->handle, "Gamestate_Draw"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Logic = dlsym(tmp->handle, "Gamestate_Logic"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Load = dlsym(tmp->handle, "Gamestate_Load"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Start = dlsym(tmp->handle, "Gamestate_Start"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Pause = dlsym(tmp->handle, "Gamestate_Pause"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Resume = dlsym(tmp->handle, "Gamestate_Resume"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Stop = dlsym(tmp->handle, "Gamestate_Stop"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Unload = dlsym(tmp->handle, "Gamestate_Unload"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; } - if (!(tmp->api.Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { GS_ERROR; } - - if (!(tmp->api.Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_ProcessEvent = dlsym(tmp->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_Reload = dlsym(tmp->handle, "Gamestate_Reload"))) { GS_ERROR; } + if (!(tmp->api->Gamestate_ProgressCount = dlsym(tmp->handle, "Gamestate_ProgressCount"))) { GS_ERROR; } + } + } + if (tmp->api) { + PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name); game->_priv.tmp_gamestate.p = 0; DrawGamestates(game); @@ -318,7 +321,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { } game->_priv.tmp_gamestate.tmp = tmp; game->_priv.current_gamestate = tmp; - tmp->data = (*tmp->api.Gamestate_Load)(game, &GamestateProgress); + tmp->data = (*tmp->api->Gamestate_Load)(game, &GamestateProgress); game->_priv.tmp_gamestate.loaded++; tmp->loaded = true; @@ -338,7 +341,7 @@ SYMBOL_EXPORT int libsuperderpy_run(struct Game *game) { PrintConsole(game, "Starting gamestate \"%s\"...", tmp->name); al_stop_timer(game->_priv.timer); game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Start)(game, tmp->data); + (*tmp->api->Gamestate_Start)(game, tmp->data); al_start_timer(game->_priv.timer); tmp->started = true; tmp->pending_start = false; @@ -429,17 +432,23 @@ SYMBOL_EXPORT void libsuperderpy_destroy(struct Game *game) { if (tmp->started) { PrintConsole(game, "Stopping gamestate \"%s\"...", tmp->name); game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Stop)(game, tmp->data); + (*tmp->api->Gamestate_Stop)(game, tmp->data); tmp->started = false; } if (tmp->loaded) { PrintConsole(game, "Unloading gamestate \"%s\"...", tmp->name); game->_priv.current_gamestate = tmp; - (*tmp->api.Gamestate_Unload)(game, tmp->data); - dlclose(tmp->handle); + (*tmp->api->Gamestate_Unload)(game, tmp->data); tmp->loaded = false; } + if (tmp->handle) { + PrintConsole(game, "Closing gamestate \"%s\"...", tmp->name); + dlclose(tmp->handle); + } free(tmp->name); + if (tmp->api) { + free(tmp->api); + } pom = tmp->next; free(tmp); tmp=pom;