1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/cit/src/RCS/mainloop.c $
21  * $Revision: 1.42 $
22  * $Author: xemu $
23  * $Date: 1994/11/09 02:09:05 $
24  */
25 
26 /*
27  * Citadel main loops
28  *
29  * The idea here is that we have a separate loop for each game mode/setup
30  * There is a 4/12 bit change flag which is 4 global and 12 local
31  * The global loop checks OS and input
32  * Then calls the local loop, which does it's internal inlined functions
33  *  and then processes it's change flags
34  * The global loop then gets control and does it's own change flags
35  * If you want to switch modes/loops you call change_loop which both sets
36  *  global change bit 3 as well setting some variables.  When the main loop
37  *  reaches the bottom it triggers on change bit 3 and calls the switch code
38  */
39 
40 #define __MAINLOOP_SRC
41 
42 #include <stdio.h>
43 
44 #include "criterr.h"
45 #include "init.h"
46 #include "rendtool.h"
47 #include "game_screen.h"
48 #include "fullscrn.h"
49 #include "loops.h"
50 #include <input.h>
51 #include <setup.h>
52 #include <status.h>
53 #include "tickcount.h"
54 #include "cutsloop.h"
55 
56 /*
57 #include <loopdbg.h>
58 #include <cutscene.h>
59 
60 #include <wsample.h>
61 */
62 // how is the game doing, anyway, set to true at end of time
63 uchar cit_success = FALSE;
64 
65 // are we "paused"
66 uchar game_paused = FALSE;
67 
68 void ShockMain(void);
69 
70 extern void automap_loop(void);
71 extern void amap_start();
72 extern void amap_exit();
73 
74 // Note that in the shipping version, the edit_loop stuff should never
75 // get called, but needs to be SOMETHING as a place holder
76 // void
77 // (*citadel_loops[])(void)={game_loop,game_loop,game_loop,game_loop,setup_loop,game_loop,cutscene_loop,game_loop,automap_loop};
78 // void
79 // (*enter_modes[])(void)={screen_start,fullscreen_start,screen_start,screen_start,setup_start,screen_start,cutscene_start,fullscreen_start,amap_start};
80 // void (*exit_modes[])(void)={screen_exit,fullscreen_exit,screen_exit,
81 // screen_exit,setup_exit,screen_exit,cutscene_exit,fullscreen_exit,amap_exit};
82 
83 void (*citadel_loops[])(void) = {game_loop, game_loop, game_loop, game_loop, setup_loop, game_loop, cutscene_loop, game_loop, automap_loop};
84 void (*enter_modes[])(void) = {screen_start, fullscreen_start, NULL, NULL, setup_start, NULL, cutscene_start, fullscreen_start, amap_start};
85 void (*exit_modes[])(void) = {screen_exit, fullscreen_exit, NULL, NULL, setup_exit, NULL, cutscene_exit, fullscreen_exit, amap_exit};
86 
loopmode_switch(short * cmode)87 void loopmode_switch(short *cmode) {
88 #ifdef SVGA_SUPPORT
89     extern uchar wrapper_screenmode_hack;
90 #endif
91 
92     // Actually switch mode
93     _last_mode = *cmode;
94     (*exit_modes[_last_mode])();
95     *cmode = _new_mode;
96     _static_change = 0;
97     if (*cmode >= 0)
98         (*enter_modes[*cmode])();
99 
100 #ifdef SVGA_SUPPORT
101     if (wrapper_screenmode_hack) {
102         extern void screenmode_screen_init(void);
103         extern void wrapper_start(void (*init)(void));
104         wrapper_start(screenmode_screen_init);
105     }
106 #endif
107 }
108 
loopmode_exit(short loopmode)109 void loopmode_exit(short loopmode) {
110     if (exit_modes[loopmode])
111         (*exit_modes[loopmode])();
112 }
113 
loopmode_enter(short loopmode)114 void loopmode_enter(short loopmode) { (*enter_modes[loopmode])(); }
115 
116 extern void MousePollProc(void);
mainloop(int argc,char * argv[])117 void mainloop(int argc, char *argv[]) {
118     extern void SDLDraw(void);
119     extern long gShockTicks;
120     extern bool gPlayingGame;
121     extern void pump_events(void);
122 
123     while (_current_loop >= 0 && gPlayingGame) {
124         gShockTicks = TickCount();
125 
126         if (!(_change_flag & (ML_CHG_BASE << 1)))
127             loopLine(ML | 1, input_chk()); // go get the UI stuff going
128 
129         // DG: at the beginning of each frame, get all the events from SDL
130         pump_events();
131 
132         // Run the loop
133         (*citadel_loops[_current_loop])();
134 
135         if (globalChanges) // really, only loopmode_switch (the <<3 case)
136         {                  // will be in the game
137             // if (_change_flag&(ML_CHG_BASE<<0)) { loopLine(ML|0x10,loop_debug()); }
138             if (_change_flag & (ML_CHG_BASE << 3)) {
139                 loopLine(ML | 0x13, loopmode_switch(&_current_loop));
140             }
141             chg_unset_flg(ML_CHG_BASE << 3);
142         }
143 #ifdef ALWAYS_SHOW_FR
144         fr_show_rate(-1);
145 #endif
146         // OR in the static change flags...
147         chg_set_flg(_static_change);
148 
149         MousePollProc(); // update the cursor, was 35 times/sec originally
150 
151         status_bio_update();
152 
153         extern void ZoomDrawProc(int erase);
154         ZoomDrawProc(FALSE); //draw zoom rectangle if enabled; if not, returns immediately
155 
156         SDLDraw();
157 
158         ZoomDrawProc(TRUE); //erase zoom rectangle if enabled; if not, returns immediately
159     }
160 
161     cit_success = TRUE;
162     // hit them atexit's
163 }
164 
static_change_copy()165 errtype static_change_copy() {
166     if (always_render)
167         chg_set_sta(_current_3d_flag);
168     else
169         chg_unset_sta(_current_3d_flag);
170     return (OK);
171 }
172