3 \details initializes necessary subsystems before invoking the preloader,
4 which loads initial game data, before finally invoking the
5 main loop main_loop(void), which may be run in either blocking
9 ------------------------------------------------------------------------------*/
14 #include <emscripten/emscripten.h>
16 /* Traditional Environment */
20 #include <SDL2/SDL_ttf.h>
22 /* ENVIRONMENT-AGNOSTIC DEFINES */
24 #include <SDL2/SDL_image.h>
28 #define TRIGGERS quit_trigger
29 #include <core/trigger.h>
30 #include <core/engine.h>
32 /* exposed functions */
35 /* private functions */
36 static int main_init(void);
38 /* unexposed externs */
39 extern int state_init(void);
40 extern void state_tick(uint32_t delta_ticks
);
41 extern const char* state_get_error(void);
42 extern void state_quit(void);
43 extern void state_handle_event(SDL_Event
*event
);
45 extern int io_init(void);
46 extern const char* io_get_error(void);
47 extern void io_quit(void);
50 /* main jump buffer */
54 initializes subsystems and calls main_loop(void)
56 main sets a jump buffer for its primary switch, which may be jumped to
57 at any time. Jumping with a 0 return value is equivalent to calling
58 setjmp directly, which initializes the system and begins the main loop.
59 Jumping with any other value will process one of the directives associated
60 with the exit codes in core.h
65 emscripten_set_main_loop(main_loop,0,0); \
66 TRIGGER_SET(quit_trigger, emscripten_cancel_main_loop); \
72 main (int argc
, char** argv
)
73 { switch(setjmp(jmp_main
))
82 //dump some debug info
85 TRIGGER(quit_trigger
);
95 Calling main_init() boots the system, and may be called multiple times to
96 cause a system-wide reboot.
97 @return 0 if successful, -1 SDL, -2 IMG, -3 TTF, -4 STATE.
98 SDL and logging is available after this is called
100 #define INIT(_cond,_errorstring,_quit) \
103 { fprintf(stderr, #_cond " failed: %s\n", _errorstring()); \
106 TRIGGER_SET(quit_trigger, _quit); \
109 #define SDL_FLAGS SDL_INIT_EVERYTHING & ~(SDL_INIT_TIMER | SDL_INIT_HAPTIC)
113 { static uint32_t bInitialized
= 0;
115 { TRIGGER(quit_trigger
);
116 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION
, "Resetting [%d]\n",
120 INIT(SDL_Init(SDL_FLAGS
) < 0, SDL_GetError
, SDL_Quit
);
121 INIT(IMG_Init(IMG_INIT_PNG
) != IMG_INIT_PNG
, IMG_GetError
, IMG_Quit
);
122 INIT(TTF_Init() == -1, TTF_GetError
, TTF_Quit
);
123 INIT(state_init(), state_get_error
, state_quit
);
124 INIT(fs_init(), fs_get_error
, fs_quit
);
126 SDL_Log("Initialization Complete.");
131 The main loop may be compiled in blocking or non-blocking mode, and
132 synchronizes time in ticks (milliseconds) as established by SDL anchored
133 on the state_tick() event.
137 { static uint32_t state_last_ticks
= 0;
139 uint32_t delta_ticks
;
141 #ifndef NON_BLOCKING_LOOPS
144 /* user/system inputs */
145 while (SDL_PollEvent(&event
))
146 state_handle_event(&event
);
148 /* change in time since last loop */
149 delta_ticks
= SDL_GetTicks() - state_last_ticks
;
150 /* handle breakpoints (long pause likely a breakpoint) */
151 if (delta_ticks
> 1000)
152 { SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM
, "Recovering from long pause.");
153 delta_ticks
= TARGET_DT
;
155 /* tick the state manager and immediately save the time */
156 state_tick(delta_ticks
);
157 state_last_ticks
= SDL_GetTicks();
159 //TODO: render(screen)
160 //TODO: SDL_Flip(screen)::sdl_geterror
162 #ifndef NON_BLOCKING_LOOPS
163 #define DIV_UP(x,y) (((x) + ((y) / 2)) / (x))
164 /* yield if we have a substantial portion of time leftover */
165 delta_ticks
+= SDL_GetTicks() - state_last_ticks
;
166 if (delta_ticks
< (TARGET_DT
- DIV_UP(TARGET_DT
, 10)))
167 SDL_Delay(TARGET_DT
- delta_ticks
);