/*!@file \brief engine entry \details initializes necessary subsystems before invoking the preloader, which loads initial game data, before finally invoking the main loop gameloop(void) \author K \date 2016 ------------------------------------------------------------------------------*/ #ifdef __EMSCRIPTEN__ /* Web Environment */ #define main em_main #include #include #else /* Traditional Environment */ #ifdef __Win32 #include #endif //__Win32 #include #endif /* ENVIRONMENT-AGNOSTIC DEFINES */ #include #include #include #include #include #define TRIGGERS quit_trigger #include #include /* private functions */ static int main_init(void); /* exposed functions */ void main_loop(void); /* unexposed externs * extern int state_init(void); extern void state_tick(uint32_t delta_ticks); extern const char* state_get_error(void); extern void state_quit(void); extern void state_handle_event(SDL_Event event); extern int io_init(void); extern const char* io_get_error(void); extern void io_quit(void);*/ /* main jump buffer */ jmp_buf jmp_main; /* Main Entry initializes subsystems and calls main_loop(void) main sets a jump buffer for its primary switch, which may be jumped to at any time. Jumping with a 0 return value is equivalent to calling setjmp directly, which initializes the system and begins the main loop. Jumping with any other value will process one of the directives associated with the exit codes in core.h *******************************************************************************/ #ifdef __EMSCRIPTEN__ #define main_loop()\ emscripten_set_main_loop(main_loop,0,0);\ TRIGGER_SET(quit_trigger, emscripten_cancel_main_loop);\ return 0; int main (int argc, char** argv) { switch(setjmp(jmp_main)) { case 0: if (main_init()) return -1; main_loop(); case EXIT_GRACEFUL: break; default: case EXIT_PANIC: //dump some debug info break; } TRIGGER(quit_trigger); return 0; } #undef main_loop #endif //EMSCRIPTEN /** subsystem initializer Calling main_init() bootstraps the system, and may be called multiple times to cause a system-wide reboot. @return 0 if successful, -1 SDL, -2 IMG, -3 TTF, -4 STATE. SDL and logging is available after this is called ******************************************************************************/ #define INIT(_subsys_id,_cond,_errorstring,_quit)\ if (_cond)\ { fprintf(stderr, #_cond " failed: %s\n", _errorstring());\ return -_subsys_id;\ }\ TRIGGER_SET(quit_trigger, _quit) #define SDL_FLAGS SDL_INIT_EVERYTHING & ~(SDL_INIT_TIMER | SDL_INIT_HAPTIC) static int main_init() { static char bInitialized = 0; if (bInitialized++) { TRIGGER(quit_trigger); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Resetting [%d]\n", bInitialized); } INIT(1, SDL_Init(SDL_FLAGS) < 0, SDL_GetError, SDL_Quit); INIT(2, IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG, IMG_GetError, IMG_Quit); INIT(3, TTF_Init() == -1, TTF_GetError, TTF_Quit); /*TODO: INIT(4, io_init(), io_get_error, io_quit); INIT(5, state_init(), state_get_error, state_quit); */ SDL_Log("Initialization Complete."); return 0; } /** main loop. *******************************************************************************/ void main_loop() { static uint32_t main_loop_last_ticks = 0; SDL_Event event; uint32_t delta_ticks; #ifdef LOOP_YIELD_OPTIONAL loop: #endif /* Poll events (user/system inputs) */ while (SDL_PollEvent(&event)) //state_handle_event(&event); ; /* change in time since last loop */ delta_ticks = SDL_GetTicks() - main_loop_last_ticks; /* handle breakpoints (long pause likely a breakpoint) */ if (delta_ticks > 1000) { SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "Recovering from long pause."); delta_ticks = TARGET_DT; } /* tick the state manager forward by the change in time */ //state_tick(delta_ticks); main_loop_last_ticks = SDL_GetTicks(); /* render the scene to backbuffer */ ////TODO: state_tick(delta_ticks); /* swap in the backbuffer for display */ ////TODO: state_render(); #ifdef LOOP_YIELD_OPTIONAL #define DIV_UP(x,y) ((x + (y / 2)) / y) /* cap the framerate if we're handling the loop mechanism directly, but only yield if we have a substantial portion of time to yield (1/10th of the target delta) */ delta_ticks = SDL_GetTicks() - main_loop_last_ticks; if ((delta_ticks + DIV_UP(TARGET_DT, 10)) < TARGET_DT) SDL_Delay(TARGET_DT - delta_ticks); goto loop; #endif }