6da220172b9dbbcd027a92ef67985f0e32176c71
[henge/webcc.git] / src / core / main.c
1 /*!@file
2 \brief engine entry
3 \details initializes necessary subsystems before invoking the preloader,
4 which loads initial game data, before finally invoking the
5 main loop gameloop(void)
6 \author K
7 \date 2016
8 ------------------------------------------------------------------------------*/
9 #ifdef __EMSCRIPTEN__
10 /* Web Environment */
11 #define main em_main
12 #include <SDL_ttf.h>
13 #include <emscripten/emscripten.h>
14 #else
15 /* Traditional Environment */
16 #ifdef __Win32
17 #include <windows.h>
18 #endif //__Win32
19 #include <SDL2/SDL_ttf.h>
20 #endif
21 /* ENVIRONMENT-AGNOSTIC DEFINES */
22 #include <SDL2/SDL.h>
23 #include <SDL2/SDL_image.h>
24 #include <stdint.h>
25 #include <setjmp.h>
26 #include <stdio.h>
27 #define TRIGGERS quit_trigger
28 #include <core/trigger.h>
29 #include <core/engine.h>
30 #include <wolfssl/wolfcrypt/sha256.h>
31
32 /* exposed functions */
33 void main_loop(void);
34
35 /* private functions */
36 static int main_init(void);
37
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);
44 extern int io_init(void);
45 extern const char* io_get_error(void);
46 extern void io_quit(void);*/
47
48 /* main jump buffer */
49 jmp_buf jmp_main;
50
51 /*@
52 initializes subsystems and calls main_loop(void)
53
54 main sets a jump buffer for its primary switch, which may be jumped to
55 at any time. Jumping with a 0 return value is equivalent to calling
56 setjmp directly, which initializes the system and begins the main loop.
57 Jumping with any other value will process one of the directives associated
58 with the exit codes in core.h
59 */
60 #ifdef __EMSCRIPTEN__
61 #define main_loop()\
62 emscripten_set_main_loop(main_loop,0,0);\
63 TRIGGER_SET(quit_trigger, emscripten_cancel_main_loop);\
64 return 0;
65 #endif
66
67 int
68 main (int argc, char** argv)
69 { Sha256 shstr = {0};
70 wc_InitSha256(&shstr);
71
72 printf("%d %d\n", sizeof(long), sizeof(long long));
73
74 switch(setjmp(jmp_main))
75 { case 0:
76 if (main_init())
77 return -1;
78 main_loop();
79 case EXIT_GRACEFUL:
80 break;
81 default:
82 case EXIT_PANIC:
83 //dump some debug info
84 break;
85 }
86 TRIGGER(quit_trigger);
87 return 0;
88 }
89
90 #ifdef __EMSCRIPTEN__
91 #undef main_loop
92 #endif
93
94 /** subsystem initializer
95 Calling main_init() bootstraps the system, and may be called multiple
96 times to 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
99 ******************************************************************************/
100 #define INIT(_subsys_id,_cond,_errorstring,_quit)\
101 if (_cond)\
102 { fprintf(stderr, #_cond " failed: %s\n", _errorstring());\
103 return -_subsys_id;\
104 }\
105 TRIGGER_SET(quit_trigger, _quit)
106
107 #define SDL_FLAGS SDL_INIT_EVERYTHING & ~(SDL_INIT_TIMER | SDL_INIT_HAPTIC)
108
109 static
110 int
111 main_init()
112 { static char bInitialized = 0;
113 if (bInitialized++)
114 { TRIGGER(quit_trigger);
115 SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Resetting [%d]\n",
116 bInitialized);
117 }
118
119 INIT(1, SDL_Init(SDL_FLAGS) < 0, SDL_GetError, SDL_Quit);
120 INIT(2, IMG_Init(IMG_INIT_PNG) != IMG_INIT_PNG, IMG_GetError, IMG_Quit);
121 INIT(3, TTF_Init() == -1, TTF_GetError, TTF_Quit);
122
123 /*TODO:
124 INIT(4, io_init(), io_get_error, io_quit);
125 INIT(5, state_init(), state_get_error, state_quit);
126 */
127
128 SDL_Log("Initialization Complete.");
129 return 0;
130 }
131
132 /** main loop.
133 *******************************************************************************/
134 void
135 main_loop()
136 { static uint32_t main_loop_last_ticks = 0;
137 SDL_Event event;
138 uint32_t delta_ticks;
139
140 #ifdef LOOP_YIELD_OPTIONAL
141 loop:
142 #endif
143 /* Poll events (user/system inputs) */
144 while (SDL_PollEvent(&event))
145 //state_handle_event(&event);
146 ;
147
148 /* change in time since last loop */
149 delta_ticks = SDL_GetTicks() - main_loop_last_ticks;
150
151 /* handle breakpoints (long pause likely a breakpoint) */
152 if (delta_ticks > 1000)
153 { SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "Recovering from long pause.");
154 delta_ticks = TARGET_DT;
155 }
156
157 /* tick the state manager forward by the change in time */
158 //state_tick(delta_ticks);
159 main_loop_last_ticks = SDL_GetTicks();
160
161 /* render the scene to backbuffer */
162 ////TODO: state_tick(delta_ticks);
163 /* swap in the backbuffer for display */
164 ////TODO: state_render();
165
166 #ifdef LOOP_YIELD_OPTIONAL
167 #define DIV_UP(x,y) ((x + (y / 2)) / y)
168
169 /* cap the framerate if we're handling the loop mechanism directly, but only
170 yield if we have a substantial portion of time to yield (1/10th of the
171 target delta) */
172 delta_ticks = SDL_GetTicks() - main_loop_last_ticks;
173 if ((delta_ticks + DIV_UP(TARGET_DT, 10)) < TARGET_DT)
174 SDL_Delay(TARGET_DT - delta_ticks);
175
176 goto loop;
177 #endif
178 }
179