reinici real (execv) des del service menu

El Reiniciar fins ara recarregava recursos però no rellegia el preset
ni recreava la finestra (idioma/dificultat/preset es quedaven pendents
fins al pròxim arrencada manual). Ara Director rep argv al constructor
i, quan Section::name passa a RESET, fa execv del propi binari
(_execv a Windows). El procés es reemplaça → init complet amb tots
els canvis aplicats.

Refactor: extret shutdownSubsystems() de close() i compartit amb
relaunch(). Si execv falla els subsistemes ja s'han destruït, no
podem tornar al bucle: exit amb error.

A Emscripten s'amaga l'opció Reiniciar al service menu (execv no
existeix; el cheat code per teclat encara cau al reset clàssic com
fallback).
This commit is contained in:
2026-05-17 10:12:22 +02:00
parent 2c1673d2dd
commit 11eec8f222
4 changed files with 64 additions and 18 deletions
+43 -7
View File
@@ -3,7 +3,9 @@
#include <SDL3/SDL.h> // Para SDL_SetLogPriority, SDL_LogCategory, SDL_LogPriority, SDL_Quit
#include <cerrno> // Para errno
#include <cstdlib> // Para srand, exit, rand, EXIT_FAILURE
#include <cstring> // Para std::strerror
#include <ctime> // Para time
#include <fstream> // Para ifstream, ofstream
#include <iostream> // Para basic_ostream, operator<<, cerr
@@ -11,6 +13,12 @@
#include <stdexcept> // Para runtime_error
#include <string> // Para allocator, basic_string, char_traits, operator+, string, operator==
#ifdef _WIN32
#include <process.h> // Per _execv
#else
#include <unistd.h> // Per execv
#endif
#include "core/audio/audio.hpp" // Para Audio
#include "core/input/input.hpp" // Para Input
#include "core/locale/lang.hpp" // Para setLanguage
@@ -71,7 +79,8 @@ namespace {
} // namespace
// Constructor
Director::Director() {
Director::Director(int /*argc*/, char** argv)
: argv_(argv) {
Section::attract_mode = Section::AttractMode::TITLE_TO_DEMO;
// Establece el nivel de prioridad de la categoría de registro
@@ -214,8 +223,8 @@ void Director::finishBoot() {
}
}
// Cierra todo y libera recursos del sistema y de los singletons
void Director::close() {
// Allibera tots els singletons i SDL (compartit entre close() i relaunch())
void Director::shutdownSubsystems() {
// Guarda las opciones actuales en el archivo de configuración
Options::saveToFile();
@@ -228,15 +237,40 @@ void Director::close() {
Screen::destroy(); // Libera el sistema de pantalla y renderizado
Asset::destroy(); // Libera el gestor de archivos
std::cout << "\nBye!\n";
// Libera todos los recursos de SDL
SDL_Quit();
}
// Cierra todo y libera recursos del sistema y de los singletons
void Director::close() {
shutdownSubsystems();
std::cout << "\nBye!\n";
// Apaga el sistema
shutdownSystem(Section::options == Section::Options::SHUTDOWN);
}
// Reemplaça el procés actual per ell mateix (reinici en calent). En cas d'èxit no torna.
// Si no es pot reiniciar (Emscripten, argv invàlid), retorna i el caller fa el reset clàssic.
void Director::relaunch() const {
#ifdef __EMSCRIPTEN__
// Al navegador el reinici real seria location.reload(); aquí caiem al reset intern.
return;
#else
if (argv_ == nullptr || argv_[0] == nullptr) { return; }
std::cout << "Relaunching " << argv_[0] << "...\n";
shutdownSubsystems();
#ifdef _WIN32
_execv(argv_[0], argv_);
#else
execv(argv_[0], argv_);
#endif
// Si arribem aquí, execv ha fallat. Tots els subsistemes ja estan destruïts: no
// podem reprendre el bucle. Sortim amb error.
std::cerr << "Relaunch failed: " << std::strerror(errno) << "\n";
std::exit(EXIT_FAILURE);
#endif
}
// Carga los parametros
void Director::loadParams() {
// Carga los parametros para configurar el juego
@@ -354,9 +388,11 @@ void Director::resetActiveSection() {
// Destruye la sección anterior y construye la nueva cuando Section::name cambia
void Director::handleSectionTransition() {
// RESET: recarga recursos y vuelve a LOGO (el propio reset() cambia Section::name)
// RESET: intenta reinici real via execv; si no es pot (Emscripten o argv invàlid),
// cau al reset intern (recarrega recursos i torna a LOGO, sense recrear Screen/Params).
if (Section::name == Section::Name::RESET) {
resetActiveSection(); // libera recursos actuales antes del reload
relaunch(); // En èxit no torna; el binari es reemplaça
resetActiveSection(); // Fallback: libera recursos actuales antes del reload
reset();
}