From d9c41f420b4e51e6d1221f8e80caa211251cc43b Mon Sep 17 00:00:00 2001 From: Sergio Date: Mon, 13 Apr 2026 11:57:01 +0200 Subject: [PATCH] fix: arrancar amb el borde desactivat feia crash al activarlo --- CMakeLists.txt | 3 +++ source/core/input/global_inputs.cpp | 12 +++++++----- source/core/rendering/screen.cpp | 16 ++++++++-------- source/core/resources/resource_cache.cpp | 10 ++++++++++ source/core/system/director.cpp | 7 +++++-- source/game/ui/console_commands.cpp | 5 +++++ 6 files changed, 38 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5343d9f..9b2bdba 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -277,6 +277,9 @@ elseif(EMSCRIPTEN) -sMAX_WEBGL_VERSION=2 -sINITIAL_MEMORY=67108864 -sASSERTIONS=1 + # ASYNCIFY només per permetre emscripten_sleep(0) durant la precàrrega de recursos + # (el bucle principal del joc ja usa SDL3 Callback API, no depèn d'ASYNCIFY). + -sASYNCIFY=1 ) set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".html") elseif(UNIX AND NOT APPLE) diff --git a/source/core/input/global_inputs.cpp b/source/core/input/global_inputs.cpp index 37d0f8d..879d515 100644 --- a/source/core/input/global_inputs.cpp +++ b/source/core/input/global_inputs.cpp @@ -20,11 +20,8 @@ namespace GlobalInputs { // Funciones internas namespace { void handleQuit() { -#ifdef __EMSCRIPTEN__ - // A la versió web no es pot eixir del joc - return; -#else - // En la escena GAME el comportamiento es siempre el mismo (con o sin modo kiosko) + // En la escena GAME el comportamiento es siempre el mismo (con o sin modo kiosko): + // Escape torna al menu principal. Això també és vàlid en la versió web. if (SceneManager::current == SceneManager::Scene::GAME) { const std::string CODE = "PRESS AGAIN TO RETURN TO MENU"; if (stringInVector(Notifier::get()->getCodes(), CODE)) { @@ -45,6 +42,11 @@ namespace GlobalInputs { return; } +#ifdef __EMSCRIPTEN__ + // A la versió web no es pot eixir del joc des de fora de l'escena GAME + // (el navegador gestiona la pestanya; Escape no tanca res). + return; +#else // Comportamiento normal fuera del modo kiosko const std::string CODE = "PRESS AGAIN TO EXIT"; if (stringInVector(Notifier::get()->getCodes(), CODE)) { diff --git a/source/core/rendering/screen.cpp b/source/core/rendering/screen.cpp index 0159a08..c0b8a74 100644 --- a/source/core/rendering/screen.cpp +++ b/source/core/rendering/screen.cpp @@ -295,16 +295,16 @@ void Screen::adjustWindowSize() { window_width_ = Options::game.width + (Options::video.border.enabled ? Options::video.border.width * 2 : 0); window_height_ = Options::game.height + (Options::video.border.enabled ? Options::video.border.height * 2 : 0); - // Reservamos memoria una sola vez. - // Si el buffer es más pequeño que la superficie, crash asegurado. - border_pixel_buffer_.resize(static_cast(window_width_ * window_height_)); + // border_surface_ sempre té el tamany complet del borde (game + 2*border_w/h), + // independentment de si el borde està visible o no. El buffer ARGB que l'ombra + // ha de ser ALMENYS tan gran com la surface; si no, toARGBBuffer() escriu fora + // de bounds i corromp el heap (bug latent a desktop fins a disparar-lo un toggleBorder). + const size_t FULL_BORDER_BUFFER_SIZE = + static_cast(Options::game.width + (Options::video.border.width * 2)) * + static_cast(Options::game.height + (Options::video.border.height * 2)); + border_pixel_buffer_.resize(FULL_BORDER_BUFFER_SIZE); game_pixel_buffer_.resize(static_cast(Options::game.width * Options::game.height)); - // border_pixel_buffer_ es el buffer que se sube a la GPU (tamaño total ventana). - if (Options::video.border.enabled) { - border_pixel_buffer_.resize(static_cast(window_width_ * window_height_)); - } - // Lógica de centrado y redimensionado de ventana SDL if (static_cast(Options::video.fullscreen) == 0) { int old_w; diff --git a/source/core/resources/resource_cache.cpp b/source/core/resources/resource_cache.cpp index 6ce0831..488da17 100644 --- a/source/core/resources/resource_cache.cpp +++ b/source/core/resources/resource_cache.cpp @@ -2,6 +2,10 @@ #include +#ifdef __EMSCRIPTEN__ +#include // Para emscripten_sleep +#endif + #include // Para find_if #include // Para exit, size_t #include // Para ifstream, istreambuf_iterator @@ -530,6 +534,12 @@ namespace Resource { #if defined(__EMSCRIPTEN__) || defined(_DEBUG) renderProgress(); checkEvents(); +#endif +#ifdef __EMSCRIPTEN__ + // Cedeix el control al navegador perquè pinte el canvas i processe + // events. Sense això, el thread principal queda bloquejat durant tota + // la precàrrega i el jugador només veu pantalla negra. + emscripten_sleep(0); #endif } diff --git a/source/core/system/director.cpp b/source/core/system/director.cpp index 07a2377..163106a 100644 --- a/source/core/system/director.cpp +++ b/source/core/system/director.cpp @@ -147,9 +147,12 @@ Director::Director() { Options::loadFromFile(); #ifdef __EMSCRIPTEN__ - // A la versió web el navegador gestiona la finestra: res de fullscreen ni zoom. + // A la versió web el navegador gestiona la finestra: forcem zoom x3 + // perquè la textura 256x192 no es vegi minúscula al canvas HTML, + // i desactivem el borde per aprofitar al màxim l'espai del canvas. Options::video.fullscreen = false; - Options::window.zoom = 1; + Options::window.zoom = 4; + Options::video.border.enabled = false; #endif // Configura la ruta y carga los presets de PostFX diff --git a/source/game/ui/console_commands.cpp b/source/game/ui/console_commands.cpp index aabca51..37a1930 100644 --- a/source/game/ui/console_commands.cpp +++ b/source/game/ui/console_commands.cpp @@ -948,11 +948,16 @@ static auto cmdKiosk(const std::vector& args) -> std::string { // EXIT / QUIT static auto cmdExit(const std::vector& args) -> std::string { +#ifdef __EMSCRIPTEN__ + (void)args; + return "Not allowed in web version"; +#else if (Options::kiosk.enabled && (args.empty() || args[0] != "PLEASE")) { return "Not allowed in kiosk mode"; } SceneManager::current = SceneManager::Scene::QUIT; return "Quitting..."; +#endif } // SIZE