1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
6 * Detmolder Strasse 189 *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
12 ***********************************************************/
19 #if defined(PLATFORM_MSDOS)
31 /* ========================================================================= */
32 /* exported variables */
33 /* ========================================================================= */
35 struct ProgramInfo program;
36 struct OptionInfo options;
37 struct VideoSystemInfo video;
38 struct AudioSystemInfo audio;
40 struct ArtworkInfo artwork;
41 struct JoystickInfo joystick;
42 struct SetupInfo setup;
44 LevelDirTree *leveldir_first_all = NULL;
45 LevelDirTree *leveldir_first = NULL;
46 LevelDirTree *leveldir_current = NULL;
49 Display *display = NULL;
50 Visual *visual = NULL;
54 DrawWindow *window = NULL;
55 DrawBuffer *backbuffer = NULL;
56 DrawBuffer *drawto = NULL;
58 int button_status = MB_NOT_PRESSED;
59 boolean motion_status = FALSE;
61 int redraw_mask = REDRAW_NONE;
67 /* ========================================================================= */
68 /* init/close functions */
69 /* ========================================================================= */
71 void InitProgramInfo(char *argv0,
72 char *userdata_subdir, char *userdata_subdir_unix,
73 char *program_title, char *window_title, char *icon_title,
74 char *x11_icon_filename, char *x11_iconmask_filename,
75 char *sdl_icon_filename, char *msdos_cursor_filename,
76 char *cookie_prefix, char *filename_prefix,
79 program.command_basepath = getBasePath(argv0);
80 program.command_basename = getBaseName(argv0);
82 program.userdata_subdir = userdata_subdir;
83 program.userdata_subdir_unix = userdata_subdir_unix;
84 program.userdata_path = getUserGameDataDir();
86 program.program_title = program_title;
87 program.window_title = window_title;
88 program.icon_title = icon_title;
90 program.x11_icon_filename = x11_icon_filename;
91 program.x11_iconmask_filename = x11_iconmask_filename;
92 program.sdl_icon_filename = sdl_icon_filename;
93 program.msdos_cursor_filename = msdos_cursor_filename;
95 program.cookie_prefix = cookie_prefix;
96 program.filename_prefix = filename_prefix;
98 program.version_major = VERSION_MAJOR(program_version);
99 program.version_minor = VERSION_MINOR(program_version);
100 program.version_patch = VERSION_PATCH(program_version);
102 program.error_filename = getErrorFilename(ERROR_BASENAME);
103 program.error_file = stderr;
106 void InitExitFunction(void (*exit_function)(int))
108 program.exit_function = exit_function;
110 /* set signal handlers to custom exit function */
111 signal(SIGINT, exit_function);
112 signal(SIGTERM, exit_function);
114 #if defined(TARGET_SDL)
115 /* set exit function to automatically cleanup SDL stuff after exit() */
120 void InitPlatformDependentStuff(void)
122 #if defined(PLATFORM_MSDOS)
126 #if defined(PLATFORM_MACOSX)
127 updateUserGameDataDir();
130 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
134 #if defined(TARGET_SDL)
135 if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
136 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
142 void ClosePlatformDependentStuff(void)
144 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
148 #if defined(PLATFORM_MSDOS)
153 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
154 int real_sx, int real_sy,
155 int full_sxsize, int full_sysize,
156 Bitmap *field_save_buffer)
162 gfx.real_sx = real_sx;
163 gfx.real_sy = real_sy;
164 gfx.full_sxsize = full_sxsize;
165 gfx.full_sysize = full_sysize;
167 gfx.field_save_buffer = field_save_buffer;
169 gfx.background_bitmap = NULL;
170 gfx.background_bitmap_mask = REDRAW_NONE;
172 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
173 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
176 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
184 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
192 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
194 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
195 gfx.scrollbuffer_width = scrollbuffer_width;
196 gfx.scrollbuffer_height = scrollbuffer_height;
199 void SetDrawDeactivationMask(int draw_deactivation_mask)
201 gfx.draw_deactivation_mask = draw_deactivation_mask;
204 void SetDrawBackgroundMask(int draw_background_mask)
206 gfx.draw_background_mask = draw_background_mask;
209 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
210 int dest_x, int dest_y, int width, int height)
212 int bitmap_xsize = width;
213 int bitmap_ysize = height;
214 int tile_xsize = tile->width;
215 int tile_ysize = tile->height;
216 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
217 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
220 for (y = 0; y < tile_ysteps; y++)
222 for (x = 0; x < tile_xsteps; x++)
224 int draw_x = dest_x + x * tile_xsize;
225 int draw_y = dest_y + y * tile_ysize;
226 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
227 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
229 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
234 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
236 if (background_bitmap_tile != NULL)
237 gfx.background_bitmap_mask |= mask;
239 gfx.background_bitmap_mask &= ~mask;
241 if (gfx.background_bitmap == NULL)
242 gfx.background_bitmap = CreateBitmap(video.width, video.height,
245 if (background_bitmap_tile == NULL) /* empty background requested */
248 if (mask == REDRAW_FIELD)
249 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
250 gfx.real_sx, gfx.real_sy,
251 gfx.full_sxsize, gfx.full_sysize);
252 else if (mask == REDRAW_DOOR_1)
254 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
256 gfx.dxsize, gfx.dysize);
260 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
262 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
265 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
267 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
271 /* ========================================================================= */
272 /* video functions */
273 /* ========================================================================= */
275 inline static int GetRealDepth(int depth)
277 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
280 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
281 int width, int height, Pixel color)
283 #if defined(TARGET_SDL)
284 SDLFillRectangle(bitmap, x, y, width, height, color);
286 X11FillRectangle(bitmap, x, y, width, height, color);
290 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
291 int src_x, int src_y, int width, int height,
292 int dst_x, int dst_y, int mask_mode)
294 #if defined(TARGET_SDL)
295 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
296 dst_x, dst_y, mask_mode);
298 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
299 dst_x, dst_y, mask_mode);
303 void InitVideoDisplay(void)
305 #if defined(TARGET_SDL)
306 SDLInitVideoDisplay();
308 X11InitVideoDisplay();
312 void CloseVideoDisplay(void)
314 KeyboardAutoRepeatOn();
316 #if defined(TARGET_SDL)
317 SDL_QuitSubSystem(SDL_INIT_VIDEO);
320 XCloseDisplay(display);
324 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
327 video.height = height;
328 video.depth = GetRealDepth(depth);
330 video.fullscreen_available = FULLSCREEN_STATUS;
331 video.fullscreen_enabled = FALSE;
332 video.fullscreen_modes = NULL;
333 video.fullscreen_mode_current = NULL;
335 #if defined(TARGET_SDL)
336 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
338 X11InitVideoBuffer(&backbuffer, &window);
344 Bitmap *CreateBitmapStruct(void)
346 #if defined(TARGET_SDL)
347 return checked_calloc(sizeof(struct SDLSurfaceInfo));
349 return checked_calloc(sizeof(struct X11DrawableInfo));
353 Bitmap *CreateBitmap(int width, int height, int depth)
355 Bitmap *new_bitmap = CreateBitmapStruct();
356 int real_depth = GetRealDepth(depth);
358 #if defined(TARGET_SDL)
359 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
361 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
364 new_bitmap->width = width;
365 new_bitmap->height = height;
370 inline static void FreeBitmapPointers(Bitmap *bitmap)
375 #if defined(TARGET_SDL)
376 SDLFreeBitmapPointers(bitmap);
378 X11FreeBitmapPointers(bitmap);
381 checked_free(bitmap->source_filename);
382 bitmap->source_filename = NULL;
385 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
388 if (src_bitmap == NULL || dst_bitmap == NULL)
391 FreeBitmapPointers(dst_bitmap);
393 *dst_bitmap = *src_bitmap;
396 void FreeBitmap(Bitmap *bitmap)
401 FreeBitmapPointers(bitmap);
406 void CloseWindow(DrawWindow *window)
408 #if defined(TARGET_X11)
409 if (window->drawable)
411 XUnmapWindow(display, window->drawable);
412 XDestroyWindow(display, window->drawable);
415 XFreeGC(display, window->gc);
419 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
422 if (draw_mask == REDRAW_NONE)
425 if (draw_mask & REDRAW_ALL)
428 if ((draw_mask & REDRAW_FIELD) &&
429 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
432 if ((draw_mask & REDRAW_DOOR_1) &&
433 x >= gfx.dx && y < gfx.dy + gfx.dysize)
436 if ((draw_mask & REDRAW_DOOR_2) &&
437 x >= gfx.dx && y >= gfx.vy)
443 boolean DrawingDeactivated(int x, int y, int width, int height)
445 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
448 boolean DrawingOnBackground(int x, int y)
450 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
451 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
454 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
455 int src_x, int src_y, int width, int height,
456 int dst_x, int dst_y)
458 if (DrawingDeactivated(dst_x, dst_y, width, height))
461 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
462 dst_x, dst_y, BLIT_OPAQUE);
465 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
466 int fade_mode, int fade_delay, int post_delay,
467 void (*draw_border_function)(void))
469 #if defined(TARGET_SDL)
470 SDLFadeRectangle(bitmap_cross, x, y, width, height,
471 fade_mode, fade_delay, post_delay, draw_border_function);
473 X11FadeRectangle(bitmap_cross, x, y, width, height,
474 fade_mode, fade_delay, post_delay, draw_border_function);
478 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
481 if (DrawingDeactivated(x, y, width, height))
484 sysFillRectangle(bitmap, x, y, width, height, color);
487 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
489 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
492 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
493 int width, int height)
495 if (DrawingOnBackground(x, y))
496 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
498 ClearRectangle(bitmap, x, y, width, height);
501 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
503 #if defined(TARGET_X11)
506 bitmap->clip_gc = clip_gc;
507 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
512 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
514 #if defined(TARGET_X11)
517 bitmap->clip_gc = clip_gc;
518 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
523 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
524 int src_x, int src_y, int width, int height,
525 int dst_x, int dst_y)
527 if (DrawingDeactivated(dst_x, dst_y, width, height))
530 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
531 dst_x, dst_y, BLIT_MASKED);
534 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
535 int src_x, int src_y, int width, int height,
536 int dst_x, int dst_y)
538 if (DrawingOnBackground(dst_x, dst_y))
540 /* draw background */
541 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
544 /* draw foreground */
545 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
546 dst_x - src_x, dst_y - src_y);
547 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
551 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
555 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
558 #if defined(TARGET_SDL)
559 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
561 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
565 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
568 #if defined(TARGET_SDL)
569 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
571 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
575 #if !defined(TARGET_X11_NATIVE)
576 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
577 int to_x, int to_y, Pixel pixel, int line_width)
581 for (x = 0; x < line_width; x++)
583 for (y = 0; y < line_width; y++)
585 int dx = x - line_width / 2;
586 int dy = y - line_width / 2;
588 if ((x == 0 && y == 0) ||
589 (x == 0 && y == line_width - 1) ||
590 (x == line_width - 1 && y == 0) ||
591 (x == line_width - 1 && y == line_width - 1))
594 #if defined(TARGET_SDL)
596 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
597 #elif defined(TARGET_ALLEGRO)
598 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
599 to_x + dx, to_y + dy, pixel);
606 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
608 #if !defined(TARGET_X11_NATIVE)
612 for (i = 0; i < num_points - 1; i++)
613 DrawLine(bitmap, points[i].x, points[i].y,
614 points[i + 1].x, points[i + 1].y, pixel, line_width);
617 SDLDrawLines(bitmap->surface, points, num_points, pixel);
620 XSetForeground(display, bitmap->line_gc[1], pixel);
621 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
622 (XPoint *)points, num_points, CoordModeOrigin);
626 Pixel GetPixel(Bitmap *bitmap, int x, int y)
628 if (x < 0 || x >= bitmap->width ||
629 y < 0 || y >= bitmap->height)
632 #if defined(TARGET_SDL)
633 return SDLGetPixel(bitmap, x, y);
634 #elif defined(TARGET_ALLEGRO)
635 return AllegroGetPixel(bitmap->drawable, x, y);
637 return X11GetPixel(bitmap, x, y);
641 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
642 unsigned int color_g, unsigned int color_b)
644 #if defined(TARGET_SDL)
645 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
646 #elif defined(TARGET_ALLEGRO)
647 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
649 return X11GetPixelFromRGB(color_r, color_g, color_b);
653 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
655 unsigned int color_r = (color >> 16) & 0xff;
656 unsigned int color_g = (color >> 8) & 0xff;
657 unsigned int color_b = (color >> 0) & 0xff;
659 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
662 /* execute all pending screen drawing operations */
663 void FlushDisplay(void)
670 /* execute and wait for all pending screen drawing operations */
671 void SyncDisplay(void)
674 XSync(display, FALSE);
678 void KeyboardAutoRepeatOn(void)
680 #if defined(TARGET_SDL)
681 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
682 SDL_DEFAULT_REPEAT_INTERVAL / 2);
683 SDL_EnableUNICODE(1);
686 XAutoRepeatOn(display);
690 void KeyboardAutoRepeatOff(void)
692 #if defined(TARGET_SDL)
693 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
694 SDL_EnableUNICODE(0);
697 XAutoRepeatOff(display);
701 boolean PointerInWindow(DrawWindow *window)
703 #if defined(TARGET_SDL)
711 /* if XQueryPointer() returns False, the pointer
712 is not on the same screen as the specified window */
713 return XQueryPointer(display, window->drawable, &root, &child,
714 &root_x, &root_y, &win_x, &win_y, &mask);
718 boolean SetVideoMode(boolean fullscreen)
720 #if defined(TARGET_SDL)
721 return SDLSetVideoMode(&backbuffer, fullscreen);
723 boolean success = TRUE;
725 if (fullscreen && video.fullscreen_available)
727 Error(ERR_WARN, "fullscreen not available in X11 version");
729 /* display error message only once */
730 video.fullscreen_available = FALSE;
739 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
741 #if defined(TARGET_SDL)
742 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
743 (!fullscreen && video.fullscreen_enabled))
744 fullscreen = SetVideoMode(fullscreen);
750 Bitmap *LoadImage(char *filename)
754 #if defined(TARGET_SDL)
755 new_bitmap = SDLLoadImage(filename);
757 new_bitmap = X11LoadImage(filename);
761 new_bitmap->source_filename = getStringCopy(filename);
766 Bitmap *LoadCustomImage(char *basename)
768 char *filename = getCustomImageFilename(basename);
771 if (filename == NULL)
772 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
774 if ((new_bitmap = LoadImage(filename)) == NULL)
775 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
780 void ReloadCustomImage(Bitmap *bitmap, char *basename)
782 char *filename = getCustomImageFilename(basename);
785 if (filename == NULL) /* (should never happen) */
787 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
791 if (strEqual(filename, bitmap->source_filename))
793 /* The old and new image are the same (have the same filename and path).
794 This usually means that this image does not exist in this graphic set
795 and a fallback to the existing image is done. */
800 if ((new_bitmap = LoadImage(filename)) == NULL)
802 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
806 if (bitmap->width != new_bitmap->width ||
807 bitmap->height != new_bitmap->height)
809 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
811 FreeBitmap(new_bitmap);
815 TransferBitmapPointers(new_bitmap, bitmap);
819 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
821 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
823 #if defined(TARGET_SDL)
824 SDLZoomBitmap(src_bitmap, dst_bitmap);
826 X11ZoomBitmap(src_bitmap, dst_bitmap);
832 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
833 boolean create_small_bitmaps)
836 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
837 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
838 int new_width, new_height;
840 /* calculate new image dimensions for normal sized image */
841 width_1 = old_bitmap->width * zoom_factor;
842 height_1 = old_bitmap->height * zoom_factor;
844 /* get image with normal size (this might require scaling up) */
845 if (zoom_factor != 1)
846 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
848 tmp_bitmap_1 = old_bitmap;
850 /* this is only needed to make compilers happy */
851 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
853 if (create_small_bitmaps)
855 /* calculate new image dimensions for small images */
856 width_2 = width_1 / 2;
857 height_2 = height_1 / 2;
858 width_4 = width_1 / 4;
859 height_4 = height_1 / 4;
860 width_8 = width_1 / 8;
861 height_8 = height_1 / 8;
863 /* get image with 1/2 of normal size (for use in the level editor) */
864 if (zoom_factor != 2)
865 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
867 tmp_bitmap_2 = old_bitmap;
869 /* get image with 1/4 of normal size (for use in the level editor) */
870 if (zoom_factor != 4)
871 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
873 tmp_bitmap_4 = old_bitmap;
875 /* get image with 1/8 of normal size (for use on the preview screen) */
876 if (zoom_factor != 8)
877 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
879 tmp_bitmap_8 = old_bitmap;
882 /* if image was scaled up, create new clipmask for normal size image */
883 if (zoom_factor != 1)
885 #if defined(TARGET_X11)
886 if (old_bitmap->clip_mask)
887 XFreePixmap(display, old_bitmap->clip_mask);
889 old_bitmap->clip_mask =
890 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
892 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
894 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
896 if (old_bitmap->surface_masked)
897 SDL_FreeSurface(old_bitmap->surface_masked);
899 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
900 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
901 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
902 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
903 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
907 if (create_small_bitmaps)
910 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
912 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
914 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
915 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
917 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
918 width_1 / 2, height_1);
919 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
920 3 * width_1 / 4, height_1);
925 new_height = height_1;
927 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
930 if (create_small_bitmaps)
932 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
933 if (zoom_factor != 1)
934 FreeBitmap(tmp_bitmap_1);
936 if (zoom_factor != 2)
937 FreeBitmap(tmp_bitmap_2);
939 if (zoom_factor != 4)
940 FreeBitmap(tmp_bitmap_4);
942 if (zoom_factor != 8)
943 FreeBitmap(tmp_bitmap_8);
946 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
947 #if defined(TARGET_SDL)
948 swap_bitmap.surface = old_bitmap->surface;
949 old_bitmap->surface = new_bitmap->surface;
950 new_bitmap->surface = swap_bitmap.surface;
952 swap_bitmap.drawable = old_bitmap->drawable;
953 old_bitmap->drawable = new_bitmap->drawable;
954 new_bitmap->drawable = swap_bitmap.drawable;
957 old_bitmap->width = new_bitmap->width;
958 old_bitmap->height = new_bitmap->height;
960 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
963 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
965 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
968 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
970 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
974 /* ------------------------------------------------------------------------- */
975 /* mouse pointer functions */
976 /* ------------------------------------------------------------------------- */
978 #if !defined(PLATFORM_MSDOS)
980 static const char *cursor_image_playfield[] =
982 /* width height num_colors chars_per_pixel */
991 /* some people complained about a "white dot" on the screen and thought it
992 was a graphical error... OK, let's just remove the whole pointer :-) */
1040 #if defined(TARGET_SDL)
1041 static const int cursor_bit_order = BIT_ORDER_MSB;
1042 #elif defined(TARGET_X11_NATIVE)
1043 static const int cursor_bit_order = BIT_ORDER_LSB;
1046 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1048 struct MouseCursorInfo *cursor;
1049 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1050 int header_lines = 4;
1053 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1055 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1058 for (y = 0; y < cursor->width; y++)
1060 for (x = 0; x < cursor->height; x++)
1063 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1068 cursor->data[i] = cursor->mask[i] = 0;
1071 switch (image[header_lines + y][x])
1074 cursor->data[i] |= bit_mask;
1075 cursor->mask[i] |= bit_mask;
1079 cursor->mask[i] |= bit_mask;
1088 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1092 #endif /* !PLATFORM_MSDOS */
1094 void SetMouseCursor(int mode)
1096 #if !defined(PLATFORM_MSDOS)
1097 static struct MouseCursorInfo *cursor_playfield = NULL;
1099 if (cursor_playfield == NULL)
1100 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1102 #if defined(TARGET_SDL)
1103 SDLSetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1104 #elif defined(TARGET_X11_NATIVE)
1105 X11SetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1111 /* ========================================================================= */
1112 /* audio functions */
1113 /* ========================================================================= */
1115 void OpenAudio(void)
1117 /* always start with reliable default values */
1118 audio.sound_available = FALSE;
1119 audio.music_available = FALSE;
1120 audio.loops_available = FALSE;
1122 audio.sound_enabled = FALSE;
1123 audio.sound_deactivated = FALSE;
1125 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1126 audio.mixer_pid = 0;
1127 audio.device_name = NULL;
1128 audio.device_fd = -1;
1130 audio.num_channels = 0;
1131 audio.music_channel = 0;
1132 audio.first_sound_channel = 0;
1134 #if defined(TARGET_SDL)
1136 #elif defined(PLATFORM_UNIX)
1138 #elif defined(PLATFORM_MSDOS)
1143 void CloseAudio(void)
1145 #if defined(TARGET_SDL)
1147 #elif defined(PLATFORM_UNIX)
1149 #elif defined(PLATFORM_MSDOS)
1153 audio.sound_enabled = FALSE;
1156 void SetAudioMode(boolean enabled)
1158 if (!audio.sound_available)
1161 audio.sound_enabled = enabled;
1165 /* ========================================================================= */
1166 /* event functions */
1167 /* ========================================================================= */
1169 void InitEventFilter(EventFilter filter_function)
1171 #if defined(TARGET_SDL)
1172 /* set event filter to filter out certain events */
1173 SDL_SetEventFilter(filter_function);
1177 boolean PendingEvent(void)
1179 #if defined(TARGET_SDL)
1180 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1182 return (XPending(display) ? TRUE : FALSE);
1186 void NextEvent(Event *event)
1188 #if defined(TARGET_SDL)
1189 SDLNextEvent(event);
1191 XNextEvent(display, event);
1195 void PeekEvent(Event *event)
1197 #if defined(TARGET_SDL)
1198 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1200 XPeekEvent(display, event);
1204 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1206 #if defined(TARGET_SDL)
1209 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1210 (int)event->keysym.unicode,
1211 (int)event->keysym.sym,
1212 (int)SDL_GetModState());
1215 if (with_modifiers &&
1216 event->keysym.unicode > 0x0000 &&
1217 event->keysym.unicode < 0x2000)
1218 return event->keysym.unicode;
1220 return event->keysym.sym;
1225 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1226 (int)XLookupKeysym(event, event->state),
1227 (int)XLookupKeysym(event, 0));
1231 return XLookupKeysym(event, event->state);
1233 return XLookupKeysym(event, 0);
1237 KeyMod HandleKeyModState(Key key, int key_status)
1239 static KeyMod current_modifiers = KMOD_None;
1241 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1243 KeyMod new_modifier = KMOD_None;
1248 new_modifier = KMOD_Shift_L;
1251 new_modifier = KMOD_Shift_R;
1253 case KSYM_Control_L:
1254 new_modifier = KMOD_Control_L;
1256 case KSYM_Control_R:
1257 new_modifier = KMOD_Control_R;
1260 new_modifier = KMOD_Meta_L;
1263 new_modifier = KMOD_Meta_R;
1266 new_modifier = KMOD_Alt_L;
1269 new_modifier = KMOD_Alt_R;
1275 if (key_status == KEY_PRESSED)
1276 current_modifiers |= new_modifier;
1278 current_modifiers &= ~new_modifier;
1281 return current_modifiers;
1284 KeyMod GetKeyModState()
1286 #if defined(TARGET_SDL)
1287 return (KeyMod)SDL_GetModState();
1289 return HandleKeyModState(KSYM_UNDEFINED, 0);
1293 KeyMod GetKeyModStateFromEvents()
1295 /* always use key modifier state as tracked from key events (this is needed
1296 if the modifier key event was injected into the event queue, but the key
1297 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1298 query the keys as held pressed on the keyboard) -- this case is currently
1299 only used to filter out clipboard insert events from "True X-Mouse" tool */
1301 return HandleKeyModState(KSYM_UNDEFINED, 0);
1304 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1306 if (event->type != EVENT_CLIENTMESSAGE)
1309 #if defined(TARGET_SDL)
1310 return TRUE; /* the only possible message here is SDL_QUIT */
1311 #elif defined(PLATFORM_UNIX)
1312 if ((event->window == window->drawable) &&
1313 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1321 /* ========================================================================= */
1322 /* joystick functions */
1323 /* ========================================================================= */
1325 void InitJoysticks()
1329 #if defined(NO_JOYSTICK)
1330 return; /* joysticks generally deactivated by compile-time directive */
1333 /* always start with reliable default values */
1334 joystick.status = JOYSTICK_NOT_AVAILABLE;
1335 for (i = 0; i < MAX_PLAYERS; i++)
1336 joystick.fd[i] = -1; /* joystick device closed */
1338 #if defined(TARGET_SDL)
1340 #elif defined(PLATFORM_UNIX)
1341 UnixInitJoysticks();
1342 #elif defined(PLATFORM_MSDOS)
1343 MSDOSInitJoysticks();
1347 for (i = 0; i < MAX_PLAYERS; i++)
1348 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1352 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1354 #if defined(TARGET_SDL)
1355 return SDLReadJoystick(nr, x, y, b1, b2);
1356 #elif defined(PLATFORM_UNIX)
1357 return UnixReadJoystick(nr, x, y, b1, b2);
1358 #elif defined(PLATFORM_MSDOS)
1359 return MSDOSReadJoystick(nr, x, y, b1, b2);