]> git.jsancho.org Git - gacela.git/blob - src/sdl.c
Gacela as Guile modules.
[gacela.git] / src / sdl.c
1 /* Gacela, a GNU Guile extension for fast games development
2    Copyright (C) 2009 by Javier Sancho Fernandez <jsf at jsancho dot org>
3
4    This program is free software: you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation, either version 3 of the License, or
7    (at your option) any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <libguile.h>
19 #include <SDL/SDL.h>
20 #include <SDL/SDL_events.h>
21 #include <SDL/SDL_image.h>
22 #include <SDL/SDL_mixer.h>
23 #include <SDL/SDL_rotozoom.h>
24 #include "gacela_SDL.h"
25
26 struct surface
27 {
28   SCM filename;
29   SDL_Surface *surface_address;
30 };
31
32 static scm_t_bits surface_tag;
33
34 SCM
35 make_surface (SCM file, SDL_Surface *surface_address)
36 {
37   SCM smob;
38   struct surface *surface;
39
40   surface = (struct surface *) scm_gc_malloc (sizeof (struct surface), "surface");
41
42   surface->filename = SCM_BOOL_F;
43   surface->surface_address = NULL;
44
45   SCM_NEWSMOB (smob, surface_tag, surface);
46
47   surface->filename = file;
48   surface->surface_address = surface_address;
49
50   return smob;
51 }
52
53 SDL_Surface *
54 get_surface_address (SCM surface_smob)
55 {
56   struct surface *surface;
57
58   scm_assert_smob_type (surface_tag, surface_smob);
59   surface = (struct surface *) SCM_SMOB_DATA (surface_smob);
60   return surface->surface_address;
61 }
62
63 SCM
64 get_surface_filename (SCM surface_smob)
65 {
66   struct surface *surface;
67
68   scm_assert_smob_type (surface_tag, surface_smob);
69   surface = (struct surface *) SCM_SMOB_DATA (surface_smob);
70   return surface->filename;
71 }
72
73 SCM
74 get_surface_width (SCM surface_smob)
75 {
76   SDL_Surface *surface = get_surface_address (surface_smob);
77
78   return scm_from_int (surface->w);
79 }
80
81 SCM
82 get_surface_height (SCM surface_smob)
83 {
84   SDL_Surface *surface = get_surface_address (surface_smob);
85
86   return scm_from_int (surface->h);
87 }
88
89 SCM
90 get_surface_pixels (SCM surface_smob)
91 {
92   SDL_Surface *surface = get_surface_address (surface_smob);
93
94   return scm_from_int ((int)surface->pixels);
95 }
96
97 SCM
98 get_surface_format_BytesPerPixel (SCM surface_smob)
99 {
100   SDL_Surface *surface = get_surface_address (surface_smob);
101
102   return scm_from_int (surface->format->BytesPerPixel);
103 }
104
105 SCM
106 mark_surface (SCM surface_smob)
107 {
108   struct surface *surface = (struct surface *) SCM_SMOB_DATA (surface_smob);
109
110   scm_gc_mark (surface->filename);
111      
112   return SCM_BOOL_F;
113 }
114
115 size_t
116 free_surface (SCM surface_smob)
117 {
118   struct surface *surface = (struct surface *) SCM_SMOB_DATA (surface_smob);
119
120   SDL_FreeSurface (surface->surface_address);
121   scm_gc_free (surface, sizeof (struct surface), "surface");
122
123   return 0;
124 }
125
126 static int
127 print_surface (SCM surface_smob, SCM port, scm_print_state *pstate)
128 {
129   struct surface *surface = (struct surface *) SCM_SMOB_DATA (surface_smob);
130
131   scm_puts ("#<surface \"", port);
132   scm_display (surface->filename, port);
133   scm_puts ("\">", port);
134
135   /* non-zero means success */
136   return 1;
137 }
138
139
140 SCM
141 gacela_SDL_Init (SCM flags)
142 {
143   return scm_from_int (SDL_Init (scm_to_int (flags)));
144 }
145
146 SCM
147 gacela_SDL_Quit (void)
148 {
149   SDL_Quit ();
150   return SCM_UNSPECIFIED;
151 }
152
153 SCM
154 gacela_SDL_SetVideoMode (SCM width, SCM height, SCM bpp, SCM flags)
155 {
156   SDL_Surface *screen = SDL_SetVideoMode (scm_to_int (width), scm_to_int (height), \
157                                           scm_to_int (bpp), scm_to_int (flags));
158
159   if (screen) {
160     return make_surface (scm_from_locale_string ("screen"), screen);
161   }
162   else {
163     return SCM_BOOL_F;
164   }
165 }
166
167 SCM
168 gacela_SDL_FreeSurface (SCM surface)
169 {
170   return scm_from_int (free_surface (surface));
171 }
172
173 SCM
174 gacela_SDL_WM_SetCaption (SCM title, SCM icon)
175 {
176   SDL_WM_SetCaption (scm_to_locale_string(title), scm_to_locale_string(icon));
177   return SCM_UNSPECIFIED;
178 }
179
180 SCM
181 gacela_SDL_Flip (SCM screen)
182 {
183   return scm_from_int (SDL_Flip (get_surface_address (screen)));
184 }
185
186 SCM
187 gacela_SDL_Delay (SCM ms)
188 {
189   SDL_Delay ((int)scm_to_double (ms));
190   return SCM_UNSPECIFIED;
191 }
192
193 SCM
194 gacela_SDL_GetTicks (void)
195 {
196   return scm_from_int (SDL_GetTicks ());
197 }
198
199 SCM
200 gacela_SDL_DisplayFormat (SCM surface)
201 {
202   SDL_Surface *new = SDL_DisplayFormat (get_surface_address (surface));
203
204   if (new) {
205     return make_surface (get_surface_filename (surface), new);
206   }
207   else {
208     return SCM_BOOL_F;
209   }
210 }
211
212 SCM
213 gacela_SDL_DisplayFormatAlpha (SCM surface)
214 {
215   SDL_Surface *new = SDL_DisplayFormatAlpha (get_surface_address (surface));
216
217   if (new) {
218     return make_surface (get_surface_filename (surface), new);
219   }
220   else {
221     return SCM_BOOL_F;
222   }
223 }
224
225 SCM
226 gacela_SDL_MapRGB (SCM format, SCM r, SCM g, SCM b)
227 {
228   return scm_from_int (SDL_MapRGB ((SDL_PixelFormat *)scm_to_int (format), scm_to_int (r), scm_to_int (g), scm_to_int (b)));
229 }
230
231 SCM
232 gacela_SDL_SetColorKey (SCM surface, SCM flag, SCM key)
233 {
234   return scm_from_int (SDL_SetColorKey (get_surface_address (surface), scm_to_int (flag), scm_to_int (key)));
235 }
236
237 SCM
238 gacela_SDL_SetAlpha (SCM surface, SCM flag, SCM alpha)
239 {
240   return scm_from_int (SDL_SetAlpha (get_surface_address (surface), scm_to_int (flag), scm_to_int (alpha)));
241 }
242
243 SCM
244 gacela_SDL_LoadBMP (SCM file)
245 {
246   SDL_Surface *image = SDL_LoadBMP (scm_to_locale_string (file));
247
248   if (image) {
249     return make_surface (file, image);
250   }
251   else {
252     return SCM_BOOL_F;
253   }
254 }
255
256 SCM
257 gacela_IMG_Load (SCM filename)
258 {
259   SDL_Surface *image = IMG_Load (scm_to_locale_string (filename));
260
261   if (image) {
262     return make_surface (filename, image);
263   }
264   else {
265     return SCM_BOOL_F;
266   }
267 }
268
269 SCM
270 gacela_SDL_GetVideoInfo (void)
271 {
272   const SDL_VideoInfo *info;
273   SCM vi;
274
275   info = SDL_GetVideoInfo ();
276   vi = scm_list_n (SCM_UNDEFINED);
277
278   vi = scm_cons (scm_cons (scm_from_locale_symbol ("blit_hw"), scm_from_int (info->blit_hw)), vi);
279   vi = scm_cons (scm_cons (scm_from_locale_symbol ("hw_available"), scm_from_int (info->hw_available)), vi);
280
281   return vi;
282 }
283
284 SCM
285 gacela_SDL_GL_SetAttribute (SCM attr, SCM value)
286 {
287   return scm_from_int (SDL_GL_SetAttribute (scm_to_int (attr), scm_to_int (value)));
288 }
289
290 SCM
291 gacela_SDL_PollEvent (void)
292 {
293   SDL_Event sdl_event;
294   SCM event;
295
296   event = scm_list_n (SCM_UNDEFINED);
297
298   if (SDL_PollEvent (&sdl_event)) {
299     switch (sdl_event.type) {
300     case SDL_KEYDOWN:
301     case SDL_KEYUP:
302       event = scm_cons (scm_cons (scm_from_locale_symbol ("key.keysym.sym"), scm_from_int (sdl_event.key.keysym.sym)), event);
303       break;
304     }
305     event = scm_cons (scm_cons (scm_from_locale_symbol ("type"), scm_from_int (sdl_event.type)), event);
306   }
307
308   return event;
309 }
310
311 SCM
312 gacela_SDL_GL_SwapBuffers (void)
313 {
314   SDL_GL_SwapBuffers ();
315   return SCM_UNSPECIFIED;
316 }
317
318 SCM
319 gacela_SDL_EnableKeyRepeat (SCM delay, SCM interval)
320 {
321   return scm_from_int (SDL_EnableKeyRepeat (scm_to_int (delay), scm_to_int (interval)));
322 }
323
324 SCM
325 gacela_zoomSurface (SCM src, SCM zoomx, SCM zoomy, SCM smooth)
326 {
327   SDL_Surface *image = zoomSurface (get_surface_address (src), scm_to_double (zoomx), scm_to_double (zoomy), scm_to_int (smooth));
328
329   if (image) {
330     return make_surface (get_surface_filename (src), image);
331   }
332   else {
333     return SCM_BOOL_F;
334   }
335 }
336
337 SCM
338 gacela_Mix_OpenAudio (SCM frequency, SCM format, SCM channels, SCM chunksize)
339 {
340   return scm_from_int (Mix_OpenAudio (scm_to_int (frequency), scm_to_int (format), scm_to_int (channels), scm_to_int (chunksize)));
341 }
342
343 SCM
344 gacela_Mix_LoadMUS (SCM file)
345 {
346   return scm_from_int ((int)Mix_LoadMUS (scm_to_locale_string (file)));
347 }
348
349 SCM
350 gacela_Mix_LoadWAV (SCM file)
351 {
352   return scm_from_int ((int)Mix_LoadWAV (scm_to_locale_string (file)));
353 }
354
355 SCM
356 gacela_Mix_PlayChannel (SCM channel, SCM chunk, SCM loops)
357 {
358   return scm_from_int (Mix_PlayChannel (scm_to_int (channel), (Mix_Chunk *)scm_to_int (chunk), scm_to_int (loops)));
359 }
360
361 SCM
362 gacela_Mix_PlayMusic (SCM music, SCM loops)
363 {
364   return scm_from_int (Mix_PlayMusic ((Mix_Music *)scm_to_int (music), scm_to_int (loops)));
365 }
366
367 SCM
368 gacela_Mix_PlayingMusic (void)
369 {
370   return scm_from_int (Mix_PlayingMusic ());
371 }
372
373 SCM
374 gacela_Mix_PausedMusic (void)
375 {
376   return scm_from_int (Mix_PausedMusic ());
377 }
378
379 SCM
380 gacela_Mix_PauseMusic (void)
381 {
382   Mix_PauseMusic ();
383   return SCM_UNSPECIFIED;
384 }
385
386 SCM
387 gacela_Mix_ResumeMusic (void)
388 {
389   Mix_ResumeMusic ();
390   return SCM_UNSPECIFIED;
391 }
392
393 SCM
394 gacela_Mix_HaltMusic (void)
395 {
396   return scm_from_int (Mix_HaltMusic ());
397 }
398
399 SCM
400 gacela_Mix_FreeMusic (SCM music)
401 {
402   Mix_FreeMusic ((Mix_Music *)scm_to_int (music));
403   return SCM_UNSPECIFIED;
404 }
405
406 SCM
407 gacela_Mix_FreeChunk (SCM chunk)
408 {
409   Mix_FreeChunk ((Mix_Chunk *)scm_to_int (chunk));
410   return SCM_UNSPECIFIED;
411 }
412
413 SCM
414 gacela_Mix_CloseAudio (void)
415 {
416   Mix_CloseAudio ();
417   return SCM_UNSPECIFIED;
418 }
419
420
421 void
422 init_gacela_sdl (void *data)
423 {
424   surface_tag = scm_make_smob_type ("surface", sizeof (struct surface));
425   scm_set_smob_mark (surface_tag, mark_surface);
426   scm_set_smob_free (surface_tag, free_surface);
427   scm_set_smob_print (surface_tag, print_surface);
428   scm_c_define_gsubr ("surface-file", 1, 0, 0, get_surface_filename);
429   scm_c_define_gsubr ("surface-w", 1, 0, 0, get_surface_width);
430   scm_c_define_gsubr ("surface-h", 1, 0, 0, get_surface_height);
431   scm_c_define_gsubr ("surface-pixels", 1, 0, 0, get_surface_pixels);
432   scm_c_define_gsubr ("surface-format-BytesPerPixel", 1, 0, 0, get_surface_format_BytesPerPixel);
433
434   scm_c_define ("SDL_INIT_TIMER", scm_from_int (SDL_INIT_TIMER));
435   scm_c_define ("SDL_INIT_AUDIO", scm_from_int (SDL_INIT_AUDIO));
436   scm_c_define ("SDL_INIT_VIDEO", scm_from_int (SDL_INIT_VIDEO));
437   scm_c_define ("SDL_INIT_CDROM", scm_from_int (SDL_INIT_CDROM));
438   scm_c_define ("SDL_INIT_JOYSTICK", scm_from_int (SDL_INIT_JOYSTICK));
439   scm_c_define ("SDL_INIT_NOPARACHUTE", scm_from_int (SDL_INIT_NOPARACHUTE));
440   scm_c_define ("SDL_INIT_EVENTTHREAD", scm_from_int (SDL_INIT_EVENTTHREAD));
441   scm_c_define ("SDL_INIT_EVERYTHING", scm_from_int (SDL_INIT_EVERYTHING));
442
443   scm_c_define ("SDL_SWSURFACE", scm_from_int (SDL_SWSURFACE));
444   scm_c_define ("SDL_HWSURFACE", scm_from_int (SDL_HWSURFACE));
445   scm_c_define ("SDL_ASYNCBLIT", scm_from_int (SDL_ASYNCBLIT));
446
447   scm_c_define ("SDL_ANYFORMAT", scm_from_int (SDL_ANYFORMAT));
448   scm_c_define ("SDL_HWPALETTE", scm_from_int (SDL_HWPALETTE));
449   scm_c_define ("SDL_DOUBLEBUF", scm_from_int (SDL_DOUBLEBUF));
450   scm_c_define ("SDL_FULLSCREEN", scm_from_int (SDL_FULLSCREEN));
451   scm_c_define ("SDL_OPENGL", scm_from_int (SDL_OPENGL));
452   scm_c_define ("SDL_OPENGLBLIT", scm_from_int (SDL_OPENGLBLIT));
453   scm_c_define ("SDL_RESIZABLE", scm_from_int (SDL_RESIZABLE));
454   scm_c_define ("SDL_NOFRAME", scm_from_int (SDL_NOFRAME));
455
456   scm_c_define ("SDL_HWACCEL", scm_from_int (SDL_HWACCEL));
457   scm_c_define ("SDL_SRCCOLORKEY", scm_from_int (SDL_SRCCOLORKEY));
458
459   scm_c_define ("SDL_GL_DOUBLEBUFFER", scm_from_int (SDL_GL_DOUBLEBUFFER));
460
461   scm_c_define ("SDL_DEFAULT_REPEAT_DELAY", scm_from_int (SDL_DEFAULT_REPEAT_DELAY));
462   scm_c_define ("SDL_DEFAULT_REPEAT_INTERVAL", scm_from_int (SDL_DEFAULT_REPEAT_INTERVAL));
463
464   scm_c_define ("SDL_LIL_ENDIAN", scm_from_int (SDL_LIL_ENDIAN));
465   scm_c_define ("SDL_BIG_ENDIAN", scm_from_int (SDL_BIG_ENDIAN));
466   scm_c_define ("SDL_BYTEORDER", scm_from_int (SDL_BYTEORDER));
467
468   scm_c_define ("MIX_DEFAULT_FORMAT", scm_from_int (MIX_DEFAULT_FORMAT));
469
470   scm_c_define ("SDL_NOEVENT", scm_from_int (SDL_NOEVENT));
471   scm_c_define ("SDL_ACTIVEEVENT", scm_from_int (SDL_ACTIVEEVENT));
472   scm_c_define ("SDL_KEYDOWN", scm_from_int (SDL_KEYDOWN));
473   scm_c_define ("SDL_KEYUP", scm_from_int (SDL_KEYUP));
474   scm_c_define ("SDL_MOUSEMOTION", scm_from_int (SDL_MOUSEMOTION));
475   scm_c_define ("SDL_MOUSEBUTTONDOWN", scm_from_int (SDL_MOUSEBUTTONDOWN));
476   scm_c_define ("SDL_MOUSEBUTTONUP", scm_from_int (SDL_MOUSEBUTTONUP));
477   scm_c_define ("SDL_JOYAXISMOTION", scm_from_int (SDL_JOYAXISMOTION));
478   scm_c_define ("SDL_JOYBALLMOTION", scm_from_int (SDL_JOYBALLMOTION));
479   scm_c_define ("SDL_JOYHATMOTION", scm_from_int (SDL_JOYHATMOTION));
480   scm_c_define ("SDL_JOYBUTTONDOWN", scm_from_int (SDL_JOYBUTTONDOWN));
481   scm_c_define ("SDL_JOYBUTTONUP", scm_from_int (SDL_JOYBUTTONUP));
482   scm_c_define ("SDL_QUIT", scm_from_int (SDL_QUIT));
483   scm_c_define ("SDL_SYSWMEVENT", scm_from_int (SDL_SYSWMEVENT));
484   scm_c_define ("SDL_EVENT_RESERVEDA", scm_from_int (SDL_EVENT_RESERVEDA));
485   scm_c_define ("SDL_EVENT_RESERVEDB", scm_from_int (SDL_EVENT_RESERVEDB));
486   scm_c_define ("SDL_VIDEORESIZE", scm_from_int (SDL_VIDEORESIZE));
487   scm_c_define ("SDL_VIDEOEXPOSE", scm_from_int (SDL_VIDEOEXPOSE));
488   scm_c_define ("SDL_EVENT_RESERVED2", scm_from_int (SDL_EVENT_RESERVED2));
489   scm_c_define ("SDL_EVENT_RESERVED3", scm_from_int (SDL_EVENT_RESERVED3));
490   scm_c_define ("SDL_EVENT_RESERVED4", scm_from_int (SDL_EVENT_RESERVED4));
491   scm_c_define ("SDL_EVENT_RESERVED5", scm_from_int (SDL_EVENT_RESERVED5));
492   scm_c_define ("SDL_EVENT_RESERVED6", scm_from_int (SDL_EVENT_RESERVED6));
493   scm_c_define ("SDL_EVENT_RESERVED7", scm_from_int (SDL_EVENT_RESERVED7));
494   scm_c_define ("SDL_USEREVENT", scm_from_int (SDL_USEREVENT));
495   scm_c_define ("SDL_NUMEVENTS", scm_from_int (SDL_NUMEVENTS));
496
497   scm_c_define_gsubr ("SDL_Init", 1, 0, 0, gacela_SDL_Init);
498   scm_c_define_gsubr ("SDL_Quit", 0, 0, 0, gacela_SDL_Quit);
499   scm_c_define_gsubr ("SDL_SetVideoMode", 4, 0, 0, gacela_SDL_SetVideoMode);
500   scm_c_define_gsubr ("SDL_FreeSurface", 1, 0, 0, gacela_SDL_FreeSurface);
501   scm_c_define_gsubr ("SDL_WM_SetCaption", 2, 0, 0, gacela_SDL_WM_SetCaption);
502   scm_c_define_gsubr ("SDL_Flip", 1, 0, 0, gacela_SDL_Flip);
503   scm_c_define_gsubr ("SDL_Delay", 1, 0, 0, gacela_SDL_Delay);
504   scm_c_define_gsubr ("SDL_GetTicks", 0, 0, 0, gacela_SDL_GetTicks);
505   scm_c_define_gsubr ("SDL_DisplayFormat", 1, 0, 0, gacela_SDL_DisplayFormat);
506   scm_c_define_gsubr ("SDL_DisplayFormatAlpha", 1, 0, 0, gacela_SDL_DisplayFormatAlpha);
507   scm_c_define_gsubr ("SDL_MapRGB", 4, 0, 0, gacela_SDL_MapRGB);
508   scm_c_define_gsubr ("SDL_SetColorKey", 3, 0, 0, gacela_SDL_SetColorKey);
509   scm_c_define_gsubr ("SDL_SetAlpha", 3, 0, 0, gacela_SDL_SetAlpha);
510   scm_c_define_gsubr ("SDL_LoadBMP", 1, 0, 0, gacela_SDL_LoadBMP);
511   scm_c_define_gsubr ("IMG_Load", 1, 0, 0, gacela_IMG_Load);
512   scm_c_define_gsubr ("SDL_GetVideoInfo", 0, 0, 0, gacela_SDL_GetVideoInfo);
513   scm_c_define_gsubr ("SDL_GL_SetAttribute", 2, 0, 0, gacela_SDL_GL_SetAttribute);
514   scm_c_define_gsubr ("SDL_PollEvent", 0, 0, 0, gacela_SDL_PollEvent);
515   scm_c_define_gsubr ("SDL_GL_SwapBuffers", 0, 0, 0, gacela_SDL_GL_SwapBuffers);
516   scm_c_define_gsubr ("SDL_EnableKeyRepeat", 2, 0, 0, gacela_SDL_EnableKeyRepeat);
517   scm_c_define_gsubr ("zoomSurface", 4, 0, 0, gacela_zoomSurface);
518   scm_c_define_gsubr ("Mix_OpenAudio", 4, 0, 0, gacela_Mix_OpenAudio);
519   scm_c_define_gsubr ("Mix_LoadMUS", 1, 0, 0, gacela_Mix_LoadMUS);
520   scm_c_define_gsubr ("Mix_LoadWAV", 1, 0, 0, gacela_Mix_LoadWAV);
521   scm_c_define_gsubr ("Mix_PlayChannel", 3, 0, 0, gacela_Mix_PlayChannel);
522   scm_c_define_gsubr ("Mix_PlayMusic", 2, 0, 0, gacela_Mix_PlayMusic);
523   scm_c_define_gsubr ("Mix_PlayingMusic", 0, 0, 0, gacela_Mix_PlayingMusic);
524   scm_c_define_gsubr ("Mix_PausedMusic", 0, 0, 0, gacela_Mix_PausedMusic);
525   scm_c_define_gsubr ("Mix_PauseMusic", 0, 0, 0, gacela_Mix_PauseMusic);
526   scm_c_define_gsubr ("Mix_ResumeMusic", 0, 0, 0, gacela_Mix_ResumeMusic);
527   scm_c_define_gsubr ("Mix_HaltMusic", 0, 0, 0, gacela_Mix_HaltMusic);
528   scm_c_define_gsubr ("Mix_FreeMusic", 1, 0, 0, gacela_Mix_FreeMusic);
529   scm_c_define_gsubr ("Mix_FreeChunk", 1, 0, 0, gacela_Mix_FreeChunk);
530   scm_c_define_gsubr ("Mix_CloseAudio", 0, 0, 0, gacela_Mix_CloseAudio);
531 }
532
533 void
534 gacela_sdl_init ()
535 {
536   scm_c_define_module ("gacela sdl", init_gacela_sdl, NULL);
537 }