1 /*
2  * XPilotNG/SDL, an SDL/OpenGL XPilot client. Copyright (C) 2003-2004 by
3  *
4  *      Juha Lindstr�m       <juhal@users.sourceforge.net>
5  *      Erik Andersson       <deity_at_home.se>
6  *      Darel Cullen         <darelcullen@users.sourceforge.net>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22 
23 #include "xpclient_sdl.h"
24 
25 #include "text.h"
26 #include "console.h"
27 #include "sdlkeys.h"
28 #include "glwidgets.h"
29 #include "sdlpaint.h"
30 #include "sdlinit.h"
31 #include "scrap.h"
32 
33 /* These are only needed for the polygon tessellation */
34 /* I'd like to move them to Paint_init/cleanup but because it */
35 /* is called before the map is ready I need separate functions */
36 /* for now.. */
37 extern int Gui_init(void);
38 extern void Gui_cleanup(void);
39 
40 int draw_depth;
41 
42 /* This holds video information assigned at initialise */
43 const SDL_VideoInfo *videoInfo;
44 
45 /* Flags to pass to SDL_SetVideoMode */
46 int videoFlags;
47 SDL_Surface  *MainSDLSurface = NULL;
48 
49 font_data gamefont;
50 font_data mapfont;
51 int gameFontSize;
52 int mapFontSize;
53 char *gamefontname;
54 
55 /* ugly kps hack */
file_exists(const char * path)56 static bool file_exists(const char *path)
57 {
58   FILE *fp;
59 
60   if (!path) {
61     return false;
62   } else {
63     fp = fopen(path ? path : "", "r");
64     if (fp) {
65       fclose(fp);
66       return true;
67     }
68     return false;
69   }
70 }
71 
Init_playing_windows(void)72 int Init_playing_windows(void)
73 {
74     /*
75     sdl_init_colors();
76     Init_spark_colors();
77     */
78     if ( !AppendGLWidgetList(&MainWidget,Init_MainWidget(&gamefont)) ) {
79 	error("widget initialization failed");
80 	return -1;
81     }
82     if (Console_init()) {
83 	error("console initialization failed");
84 	return -1;
85     }
86     if (Gui_init()) {
87 	error("gui initialization failed");
88 	return -1;
89     }
90 
91     return 0;
92 }
93 
find_size(int * w,int * h)94 static bool find_size(int *w, int *h)
95 {
96     SDL_Rect **modes, *m;
97     int i, d, best_i, best_d;
98 
99     modes = SDL_ListModes(NULL, videoFlags);
100     if (modes == NULL) return false;
101     if (modes == (SDL_Rect**)-1) return true;
102 
103     best_i = 0;
104     best_d = INT_MAX;
105     for (i = 0; modes[i]; i++) {
106 	m = modes[i];
107 	d = (m->w - *w)*(m->w - *w) + (m->h - *h)*(m->h - *h);
108 	if (d < best_d) {
109 	    best_d = d;
110 	    best_i = i;
111 	}
112     }
113     *w = modes[best_i]->w;
114     *h = modes[best_i]->h;
115     return true;
116 }
117 
Init_window(void)118 int Init_window(void)
119 {
120     int value;
121     char defaultfontname[] = CONF_FONTDIR "FreeSansBoldOblique.ttf";
122     bool gf_exists = true,df_exists = true,gf_init = false, mf_init = false;
123 
124     if (TTF_Init()) {
125     	error("SDL_ttf initialization failed: %s", SDL_GetError());
126     	return -1;
127     }
128     warn("SDL_ttf initialized.\n");
129 
130     Conf_print();
131 
132     if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0) {
133         error("failed to initialize SDL: %s", SDL_GetError());
134         return -1;
135     }
136 
137     atexit(SDL_Quit);
138 
139     /* Fetch the video info */
140     videoInfo = SDL_GetVideoInfo( );
141 
142     num_spark_colors=8;
143 
144     /* the flags to pass to SDL_SetVideoMode */
145     videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL          */
146     videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering       */
147     videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
148 #ifndef _WINDOWS
149     videoFlags |= SDL_RESIZABLE;       /* Enable window resizing        */
150 #else
151     videoFlags |= SDL_FULLSCREEN;
152 #endif
153 
154     /** This checks to see if surfaces can be stored in memory */
155     if ( videoInfo->hw_available )
156         videoFlags |= SDL_HWSURFACE;
157     else
158         videoFlags |= SDL_SWSURFACE;
159 
160     /* This checks if hardware blits can be done */
161     if ( videoInfo->blit_hw )
162         videoFlags |= SDL_HWACCEL;
163 
164     draw_depth =  videoInfo->vfmt->BitsPerPixel;
165 
166     SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
167 
168     if (videoFlags & SDL_FULLSCREEN)
169       if (!find_size((int*)&draw_width, (int*)&draw_height))
170       	videoFlags ^= SDL_FULLSCREEN;
171 
172     if ((MainSDLSurface = SDL_SetVideoMode(draw_width,
173 			 draw_height,
174 			 draw_depth,
175 			 videoFlags )) == NULL) {
176       error("Could not find a valid GLX visual for your display");
177 	  return -1;
178     }
179 
180     SDL_GL_GetAttribute(SDL_GL_RED_SIZE, &value);
181     printf("RGB bpp %d/", value);
182     SDL_GL_GetAttribute(SDL_GL_GREEN_SIZE,&value);
183     printf("%d/", value);
184     SDL_GL_GetAttribute(SDL_GL_BLUE_SIZE, &value);
185     printf("%d ", value);
186     SDL_GL_GetAttribute(SDL_GL_DEPTH_SIZE, &value);
187     printf("Bit Depth is %d\n",value);
188 
189     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
190     glViewport(0, 0, draw_width, draw_height);
191     glMatrixMode(GL_PROJECTION);
192     gluOrtho2D(0, draw_width, 0, draw_height);
193     glMatrixMode(GL_MODELVIEW);
194     glEnable(GL_BLEND);
195     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
196 
197     /* Set title for window */
198     SDL_WM_SetCaption(TITLE, NULL);
199 
200     /* this prevents a freetype crash if you pass non existant fonts */
201     if (!file_exists(gamefontname)) {
202     	error("cannot find your game font '%s'.\n" \
203             "Please check that it exists!",gamefontname);
204     	xpprintf("Reverting to defaultfont '%s'\n",defaultfontname);
205     	gf_exists = false;
206     }
207     if (!file_exists(defaultfontname)) {
208     	error("cannot find the default font! '%s'" ,defaultfontname);
209 	df_exists = false;
210     }
211 
212     if (!gf_exists && !df_exists) {
213     	error("Failed to find any font files!\n" \
214 	    	"Probably you forgot to run 'make install',use '-TTFont <font.ttf>' argument" \
215 		" until you do");
216 	return -1;
217     }
218 
219     if (gf_exists) {
220     	if (fontinit(&gamefont,gamefontname,gameFontSize)) {
221     	    error("Font initialization failed with %s", gamefontname);
222 	} else gf_init = true;
223     }
224     if (!gf_init && df_exists) {
225     	if (fontinit(&gamefont,defaultfontname,gameFontSize)) {
226     	    error("Default font initialization failed with %s", defaultfontname);
227     	} else gf_init = true;
228     }
229 
230     if (!gf_init) {
231     	error("Failed to initialize any game font! (quitting)");
232 	return -1;
233     }
234 
235     if (gf_exists) {
236     	if (fontinit(&mapfont,gamefontname,mapFontSize)) {
237     	    error("Font initialization failed with %s", gamefontname);
238 	} else mf_init = true;
239     }
240     if (!mf_init && df_exists) {
241     	if (fontinit(&mapfont,defaultfontname,mapFontSize)) {
242     	    error("Default font initialization failed with %s", defaultfontname);
243     	} else mf_init = true;
244     }
245 
246     if (!mf_init) {
247     	error("Failed to initialize any map font! (quitting)");
248 	return -1;
249     }
250 
251     /* Set up the clipboard */
252     if ( init_scrap() < 0 ) {
253     	error("Couldn't init clipboard: %s\n");
254     }
255 
256     return 0;
257 }
258 
259 /* function to reset our viewport after a window resize */
Resize_Window(int width,int height)260 int Resize_Window( int width, int height )
261 {
262     SDL_Rect b = {0,0,0,0};
263 
264 	if (videoFlags & SDL_FULLSCREEN)
265 		if (!find_size(&width, &height))
266 			return -1;
267 
268     b.w = draw_width = width;
269     b.h = draw_height = height;
270 
271     SetBounds_GLWidget(MainWidget,&b);
272 
273     if (!SDL_SetVideoMode( width,
274 			   height,
275 			   draw_depth,
276 			   videoFlags ))
277 	return -1;
278 
279 
280     /* change to the projection matrix and set our viewing volume. */
281     glMatrixMode( GL_PROJECTION );
282 
283     glLoadIdentity( );
284 
285     gluOrtho2D(0, draw_width, 0, draw_height);
286 
287     /* Make sure we're chaning the model view and not the projection */
288     glMatrixMode( GL_MODELVIEW );
289 
290     /* Reset The View */
291     glLoadIdentity( );
292 
293     /* Setup our viewport. */
294     glViewport( 0, 0, ( GLint )draw_width, ( GLint )draw_height );
295     return 0;
296 }
297 
298 
Platform_specific_cleanup(void)299 void Platform_specific_cleanup(void)
300 {
301     Close_Widget(&MainWidget);
302     Gui_cleanup();
303     Console_cleanup();
304     fontclean(&gamefont);
305     fontclean(&mapfont);
306     TTF_Quit();
307     SDL_Quit();
308 }
309 
Set_geometry(xp_option_t * opt,const char * s)310 static bool Set_geometry(xp_option_t *opt, const char *s)
311 {
312     int w = 0, h = 0;
313 
314     if (s[0] == '=') {
315 	sscanf(s, "%*c%d%*c%d", &w, &h);
316     } else {
317 	sscanf(s, "%d%*c%d", &w, &h);
318     }
319     if (w == 0 || h == 0) return false;
320     if (MainSDLSurface != NULL) {
321 	Resize_Window(w, h);
322     } else {
323 	draw_width = w;
324 	draw_height = h;
325     }
326     return true;
327 }
328 
Get_geometry(xp_option_t * opt)329 static const char* Get_geometry(xp_option_t *opt)
330 {
331     static char buf[20]; /* should be enough */
332     snprintf(buf, 20, "%dx%d", draw_width, draw_height);
333     return buf;
334 }
335 
Set_fontName(xp_option_t * opt,const char * value)336 static bool Set_fontName(xp_option_t *opt, const char *value)
337 {
338     UNUSED_PARAM(opt);
339     XFREE(gamefontname);
340     gamefontname = xp_safe_strdup(value);
341 
342     return true;
343 }
344 
Get_fontName(xp_option_t * opt)345 static const char *Get_fontName(xp_option_t *opt)
346 {
347     UNUSED_PARAM(opt);
348     return gamefontname;
349 }
350 
351 static xp_option_t sdlinit_options[] = {
352     XP_STRING_OPTION(
353 	"geometry",
354 	"1280x1024",
355 	NULL,
356 	0,
357 	Set_geometry, NULL, Get_geometry,
358 	XP_OPTFLAG_DEFAULT,
359 	"Set the initial window geometry.\n"),
360 
361      XP_INT_OPTION(
362         "gameFontSize",
363 	16, 12, 32,
364 	&gameFontSize,
365 	NULL,
366 	XP_OPTFLAG_DEFAULT,
367 	"Height of font used for game strings.\n"),
368 
369     XP_INT_OPTION(
370         "mapFontSize",
371 	16, 12, 64,
372 	&mapFontSize,
373 	NULL,
374 	XP_OPTFLAG_DEFAULT,
375 	"Height of font used for strings painted on the map.\n"),
376 
377     XP_STRING_OPTION(
378 	"TTFont",
379 	CONF_FONTDIR "FreeSansBoldOblique.ttf",
380 	NULL, 0,
381 	Set_fontName, NULL, Get_fontName,
382 	XP_OPTFLAG_DEFAULT,
383 	"Set the font to use.\n")
384 };
385 
Store_sdlinit_options(void)386 void Store_sdlinit_options(void)
387 {
388     STORE_OPTIONS(sdlinit_options);
389 }
390