1 /*
2  * Phlipple
3  * Copyright (C) Remigiusz Dybka 2011 <remigiusz.dybka@gmail.com>
4  *
5  Phlipple is free software: you can redistribute it and/or modify it
6  under the terms of the GNU General Public License as published by the
7  Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  Phlipple is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  See the GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #ifdef WIN32
20 #include <windows.h>
21 #endif
22 
23 #ifndef WIN32
24 #include <limits.h>
25 #define MAX_PATH PATH_MAX
26 #endif
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <sys/time.h>
36 #include <SDL/SDL.h>
37 #include <SDL/SDL_mixer.h>
38 
39 #include "osinterface.h"
40 #include "GL/glew.h"
41 #include "engine.h"
42 #include "settings.h"
43 
44 void keyboard(unsigned char key, int x, int y);
45 void special(int key, int x, int y);
46 void mouse(int butt, int state, int x, int y);
47 
48 void display(void);
49 void reshape(int width, int height);
50 void gameLoop();
51 
52 static int recordVideo = 0;
53 static GLbyte *buff = 0;
54 FILE *videoFile = 0;
55 static int width;
56 static int height;
57 
58 double ltime;
59 double timenow;
60 double frameTime;
61 
62 static int hasQuit = 0;
63 static int audioInitialized = 0;
64 
65 static Mix_Music *music_theme = NULL;
66 static Mix_Music *music_success = NULL;
67 static Mix_Music *music_failure = NULL;
68 
69 static Mix_Chunk *snd_phlip = NULL;
70 static Mix_Chunk *snd_click = NULL;
71 static Mix_Chunk *snd_click2 = NULL;
72 static Mix_Chunk *snd_buzz = NULL;
73 
74 SDL_Surface *screen;
75 SceneEvents *evts;
76 const SDL_VideoInfo *vi;
77 
78 int OS_sound_On = 0;
79 int mouseX;
80 int mouseY;
81 
getNanoTime()82 double getNanoTime()
83 {
84 	struct timeval tv;
85 	gettimeofday(&tv, 0);
86 	return (double) tv.tv_sec + ((double) tv.tv_usec / 1000000.0L);
87 }
88 
OS_init(int * argc,char ** argv)89 void OS_init(int *argc, char **argv)
90 {
91 	settings_load();
92 	frameTime = 1.0 / ((double) ENGINE_DEFAULT_FPS);
93 
94 	evts = SceneManager_eventsInit();
95 	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_TIMER) < 0)
96 	{
97 		fprintf(stderr, "Could not initialize SDL:%s\n", SDL_GetError());
98 		exit(-1);
99 	}
100 
101 	if (Mix_OpenAudio(44100, AUDIO_S16, 2, 4096) < 0)
102 	{
103 		fprintf(stderr, "No audio: %s\n", SDL_GetError());
104 	}
105 	else
106 	{
107 		audioInitialized = 1;
108 
109 		music_theme = Mix_LoadMUS(OS_getFileName("theme.ogg"));
110 		music_success = Mix_LoadMUS(OS_getFileName("success.ogg"));
111 		music_failure = Mix_LoadMUS(OS_getFileName("failure.ogg"));
112 
113 		snd_phlip = Mix_LoadWAV(OS_getFileName("phlip.ogg"));
114 		snd_click = Mix_LoadWAV(OS_getFileName("click.ogg"));
115 		snd_click2 = Mix_LoadWAV(OS_getFileName("click2.ogg"));
116 		snd_buzz = Mix_LoadWAV(OS_getFileName("glitch.ogg"));
117 
118 		Mix_VolumeMusic(MIX_MAX_VOLUME);
119 	}
120 
121 	vi = SDL_GetVideoInfo();
122 	int bpp = vi->vfmt->BitsPerPixel;
123 
124 	switch (bpp)
125 	{
126 	case 16:
127 		SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 4 );
128 		SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 4 );
129 		SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 4 );
130 		SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
131 		SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
132 		break;
133 
134 	case 24:
135 	case 32:
136 		SDL_GL_SetAttribute( SDL_GL_RED_SIZE, 8 );
137 		SDL_GL_SetAttribute( SDL_GL_GREEN_SIZE, 8 );
138 		SDL_GL_SetAttribute( SDL_GL_BLUE_SIZE, 8 );
139 		SDL_GL_SetAttribute( SDL_GL_DEPTH_SIZE, 16 );
140 		SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
141 		break;
142 
143 	default:
144 		fprintf(stderr, "This program requires at least 16bit display");
145 		exit(-1);
146 	}
147 
148 	screen = SDL_SetVideoMode(640, 480, bpp, SDL_OPENGL | SDL_RESIZABLE);
149 	width = screen->w;
150 	height = screen->h;
151 
152 	char wmcapt[256];
153 	sprintf(wmcapt, "Phlipple ver %s", PACKAGE_VERSION);
154 
155 	SDL_WM_SetCaption(wmcapt, wmcapt);
156 }
157 
OS_mainLoop()158 int OS_mainLoop()
159 {
160 	GLenum err = glewInit();
161 	if (err == GLEW_OK)
162 	{
163 		SceneManager_reshape(screen->w, screen->h);
164 		while(!hasQuit)
165 			gameLoop();
166 	}
167 
168 	return EXIT_SUCCESS;
169 }
170 
OS_quit()171 void OS_quit()
172 {
173 	SceneManager_destroy();
174 	SceneManager_eventsDestroy(evts);
175 	hasQuit = 1;
176 
177 	if (audioInitialized)
178 	{
179 		if (Mix_PlayingMusic())
180 			Mix_FadeOutMusic(200);
181 
182 		if (music_theme)
183 			Mix_FreeMusic(music_theme);
184 
185 		if (music_success)
186 			Mix_FreeMusic(music_success);
187 
188 		if (music_failure)
189 			Mix_FreeMusic(music_failure);
190 
191 		Mix_CloseAudio();
192 	}
193 
194 	SDL_Quit();
195 	settings_save();
196 }
197 
keyboard(unsigned char key,int x,int y)198 void keyboard(unsigned char key, int x, int y)
199 {
200 	SceneManager_eventsAdd(evts, SCENEEVENT_TYPE_KEYDOWN, key, x, y);
201 }
202 
reshape(int _width,int _height)203 void reshape(int _width, int _height)
204 {
205 	width = _width;
206 	height = _height;
207 	screen = SDL_SetVideoMode(width, height, vi->vfmt->BitsPerPixel, SDL_OPENGL | SDL_RESIZABLE);
208 	SceneManager_reshape(width, height);
209 }
210 
211 
gameLoop()212 void gameLoop()
213 {
214 	SDL_Event event;
215 
216 	/* Grab all the events off the queue. */
217 	while( SDL_PollEvent( &event ) )
218 	{
219 		int k = -1;
220 
221 		switch( event.type )
222 		{
223 		case SDL_MOUSEMOTION:
224 			mouseX = event.motion.x;
225 			mouseY = event.motion.y;
226 			break;
227 
228 		case SDL_MOUSEBUTTONDOWN:
229 			SceneManager_eventsAdd(evts, SCENEEVENT_TYPE_FINGERDOWN, 0, event.button.x, event.button.y);
230 			break;
231 
232 		case SDL_MOUSEBUTTONUP:
233 			SceneManager_eventsAdd(evts, SCENEEVENT_TYPE_FINGERUP, 0, event.button.x, event.button.y);
234 			break;
235 
236 		case SDL_VIDEORESIZE:
237 			reshape(event.resize.w, event.resize.h);
238 			break;
239 
240 		case SDL_KEYDOWN:
241 			switch (event.key.keysym.sym)
242 			{
243 			case SDLK_UP:
244 				k = OS_key_up;
245 				break;
246 			case SDLK_DOWN:
247 				k = OS_key_down;
248 				break;
249 			case SDLK_LEFT:
250 				k = OS_key_left;
251 				break;
252 			case SDLK_RIGHT:
253 				k = OS_key_right;
254 				break;
255 			case SDLK_a:
256 				k = OS_key_rol;
257 				break;
258 			case SDLK_d:
259 				k = OS_key_ror;
260 				break;
261 			case SDLK_RETURN:
262 			case SDLK_KP_ENTER:
263 				k = OS_key_ok;
264 				break;
265 			case SDLK_ESCAPE:
266 				k = OS_key_cancel;
267 				break;
268 			default:
269 				break;
270 			}
271 
272 			if (k != -1)
273 				SceneManager_eventsAdd(evts, SCENEEVENT_TYPE_KEYDOWN, k, 0, 0);
274 			break;
275 
276 		case SDL_QUIT:
277 			OS_quit();
278 			break;
279 
280 		default:
281 			break;
282 		}
283 	}
284 
285 
286 	timenow = getNanoTime();
287 
288 	while (timenow - ltime < (frameTime))
289 	{
290 		timenow = getNanoTime();
291 	}
292 
293 	display();
294 	ltime = timenow;
295 }
296 
display()297 void display()
298 {
299 	if (recordVideo)
300 	{
301 		SceneManager_pump(1.0 / 25.0, evts);
302 	}
303 	else
304 	{
305 		SceneManager_pump(timenow - ltime, evts);
306 	}
307 	if (hasQuit)
308 		return;
309 
310 	SceneManager_eventsZero(evts);
311 	if (recordVideo)
312 	{
313 		if (buff == 0)
314 			buff = malloc(width * height * 3);
315 
316 
317 		glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, buff);
318 		fwrite(buff, width * height *3, 1, videoFile);
319 	}
320 
321 	SDL_GL_SwapBuffers();
322 }
323 
OS_getFileName(const char * fileName)324 const char *OS_getFileName(const char *fileName)
325 {
326 	static char ret[MAX_PATH];
327 #ifdef WIN32
328 	wchar_t defDirW[MAX_PATH *2];
329 	char defDir[MAX_PATH];
330 
331 	GetCurrentDirectoryW(MAX_PATH, defDirW);
332 	WideCharToMultiByte(CP_UTF8, 0, defDirW, -1, defDir, MAX_PATH * 2, NULL, NULL);
333 
334 	sprintf(ret, "%s%sdata%s%s", defDir, SEPARATOR, SEPARATOR, fileName);
335 	return w32_getFileName(ret);
336 #endif
337 #ifndef WIN32
338 	sprintf(ret, "%s/%s/%s", PACKAGE_DATA_DIR, PACKAGE, fileName);
339 #endif
340 	return ret;
341 }
342 
OS_getFile(const char * fileName)343 FILE *OS_getFile(const char *fileName)
344 {
345 	FILE *ph = fopen(OS_getFileName(fileName), "rb");
346 	return ph;
347 
348 }
349 
OS_getResource(const char * resName,char ** data)350 size_t OS_getResource(const char *resName, char **data)
351 {
352 	FILE *inph = OS_getFile(resName);
353 
354 	if (inph == NULL)
355 		return 0;
356 
357 	fseek(inph, 0, SEEK_END);
358 	size_t len = ftell(inph);
359 	fseek(inph, 0, SEEK_SET);
360 
361 	*data = malloc(len);
362 	size_t ret = fread(*data, 1, len, inph);
363 	fclose(inph);
364 	return ret;
365 }
366 
OS_getPref(const char * name,const char * defVal)367 const char *OS_getPref(const char *name, const char *defVal)
368 {
369 	return settings_get(name, defVal);
370 }
371 
OS_setPref(const char * name,const char * value)372 void OS_setPref(const char *name, const char *value)
373 {
374 	settings_set(name, value);
375 }
376 
377 
OS_playSound(int id)378 void OS_playSound(int id)
379 {
380 	if(!OS_sound_On)
381 		return;
382 
383 	if (id == OS_snd_phlip)
384 		Mix_PlayChannel(0, snd_phlip, 0);
385 
386 	if (id == OS_snd_click)
387 		Mix_PlayChannel(0, snd_click, 0);
388 
389 	if (id == OS_snd_click2)
390 		Mix_PlayChannel(0, snd_click2, 0);
391 
392 	if (id == OS_snd_buzz)
393 		Mix_PlayChannel(0, snd_buzz, 0);
394 
395 
396 }
397 
OS_playMusic(int id)398 void OS_playMusic(int id)
399 {
400 	if(!OS_sound_On)
401 		return;
402 
403 	if (id == OS_music_theme)
404 		Mix_FadeInMusic(music_theme, -1, 0);
405 
406 	if (id == OS_music_success)
407 		Mix_FadeInMusic(music_success, 0, 0);
408 
409 	if (id == OS_music_failure)
410 		Mix_FadeInMusic(music_failure, 0, 0);
411 
412 }
413 
OS_stopMusic(int id)414 void OS_stopMusic(int id)
415 {
416 	Mix_FadeOutMusic(200);
417 }
418 
OS_getMouseX()419 int OS_getMouseX()
420 {
421 	return mouseX;
422 }
423 
OS_getMouseY()424 int OS_getMouseY()
425 {
426 	return mouseY;
427 }
428