From f3326f4f170a952dfb7f35fc3647e21db96dc18d Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 20 Jun 2024 22:14:42 +1000 Subject: [PATCH] Consoles: Make Quit Game more stable --- src/Game.c | 51 ++++++++++++++------------- src/Graphics_GCWii.c | 7 +++- src/Window_Web.c | 19 +++++----- third_party/gldc/src/aligned_vector.h | 15 ++++---- 4 files changed, 49 insertions(+), 43 deletions(-) diff --git a/src/Game.c b/src/Game.c index 6140a7c8e..10dac0d70 100644 --- a/src/Game.c +++ b/src/Game.c @@ -400,7 +400,7 @@ static void LoadPlugins(void) { static void LoadPlugins(void) { } #endif -static void Game_Free(void* obj); +static void Game_PendingClose(void* obj) { gameRunning = false; } static void Game_Load(void) { struct IGameComponent* comp; Game_UpdateDimensions(); @@ -415,7 +415,7 @@ static void Game_Load(void) { Event_Register_(&WorldEvents.NewMap, NULL, HandleOnNewMap); Event_Register_(&WorldEvents.MapLoaded, NULL, HandleOnNewMapLoaded); Event_Register_(&WindowEvents.Resized, NULL, Game_OnResize); - Event_Register_(&WindowEvents.Closing, NULL, Game_Free); + Event_Register_(&WindowEvents.Closing, NULL, Game_PendingClose); Event_Register_(&WindowEvents.InactiveChanged, NULL, HandleInactiveChanged); Game_AddComponent(&World_Component); @@ -647,10 +647,18 @@ static void DrawSplitscreen(float delta, float t, int i, int x, int y, int w, in } #endif -static CC_INLINE void Game_RenderFrame(double delta) { +static CC_INLINE void Game_RenderFrame(void) { struct ScheduledTask entTask; float t; + cc_uint64 render = Stopwatch_Measure(); + double delta = Stopwatch_ElapsedMicroseconds(Game_FrameStart, render) / (1000.0 * 1000.0); + Window_ProcessEvents(delta); + + if (delta > 5.0) delta = 5.0; /* avoid large delta with suspended process */ + if (delta <= 0.0) return; + Game_FrameStart = render; + /* TODO: Should other tasks get called back too? */ /* Might not be such a good idea for the http_clearcache, */ /* don't really want all skins getting lost */ @@ -722,7 +730,7 @@ static CC_INLINE void Game_RenderFrame(double delta) { Gfx_EndFrame(); } -static void Game_Free(void* obj) { +static void Game_Free(void) { struct IGameComponent* comp; /* Most components will call OnContextLost in their Free functions */ /* Set to false so components will always free managed textures too */ @@ -730,7 +738,8 @@ static void Game_Free(void* obj) { Event_UnregisterAll(); tasksCount = 0; - for (comp = comps_head; comp; comp = comp->next) { + for (comp = comps_head; comp; comp = comp->next) + { if (comp->Free) comp->Free(); } @@ -741,25 +750,17 @@ static void Game_Free(void* obj) { Window_DisableRawMouse(); } -#define Game_DoFrameBody() \ - render = Stopwatch_Measure();\ - delta = Stopwatch_ElapsedMicroseconds(Game_FrameStart, render) / (1000.0 * 1000.0);\ - \ - Window_ProcessEvents(delta);\ - if (!gameRunning) return;\ - \ - if (delta > 5.0) delta = 5.0; /* avoid large delta with suspended process */ \ - if (delta > 0.0) { Game_FrameStart = render; Game_RenderFrame(delta); } - #ifdef CC_BUILD_WEB void Game_DoFrame(void) { - cc_uint64 render; - double delta; - Game_DoFrameBody() + if (gameRunning) { + Game_RenderFrame(); + } else if (tasksCount) { + Game_Free(); + Window_Free(); + } } static void Game_RunLoop(void) { - Game_FrameStart = Stopwatch_Measure(); /* Window_Web.c sets Game_DoFrame as the main loop callback function */ /* (i.e. web browser is in charge of calling Game_DoFrame, not us) */ } @@ -777,11 +778,11 @@ cc_bool Game_ShouldClose(void) { } #else static void Game_RunLoop(void) { - cc_uint64 render; - double delta; - - Game_FrameStart = Stopwatch_Measure(); - for (;;) { Game_DoFrameBody() } + while (gameRunning) + { + Game_RenderFrame(); + } + Game_Free(); } #endif @@ -793,5 +794,7 @@ void Game_Run(int width, int height, const cc_string* title) { Game_Load(); Event_RaiseVoid(&WindowEvents.Resized); + + Game_FrameStart = Stopwatch_Measure(); Game_RunLoop(); } diff --git a/src/Graphics_GCWii.c b/src/Graphics_GCWii.c index 9210a2fe7..b79cff61b 100644 --- a/src/Graphics_GCWii.c +++ b/src/Graphics_GCWii.c @@ -14,6 +14,7 @@ extern void* Window_XFB; static void* xfbs[2]; static int curFB; static GfxResourceID white_square; +static GXTexRegionCallback regionCB; // https://wiibrew.org/wiki/Developer_tips // https://devkitpro.org/wiki/libogc/GX @@ -44,6 +45,9 @@ static void InitGX(void) { xfbs[0] = Window_XFB; xfbs[1] = MEM_K0_TO_K1(SYS_AllocateFramebuffer(mode)); + + regionCB = GX_SetTexRegionCallback(NULL); + GX_SetTexRegionCallback(regionCB); } void Gfx_Create(void) { @@ -173,7 +177,8 @@ void Gfx_BindTexture(GfxResourceID texId) { CCTexture* tex = (CCTexture*)texId; if (!tex) tex = white_square; - GX_LoadTexObj(&tex->obj, GX_TEXMAP0); + GXTexRegion* reg = regionCB(&tex->obj, GX_TEXMAP0); + GX_LoadTexObjPreloaded(&tex->obj, reg, GX_TEXMAP0); } diff --git a/src/Window_Web.c b/src/Window_Web.c index e438b18cc..522eac22f 100644 --- a/src/Window_Web.c +++ b/src/Window_Web.c @@ -413,7 +413,15 @@ void Window_Init(void) { interop_ForceTouchPageLayout(); } -void Window_Free(void) { } +void Window_Free(void) { + /* If the game is closed while in fullscreen, the last rendered frame stays */ + /* shown in fullscreen, but the game can't be interacted with anymore */ + Window_ExitFullscreen(); + + Window_SetSize(0, 0); + UnhookEvents(); + emscripten_cancel_main_loop(); +} extern void interop_InitContainer(void); static void DoCreateWindow(void) { @@ -525,15 +533,6 @@ void Window_SetSize(int width, int height) { void Window_RequestClose(void) { Window_Main.Exists = false; Event_RaiseVoid(&WindowEvents.Closing); - /* If the game is closed while in fullscreen, the last rendered frame stays */ - /* shown in fullscreen, but the game can't be interacted with anymore */ - Window_ExitFullscreen(); - - Window_SetSize(0, 0); - UnhookEvents(); - /* Game_DoFrame doesn't do anything when WindowExists.False is false, */ - /* but it's still better to cancel main loop to minimise resource usage */ - emscripten_cancel_main_loop(); } extern void interop_RequestCanvasResize(void); diff --git a/third_party/gldc/src/aligned_vector.h b/third_party/gldc/src/aligned_vector.h index 52557c21b..30dd4ae7e 100644 --- a/third_party/gldc/src/aligned_vector.h +++ b/third_party/gldc/src/aligned_vector.h @@ -19,6 +19,13 @@ typedef struct { #define ALIGNED_VECTOR_CHUNK_SIZE 256u +#define av_assert(x) \ + do {\ + if(!(x)) {\ + fprintf(stderr, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\ + exit(1);\ + }\ + } while(0); \ #define ROUND_TO_CHUNK_SIZE(v) \ ((((v) + ALIGNED_VECTOR_CHUNK_SIZE - 1) / ALIGNED_VECTOR_CHUNK_SIZE) * ALIGNED_VECTOR_CHUNK_SIZE) @@ -52,14 +59,6 @@ AV_FORCE_INLINE void* aligned_vector_reserve(AlignedVector* vector, uint32_t ele return vector->data + original_byte_size; } -#define av_assert(x) \ - do {\ - if(!(x)) {\ - fprintf(stderr, "Assertion failed at %s:%d\n", __FILE__, __LINE__);\ - exit(1);\ - }\ - } while(0); \ - /* Resizes the array and returns a pointer to the first new element (if upsizing) or NULL (if downsizing) */ AV_FORCE_INLINE void* aligned_vector_resize(AlignedVector* vector, const uint32_t element_count) { void* ret = NULL;