1 /***********************************************************
2 * Rocks'n'Diamonds -- McDuffin Strikes Back! *
3 *----------------------------------------------------------*
4 * ©1995 Artsoft Development *
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 *----------------------------------------------------------*
13 ***********************************************************/
18 /* ========================================================================= */
19 /* exported variables */
20 /* ========================================================================= */
22 struct ProgramInfo program;
23 struct OptionInfo options;
24 struct VideoSystemInfo video;
25 struct AudioSystemInfo audio;
26 struct PlayfieldInfo playfield;
28 Display *display = NULL;
29 Visual *visual = NULL;
33 DrawWindow window = NULL;
34 DrawBuffer backbuffer = NULL;
35 DrawBuffer drawto = NULL;
43 /* ========================================================================= */
45 /* ========================================================================= */
47 inline void InitProgramInfo(char *command_name, char *program_title,
48 char *window_title, char *icon_title,
49 char *x11_icon_filename,
50 char *x11_iconmask_filename,
51 char *msdos_pointer_filename)
53 program.command_name = command_name;
54 program.program_title = program_title;
55 program.window_title = window_title;
56 program.icon_title = icon_title;
57 program.x11_icon_filename = x11_icon_filename;
58 program.x11_iconmask_filename = x11_iconmask_filename;
59 program.msdos_pointer_filename = msdos_pointer_filename;
62 inline void InitPlayfieldInfo(int sx, int sy, int sxsize, int sysize,
63 int real_sx, int real_sy,
64 int full_sxsize, int full_sysize)
68 playfield.sxsize = sxsize;
69 playfield.sysize = sysize;
70 playfield.real_sx = real_sx;
71 playfield.real_sy = real_sy;
72 playfield.full_sxsize = full_sxsize;
73 playfield.full_sysize = full_sysize;
76 inline void InitDoor1Info(int dx, int dy, int dxsize, int dysize)
80 playfield.dxsize = dxsize;
81 playfield.dysize = dysize;
84 inline void InitDoor2Info(int vx, int vy, int vxsize, int vysize)
88 playfield.vxsize = vxsize;
89 playfield.vysize = vysize;
92 inline void InitScrollbufferInfo(int scrollbuffer_width,
93 int scrollbuffer_height)
95 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
96 playfield.scrollbuffer_width = scrollbuffer_width;
97 playfield.scrollbuffer_height = scrollbuffer_height;
100 inline static int GetRealDepth(int depth)
102 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
105 inline void InitVideoDisplay(void)
108 SDLInitVideoDisplay();
110 X11InitVideoDisplay();
114 inline void InitVideoBuffer(DrawBuffer *backbuffer, DrawWindow *window,
115 int width, int height, int depth,
119 video.height = height;
120 video.depth = GetRealDepth(depth);
121 video.fullscreen_available = FULLSCREEN_STATUS;
122 video.fullscreen_enabled = FALSE;
125 SDLInitVideoBuffer(backbuffer, window, fullscreen);
127 X11InitVideoBuffer(backbuffer, window);
131 inline Bitmap CreateBitmapStruct(void)
134 return checked_calloc(sizeof(struct SDLSurfaceInfo));
136 return checked_calloc(sizeof(struct X11DrawableInfo));
140 inline Bitmap CreateBitmap(int width, int height, int depth)
142 Bitmap new_bitmap = CreateBitmapStruct();
143 int real_depth = GetRealDepth(depth);
146 SDL_Surface *surface_tmp, *surface_native;
148 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height,
149 real_depth, 0, 0, 0, 0))
151 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
153 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
154 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
156 SDL_FreeSurface(surface_tmp);
158 new_bitmap->surface = surface_native;
162 if (!(pixmap = XCreatePixmap(display, window->drawable,
163 width, height, real_depth)))
164 Error(ERR_EXIT, "cannot create pixmap");
166 new_bitmap->drawable = pixmap;
170 Error(ERR_EXIT, "Window GC needed for Bitmap -- create Window first");
171 new_bitmap->gc = window->gc;
176 inline void FreeBitmap(Bitmap bitmap)
183 SDL_FreeSurface(bitmap->surface);
184 if (bitmap->surface_masked)
185 SDL_FreeSurface(bitmap->surface_masked);
187 if (bitmap->drawable)
188 XFreePixmap(display, bitmap->drawable);
189 if (bitmap->clip_mask)
190 XFreePixmap(display, bitmap->clip_mask);
191 if (bitmap->stored_clip_gc)
192 XFreeGC(display, bitmap->stored_clip_gc);
198 inline void CloseWindow(DrawWindow window)
201 if (window->drawable)
203 XUnmapWindow(display, window->drawable);
204 XDestroyWindow(display, window->drawable);
207 XFreeGC(display, window->gc);
211 inline void BlitBitmap(Bitmap src_bitmap, Bitmap dst_bitmap,
212 int src_x, int src_y,
213 int width, int height,
214 int dst_x, int dst_y)
217 SDLCopyArea(src_bitmap, dst_bitmap,
218 src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_OPAQUE);
220 XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
221 dst_bitmap->gc, src_x, src_y, width, height, dst_x, dst_y);
225 inline void ClearRectangle(Bitmap bitmap, int x, int y, int width, int height)
228 SDLFillRectangle(bitmap, x, y, width, height, 0x000000);
230 XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height);
236 static GC last_clip_gc = 0; /* needed for XCopyArea() through clip mask */
240 inline void SetClipMask(Bitmap bitmap, GC clip_gc, Pixmap clip_pixmap)
245 bitmap->clip_gc = clip_gc;
246 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
249 last_clip_gc = clip_gc;
254 inline void SetClipOrigin(Bitmap bitmap, GC clip_gc, int clip_x, int clip_y)
259 bitmap->clip_gc = clip_gc;
260 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
263 last_clip_gc = clip_gc;
268 inline void BlitBitmapMasked(Bitmap src_bitmap, Bitmap dst_bitmap,
269 int src_x, int src_y,
270 int width, int height,
271 int dst_x, int dst_y)
274 SDLCopyArea(src_bitmap, dst_bitmap,
275 src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_MASKED);
277 XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
278 src_bitmap->clip_gc, src_x, src_y, width, height, dst_x, dst_y);
282 inline void DrawSimpleWhiteLine(Bitmap bitmap, int from_x, int from_y,
286 SDLDrawSimpleLine(bitmap->drawable, from_x, from_y, to_x, to_y, 0xffffff);
288 XSetForeground(display, bitmap->gc, WhitePixel(display, screen));
289 XDrawLine(display, bitmap->drawable, bitmap->gc, from_x, from_y, to_x, to_y);
290 XSetForeground(display, bitmap->gc, BlackPixel(display, screen));
294 /* execute all pending screen drawing operations */
295 inline void FlushDisplay(void)
302 /* execute and wait for all pending screen drawing operations */
303 inline void SyncDisplay(void)
306 XSync(display, FALSE);
310 inline void KeyboardAutoRepeatOn(void)
313 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
314 SDL_DEFAULT_REPEAT_INTERVAL / 2);
315 SDL_EnableUNICODE(1);
317 XAutoRepeatOn(display);
321 inline void KeyboardAutoRepeatOff(void)
324 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
325 SDL_EnableUNICODE(0);
327 XAutoRepeatOff(display);
331 inline boolean PointerInWindow(DrawWindow window)
341 /* if XQueryPointer() returns False, the pointer
342 is not on the same screen as the specified window */
343 return XQueryPointer(display, window->drawable, &root, &child,
344 &root_x, &root_y, &win_x, &win_y, &mask);
348 inline boolean SetVideoMode(boolean fullscreen)
351 return SDLSetVideoMode(&backbuffer, fullscreen);
353 boolean success = TRUE;
355 if (fullscreen && video.fullscreen_available)
357 Error(ERR_WARN, "fullscreen not available in X11 version");
359 /* display error message only once */
360 video.fullscreen_available = FALSE;
369 inline boolean ChangeVideoModeIfNeeded(boolean fullscreen)
372 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
373 (!fullscreen && video.fullscreen_enabled))
374 fullscreen = SetVideoMode(fullscreen);
381 /* ========================================================================= */
382 /* audio functions */
383 /* ========================================================================= */
385 inline boolean OpenAudio(struct AudioSystemInfo *audio)
387 audio->sound_available = FALSE;
388 audio->loops_available = FALSE;
389 audio->soundserver_pipe[0] = audio->soundserver_pipe[1] = 0;
390 audio->soundserver_pid = 0;
391 audio->device_name = NULL;
392 audio->device_fd = 0;
394 #if defined(TARGET_SDL)
397 audio->sound_available = TRUE;
398 audio->loops_available = TRUE;
400 #elif defined(PLATFORM_MSDOS)
401 if (MSDOSOpenAudio())
403 audio->sound_available = TRUE;
404 audio->loops_available = TRUE;
406 #elif defined(PLATFORM_UNIX)
407 UnixOpenAudio(audio);
410 return audio->sound_available;
413 inline void CloseAudio(struct AudioSystemInfo *audio)
415 #if defined(TARGET_SDL)
417 #elif defined(PLATFORM_MSDOS)
419 #elif defined(PLATFORM_UNIX)
420 UnixCloseAudio(audio);
423 audio->sound_available = FALSE;
424 audio->loops_available = FALSE;
428 /* ========================================================================= */
429 /* event functions */
430 /* ========================================================================= */
432 inline void InitEventFilter(EventFilter filter_function)
435 /* set event filter to filter out certain events */
436 SDL_SetEventFilter(filter_function);
440 inline boolean PendingEvent(void)
443 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
445 return (XPending(display) ? TRUE : FALSE);
449 inline void NextEvent(Event *event)
452 SDL_WaitEvent(event);
454 XNextEvent(display, event);
458 inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
462 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
463 (int)event->keysym.unicode,
464 (int)event->keysym.sym,
465 (int)SDL_GetModState());
468 if (with_modifiers && event->keysym.unicode != 0)
469 return event->keysym.unicode;
471 return event->keysym.sym;
474 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
475 (int)XLookupKeysym(event, event->state),
476 (int)XLookupKeysym(event, 0));
480 return XLookupKeysym(event, event->state);
482 return XLookupKeysym(event, 0);
486 inline boolean CheckCloseWindowEvent(ClientMessageEvent *event)
488 if (event->type != EVENT_CLIENTMESSAGE)
491 #if defined(TARGET_SDL)
492 return TRUE; /* the only possible message here is SDL_QUIT */
493 #elif defined(PLATFORM_UNIX)
494 if ((event->window == window->drawable) &&
495 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
503 inline void dummy(void)