]> git.xonotic.org Git - xonotic/darkplaces.git/blob - sys_sdl.c
qdefs: Define separate FLOAT_ and DOUBLE_ versions of lossless format and true for...
[xonotic/darkplaces.git] / sys_sdl.c
1 #ifdef WIN32
2 #include <io.h> // Include this BEFORE darkplaces.h because it uses strncpy which trips DP_STATIC_ASSERT
3 #include "conio.h"
4 #else
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/time.h>
8 #endif
9
10 #ifdef __ANDROID__
11 #include <android/log.h>
12 #endif
13
14 #include <signal.h>
15
16 /*
17  * Include this BEFORE darkplaces.h because it breaks wrapping
18  * _Static_assert. Cloudwalk has no idea how or why so don't ask.
19  */
20 #include <SDL.h>
21
22 #include "darkplaces.h"
23
24 #ifdef WIN32
25 #ifdef _MSC_VER
26 #pragma comment(lib, "sdl2.lib")
27 #pragma comment(lib, "sdl2main.lib")
28 #endif
29 #endif
30
31 sys_t sys;
32
33 // =======================================================================
34 // General routines
35 // =======================================================================
36
37 void Sys_Shutdown (void)
38 {
39 #ifdef __ANDROID__
40         Sys_AllowProfiling(false);
41 #endif
42 #ifndef WIN32
43         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
44 #endif
45         fflush(stdout);
46         SDL_Quit();
47 }
48
49 static qbool nocrashdialog;
50 void Sys_Error (const char *error, ...)
51 {
52         va_list argptr;
53         char string[MAX_INPUTLINE];
54
55 // change stdin to non blocking
56 #ifndef WIN32
57         fcntl (0, F_SETFL, fcntl (0, F_GETFL, 0) & ~O_NONBLOCK);
58 #endif
59
60         va_start (argptr,error);
61         dpvsnprintf (string, sizeof (string), error, argptr);
62         va_end (argptr);
63
64         Con_Printf(CON_ERROR "Engine Error: %s\n", string);
65         
66         if(!nocrashdialog)
67                 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Engine Error", string, NULL);
68
69         //Host_Shutdown ();
70         exit (1);
71 }
72
73 void Sys_Print(const char *text)
74 {
75 #ifdef __ANDROID__
76         if (developer.integer > 0)
77         {
78                 __android_log_write(ANDROID_LOG_DEBUG, sys.argv[0], text);
79         }
80 #else
81         if(sys.outfd < 0)
82                 return;
83 #ifndef WIN32
84         // BUG: for some reason, NDELAY also affects stdout (1) when used on stdin (0).
85         // this is because both go to /dev/tty by default!
86         {
87                 int origflags = fcntl (sys.outfd, F_GETFL, 0);
88                 fcntl (sys.outfd, F_SETFL, origflags & ~O_NONBLOCK);
89 #endif
90 #ifdef WIN32
91 #define write _write
92 #endif
93                 while(*text)
94                 {
95                         fs_offset_t written = (fs_offset_t)write(sys.outfd, text, (int)strlen(text));
96                         if(written <= 0)
97                                 break; // sorry, I cannot do anything about this error - without an output
98                         text += written;
99                 }
100 #ifndef WIN32
101                 fcntl (sys.outfd, F_SETFL, origflags);
102         }
103 #endif
104         //fprintf(stdout, "%s", text);
105 #endif
106 }
107
108 char *Sys_ConsoleInput(void)
109 {
110         static char text[MAX_INPUTLINE];
111         int len = 0;
112 #ifdef WIN32
113         int c;
114
115         // read a line out
116         while (_kbhit ())
117         {
118                 c = _getch ();
119                 _putch (c);
120                 if (c == '\r')
121                 {
122                         text[len] = 0;
123                         _putch ('\n');
124                         len = 0;
125                         return text;
126                 }
127                 if (c == 8)
128                 {
129                         if (len)
130                         {
131                                 _putch (' ');
132                                 _putch (c);
133                                 len--;
134                                 text[len] = 0;
135                         }
136                         continue;
137                 }
138                 text[len] = c;
139                 len++;
140                 text[len] = 0;
141                 if (len == sizeof (text))
142                         len = 0;
143         }
144 #else
145         fd_set fdset;
146         struct timeval timeout;
147         FD_ZERO(&fdset);
148         FD_SET(0, &fdset); // stdin
149         timeout.tv_sec = 0;
150         timeout.tv_usec = 0;
151         if (select (1, &fdset, NULL, NULL, &timeout) != -1 && FD_ISSET(0, &fdset))
152         {
153                 len = read (0, text, sizeof(text));
154                 if (len >= 1)
155                 {
156                         // rip off the \n and terminate
157                         text[len-1] = 0;
158                         return text;
159                 }
160         }
161 #endif
162         return NULL;
163 }
164
165 char *Sys_GetClipboardData (void)
166 {
167         char *data = NULL;
168         char *cliptext;
169
170         cliptext = SDL_GetClipboardText();
171         if (cliptext != NULL) {
172                 size_t allocsize;
173                 allocsize = min(MAX_INPUTLINE, strlen(cliptext) + 1);
174                 data = (char *)Z_Malloc (allocsize);
175                 strlcpy (data, cliptext, allocsize);
176                 SDL_free(cliptext);
177         }
178
179         return data;
180 }
181
182 int main (int argc, char *argv[])
183 {
184         signal(SIGFPE, SIG_IGN);
185
186 #ifdef __ANDROID__
187         Sys_AllowProfiling(true);
188 #endif
189
190         sys.selffd = -1;
191         sys.argc = argc;
192         sys.argv = (const char **)argv;
193
194         // Sys_Error this early in startup might screw with automated
195         // workflows or something if we show the dialog by default.
196         nocrashdialog = true;
197
198         Sys_ProvideSelfFD();
199
200         // COMMANDLINEOPTION: -nocrashdialog disables "Engine Error" crash dialog boxes
201         if(!Sys_CheckParm("-nocrashdialog"))
202                 nocrashdialog = false;
203         // COMMANDLINEOPTION: sdl: -noterminal disables console output on stdout
204         if(Sys_CheckParm("-noterminal"))
205                 sys.outfd = -1;
206         // COMMANDLINEOPTION: sdl: -stderr moves console output to stderr
207         else if(Sys_CheckParm("-stderr"))
208                 sys.outfd = 2;
209         else
210                 sys.outfd = 1;
211
212 #ifndef WIN32
213         fcntl(0, F_SETFL, fcntl (0, F_GETFL, 0) | O_NONBLOCK);
214 #endif
215
216         // we don't know which systems we'll want to init, yet...
217         SDL_Init(0);
218
219         // used by everything
220         Memory_Init();
221
222         Host_Main();
223
224         Sys_Quit(0);
225         
226         return 0;
227 }
228
229 qbool sys_supportsdlgetticks = true;
230 unsigned int Sys_SDL_GetTicks (void)
231 {
232         return SDL_GetTicks();
233 }
234 void Sys_SDL_Delay (unsigned int milliseconds)
235 {
236         SDL_Delay(milliseconds);
237 }