rnd-20001202-1-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 "libgame.h"
16
17
18 /* ========================================================================= */
19 /* internal variables                                                        */
20 /* ========================================================================= */
21
22 Display        *display;
23 Visual         *visual;
24 int             screen;
25 Colormap        cmap;
26
27 DrawWindow      window = None;
28 GC              gc;
29
30 int             FrameCounter;
31
32
33 /* ========================================================================= */
34 /* exported variables                                                        */
35 /* ========================================================================= */
36
37 struct ProgramInfo      program;
38 struct VideoSystemInfo  video;
39 struct AudioSystemInfo  audio;
40 struct OptionInfo       options;
41
42
43 /* ========================================================================= */
44 /* video functions                                                           */
45 /* ========================================================================= */
46
47 inline static int GetRealDepth(int depth)
48 {
49   return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
50 }
51
52 inline void InitProgramInfo(char *command_name, char *program_title,
53                             char *window_title, char *icon_title,
54                             char *x11_icon_filename,
55                             char *x11_iconmask_filename)
56 {
57   program.command_name = command_name;
58   program.program_title = program_title;
59   program.window_title = window_title;
60   program.icon_title = icon_title;
61   program.x11_icon_filename = x11_icon_filename;
62   program.x11_iconmask_filename = x11_iconmask_filename;
63 }
64
65 inline void InitVideoDisplay(void)
66 {
67 #ifdef TARGET_SDL
68   SDLInitVideoDisplay();
69 #else
70   X11InitVideoDisplay();
71 #endif
72 }
73
74 inline void InitVideoBuffer(DrawBuffer *backbuffer, DrawWindow *window,
75                             int width, int height, int depth,
76                             boolean fullscreen)
77 {
78   video.width = width;
79   video.height = height;
80   video.depth = GetRealDepth(depth);
81   video.fullscreen_available = FULLSCREEN_STATUS;
82   video.fullscreen_enabled = FALSE;
83
84 #ifdef TARGET_SDL
85   SDLInitVideoBuffer(backbuffer, window, fullscreen);
86 #else
87   X11InitVideoBuffer(backbuffer, window);
88 #endif
89 }
90
91 inline Bitmap CreateBitmap(int width, int height, int depth)
92 {
93   int real_depth = GetRealDepth(depth);
94
95 #ifdef TARGET_SDL
96   SDL_Surface *surface_tmp, *surface_native;
97
98   if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height,
99                                           real_depth, 0, 0, 0, 0))
100       == NULL)
101     Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
102
103   if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
104     Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
105
106   SDL_FreeSurface(surface_tmp);
107
108   return surface_native;
109 #else
110   Pixmap pixmap;
111
112   if (!(pixmap = XCreatePixmap(display, window, width, height, real_depth)))
113     Error(ERR_EXIT, "cannot create pixmap");
114
115   return pixmap;
116 #endif
117 }
118
119 inline void FreeBitmap(Bitmap bitmap)
120 {
121 #ifdef TARGET_SDL
122   SDL_FreeSurface(bitmap);
123 #else
124   XFreePixmap(display, bitmap);
125 #endif
126 }
127
128 inline void ClearRectangle(Bitmap bitmap, int x, int y, int width, int height)
129 {
130 #ifdef TARGET_SDL
131   SDLFillRectangle(bitmap, x, y, width, height, 0x000000);
132 #else
133   XFillRectangle(display, bitmap, gc, x, y, width, height);
134 #endif
135 }
136
137 inline void BlitBitmap(Bitmap src_bitmap, Bitmap dst_bitmap,
138                        int src_x, int src_y,
139                        int width, int height,
140                        int dst_x, int dst_y)
141 {
142 #ifdef TARGET_SDL
143   SDLCopyArea(src_bitmap, dst_bitmap,
144               src_x, src_y, width, height, dst_x, dst_y);
145 #else
146   XCopyArea(display, src_bitmap, dst_bitmap, gc,
147             src_x, src_y, width, height, dst_x, dst_y);
148 #endif
149 }
150
151 #ifndef TARGET_SDL
152 static GC last_clip_gc = 0;     /* needed for XCopyArea() through clip mask */
153 #endif
154
155 inline void SetClipMask(GC clip_gc, Pixmap clip_pixmap)
156 {
157 #ifndef TARGET_SDL
158   XSetClipMask(display, clip_gc, clip_pixmap);
159   last_clip_gc = clip_gc;
160 #endif
161 }
162
163 inline void SetClipOrigin(GC clip_gc, int clip_x, int clip_y)
164 {
165 #ifndef TARGET_SDL
166   XSetClipOrigin(display, clip_gc, clip_x, clip_y);
167   last_clip_gc = clip_gc;
168 #endif
169 }
170
171 inline void BlitBitmapMasked(Bitmap src_bitmap, Bitmap dst_bitmap,
172                              int src_x, int src_y,
173                              int width, int height,
174                              int dst_x, int dst_y)
175 {
176 #ifdef TARGET_SDL
177   SDLCopyArea(src_bitmap, dst_bitmap,
178               src_x, src_y, width, height, dst_x, dst_y);
179 #else
180   XCopyArea(display, src_bitmap, dst_bitmap, last_clip_gc,
181             src_x, src_y, width, height, dst_x, dst_y);
182 #endif
183 }
184
185 inline void DrawSimpleWhiteLine(Bitmap bitmap, int from_x, int from_y,
186                                 int to_x, int to_y)
187 {
188 #ifdef TARGET_SDL
189   SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, 0xffffff);
190 #else
191   XSetForeground(display, gc, WhitePixel(display, screen));
192   XDrawLine(display, bitmap, gc, from_x, from_y, to_x, to_y);
193   XSetForeground(display, gc, BlackPixel(display, screen));
194 #endif
195 }
196
197 /* execute all pending screen drawing operations */
198 inline void FlushDisplay(void)
199 {
200 #ifndef TARGET_SDL
201   XFlush(display);
202 #endif
203 }
204
205 /* execute and wait for all pending screen drawing operations */
206 inline void SyncDisplay(void)
207 {
208 #ifndef TARGET_SDL
209   XSync(display, FALSE);
210 #endif
211 }
212
213 inline void KeyboardAutoRepeatOn(void)
214 {
215 #ifdef TARGET_SDL
216   SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
217                       SDL_DEFAULT_REPEAT_INTERVAL / 2);
218   SDL_EnableUNICODE(1);
219 #else
220   XAutoRepeatOn(display);
221 #endif
222 }
223
224 inline void KeyboardAutoRepeatOff(void)
225 {
226 #ifdef TARGET_SDL
227   SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
228   SDL_EnableUNICODE(0);
229 #else
230   XAutoRepeatOff(display);
231 #endif
232 }
233
234 inline boolean PointerInWindow(DrawWindow window)
235 {
236 #ifdef TARGET_SDL
237   return TRUE;
238 #else
239   DrawWindow root, child;
240   int root_x, root_y;
241   unsigned int mask;
242   int win_x, win_y;
243
244   /* if XQueryPointer() returns False, the pointer
245      is not on the same screen as the specified window */
246   return XQueryPointer(display, window, &root, &child, &root_x, &root_y,
247                        &win_x, &win_y, &mask);
248 #endif
249 }
250
251 inline boolean SetVideoMode(boolean fullscreen)
252 {
253 #ifdef TARGET_SDL
254   return SDLSetVideoMode(&backbuffer, fullscreen);
255 #else
256   boolean success = TRUE;
257
258   if (fullscreen && video.fullscreen_available)
259   {
260     Error(ERR_WARN, "fullscreen not available in X11 version");
261
262     /* display error message only once */
263     video.fullscreen_available = FALSE;
264
265     success = FALSE;
266   }
267
268   return success;
269 #endif
270 }
271
272 inline boolean ChangeVideoModeIfNeeded(boolean fullscreen)
273 {
274 #ifdef TARGET_SDL
275   if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
276       (!fullscreen && video.fullscreen_enabled))
277     fullscreen = SetVideoMode(fullscreen_wanted);
278 #endif
279
280   return fullscreen;
281 }
282
283
284 /* ========================================================================= */
285 /* audio functions                                                           */
286 /* ========================================================================= */
287
288 inline boolean OpenAudio(struct AudioSystemInfo *audio)
289 {
290   audio->sound_available = FALSE;
291   audio->loops_available = FALSE;
292   audio->soundserver_pipe[0] = audio->soundserver_pipe[1] = 0;
293   audio->soundserver_pid = 0;
294   audio->device_name = NULL;
295   audio->device_fd = 0;
296
297 #if defined(TARGET_SDL)
298   if (SDLOpenAudio())
299   {
300     audio->sound_available = TRUE;
301     audio->loops_available = TRUE;
302   }
303 #elif defined(PLATFORM_MSDOS)
304   if (MSDOSOpenAudio())
305   {
306     audio->sound_available = TRUE;
307     audio->loops_available = TRUE;
308   }
309 #elif defined(PLATFORM_UNIX)
310   UnixOpenAudio(audio);
311 #endif
312
313   return audio->sound_available;
314 }
315
316 inline void CloseAudio(struct AudioSystemInfo *audio)
317 {
318 #if defined(TARGET_SDL)
319   SDLCloseAudio();
320 #elif defined(PLATFORM_MSDOS)
321   MSDOSCloseAudio();
322 #elif defined(PLATFORM_UNIX)
323   UnixCloseAudio(audio);
324 #endif
325
326   audio->sound_available = FALSE;
327   audio->loops_available = FALSE;
328 }
329
330
331 /* ========================================================================= */
332 /* event functions                                                           */
333 /* ========================================================================= */
334
335 inline void InitEventFilter(EventFilter filter_function)
336 {
337 #ifdef TARGET_SDL
338   /* set event filter to filter out certain events */
339   SDL_SetEventFilter(filter_function);
340 #endif
341 }
342
343 inline boolean PendingEvent(void)
344 {
345 #ifdef TARGET_SDL
346   return (SDL_PollEvent(NULL) ? TRUE : FALSE);
347 #else
348   return (XPending(display) ? TRUE : FALSE);
349 #endif
350 }
351
352 inline void NextEvent(Event *event)
353 {
354 #ifdef TARGET_SDL
355   SDL_WaitEvent(event);
356 #else
357   XNextEvent(display, event);
358 #endif
359 }
360
361 inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
362 {
363 #ifdef TARGET_SDL
364 #if 0
365   printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
366          (int)event->keysym.unicode,
367          (int)event->keysym.sym,
368          (int)SDL_GetModState());
369 #endif
370
371   if (with_modifiers && event->keysym.unicode != 0)
372     return event->keysym.unicode;
373   else
374     return event->keysym.sym;
375 #else
376 #if 0
377   printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
378          (int)XLookupKeysym(event, event->state),
379          (int)XLookupKeysym(event, 0));
380 #endif
381
382   if (with_modifiers)
383     return XLookupKeysym(event, event->state);
384   else
385     return XLookupKeysym(event, 0);
386 #endif
387 }
388
389 inline boolean CheckCloseWindowEvent(ClientMessageEvent *event)
390 {
391   if (event->type != EVENT_CLIENTMESSAGE)
392     return FALSE;
393
394 #if defined(TARGET_SDL)
395   return TRUE;          /* the only possible message here is SDL_QUIT */
396 #elif defined(PLATFORM_UNIX)
397   if ((event->window == window) &&
398       (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
399     return TRUE;
400 #endif
401
402   return FALSE;
403 }
404
405
406 inline void dummy(void)
407 {
408 #ifdef TARGET_SDL
409 #else
410 #endif
411 }