diff --git a/src/gamestate.c b/src/gamestate.c index d1fa1e3..0993361 100644 --- a/src/gamestate.c +++ b/src/gamestate.c @@ -147,7 +147,9 @@ SYMBOL_EXPORT void PauseGamestate(struct Game* game, const char* name) { } gs->paused = true; game->_priv.current_gamestate = gs; - (*gs->api->Gamestate_Pause)(game, gs->data); + if (gs->api->Gamestate_Pause) { + (*gs->api->Gamestate_Pause)(game, gs->data); + } PrintConsole(game, "Gamestate \"%s\" paused.", name); } else { PrintConsole(game, "Tried to pause nonexisitent gamestate \"%s\"", name); @@ -167,7 +169,9 @@ SYMBOL_EXPORT void ResumeGamestate(struct Game* game, const char* name) { } gs->paused = false; game->_priv.current_gamestate = gs; - (*gs->api->Gamestate_Resume)(game, gs->data); + if (gs->api->Gamestate_Resume) { + (*gs->api->Gamestate_Resume)(game, gs->data); + } PrintConsole(game, "Gamestate \"%s\" resumed.", name); } else { PrintConsole(game, "Tried to resume nonexisitent gamestate \"%s\"", name); diff --git a/src/gamestate.h b/src/gamestate.h index 7d81416..85b5a62 100644 --- a/src/gamestate.h +++ b/src/gamestate.h @@ -51,6 +51,7 @@ struct Gamestate { struct Gamestate* next; struct Gamestate_API* api; ALLEGRO_BITMAP* fb; + int progressCount; void* data; }; diff --git a/src/internal.c b/src/internal.c index 8cccc38..4c8a89f 100644 --- a/src/internal.c +++ b/src/internal.c @@ -98,7 +98,9 @@ SYMBOL_INTERNAL void ReloadGamestates(struct Game* game) { while (tmp) { if (tmp->loaded) { game->_priv.current_gamestate = tmp; - (*tmp->api->Gamestate_Reload)(game, tmp->data); + if (tmp->api->Gamestate_Reload) { + (*tmp->api->Gamestate_Reload)(game, tmp->data); + } } tmp = tmp->next; } @@ -219,11 +221,10 @@ SYMBOL_INTERNAL void* GamestateLoadingThread(void* arg) { struct GamestateLoadingThreadData* data = arg; data->game->_priv.loading.inProgress = true; al_set_new_bitmap_flags(data->bitmap_flags); - GamestateProgress(data->game); double time = al_get_time(); data->gamestate->data = (*data->gamestate->api->Gamestate_Load)(data->game, &GamestateProgress); PrintConsole(data->game, "[%s] Loading took %f seconds.", data->gamestate->name, al_get_time() - time); - if (data->game->_priv.loading.progress != *(data->gamestate->api->Gamestate_ProgressCount)) { + if (data->game->_priv.loading.progress != data->gamestate->progressCount) { PrintConsole(data->game, "[%s] WARNING: Gamestate_ProgressCount does not match the number of progress invokations (%d)!", data->gamestate->name, data->game->_priv.loading.progress); if (data->game->config.debug) { PrintConsole(data->game, "(sleeping for 3 seconds...)"); @@ -250,15 +251,18 @@ SYMBOL_INTERNAL void* ScreenshotThread(void* arg) { return NULL; } -SYMBOL_INTERNAL void GamestateProgress(struct Game* game) { +SYMBOL_INTERNAL void CalculateProgress(struct Game* game) { struct Gamestate* tmp = game->_priv.loading.current; - game->_priv.loading.progress++; - float progressCount = *(tmp->api->Gamestate_ProgressCount) ? (float)*(tmp->api->Gamestate_ProgressCount) : 1; - float progress = ((game->_priv.loading.progress / progressCount) / (float)game->_priv.loading.toLoad) + (game->_priv.loading.loaded / (float)game->_priv.loading.toLoad); - game->loading_progress = progress; + float progress = ((game->_priv.loading.progress / (float)(tmp->progressCount + 1)) / (float)game->_priv.loading.toLoad) + (game->_priv.loading.loaded / (float)game->_priv.loading.toLoad); if (game->config.debug) { - PrintConsole(game, "[%s] Progress: %d%% (%d/%d)", tmp->name, (int)(progress * 100), game->_priv.loading.progress, *(tmp->api->Gamestate_ProgressCount)); + PrintConsole(game, "[%s] Progress: %d%% (%d/%d)", tmp->name, (int)(progress * 100), game->_priv.loading.progress, tmp->progressCount + 1); } + game->loading_progress = progress; +} + +SYMBOL_INTERNAL void GamestateProgress(struct Game* game) { + game->_priv.loading.progress++; + CalculateProgress(game); #ifndef LIBSUPERDERPY_SINGLE_THREAD // TODO: debounce thread synchronization to reduce overhead al_lock_mutex(game->_priv.texture_sync_mutex); @@ -308,18 +312,21 @@ SYMBOL_INTERNAL bool LinkGamestate(struct Game* game, struct Gamestate* gamestat if (!(gamestate->api->Gamestate_Draw = dlsym(gamestate->handle, "Gamestate_Draw"))) { GS_ERROR; } if (!(gamestate->api->Gamestate_Logic = dlsym(gamestate->handle, "Gamestate_Logic"))) { GS_ERROR; } - if (!(gamestate->api->Gamestate_Load = dlsym(gamestate->handle, "Gamestate_Load"))) { GS_ERROR; } - if (!(gamestate->api->Gamestate_Start = dlsym(gamestate->handle, "Gamestate_Start"))) { GS_ERROR; } - if (!(gamestate->api->Gamestate_Pause = dlsym(gamestate->handle, "Gamestate_Pause"))) { GS_ERROR; } - if (!(gamestate->api->Gamestate_Resume = dlsym(gamestate->handle, "Gamestate_Resume"))) { GS_ERROR; } - if (!(gamestate->api->Gamestate_Stop = dlsym(gamestate->handle, "Gamestate_Stop"))) { GS_ERROR; } if (!(gamestate->api->Gamestate_Unload = dlsym(gamestate->handle, "Gamestate_Unload"))) { GS_ERROR; } - + if (!(gamestate->api->Gamestate_Start = dlsym(gamestate->handle, "Gamestate_Start"))) { GS_ERROR; } + if (!(gamestate->api->Gamestate_Stop = dlsym(gamestate->handle, "Gamestate_Stop"))) { GS_ERROR; } if (!(gamestate->api->Gamestate_ProcessEvent = dlsym(gamestate->handle, "Gamestate_ProcessEvent"))) { GS_ERROR; } - if (!(gamestate->api->Gamestate_Reload = dlsym(gamestate->handle, "Gamestate_Reload"))) { GS_ERROR; } - if (!(gamestate->api->Gamestate_ProgressCount = dlsym(gamestate->handle, "Gamestate_ProgressCount"))) { GS_ERROR; } + // optional + gamestate->api->Gamestate_Pause = dlsym(gamestate->handle, "Gamestate_Pause"); + gamestate->api->Gamestate_Resume = dlsym(gamestate->handle, "Gamestate_Resume"); + gamestate->api->Gamestate_Reload = dlsym(gamestate->handle, "Gamestate_Reload"); + gamestate->api->Gamestate_ProgressCount = dlsym(gamestate->handle, "Gamestate_ProgressCount"); + + if (gamestate->api->Gamestate_ProgressCount) { + gamestate->progressCount = *gamestate->api->Gamestate_ProgressCount; + } #undef GS_ERROR @@ -340,6 +347,7 @@ SYMBOL_INTERNAL struct Gamestate* AllocateGamestate(struct Game* game, const cha tmp->pending_unload = false; tmp->next = NULL; tmp->api = NULL; + tmp->progressCount = 0; return tmp; } @@ -541,7 +549,9 @@ SYMBOL_INTERNAL void ResumeExecution(struct Game* game) { CloseGamestate(game, tmp); tmp->name = name; if (OpenGamestate(game, tmp) && LinkGamestate(game, tmp)) { - tmp->api->Gamestate_Reload(game, tmp->data); + if (tmp->api->Gamestate_Reload) { + tmp->api->Gamestate_Reload(game, tmp->data); + } } tmp = tmp->next; } diff --git a/src/internal.h b/src/internal.h index 09e982e..22aa19c 100644 --- a/src/internal.h +++ b/src/internal.h @@ -75,6 +75,7 @@ void Console_Load(struct Game* game); void Console_Unload(struct Game* game); void* GamestateLoadingThread(void* arg); void* ScreenshotThread(void* arg); +void CalculateProgress(struct Game* game); void GamestateProgress(struct Game* game); void* AddGarbage(struct Game* game, void* data); void ClearGarbage(struct Game* game); diff --git a/src/libsuperderpy.c b/src/libsuperderpy.c index 2b316ab..c9f0ae3 100644 --- a/src/libsuperderpy.c +++ b/src/libsuperderpy.c @@ -408,7 +408,7 @@ SYMBOL_INTERNAL void libsuperderpy_mainloop(void* g) { } if (tmp->api) { PrintConsole(game, "Loading gamestate \"%s\"...", tmp->name); - game->_priv.loading.progress = -1; + game->_priv.loading.progress = 0; game->_priv.loading.current = tmp; game->_priv.current_gamestate = tmp; @@ -417,6 +417,7 @@ SYMBOL_INTERNAL void libsuperderpy_mainloop(void* g) { game->_priv.loading.inProgress = true; game->_priv.loading.time = al_get_time(); + CalculateProgress(game); #ifndef LIBSUPERDERPY_SINGLE_THREAD al_run_detached_thread(GamestateLoadingThread, &data); while (game->_priv.loading.inProgress) { @@ -443,6 +444,9 @@ SYMBOL_INTERNAL void libsuperderpy_mainloop(void* g) { al_set_new_bitmap_flags(data.bitmap_flags); ReloadShaders(game, false); + + game->_priv.loading.progress++; + CalculateProgress(game); PrintConsole(game, "Gamestate \"%s\" loaded successfully.", tmp->name); game->_priv.loading.loaded++;