1 module unde.main;
2 
3 import unde.draw;
4 import unde.global_state;
5 import unde.tick;
6 import unde.slash;
7 
8 import derelict.sdl2.sdl;
9 
10 import std.stdio;
11 import std.file;
12 import core.stdc.stdlib;
13 
14 import core.sys.posix.signal;
15 
16 extern(C) void mybye(int value){
17     exit(1);
18 }
19 
20 int main(string[] args)
21 {
22     bool force_recover;
23     if (args.length > 1)
24        force_recover = (args[1] == "--force_recover");
25     GlobalState gs = new GlobalState(force_recover);
26     gs.args = args;
27     gs.start_cwd = getcwd();
28     version(Posix)
29     {
30     sigset(SIGINT, &mybye);
31     }
32     gs.main_path = gs.path = SL;
33 
34     /* How many frames was skipped */
35     uint skipframe;
36     /* How long rendering was last frame */
37     uint last_draw_time;
38 
39     /* Sum of time which was taken by rendering */
40     uint drawtime;
41     /* Minumum time between 2 frames */
42     uint min_frame_time = 2;
43     /* Maximum skip frames running */
44     uint max_skip_frames = 10;
45 
46     /* Start time used in below scope(exit) to calculate avarage
47        rendering time*/
48     uint starttime=SDL_GetTicks();
49     scope(exit)
50     {
51         uint endtime = SDL_GetTicks();
52         writefln("FPS= %f, average draw time: %f ms\n",
53             (cast(float)gs.frame)*1000/(endtime-starttime), 
54             (cast(float)drawtime)/gs.frame);
55         /* EN: Necessary because otherwise it will destroy 
56            gs.dbenv, gs.db_map before and it lead to Seg.Fault
57            RU: Необходим, т.к. иначе до gs будут уничтожены
58            gs.dbenv, gs.db_map, что ведёт к ошибке сегментирования */
59         destroy(gs);
60     }
61 
62     /* The main Idea of rendering process:
63        Splitting the actions which must be done on frame on 2:
64        1. Process events and make tick
65        2. Draw Frame
66        "Draw frame" maybe skipped to catch up real time,
67        But "Make tick" can't be skipped
68      */
69     while(!gs.finish)
70     {
71         uint time_before_frame=SDL_GetTicks();
72 
73         /* Process incoming events. */
74 
75         process_events(gs);
76 
77         make_tick(gs);
78 	stdout.flush();
79 
80         uint now=SDL_GetTicks();
81         /* Draw the screen. */
82         /* Don't skip frame when:
83             1. Too much frame skipped
84             2. The virtual time (gs.time) too big (more than real time)
85             3. Estimation time of the next frame less than minumum frame time  */
86         if ( skipframe>=max_skip_frames || (gs.time+250.0)>now ||
87                 (now+last_draw_time)<(time_before_frame+min_frame_time) )
88         {
89             gs.txn = null;//dbenv.txn_begin(null, DB_TXN_SNAPSHOT);
90             uint time_before_draw=SDL_GetTicks();
91 
92 	    draw_screen(gs, gs.txn);
93 
94             last_draw_time=SDL_GetTicks()-time_before_draw;
95             drawtime+=last_draw_time;
96 
97             //gs.txn.commit();
98 
99             gs.frame++;
100             skipframe=0;
101         }
102         else skipframe++;
103 
104         now=SDL_GetTicks();
105         /* Virtual time more real time? */
106         if (gs.time>now)
107             SDL_Delay(gs.time-now);
108         else /* If time of frame too small */
109             if ( (now - time_before_frame)<min_frame_time )
110                 SDL_Delay( min_frame_time - (now - time_before_frame) );
111         
112         /* Add 10 ms to time, because we want render with speed 100 FPS
113            1 frame / 100 FPS = 1/100s = 10ms */
114         gs.time += 10;
115 
116     }
117     return 0;
118 }