1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2000 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
19 #if defined(PLATFORM_MSDOS)
28 /* ========================================================================= */
29 /* exported variables */
30 /* ========================================================================= */
32 struct ProgramInfo program;
33 struct OptionInfo options;
34 struct VideoSystemInfo video;
35 struct AudioSystemInfo audio;
38 struct LevelDirInfo *leveldir_first = NULL;
39 struct LevelDirInfo *leveldir_current = NULL;
41 Display *display = NULL;
42 Visual *visual = NULL;
46 DrawWindow *window = NULL;
47 DrawBuffer *backbuffer = NULL;
48 DrawBuffer *drawto = NULL;
50 int button_status = MB_NOT_PRESSED;
51 boolean motion_status = FALSE;
53 int redraw_mask = REDRAW_NONE;
59 /* ========================================================================= */
60 /* init/close functions */
61 /* ========================================================================= */
63 void InitCommandName(char *argv0)
65 program.command_basename =
66 (strrchr(argv0, '/') ? strrchr(argv0, '/') + 1 : argv0);
69 void InitExitFunction(void (*exit_function)(int))
71 program.exit_function = exit_function;
73 /* set signal handlers to custom exit function */
74 signal(SIGINT, exit_function);
75 signal(SIGTERM, exit_function);
77 #if defined(TARGET_SDL)
78 /* set exit function to automatically cleanup SDL stuff after exit() */
83 void InitPlatformDependantStuff(void)
85 #if defined(PLATFORM_MSDOS)
89 #if !defined(PLATFORM_UNIX)
93 #if defined(TARGET_SDL)
94 if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
95 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
99 void ClosePlatformDependantStuff(void)
101 #if !defined(PLATFORM_UNIX)
106 void InitProgramInfo(char *unix_userdata_directory, char *program_title,
107 char *window_title, char *icon_title,
108 char *x11_icon_basename, char *x11_iconmask_basename,
109 char *msdos_pointer_basename)
111 char *gfx_dir = getPath2(options.ro_base_directory, GRAPHICS_DIRECTORY);
112 char *x11_icon_filename = getPath2(gfx_dir, x11_icon_basename);
113 char *x11_iconmask_filename = getPath2(gfx_dir, x11_iconmask_basename);
114 char *msdos_pointer_filename = getPath2(gfx_dir, msdos_pointer_basename);
118 #if defined(PLATFORM_UNIX)
119 program.userdata_directory = unix_userdata_directory;
121 program.userdata_directory = "userdata";
124 program.program_title = program_title;
125 program.window_title = window_title;
126 program.icon_title = icon_title;
127 program.x11_icon_filename = x11_icon_filename;
128 program.x11_iconmask_filename = x11_iconmask_filename;
129 program.msdos_pointer_filename = msdos_pointer_filename;
132 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
133 int real_sx, int real_sy,
134 int full_sxsize, int full_sysize)
140 gfx.real_sx = real_sx;
141 gfx.real_sy = real_sy;
142 gfx.full_sxsize = full_sxsize;
143 gfx.full_sysize = full_sysize;
146 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
154 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
162 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
164 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
165 gfx.scrollbuffer_width = scrollbuffer_width;
166 gfx.scrollbuffer_height = scrollbuffer_height;
170 /* ========================================================================= */
171 /* video functions */
172 /* ========================================================================= */
174 inline static int GetRealDepth(int depth)
176 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
179 inline void InitVideoDisplay(void)
182 SDLInitVideoDisplay();
184 X11InitVideoDisplay();
188 inline void CloseVideoDisplay(void)
190 #if defined(TARGET_X11)
192 XCloseDisplay(display);
196 inline void InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
197 int width, int height, int depth,
201 video.height = height;
202 video.depth = GetRealDepth(depth);
203 video.fullscreen_available = FULLSCREEN_STATUS;
204 video.fullscreen_enabled = FALSE;
207 SDLInitVideoBuffer(backbuffer, window, fullscreen);
209 X11InitVideoBuffer(backbuffer, window);
213 inline Bitmap *CreateBitmapStruct(void)
216 return checked_calloc(sizeof(struct SDLSurfaceInfo));
218 return checked_calloc(sizeof(struct X11DrawableInfo));
222 inline Bitmap *CreateBitmap(int width, int height, int depth)
224 Bitmap *new_bitmap = CreateBitmapStruct();
225 int real_depth = GetRealDepth(depth);
228 SDL_Surface *surface_tmp, *surface_native;
230 if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height,
231 real_depth, 0, 0, 0, 0))
233 Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
235 if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
236 Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
238 SDL_FreeSurface(surface_tmp);
240 new_bitmap->surface = surface_native;
244 if ((pixmap = XCreatePixmap(display, window->drawable,
245 width, height, real_depth))
247 Error(ERR_EXIT, "cannot create pixmap");
249 new_bitmap->drawable = pixmap;
252 Error(ERR_EXIT, "Window GC needed for Bitmap -- create Window first");
254 new_bitmap->gc = window->gc;
256 new_bitmap->line_gc[0] = window->line_gc[0];
257 new_bitmap->line_gc[1] = window->line_gc[1];
263 inline void FreeBitmap(Bitmap *bitmap)
270 SDL_FreeSurface(bitmap->surface);
271 if (bitmap->surface_masked)
272 SDL_FreeSurface(bitmap->surface_masked);
274 if (bitmap->drawable)
275 XFreePixmap(display, bitmap->drawable);
276 if (bitmap->clip_mask)
277 XFreePixmap(display, bitmap->clip_mask);
278 if (bitmap->stored_clip_gc)
279 XFreeGC(display, bitmap->stored_clip_gc);
285 inline void CloseWindow(DrawWindow *window)
288 if (window->drawable)
290 XUnmapWindow(display, window->drawable);
291 XDestroyWindow(display, window->drawable);
294 XFreeGC(display, window->gc);
298 inline void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
299 int src_x, int src_y,
300 int width, int height,
301 int dst_x, int dst_y)
304 SDLCopyArea(src_bitmap, dst_bitmap,
305 src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_OPAQUE);
307 XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
308 dst_bitmap->gc, src_x, src_y, width, height, dst_x, dst_y);
312 inline void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
315 SDLFillRectangle(bitmap, x, y, width, height, 0x000000);
317 XFillRectangle(display, bitmap->drawable, bitmap->gc, x, y, width, height);
323 static GC last_clip_gc = 0; /* needed for XCopyArea() through clip mask */
327 inline void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
332 bitmap->clip_gc = clip_gc;
333 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
336 last_clip_gc = clip_gc;
341 inline void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
346 bitmap->clip_gc = clip_gc;
347 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
350 last_clip_gc = clip_gc;
355 inline void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
356 int src_x, int src_y,
357 int width, int height,
358 int dst_x, int dst_y)
361 SDLCopyArea(src_bitmap, dst_bitmap,
362 src_x, src_y, width, height, dst_x, dst_y, SDLCOPYAREA_MASKED);
364 XCopyArea(display, src_bitmap->drawable, dst_bitmap->drawable,
365 src_bitmap->clip_gc, src_x, src_y, width, height, dst_x, dst_y);
369 inline void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
373 SDLDrawSimpleLine(bitmap->surface, from_x, from_y, to_x, to_y, 0xffffff);
375 XSetForeground(display, bitmap->gc, WhitePixel(display, screen));
376 XDrawLine(display, bitmap->drawable, bitmap->gc, from_x, from_y, to_x, to_y);
377 XSetForeground(display, bitmap->gc, BlackPixel(display, screen));
381 #if !defined(TARGET_X11_NATIVE)
382 inline void DrawLine(Bitmap *bitmap, int from_x, int from_y,
383 int to_x, int to_y, Pixel pixel, int line_width)
387 for (x=0; x<line_width; x++)
389 for (y=0; y<line_width; y++)
391 int dx = x - line_width / 2;
392 int dy = y - line_width / 2;
394 if ((x == 0 && y == 0) ||
395 (x == 0 && y == line_width - 1) ||
396 (x == line_width - 1 && y == 0) ||
397 (x == line_width - 1 && y == line_width - 1))
400 #if defined(TARGET_SDL)
401 sge_Line(bitmap->surface,
402 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
403 #elif defined(TARGET_ALLEGRO)
404 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
405 to_x + dx, to_y + dy, pixel);
412 inline void DrawLines(Bitmap *bitmap, struct XY *points, int num_points,
415 #if !defined(TARGET_X11_NATIVE)
419 for (i=0; i<num_points - 1; i++)
420 DrawLine(bitmap, points[i].x, points[i].y,
421 points[i + 1].x, points[i + 1].y, pixel, line_width);
424 SDLDrawLines(bitmap->surface, points, num_points, pixel);
427 XSetForeground(display, bitmap->line_gc[1], pixel);
428 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
429 (XPoint *)points, num_points, CoordModeOrigin);
431 XSetForeground(display, gc, BlackPixel(display, screen));
436 inline Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
437 unsigned int color_g, unsigned int color_b)
441 #if defined(TARGET_SDL)
442 pixel = SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
443 #elif defined(TARGET_X11_NATIVE)
446 xcolor.flags = DoRed | DoGreen | DoBlue;
447 xcolor.red = (color_r << 8);
448 xcolor.green = (color_g << 8);
449 xcolor.blue = (color_b << 8);
450 XAllocColor(display, cmap, &xcolor);
451 pixel = xcolor.pixel;
457 inline Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
459 unsigned int color_r = (color >> 16) & 0xff;
460 unsigned int color_g = (color >> 8) & 0xff;
461 unsigned int color_b = (color >> 0) & 0xff;
463 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
466 /* execute all pending screen drawing operations */
467 inline void FlushDisplay(void)
474 /* execute and wait for all pending screen drawing operations */
475 inline void SyncDisplay(void)
478 XSync(display, FALSE);
482 inline void KeyboardAutoRepeatOn(void)
485 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
486 SDL_DEFAULT_REPEAT_INTERVAL / 2);
487 SDL_EnableUNICODE(1);
490 XAutoRepeatOn(display);
494 inline void KeyboardAutoRepeatOff(void)
497 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
498 SDL_EnableUNICODE(0);
501 XAutoRepeatOff(display);
505 inline boolean PointerInWindow(DrawWindow *window)
515 /* if XQueryPointer() returns False, the pointer
516 is not on the same screen as the specified window */
517 return XQueryPointer(display, window->drawable, &root, &child,
518 &root_x, &root_y, &win_x, &win_y, &mask);
522 inline boolean SetVideoMode(boolean fullscreen)
525 return SDLSetVideoMode(&backbuffer, fullscreen);
527 boolean success = TRUE;
529 if (fullscreen && video.fullscreen_available)
531 Error(ERR_WARN, "fullscreen not available in X11 version");
533 /* display error message only once */
534 video.fullscreen_available = FALSE;
543 inline boolean ChangeVideoModeIfNeeded(boolean fullscreen)
546 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
547 (!fullscreen && video.fullscreen_enabled))
548 fullscreen = SetVideoMode(fullscreen);
554 Bitmap *LoadImage(char *basename)
559 sprintf(filename, "%s/%s/%s",
560 options.ro_base_directory, GRAPHICS_DIRECTORY, basename);
562 #if defined(TARGET_SDL)
563 new_bitmap = SDLLoadImage(filename);
565 new_bitmap = X11LoadImage(filename);
572 /* ========================================================================= */
573 /* audio functions */
574 /* ========================================================================= */
576 inline boolean OpenAudio(struct AudioSystemInfo *audio)
578 audio->sound_available = FALSE;
579 audio->loops_available = FALSE;
580 audio->sound_enabled = FALSE;
581 audio->soundserver_pipe[0] = audio->soundserver_pipe[1] = 0;
582 audio->soundserver_pid = 0;
583 audio->device_name = NULL;
584 audio->device_fd = 0;
586 #if defined(TARGET_SDL)
589 audio->sound_available = TRUE;
590 audio->loops_available = TRUE;
591 audio->sound_enabled = TRUE;
593 #elif defined(PLATFORM_MSDOS)
594 if (MSDOSOpenAudio())
596 audio->sound_available = TRUE;
597 audio->loops_available = TRUE;
598 audio->sound_enabled = TRUE;
600 #elif defined(PLATFORM_UNIX)
601 UnixOpenAudio(audio);
604 return audio->sound_available;
607 inline void CloseAudio(struct AudioSystemInfo *audio)
609 #if defined(TARGET_SDL)
611 #elif defined(PLATFORM_MSDOS)
613 #elif defined(PLATFORM_UNIX)
614 UnixCloseAudio(audio);
617 audio->sound_available = FALSE;
618 audio->loops_available = FALSE;
619 audio->sound_enabled = FALSE;
622 inline void SetAudioMode(boolean enabled)
624 if (!audio.sound_available)
627 audio.sound_enabled = enabled;
631 /* ========================================================================= */
632 /* event functions */
633 /* ========================================================================= */
635 inline void InitEventFilter(EventFilter filter_function)
638 /* set event filter to filter out certain events */
639 SDL_SetEventFilter(filter_function);
643 inline boolean PendingEvent(void)
646 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
648 return (XPending(display) ? TRUE : FALSE);
652 inline void NextEvent(Event *event)
655 SDL_WaitEvent(event);
657 XNextEvent(display, event);
661 inline Key GetEventKey(KeyEvent *event, boolean with_modifiers)
665 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
666 (int)event->keysym.unicode,
667 (int)event->keysym.sym,
668 (int)SDL_GetModState());
671 if (with_modifiers && event->keysym.unicode != 0)
672 return event->keysym.unicode;
674 return event->keysym.sym;
677 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
678 (int)XLookupKeysym(event, event->state),
679 (int)XLookupKeysym(event, 0));
683 return XLookupKeysym(event, event->state);
685 return XLookupKeysym(event, 0);
689 inline boolean CheckCloseWindowEvent(ClientMessageEvent *event)
691 if (event->type != EVENT_CLIENTMESSAGE)
694 #if defined(TARGET_SDL)
695 return TRUE; /* the only possible message here is SDL_QUIT */
696 #elif defined(PLATFORM_UNIX)
697 if ((event->window == window->drawable) &&
698 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
706 inline void dummy(void)