1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2002 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 *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.msdos_cursor_filename = msdos_cursor_filename;
94 program.cookie_prefix = cookie_prefix;
95 program.filename_prefix = filename_prefix;
97 program.version_major = VERSION_MAJOR(program_version);
98 program.version_minor = VERSION_MINOR(program_version);
99 program.version_patch = VERSION_PATCH(program_version);
101 program.error_filename = getErrorFilename(ERROR_BASENAME);
102 program.error_file = stderr;
105 void InitExitFunction(void (*exit_function)(int))
107 program.exit_function = exit_function;
109 /* set signal handlers to custom exit function */
110 signal(SIGINT, exit_function);
111 signal(SIGTERM, exit_function);
113 #if defined(TARGET_SDL)
114 /* set exit function to automatically cleanup SDL stuff after exit() */
119 void InitPlatformDependentStuff(void)
121 #if defined(PLATFORM_MSDOS)
125 #if defined(PLATFORM_MACOSX)
126 updateUserGameDataDir();
129 #if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
133 #if defined(TARGET_SDL)
134 if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
135 Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
141 void ClosePlatformDependentStuff(void)
143 #if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
147 #if defined(PLATFORM_MSDOS)
152 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
153 int real_sx, int real_sy,
154 int full_sxsize, int full_sysize,
155 Bitmap *field_save_buffer)
161 gfx.real_sx = real_sx;
162 gfx.real_sy = real_sy;
163 gfx.full_sxsize = full_sxsize;
164 gfx.full_sysize = full_sysize;
166 gfx.field_save_buffer = field_save_buffer;
168 gfx.background_bitmap = NULL;
169 gfx.background_bitmap_mask = REDRAW_NONE;
171 SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
172 SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
175 void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
183 void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
191 void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
193 /* currently only used by MSDOS code to alloc VRAM buffer, if available */
194 gfx.scrollbuffer_width = scrollbuffer_width;
195 gfx.scrollbuffer_height = scrollbuffer_height;
198 void SetDrawDeactivationMask(int draw_deactivation_mask)
200 gfx.draw_deactivation_mask = draw_deactivation_mask;
203 void SetDrawBackgroundMask(int draw_background_mask)
205 gfx.draw_background_mask = draw_background_mask;
208 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
209 int dest_x, int dest_y, int width, int height)
211 int bitmap_xsize = width;
212 int bitmap_ysize = height;
213 int tile_xsize = tile->width;
214 int tile_ysize = tile->height;
215 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
216 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
219 for (y = 0; y < tile_ysteps; y++)
221 for (x = 0; x < tile_xsteps; x++)
223 int draw_x = dest_x + x * tile_xsize;
224 int draw_y = dest_y + y * tile_ysize;
225 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
226 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
228 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
233 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
235 if (background_bitmap_tile != NULL)
236 gfx.background_bitmap_mask |= mask;
238 gfx.background_bitmap_mask &= ~mask;
240 if (gfx.background_bitmap == NULL)
241 gfx.background_bitmap = CreateBitmap(video.width, video.height,
244 if (background_bitmap_tile == NULL) /* empty background requested */
247 if (mask == REDRAW_FIELD)
248 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
249 gfx.real_sx, gfx.real_sy,
250 gfx.full_sxsize, gfx.full_sysize);
251 else if (mask == REDRAW_DOOR_1)
253 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
255 gfx.dxsize, gfx.dysize);
259 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
261 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
264 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
266 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
270 /* ========================================================================= */
271 /* video functions */
272 /* ========================================================================= */
274 inline static int GetRealDepth(int depth)
276 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
279 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
280 int width, int height, Pixel color)
282 #if defined(TARGET_SDL)
283 SDLFillRectangle(bitmap, x, y, width, height, color);
285 X11FillRectangle(bitmap, x, y, width, height, color);
289 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
290 int src_x, int src_y, int width, int height,
291 int dst_x, int dst_y, int mask_mode)
293 #if defined(TARGET_SDL)
294 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
295 dst_x, dst_y, mask_mode);
297 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
298 dst_x, dst_y, mask_mode);
302 void InitVideoDisplay(void)
304 #if defined(TARGET_SDL)
305 SDLInitVideoDisplay();
307 X11InitVideoDisplay();
311 void CloseVideoDisplay(void)
313 KeyboardAutoRepeatOn();
315 #if defined(TARGET_SDL)
316 SDL_QuitSubSystem(SDL_INIT_VIDEO);
319 XCloseDisplay(display);
323 void InitVideoBuffer(DrawBuffer **backbuffer, DrawWindow **window,
324 int width, int height, int depth, boolean fullscreen)
327 video.height = height;
328 video.depth = GetRealDepth(depth);
329 video.fullscreen_available = FULLSCREEN_STATUS;
330 video.fullscreen_enabled = FALSE;
331 video.fullscreen_modes = NULL;
332 video.fullscreen_mode_current = NULL;
334 #if defined(TARGET_SDL)
335 SDLInitVideoBuffer(backbuffer, window, fullscreen);
337 X11InitVideoBuffer(backbuffer, window);
341 Bitmap *CreateBitmapStruct(void)
343 #if defined(TARGET_SDL)
344 return checked_calloc(sizeof(struct SDLSurfaceInfo));
346 return checked_calloc(sizeof(struct X11DrawableInfo));
350 Bitmap *CreateBitmap(int width, int height, int depth)
352 Bitmap *new_bitmap = CreateBitmapStruct();
353 int real_depth = GetRealDepth(depth);
355 #if defined(TARGET_SDL)
356 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
358 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
361 new_bitmap->width = width;
362 new_bitmap->height = height;
367 inline static void FreeBitmapPointers(Bitmap *bitmap)
372 #if defined(TARGET_SDL)
373 SDLFreeBitmapPointers(bitmap);
375 X11FreeBitmapPointers(bitmap);
378 checked_free(bitmap->source_filename);
379 bitmap->source_filename = NULL;
382 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
385 if (src_bitmap == NULL || dst_bitmap == NULL)
388 FreeBitmapPointers(dst_bitmap);
390 *dst_bitmap = *src_bitmap;
393 void FreeBitmap(Bitmap *bitmap)
398 FreeBitmapPointers(bitmap);
403 void CloseWindow(DrawWindow *window)
405 #if defined(TARGET_X11)
406 if (window->drawable)
408 XUnmapWindow(display, window->drawable);
409 XDestroyWindow(display, window->drawable);
412 XFreeGC(display, window->gc);
416 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
419 if (draw_mask == REDRAW_NONE)
422 if (draw_mask & REDRAW_ALL)
425 if ((draw_mask & REDRAW_FIELD) && x < gfx.real_sx + gfx.full_sxsize)
428 if ((draw_mask & REDRAW_DOOR_1) && x >= gfx.dx && y < gfx.dy + gfx.dysize)
431 if ((draw_mask & REDRAW_DOOR_2) && x >= gfx.dx && y >= gfx.vy)
437 boolean DrawingDeactivated(int x, int y, int width, int height)
439 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
442 boolean DrawingOnBackground(int x, int y)
444 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
445 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
448 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
449 int src_x, int src_y, int width, int height,
450 int dst_x, int dst_y)
452 if (DrawingDeactivated(dst_x, dst_y, width, height))
455 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
456 dst_x, dst_y, BLIT_OPAQUE);
459 void FadeScreen(Bitmap *bitmap_cross, int fade_mode, int fade_delay,
462 #if defined(TARGET_SDL)
463 SDLFadeScreen(bitmap_cross, fade_mode, fade_delay, post_delay);
465 X11FadeScreen(bitmap_cross, fade_mode, fade_delay, post_delay);
469 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
472 if (DrawingDeactivated(x, y, width, height))
475 sysFillRectangle(bitmap, x, y, width, height, color);
478 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
480 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
483 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
484 int width, int height)
486 if (DrawingOnBackground(x, y))
487 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
489 ClearRectangle(bitmap, x, y, width, height);
492 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
494 #if defined(TARGET_X11)
497 bitmap->clip_gc = clip_gc;
498 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
503 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
505 #if defined(TARGET_X11)
508 bitmap->clip_gc = clip_gc;
509 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
514 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
515 int src_x, int src_y, int width, int height,
516 int dst_x, int dst_y)
518 if (DrawingDeactivated(dst_x, dst_y, width, height))
521 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
522 dst_x, dst_y, BLIT_MASKED);
525 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
526 int src_x, int src_y, int width, int height,
527 int dst_x, int dst_y)
529 if (DrawingOnBackground(dst_x, dst_y))
531 /* draw background */
532 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
535 /* draw foreground */
536 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
537 dst_x - src_x, dst_y - src_y);
538 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
542 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
546 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
549 #if defined(TARGET_SDL)
550 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
552 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
556 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
559 #if defined(TARGET_SDL)
560 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
562 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
566 #if !defined(TARGET_X11_NATIVE)
567 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
568 int to_x, int to_y, Pixel pixel, int line_width)
572 for (x = 0; x < line_width; x++)
574 for (y = 0; y < line_width; y++)
576 int dx = x - line_width / 2;
577 int dy = y - line_width / 2;
579 if ((x == 0 && y == 0) ||
580 (x == 0 && y == line_width - 1) ||
581 (x == line_width - 1 && y == 0) ||
582 (x == line_width - 1 && y == line_width - 1))
585 #if defined(TARGET_SDL)
587 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
588 #elif defined(TARGET_ALLEGRO)
589 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
590 to_x + dx, to_y + dy, pixel);
597 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
599 #if !defined(TARGET_X11_NATIVE)
603 for (i = 0; i < num_points - 1; i++)
604 DrawLine(bitmap, points[i].x, points[i].y,
605 points[i + 1].x, points[i + 1].y, pixel, line_width);
608 SDLDrawLines(bitmap->surface, points, num_points, pixel);
611 XSetForeground(display, bitmap->line_gc[1], pixel);
612 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
613 (XPoint *)points, num_points, CoordModeOrigin);
617 Pixel GetPixel(Bitmap *bitmap, int x, int y)
619 if (x < 0 || x >= bitmap->width ||
620 y < 0 || y >= bitmap->height)
623 #if defined(TARGET_SDL)
624 return SDLGetPixel(bitmap, x, y);
625 #elif defined(TARGET_ALLEGRO)
626 return AllegroGetPixel(bitmap->drawable, x, y);
628 return X11GetPixel(bitmap, x, y);
632 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
633 unsigned int color_g, unsigned int color_b)
635 #if defined(TARGET_SDL)
636 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
637 #elif defined(TARGET_ALLEGRO)
638 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
640 return X11GetPixelFromRGB(color_r, color_g, color_b);
644 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
646 unsigned int color_r = (color >> 16) & 0xff;
647 unsigned int color_g = (color >> 8) & 0xff;
648 unsigned int color_b = (color >> 0) & 0xff;
650 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
653 /* execute all pending screen drawing operations */
654 void FlushDisplay(void)
661 /* execute and wait for all pending screen drawing operations */
662 void SyncDisplay(void)
665 XSync(display, FALSE);
669 void KeyboardAutoRepeatOn(void)
671 #if defined(TARGET_SDL)
672 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
673 SDL_DEFAULT_REPEAT_INTERVAL / 2);
674 SDL_EnableUNICODE(1);
677 XAutoRepeatOn(display);
681 void KeyboardAutoRepeatOff(void)
683 #if defined(TARGET_SDL)
684 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
685 SDL_EnableUNICODE(0);
688 XAutoRepeatOff(display);
692 boolean PointerInWindow(DrawWindow *window)
694 #if defined(TARGET_SDL)
702 /* if XQueryPointer() returns False, the pointer
703 is not on the same screen as the specified window */
704 return XQueryPointer(display, window->drawable, &root, &child,
705 &root_x, &root_y, &win_x, &win_y, &mask);
709 boolean SetVideoMode(boolean fullscreen)
711 #if defined(TARGET_SDL)
712 return SDLSetVideoMode(&backbuffer, fullscreen);
714 boolean success = TRUE;
716 if (fullscreen && video.fullscreen_available)
718 Error(ERR_WARN, "fullscreen not available in X11 version");
720 /* display error message only once */
721 video.fullscreen_available = FALSE;
730 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
732 #if defined(TARGET_SDL)
733 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
734 (!fullscreen && video.fullscreen_enabled))
735 fullscreen = SetVideoMode(fullscreen);
741 Bitmap *LoadImage(char *filename)
745 #if defined(TARGET_SDL)
746 new_bitmap = SDLLoadImage(filename);
748 new_bitmap = X11LoadImage(filename);
752 new_bitmap->source_filename = getStringCopy(filename);
757 Bitmap *LoadCustomImage(char *basename)
759 char *filename = getCustomImageFilename(basename);
762 if (filename == NULL)
763 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
765 if ((new_bitmap = LoadImage(filename)) == NULL)
766 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
771 void ReloadCustomImage(Bitmap *bitmap, char *basename)
773 char *filename = getCustomImageFilename(basename);
776 if (filename == NULL) /* (should never happen) */
778 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
782 if (strEqual(filename, bitmap->source_filename))
784 /* The old and new image are the same (have the same filename and path).
785 This usually means that this image does not exist in this graphic set
786 and a fallback to the existing image is done. */
791 if ((new_bitmap = LoadImage(filename)) == NULL)
793 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
797 if (bitmap->width != new_bitmap->width ||
798 bitmap->height != new_bitmap->height)
800 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
802 FreeBitmap(new_bitmap);
806 TransferBitmapPointers(new_bitmap, bitmap);
810 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
812 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
814 #if defined(TARGET_SDL)
815 SDLZoomBitmap(src_bitmap, dst_bitmap);
817 X11ZoomBitmap(src_bitmap, dst_bitmap);
823 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
824 boolean create_small_bitmaps)
827 Bitmap *new_bitmap, *tmp_bitmap_1, *tmp_bitmap_2, *tmp_bitmap_4,*tmp_bitmap_8;
828 int width_1, height_1, width_2, height_2, width_4, height_4, width_8,height_8;
829 int new_width, new_height;
831 /* calculate new image dimensions for normal sized image */
832 width_1 = old_bitmap->width * zoom_factor;
833 height_1 = old_bitmap->height * zoom_factor;
835 /* get image with normal size (this might require scaling up) */
836 if (zoom_factor != 1)
837 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
839 tmp_bitmap_1 = old_bitmap;
841 /* this is only needed to make compilers happy */
842 tmp_bitmap_2 = tmp_bitmap_4 = tmp_bitmap_8 = NULL;
844 if (create_small_bitmaps)
846 /* calculate new image dimensions for small images */
847 width_2 = width_1 / 2;
848 height_2 = height_1 / 2;
849 width_4 = width_1 / 4;
850 height_4 = height_1 / 4;
851 width_8 = width_1 / 8;
852 height_8 = height_1 / 8;
854 /* get image with 1/2 of normal size (for use in the level editor) */
855 if (zoom_factor != 2)
856 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
858 tmp_bitmap_2 = old_bitmap;
860 /* get image with 1/4 of normal size (for use in the level editor) */
861 if (zoom_factor != 4)
862 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
864 tmp_bitmap_4 = old_bitmap;
866 /* get image with 1/8 of normal size (for use on the preview screen) */
867 if (zoom_factor != 8)
868 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
870 tmp_bitmap_8 = old_bitmap;
873 /* if image was scaled up, create new clipmask for normal size image */
874 if (zoom_factor != 1)
876 #if defined(TARGET_X11)
877 if (old_bitmap->clip_mask)
878 XFreePixmap(display, old_bitmap->clip_mask);
880 old_bitmap->clip_mask =
881 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
883 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
885 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
887 if (old_bitmap->surface_masked)
888 SDL_FreeSurface(old_bitmap->surface_masked);
890 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
891 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
892 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
893 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
894 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
898 if (create_small_bitmaps)
901 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
903 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
905 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
906 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
908 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
909 width_1 / 2, height_1);
910 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
911 3 * width_1 / 4, height_1);
916 new_height = height_1;
918 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
921 if (create_small_bitmaps)
923 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
924 if (zoom_factor != 1)
925 FreeBitmap(tmp_bitmap_1);
927 if (zoom_factor != 2)
928 FreeBitmap(tmp_bitmap_2);
930 if (zoom_factor != 4)
931 FreeBitmap(tmp_bitmap_4);
933 if (zoom_factor != 8)
934 FreeBitmap(tmp_bitmap_8);
937 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
938 #if defined(TARGET_SDL)
939 swap_bitmap.surface = old_bitmap->surface;
940 old_bitmap->surface = new_bitmap->surface;
941 new_bitmap->surface = swap_bitmap.surface;
943 swap_bitmap.drawable = old_bitmap->drawable;
944 old_bitmap->drawable = new_bitmap->drawable;
945 new_bitmap->drawable = swap_bitmap.drawable;
948 old_bitmap->width = new_bitmap->width;
949 old_bitmap->height = new_bitmap->height;
951 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
954 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
956 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
959 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
961 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
965 /* ------------------------------------------------------------------------- */
966 /* mouse pointer functions */
967 /* ------------------------------------------------------------------------- */
969 #if !defined(PLATFORM_MSDOS)
971 static const char *cursor_image_playfield[] =
973 /* width height num_colors chars_per_pixel */
982 /* some people complained about a "white dot" on the screen and thought it
983 was a graphical error... OK, let's just remove the whole pointer :-) */
1031 #if defined(TARGET_SDL)
1032 static const int cursor_bit_order = BIT_ORDER_MSB;
1033 #elif defined(TARGET_X11_NATIVE)
1034 static const int cursor_bit_order = BIT_ORDER_LSB;
1037 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1039 struct MouseCursorInfo *cursor;
1040 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1041 int header_lines = 4;
1044 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1046 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1049 for (y = 0; y < cursor->width; y++)
1051 for (x = 0; x < cursor->height; x++)
1054 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1059 cursor->data[i] = cursor->mask[i] = 0;
1062 switch (image[header_lines + y][x])
1065 cursor->data[i] |= bit_mask;
1066 cursor->mask[i] |= bit_mask;
1070 cursor->mask[i] |= bit_mask;
1079 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1083 #endif /* !PLATFORM_MSDOS */
1085 void SetMouseCursor(int mode)
1087 #if !defined(PLATFORM_MSDOS)
1088 static struct MouseCursorInfo *cursor_playfield = NULL;
1090 if (cursor_playfield == NULL)
1091 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1093 #if defined(TARGET_SDL)
1094 SDLSetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1095 #elif defined(TARGET_X11_NATIVE)
1096 X11SetMouseCursor(mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1102 /* ========================================================================= */
1103 /* audio functions */
1104 /* ========================================================================= */
1106 void OpenAudio(void)
1108 /* always start with reliable default values */
1109 audio.sound_available = FALSE;
1110 audio.music_available = FALSE;
1111 audio.loops_available = FALSE;
1113 audio.sound_enabled = FALSE;
1114 audio.sound_deactivated = FALSE;
1116 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1117 audio.mixer_pid = 0;
1118 audio.device_name = NULL;
1119 audio.device_fd = -1;
1121 audio.num_channels = 0;
1122 audio.music_channel = 0;
1123 audio.first_sound_channel = 0;
1125 #if defined(TARGET_SDL)
1127 #elif defined(PLATFORM_UNIX)
1129 #elif defined(PLATFORM_MSDOS)
1134 void CloseAudio(void)
1136 #if defined(TARGET_SDL)
1138 #elif defined(PLATFORM_UNIX)
1140 #elif defined(PLATFORM_MSDOS)
1144 audio.sound_enabled = FALSE;
1147 void SetAudioMode(boolean enabled)
1149 if (!audio.sound_available)
1152 audio.sound_enabled = enabled;
1156 /* ========================================================================= */
1157 /* event functions */
1158 /* ========================================================================= */
1160 void InitEventFilter(EventFilter filter_function)
1162 #if defined(TARGET_SDL)
1163 /* set event filter to filter out certain events */
1164 SDL_SetEventFilter(filter_function);
1168 boolean PendingEvent(void)
1170 #if defined(TARGET_SDL)
1171 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1173 return (XPending(display) ? TRUE : FALSE);
1177 void NextEvent(Event *event)
1179 #if defined(TARGET_SDL)
1180 SDLNextEvent(event);
1182 XNextEvent(display, event);
1186 void PeekEvent(Event *event)
1188 #if defined(TARGET_SDL)
1189 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1191 XPeekEvent(display, event);
1195 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1197 #if defined(TARGET_SDL)
1200 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1201 (int)event->keysym.unicode,
1202 (int)event->keysym.sym,
1203 (int)SDL_GetModState());
1206 if (with_modifiers &&
1207 event->keysym.unicode > 0x0000 &&
1208 event->keysym.unicode < 0x2000)
1209 return event->keysym.unicode;
1211 return event->keysym.sym;
1216 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1217 (int)XLookupKeysym(event, event->state),
1218 (int)XLookupKeysym(event, 0));
1222 return XLookupKeysym(event, event->state);
1224 return XLookupKeysym(event, 0);
1228 KeyMod HandleKeyModState(Key key, int key_status)
1230 static KeyMod current_modifiers = KMOD_None;
1232 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1234 KeyMod new_modifier = KMOD_None;
1239 new_modifier = KMOD_Shift_L;
1242 new_modifier = KMOD_Shift_R;
1244 case KSYM_Control_L:
1245 new_modifier = KMOD_Control_L;
1247 case KSYM_Control_R:
1248 new_modifier = KMOD_Control_R;
1251 new_modifier = KMOD_Meta_L;
1254 new_modifier = KMOD_Meta_R;
1257 new_modifier = KMOD_Alt_L;
1260 new_modifier = KMOD_Alt_R;
1266 if (key_status == KEY_PRESSED)
1267 current_modifiers |= new_modifier;
1269 current_modifiers &= ~new_modifier;
1272 return current_modifiers;
1275 KeyMod GetKeyModState()
1277 #if defined(TARGET_SDL)
1278 return (KeyMod)SDL_GetModState();
1280 return HandleKeyModState(KSYM_UNDEFINED, 0);
1284 KeyMod GetKeyModStateFromEvents()
1286 /* always use key modifier state as tracked from key events (this is needed
1287 if the modifier key event was injected into the event queue, but the key
1288 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1289 query the keys as held pressed on the keyboard) -- this case is currently
1290 only used to filter out clipboard insert events from "True X-Mouse" tool */
1292 return HandleKeyModState(KSYM_UNDEFINED, 0);
1295 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1297 if (event->type != EVENT_CLIENTMESSAGE)
1300 #if defined(TARGET_SDL)
1301 return TRUE; /* the only possible message here is SDL_QUIT */
1302 #elif defined(PLATFORM_UNIX)
1303 if ((event->window == window->drawable) &&
1304 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1312 /* ========================================================================= */
1313 /* joystick functions */
1314 /* ========================================================================= */
1316 void InitJoysticks()
1320 #if defined(NO_JOYSTICK)
1321 return; /* joysticks generally deactivated by compile-time directive */
1324 /* always start with reliable default values */
1325 joystick.status = JOYSTICK_NOT_AVAILABLE;
1326 for (i = 0; i < MAX_PLAYERS; i++)
1327 joystick.fd[i] = -1; /* joystick device closed */
1329 #if defined(TARGET_SDL)
1331 #elif defined(PLATFORM_UNIX)
1332 UnixInitJoysticks();
1333 #elif defined(PLATFORM_MSDOS)
1334 MSDOSInitJoysticks();
1338 for (i = 0; i < MAX_PLAYERS; i++)
1339 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1343 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1345 #if defined(TARGET_SDL)
1346 return SDLReadJoystick(nr, x, y, b1, b2);
1347 #elif defined(PLATFORM_UNIX)
1348 return UnixReadJoystick(nr, x, y, b1, b2);
1349 #elif defined(PLATFORM_MSDOS)
1350 return MSDOSReadJoystick(nr, x, y, b1, b2);