rnd-20001203-4-src
[rocksndiamonds.git] / src / libgame / system.c
1 /***********************************************************
2 *  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
3 *----------------------------------------------------------*
4 *  ©1995 Artsoft Development                               *
5 *        Holger Schemel                                    *
6 *        33659 Bielefeld-Senne                             *
7 *        Telefon: (0521) 493245                            *
8 *        eMail: aeglos@valinor.owl.de                      *
9 *               aeglos@uni-paderborn.de                    *
10 *               q99492@pbhrzx.uni-paderborn.de             *
11 *----------------------------------------------------------*
12 *  system.c                                                *
13 ***********************************************************/
14
15 #include <string.h>
16
17 #include "platform.h"
18
19 #if defined(PLATFORM_MSDOS)
20 #include <fcntl.h>
21 #endif
22
23 #include "libgame.h"
24
25 #if 0
26 /* ========================================================================= */
27 /* exported variables                                                        */
28 /* ========================================================================= */
29
30 struct ProgramInfo      program;
31 struct OptionInfo       options;
32 struct VideoSystemInfo  video;
33 struct AudioSystemInfo  audio;
34 struct GfxInfo          gfx;
35
36 Display        *display = NULL;
37 Visual         *visual = NULL;
38 int             screen = 0;
39 Colormap        cmap = None;
40
41 DrawWindow      window = NULL;
42 DrawBuffer      backbuffer = NULL;
43 DrawBuffer      drawto = NULL;
44
45 int             button_status = MB_NOT_PRESSED;
46 boolean         motion_status = FALSE;
47
48 int             redraw_mask = REDRAW_NONE;
49 int             redraw_tiles = 0;
50
51 int             FrameCounter = 0;
52
53 #endif
54
55 /* ========================================================================= */
56 /* init functions                                                            */
57 /* ========================================================================= */
58
59 void InitCommandName(char *argv0)
60 {
61   program.command_basename =
62     (strrchr(argv0, '/') ? strrchr(argv0, '/') + 1 : argv0);
63 }
64
65 void InitExitFunction(void (*exit_function)(int))
66 {
67   program.exit_function = exit_function;
68 }
69
70 void InitPlatformDependantStuff(void)
71 {
72 #if defined(PLATFORM_MSDOS)
73   _fmode = O_BINARY;
74 #endif
75 }
76
77 void InitProgramInfo(char *unix_userdata_directory, char *program_title,
78                      char *window_title, char *icon_title,
79                      char *x11_icon_basename, char *x11_iconmask_basename,
80                      char *msdos_pointer_basename)
81 {
82   char *gfx_dir = getPath2(options.ro_base_directory, GRAPHICS_DIRECTORY);
83   char *x11_icon_filename = getPath2(gfx_dir, x11_icon_basename);
84   char *x11_iconmask_filename = getPath2(gfx_dir, x11_iconmask_basename);
85   char *msdos_pointer_filename = getPath2(gfx_dir, msdos_pointer_basename);
86
87   free(gfx_dir);
88
89 #if defined(PLATFORM_UNIX)
90   program.userdata_directory = unix_userdata_directory;
91 #else
92   program.userdata_directory = "userdata";
93 #endif
94
95   program.program_title = program_title;
96   program.window_title = window_title;
97   program.icon_title = icon_title;
98   program.x11_icon_filename = x11_icon_filename;
99   program.x11_iconmask_filename = x11_iconmask_filename;
100   program.msdos_pointer_filename = msdos_pointer_filename;
101 }
102
103 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
104                       int real_sx, int real_sy,
105                       int full_sxsize, int full_sysize)
106 {
107   gfx.sx = sx;
108   gfx.sy = sy;
109   gfx.sxsize = sxsize;
110   gfx.sysize = sysize;
111   gfx.real_sx = real_sx;
112   gfx.real_sy = real_sy;
113   gfx.full_sxsize = full_sxsize;
114   gfx.full_sysize = full_sysize;
115 }
116
117 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
118 {
119   gfx.dx = dx;
120   gfx.dy = dy;
121   gfx.dxsize = dxsize;
122   gfx.dysize = dysize;
123 }
124
125 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
126 {
127   gfx.vx = vx;
128   gfx.vy = vy;
129   gfx.vxsize = vxsize;
130   gfx.vysize = vysize;
131 }
132
133 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
134 {
135   /* currently only used by MSDOS code to alloc VRAM buffer, if available */
136   gfx.scrollbuffer_width = scrollbuffer_width;
137   gfx.scrollbuffer_height = scrollbuffer_height;
138 }
139
140
141 /* ========================================================================= */
142 /* video functions                                                           */
143 /* ========================================================================= */
144
145 inline static int GetRealDepth(int depth)
146 {
147   return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
148 }
149
150 inline void InitVideoDisplay(void)
151 {
152 #ifdef TARGET_SDL
153   SDLInitVideoDisplay();
154 #else
155   X11InitVideoDisplay();
156 #endif
157 }
158
159 inline void InitVideoBuffer(DrawBuffer *backbuffer, DrawWindow *window,
160                             int width, int height, int depth,
161                             boolean fullscreen)
162 {
163   video.width = width;
164   video.height = height;
165   video.depth = GetRealDepth(depth);
166   video.fullscreen_available = FULLSCREEN_STATUS;
167   video.fullscreen_enabled = FALSE;
168
169 #ifdef TARGET_SDL
170   SDLInitVideoBuffer(backbuffer, window, fullscreen);
171 #else
172   X11InitVideoBuffer(backbuffer, window);
173 #endif
174 }
175
176 inline Bitmap CreateBitmapStruct(void)
177 {
178 #ifdef TARGET_SDL
179   return checked_calloc(sizeof(struct SDLSurfaceInfo));
180 #else
181   return checked_calloc(sizeof(struct X11DrawableInfo));
182 #endif
183 }
184
185 inline Bitmap CreateBitmap(int width, int height, int depth)
186 {
187   Bitmap new_bitmap = CreateBitmapStruct();
188   int real_depth = GetRealDepth(depth);
189
190 #ifdef TARGET_SDL
191   SDL_Surface *surface_tmp, *surface_native;
192
193   if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height,
194                                           real_depth, 0, 0, 0, 0))
195       == NULL)
196     Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
197
198   if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
199     Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
200
201   SDL_FreeSurface(surface_tmp);
202
203   new_bitmap->surface = surface_native;
204 #else
205   Pixmap pixmap;
206
207   if (!(pixmap = XCreatePixmap(display, window->drawable,
208                                width, height, real_depth)))
209     Error(ERR_EXIT, "cannot create pixmap");
210   new_bitmap->drawable = pixmap;
211
212   if (window == NULL)
213     Error(ERR_EXIT, "Window GC needed for Bitmap -- create Window first");
214   new_bitmap->gc = window->gc;
215
216 #endif
217
218   return new_bitmap;
219 }
220
221 inline void FreeBitmap(Bitmap bitmap)
222 {
223   if (bitmap == NULL)
224     return;
225
226 #ifdef TARGET_SDL
227   if (bitmap->surface)
228     SDL_FreeSurface(bitmap->surface);
229   if (bitmap->surface_masked)
230     SDL_FreeSurface(bitmap->surface_masked);
231 #else
232   if (bitmap->drawable)
233     XFreePixmap(display, bitmap->drawable);
234   if (bitmap->clip_mask)
235     XFreePixmap(display, bitmap->clip_mask);
236   if (bitmap->stored_clip_gc)
237     XFreeGC(display, bitmap->stored_clip_gc);
238 #endif
239
240   free(bitmap);
241 }
242
243 inline void CloseWindow(DrawWindow window)
244 {
245 #ifdef TARGET_X11
246   if (window->drawable)
247   {
248     XUnmapWindow(display, window->drawable);
249     XDestroyWindow(display, window->drawable);
250   }
251   if (window->gc)
252     XFreeGC(display, window->gc);
253 #endif
254 }
255
256 inline void BlitBitmap(Bitmap src_bitmap, Bitmap dst_bitmap,
257                        int src_x, int src_y,
258                        int width, int height,
259                        int dst_x, int dst_y)
260 {
261 #ifdef TARGET_SDL
262   SDLCopyArea(src_bitmap, dst_bitmap,
263               src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_OPAQUE);
264 #else
265   XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
266             dst_bitmap->gc, src_x, src_y, width, height, dst_x, dst_y);
267 #endif
268 }
269
270 inline void ClearRectangle(Bitmap bitmap, int x, int y, int width, int height)
271 {
272 #ifdef TARGET_SDL
273   SDLFillRectangle(bitmap, x, y, width, height, 0x000000);
274 #else
275   XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height);
276 #endif
277 }
278
279 #if 0
280 #ifndef TARGET_SDL
281 static GC last_clip_gc = 0;     /* needed for XCopyArea() through clip mask */
282 #endif
283 #endif
284
285 inline void SetClipMask(Bitmap bitmap, GC clip_gc, Pixmap clip_pixmap)
286 {
287 #ifdef TARGET_X11
288   if (clip_gc)
289   {
290     bitmap->clip_gc = clip_gc;
291     XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
292   }
293 #if 0
294   last_clip_gc = clip_gc;
295 #endif
296 #endif
297 }
298
299 inline void SetClipOrigin(Bitmap bitmap, GC clip_gc, int clip_x, int clip_y)
300 {
301 #ifdef TARGET_X11
302   if (clip_gc)
303   {
304     bitmap->clip_gc = clip_gc;
305     XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
306   }
307 #if 0
308   last_clip_gc = clip_gc;
309 #endif
310 #endif
311 }
312
313 inline void BlitBitmapMasked(Bitmap src_bitmap, Bitmap dst_bitmap,
314                              int src_x, int src_y,
315                              int width, int height,
316                              int dst_x, int dst_y)
317 {
318 #ifdef TARGET_SDL
319   SDLCopyArea(src_bitmap, dst_bitmap,
320               src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_MASKED);
321 #else
322   XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
323             src_bitmap->clip_gc, src_x, src_y, width, height, dst_x, dst_y);
324 #endif
325 }
326
327 inline void DrawSimpleWhiteLine(Bitmap bitmap, int from_x, int from_y,
328                                 int to_x, int to_y)
329 {
330 #ifdef TARGET_SDL
331   SDLDrawSimpleLine(bitmap->surface, from_x, from_y, to_x, to_y, 0xffffff);
332 #else
333   XSetForeground(display, bitmap->gc, WhitePixel(display, screen));
334   XDrawLine(display, bitmap->drawable, bitmap->gc, from_x, from_y, to_x, to_y);
335   XSetForeground(display, bitmap->gc, BlackPixel(display, screen));
336 #endif
337 }
338
339 /* execute all pending screen drawing operations */
340 inline void FlushDisplay(void)
341 {
342 #ifndef TARGET_SDL
343   XFlush(display);
344 #endif
345 }
346
347 /* execute and wait for all pending screen drawing operations */
348 inline void SyncDisplay(void)
349 {
350 #ifndef TARGET_SDL
351   XSync(display, FALSE);
352 #endif
353 }
354
355 inline void KeyboardAutoRepeatOn(void)
356 {
357 #ifdef TARGET_SDL
358   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
359                       SDL_DEFAULT_REPEAT_INTERVAL / 2);
360   SDL_EnableUNICODE(1);
361 #else
362   XAutoRepeatOn(display);
363 #endif
364 }
365
366 inline void KeyboardAutoRepeatOff(void)
367 {
368 #ifdef TARGET_SDL
369   SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
370   SDL_EnableUNICODE(0);
371 #else
372   XAutoRepeatOff(display);
373 #endif
374 }
375
376 inline boolean PointerInWindow(DrawWindow window)
377 {
378 #ifdef TARGET_SDL
379   return TRUE;
380 #else
381   Window root, child;
382   int root_x, root_y;
383   unsigned int mask;
384   int win_x, win_y;
385
386   /* if XQueryPointer() returns False, the pointer
387      is not on the same screen as the specified window */
388   return XQueryPointer(display, window->drawable, &root, &child,
389                        &root_x, &root_y, &win_x, &win_y, &mask);
390 #endif
391 }
392
393 inline boolean SetVideoMode(boolean fullscreen)
394 {
395 #ifdef TARGET_SDL
396   return SDLSetVideoMode(&backbuffer, fullscreen);
397 #else
398   boolean success = TRUE;
399
400   if (fullscreen && video.fullscreen_available)
401   {
402     Error(ERR_WARN, "fullscreen not available in X11 version");
403
404     /* display error message only once */
405     video.fullscreen_available = FALSE;
406
407     success = FALSE;
408   }
409
410   return success;
411 #endif
412 }
413
414 inline boolean ChangeVideoModeIfNeeded(boolean fullscreen)
415 {
416 #ifdef TARGET_SDL
417   if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
418       (!fullscreen && video.fullscreen_enabled))
419     fullscreen = SetVideoMode(fullscreen);
420 #endif
421
422   return fullscreen;
423 }
424
425
426 /* ========================================================================= */
427 /* audio functions                                                           */
428 /* ========================================================================= */
429
430 inline boolean OpenAudio(struct AudioSystemInfo *audio)
431 {
432   audio->sound_available = FALSE;
433   audio->loops_available = FALSE;
434   audio->soundserver_pipe[0] = audio->soundserver_pipe[1] = 0;
435   audio->soundserver_pid = 0;
436   audio->device_name = NULL;
437   audio->device_fd = 0;
438
439 #if defined(TARGET_SDL)
440   if (SDLOpenAudio())
441   {
442     audio->sound_available = TRUE;
443     audio->loops_available = TRUE;
444   }
445 #elif defined(PLATFORM_MSDOS)
446   if (MSDOSOpenAudio())
447   {
448     audio->sound_available = TRUE;
449     audio->loops_available = TRUE;
450   }
451 #elif defined(PLATFORM_UNIX)
452   UnixOpenAudio(audio);
453 #endif
454
455   return audio->sound_available;
456 }
457
458 inline void CloseAudio(struct AudioSystemInfo *audio)
459 {
460 #if defined(TARGET_SDL)
461   SDLCloseAudio();
462 #elif defined(PLATFORM_MSDOS)
463   MSDOSCloseAudio();
464 #elif defined(PLATFORM_UNIX)
465   UnixCloseAudio(audio);
466 #endif
467
468   audio->sound_available = FALSE;
469   audio->loops_available = FALSE;
470 }
471
472
473 /* ========================================================================= */
474 /* event functions                                                           */
475 /* ========================================================================= */
476
477 inline void InitEventFilter(EventFilter filter_function)
478 {
479 #ifdef TARGET_SDL
480   /* set event filter to filter out certain events */
481   SDL_SetEventFilter(filter_function);
482 #endif
483 }
484
485 inline boolean PendingEvent(void)
486 {
487 #ifdef TARGET_SDL
488   return (SDL_PollEvent(NULL) ? TRUE : FALSE);
489 #else
490   return (XPending(display) ? TRUE : FALSE);
491 #endif
492 }
493
494 inline void NextEvent(Event *event)
495 {
496 #ifdef TARGET_SDL
497   SDL_WaitEvent(event);
498 #else
499   XNextEvent(display, event);
500 #endif
501 }
502
503 inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
504 {
505 #ifdef TARGET_SDL
506 #if 0
507   printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
508          (int)event->keysym.unicode,
509          (int)event->keysym.sym,
510          (int)SDL_GetModState());
511 #endif
512
513   if (with_modifiers && event->keysym.unicode != 0)
514     return event->keysym.unicode;
515   else
516     return event->keysym.sym;
517 #else
518 #if 0
519   printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
520          (int)XLookupKeysym(event, event->state),
521          (int)XLookupKeysym(event, 0));
522 #endif
523
524   if (with_modifiers)
525     return XLookupKeysym(event, event->state);
526   else
527     return XLookupKeysym(event, 0);
528 #endif
529 }
530
531 inline boolean CheckCloseWindowEvent(ClientMessageEvent *event)
532 {
533   if (event->type != EVENT_CLIENTMESSAGE)
534     return FALSE;
535
536 #if defined(TARGET_SDL)
537   return TRUE;          /* the only possible message here is SDL_QUIT */
538 #elif defined(PLATFORM_UNIX)
539   if ((event->window == window->drawable) &&
540       (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
541     return TRUE;
542 #endif
543
544   return FALSE;
545 }
546
547
548 inline void dummy(void)
549 {
550 #ifdef TARGET_SDL
551 #else
552 #endif
553 }