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