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