// Port a l'API de callbacks de SDL3: el runtime posseïx el main loop i ens // crida a SDL_AppInit/SDL_AppIterate/SDL_AppEvent/SDL_AppQuit. Imprescindible // per al port a emscripten on no podem tindre un bucle while propi al hilo // principal. Funciona igual en build natiu (Linux/macOS/Windows) perquè // SDL3 embolcalla el seu propi main loop darrere d'aquestes callbacks. #define SDL_MAIN_USE_CALLBACKS #include #include #include #include #include "core/jail/jail_audio.hpp" #include "core/jail/jdraw8.hpp" #include "core/jail/jfile.hpp" #include "core/jail/jgame.hpp" #include "core/locale/locale.hpp" #include "core/rendering/menu.hpp" #include "core/rendering/overlay.hpp" #include "core/rendering/screen.hpp" #include "core/system/director.hpp" #include "game/options.hpp" SDL_AppResult SDL_AppInit(void** /*appstate*/, int /*argc*/, char* /*argv*/[]) { srand(unsigned(time(nullptr))); // Crea la carpeta de configuració i carrega les opcions file_setconfigfolder("jailgames/aee"); // Ruta absoluta a data/ basada en la ubicació de l'executable. // SDL_GetBasePath() detecta automàticament si estem dins d'un .app bundle // (retorna Contents/Resources/) o en un executable normal (carpeta del binari). const char* base_path = SDL_GetBasePath(); if (base_path) { const std::string data_path = std::string(base_path) + "data/"; file_setresourcefolder(data_path.c_str()); } Options::setConfigFile(std::string(file_getconfigfolder()) + "config.yaml"); Options::loadFromFile(); #ifdef __EMSCRIPTEN__ // MEMFS no persistix entre recàrregues: força valors sensats per a web. Options::window.fullscreen = false; Options::window.zoom = 1; Options::video.aspect_ratio_4_3 = true; Options::video.integer_scale = true; Options::video.stretch_filter_linear = true; #endif // Carrega textos (idioma per defecte: valencià) Locale::load("locale/ca.yaml"); // Carrega presets de shaders Options::setPostFXFile(std::string(file_getconfigfolder()) + "postfx.yaml"); Options::loadPostFXFromFile(); Options::setCrtPiFile(std::string(file_getconfigfolder()) + "crtpi.yaml"); Options::loadCrtPiFromFile(); JG_Init(); Screen::init(); JD8_Init(); JA_Init(48000, SDL_AUDIO_S16, 2); Options::applyAudio(); Overlay::init(); Menu::init(); Director::init(); Director::get()->setup(); return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppIterate(void* /*appstate*/) { // Una iteració del bucle del Director. Abans els events es drenaven // amb SDL_PollEvent dins d'aquesta funció; ara SDL ens els lliura // d'un en un via SDL_AppEvent, així que iterate() no els toca. if (!Director::get()->iterate()) { return SDL_APP_SUCCESS; } return SDL_APP_CONTINUE; } SDL_AppResult SDL_AppEvent(void* /*appstate*/, SDL_Event* event) { if (!event) return SDL_APP_CONTINUE; Director::get()->handleEvent(*event); if (Director::get()->isQuitRequested()) { return SDL_APP_SUCCESS; } return SDL_APP_CONTINUE; } void SDL_AppQuit(void* /*appstate*/, SDL_AppResult /*result*/) { // Neteja en ordre invers al de SDL_AppInit. Director::get()->teardown(); Options::saveToFile(); Director::destroy(); Menu::destroy(); Overlay::destroy(); JA_Quit(); JD8_Quit(); Screen::destroy(); JG_Finalize(); }