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