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 InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
201 gfx.draw_busy_anim_function = draw_busy_anim_function;
204 void InitGfxCustomArtworkInfo()
206 gfx.override_level_graphics = FALSE;
207 gfx.override_level_sounds = FALSE;
208 gfx.override_level_music = FALSE;
210 gfx.draw_init_text = TRUE;
213 void SetDrawDeactivationMask(int draw_deactivation_mask)
215 gfx.draw_deactivation_mask = draw_deactivation_mask;
218 void SetDrawBackgroundMask(int draw_background_mask)
220 gfx.draw_background_mask = draw_background_mask;
223 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
224 int dest_x, int dest_y, int width, int height)
226 int bitmap_xsize = width;
227 int bitmap_ysize = height;
228 int tile_xsize = tile->width;
229 int tile_ysize = tile->height;
230 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
231 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
234 for (y = 0; y < tile_ysteps; y++)
236 for (x = 0; x < tile_xsteps; x++)
238 int draw_x = dest_x + x * tile_xsize;
239 int draw_y = dest_y + y * tile_ysize;
240 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
241 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
243 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
248 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
250 if (background_bitmap_tile != NULL)
251 gfx.background_bitmap_mask |= mask;
253 gfx.background_bitmap_mask &= ~mask;
255 if (gfx.background_bitmap == NULL)
256 gfx.background_bitmap = CreateBitmap(video.width, video.height,
259 if (background_bitmap_tile == NULL) /* empty background requested */
262 if (mask == REDRAW_ALL)
263 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
264 0, 0, video.width, video.height);
265 else if (mask == REDRAW_FIELD)
266 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
267 gfx.real_sx, gfx.real_sy,
268 gfx.full_sxsize, gfx.full_sysize);
269 else if (mask == REDRAW_DOOR_1)
271 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
273 gfx.dxsize, gfx.dysize);
277 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
279 /* remove every mask before setting mask for window */
280 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
281 SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
282 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
285 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
287 /* remove window area mask before setting mask for main area */
288 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
289 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
290 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
293 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
295 /* remove window area mask before setting mask for door area */
296 /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
297 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
298 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
302 /* ========================================================================= */
303 /* video functions */
304 /* ========================================================================= */
306 inline static int GetRealDepth(int depth)
308 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
311 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
312 int width, int height, Pixel color)
314 #if defined(TARGET_SDL)
315 SDLFillRectangle(bitmap, x, y, width, height, color);
317 X11FillRectangle(bitmap, x, y, width, height, color);
321 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
322 int src_x, int src_y, int width, int height,
323 int dst_x, int dst_y, int mask_mode)
325 #if defined(TARGET_SDL)
326 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
327 dst_x, dst_y, mask_mode);
329 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
330 dst_x, dst_y, mask_mode);
334 void InitVideoDisplay(void)
336 #if defined(TARGET_SDL)
337 SDLInitVideoDisplay();
339 X11InitVideoDisplay();
343 void CloseVideoDisplay(void)
345 KeyboardAutoRepeatOn();
347 #if defined(TARGET_SDL)
348 SDL_QuitSubSystem(SDL_INIT_VIDEO);
351 XCloseDisplay(display);
355 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
358 video.height = height;
359 video.depth = GetRealDepth(depth);
361 video.fullscreen_available = FULLSCREEN_STATUS;
362 video.fullscreen_enabled = FALSE;
363 video.fullscreen_modes = NULL;
364 video.fullscreen_mode_current = NULL;
366 #if defined(TARGET_SDL)
367 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
369 X11InitVideoBuffer(&backbuffer, &window);
375 Bitmap *CreateBitmapStruct(void)
377 #if defined(TARGET_SDL)
378 return checked_calloc(sizeof(struct SDLSurfaceInfo));
380 return checked_calloc(sizeof(struct X11DrawableInfo));
384 Bitmap *CreateBitmap(int width, int height, int depth)
386 Bitmap *new_bitmap = CreateBitmapStruct();
387 int real_width = MAX(1, width); /* prevent zero bitmap width */
388 int real_height = MAX(1, height); /* prevent zero bitmap height */
389 int real_depth = GetRealDepth(depth);
391 #if defined(TARGET_SDL)
392 SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
394 X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
397 new_bitmap->width = real_width;
398 new_bitmap->height = real_height;
403 inline static void FreeBitmapPointers(Bitmap *bitmap)
408 #if defined(TARGET_SDL)
409 SDLFreeBitmapPointers(bitmap);
411 X11FreeBitmapPointers(bitmap);
414 checked_free(bitmap->source_filename);
415 bitmap->source_filename = NULL;
418 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
421 if (src_bitmap == NULL || dst_bitmap == NULL)
424 FreeBitmapPointers(dst_bitmap);
426 *dst_bitmap = *src_bitmap;
429 void FreeBitmap(Bitmap *bitmap)
434 FreeBitmapPointers(bitmap);
439 void CloseWindow(DrawWindow *window)
441 #if defined(TARGET_X11)
442 if (window->drawable)
444 XUnmapWindow(display, window->drawable);
445 XDestroyWindow(display, window->drawable);
448 XFreeGC(display, window->gc);
452 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
455 if (draw_mask == REDRAW_NONE)
458 if (draw_mask & REDRAW_ALL)
461 if ((draw_mask & REDRAW_FIELD) &&
462 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
465 if ((draw_mask & REDRAW_DOOR_1) &&
466 x >= gfx.dx && y < gfx.dy + gfx.dysize)
469 if ((draw_mask & REDRAW_DOOR_2) &&
470 x >= gfx.dx && y >= gfx.vy)
476 boolean DrawingDeactivated(int x, int y, int width, int height)
478 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
481 boolean DrawingOnBackground(int x, int y)
483 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
484 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
487 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
488 int src_x, int src_y, int width, int height,
489 int dst_x, int dst_y)
491 if (DrawingDeactivated(dst_x, dst_y, width, height))
494 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
495 dst_x, dst_y, BLIT_OPAQUE);
498 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
499 int fade_mode, int fade_delay, int post_delay,
500 void (*draw_border_function)(void))
502 #if defined(TARGET_SDL)
503 SDLFadeRectangle(bitmap_cross, x, y, width, height,
504 fade_mode, fade_delay, post_delay, draw_border_function);
506 X11FadeRectangle(bitmap_cross, x, y, width, height,
507 fade_mode, fade_delay, post_delay, draw_border_function);
511 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
514 if (DrawingDeactivated(x, y, width, height))
517 sysFillRectangle(bitmap, x, y, width, height, color);
520 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
522 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
525 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
526 int width, int height)
528 if (DrawingOnBackground(x, y))
529 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
531 ClearRectangle(bitmap, x, y, width, height);
534 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
536 #if defined(TARGET_X11)
539 bitmap->clip_gc = clip_gc;
540 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
545 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
547 #if defined(TARGET_X11)
550 bitmap->clip_gc = clip_gc;
551 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
556 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
557 int src_x, int src_y, int width, int height,
558 int dst_x, int dst_y)
560 if (DrawingDeactivated(dst_x, dst_y, width, height))
563 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
564 dst_x, dst_y, BLIT_MASKED);
567 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
568 int src_x, int src_y, int width, int height,
569 int dst_x, int dst_y)
571 if (DrawingOnBackground(dst_x, dst_y))
573 /* draw background */
574 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
577 /* draw foreground */
578 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
579 dst_x - src_x, dst_y - src_y);
580 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
584 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
588 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
591 #if defined(TARGET_SDL)
592 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
594 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
598 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
601 #if defined(TARGET_SDL)
602 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
604 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
608 #if !defined(TARGET_X11_NATIVE)
609 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
610 int to_x, int to_y, Pixel pixel, int line_width)
614 for (x = 0; x < line_width; x++)
616 for (y = 0; y < line_width; y++)
618 int dx = x - line_width / 2;
619 int dy = y - line_width / 2;
621 if ((x == 0 && y == 0) ||
622 (x == 0 && y == line_width - 1) ||
623 (x == line_width - 1 && y == 0) ||
624 (x == line_width - 1 && y == line_width - 1))
627 #if defined(TARGET_SDL)
629 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
630 #elif defined(TARGET_ALLEGRO)
631 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
632 to_x + dx, to_y + dy, pixel);
639 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
641 #if !defined(TARGET_X11_NATIVE)
645 for (i = 0; i < num_points - 1; i++)
646 DrawLine(bitmap, points[i].x, points[i].y,
647 points[i + 1].x, points[i + 1].y, pixel, line_width);
650 SDLDrawLines(bitmap->surface, points, num_points, pixel);
653 XSetForeground(display, bitmap->line_gc[1], pixel);
654 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
655 (XPoint *)points, num_points, CoordModeOrigin);
659 Pixel GetPixel(Bitmap *bitmap, int x, int y)
661 if (x < 0 || x >= bitmap->width ||
662 y < 0 || y >= bitmap->height)
665 #if defined(TARGET_SDL)
666 return SDLGetPixel(bitmap, x, y);
667 #elif defined(TARGET_ALLEGRO)
668 return AllegroGetPixel(bitmap->drawable, x, y);
670 return X11GetPixel(bitmap, x, y);
674 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
675 unsigned int color_g, unsigned int color_b)
677 #if defined(TARGET_SDL)
678 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
679 #elif defined(TARGET_ALLEGRO)
680 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
682 return X11GetPixelFromRGB(color_r, color_g, color_b);
686 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
688 unsigned int color_r = (color >> 16) & 0xff;
689 unsigned int color_g = (color >> 8) & 0xff;
690 unsigned int color_b = (color >> 0) & 0xff;
692 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
695 /* execute all pending screen drawing operations */
696 void FlushDisplay(void)
703 /* execute and wait for all pending screen drawing operations */
704 void SyncDisplay(void)
707 XSync(display, FALSE);
711 void KeyboardAutoRepeatOn(void)
713 #if defined(TARGET_SDL)
714 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
715 SDL_DEFAULT_REPEAT_INTERVAL / 2);
716 SDL_EnableUNICODE(1);
719 XAutoRepeatOn(display);
723 void KeyboardAutoRepeatOff(void)
725 #if defined(TARGET_SDL)
726 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
727 SDL_EnableUNICODE(0);
730 XAutoRepeatOff(display);
734 boolean PointerInWindow(DrawWindow *window)
736 #if defined(TARGET_SDL)
744 /* if XQueryPointer() returns False, the pointer
745 is not on the same screen as the specified window */
746 return XQueryPointer(display, window->drawable, &root, &child,
747 &root_x, &root_y, &win_x, &win_y, &mask);
751 boolean SetVideoMode(boolean fullscreen)
753 #if defined(TARGET_SDL)
754 return SDLSetVideoMode(&backbuffer, fullscreen);
756 boolean success = TRUE;
758 if (fullscreen && video.fullscreen_available)
760 Error(ERR_WARN, "fullscreen not available in X11 version");
762 /* display error message only once */
763 video.fullscreen_available = FALSE;
772 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
774 #if defined(TARGET_SDL)
775 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
776 (!fullscreen && video.fullscreen_enabled))
777 fullscreen = SetVideoMode(fullscreen);
783 Bitmap *LoadImage(char *filename)
787 #if defined(TARGET_SDL)
788 new_bitmap = SDLLoadImage(filename);
790 new_bitmap = X11LoadImage(filename);
794 new_bitmap->source_filename = getStringCopy(filename);
799 Bitmap *LoadCustomImage(char *basename)
801 char *filename = getCustomImageFilename(basename);
804 if (filename == NULL)
805 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
807 if ((new_bitmap = LoadImage(filename)) == NULL)
808 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
813 void ReloadCustomImage(Bitmap *bitmap, char *basename)
815 char *filename = getCustomImageFilename(basename);
818 if (filename == NULL) /* (should never happen) */
820 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
824 if (strEqual(filename, bitmap->source_filename))
826 /* The old and new image are the same (have the same filename and path).
827 This usually means that this image does not exist in this graphic set
828 and a fallback to the existing image is done. */
833 if ((new_bitmap = LoadImage(filename)) == NULL)
835 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
839 if (bitmap->width != new_bitmap->width ||
840 bitmap->height != new_bitmap->height)
842 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
844 FreeBitmap(new_bitmap);
848 TransferBitmapPointers(new_bitmap, bitmap);
852 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
854 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
856 #if defined(TARGET_SDL)
857 SDLZoomBitmap(src_bitmap, dst_bitmap);
859 X11ZoomBitmap(src_bitmap, dst_bitmap);
865 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
866 boolean create_small_bitmaps)
870 Bitmap *tmp_bitmap_1;
871 Bitmap *tmp_bitmap_2;
872 Bitmap *tmp_bitmap_4;
873 Bitmap *tmp_bitmap_8;
874 Bitmap *tmp_bitmap_16;
875 Bitmap *tmp_bitmap_32;
876 int width_1, height_1;
877 int width_2, height_2;
878 int width_4, height_4;
879 int width_8, height_8;
880 int width_16, height_16;
881 int width_32, height_32;
882 int new_width, new_height;
884 /* calculate new image dimensions for normal sized image */
885 width_1 = old_bitmap->width * zoom_factor;
886 height_1 = old_bitmap->height * zoom_factor;
888 /* get image with normal size (this might require scaling up) */
889 if (zoom_factor != 1)
890 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
892 tmp_bitmap_1 = old_bitmap;
894 /* this is only needed to make compilers happy */
898 tmp_bitmap_16 = NULL;
899 tmp_bitmap_32 = NULL;
901 if (create_small_bitmaps)
903 /* calculate new image dimensions for small images */
904 width_2 = width_1 / 2;
905 height_2 = height_1 / 2;
906 width_4 = width_1 / 4;
907 height_4 = height_1 / 4;
908 width_8 = width_1 / 8;
909 height_8 = height_1 / 8;
910 width_16 = width_1 / 16;
911 height_16 = height_1 / 16;
912 width_32 = width_1 / 32;
913 height_32 = height_1 / 32;
917 /* get image with 1/2 of normal size (for use in the level editor) */
918 if (zoom_factor != 2)
919 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
921 tmp_bitmap_2 = old_bitmap;
925 /* get image with 1/4 of normal size (for use in the level editor) */
926 if (zoom_factor != 4)
927 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
929 tmp_bitmap_4 = old_bitmap;
933 /* get image with 1/8 of normal size (for use on the preview screen) */
934 if (zoom_factor != 8)
935 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
937 tmp_bitmap_8 = old_bitmap;
941 /* get image with 1/16 of normal size (for use on the preview screen) */
942 if (zoom_factor != 16)
943 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
945 tmp_bitmap_16 = old_bitmap;
949 /* get image with 1/32 of normal size (for use on the preview screen) */
950 if (zoom_factor != 32)
951 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
953 tmp_bitmap_32 = old_bitmap;
959 /* if image was scaled up, create new clipmask for normal size image */
960 if (zoom_factor != 1)
962 #if defined(TARGET_X11)
963 if (old_bitmap->clip_mask)
964 XFreePixmap(display, old_bitmap->clip_mask);
966 old_bitmap->clip_mask =
967 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
969 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
971 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
973 if (old_bitmap->surface_masked)
974 SDL_FreeSurface(old_bitmap->surface_masked);
976 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
977 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
978 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
979 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
980 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
985 if (create_small_bitmaps)
988 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
990 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
992 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
993 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
995 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
996 width_1 / 2, height_1);
997 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
998 3 * width_1 / 4, height_1);
999 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
1000 7 * width_1 / 8, height_1);
1001 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
1002 15 * width_1 / 16, height_1);
1004 UPDATE_BUSY_STATE();
1008 new_width = width_1;
1009 new_height = height_1;
1011 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
1014 if (create_small_bitmaps)
1016 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
1017 if (zoom_factor != 1)
1018 FreeBitmap(tmp_bitmap_1);
1020 if (zoom_factor != 2)
1021 FreeBitmap(tmp_bitmap_2);
1023 if (zoom_factor != 4)
1024 FreeBitmap(tmp_bitmap_4);
1026 if (zoom_factor != 8)
1027 FreeBitmap(tmp_bitmap_8);
1029 if (zoom_factor != 16)
1030 FreeBitmap(tmp_bitmap_16);
1032 if (zoom_factor != 32)
1033 FreeBitmap(tmp_bitmap_32);
1036 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1037 #if defined(TARGET_SDL)
1038 swap_bitmap.surface = old_bitmap->surface;
1039 old_bitmap->surface = new_bitmap->surface;
1040 new_bitmap->surface = swap_bitmap.surface;
1042 swap_bitmap.drawable = old_bitmap->drawable;
1043 old_bitmap->drawable = new_bitmap->drawable;
1044 new_bitmap->drawable = swap_bitmap.drawable;
1047 old_bitmap->width = new_bitmap->width;
1048 old_bitmap->height = new_bitmap->height;
1051 /* this replaces all blit masks created when loading -- maybe optimize this */
1053 #if defined(TARGET_X11)
1054 if (old_bitmap->clip_mask)
1055 XFreePixmap(display, old_bitmap->clip_mask);
1057 old_bitmap->clip_mask =
1058 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1060 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1062 SDL_Surface *old_surface = old_bitmap->surface;
1064 if (old_bitmap->surface_masked)
1065 SDL_FreeSurface(old_bitmap->surface_masked);
1067 SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
1068 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1069 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1070 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1071 SDL_SetColorKey(old_surface, 0, 0); /* reset transparent pixel */
1076 UPDATE_BUSY_STATE();
1078 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1081 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1083 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1086 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1088 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1092 /* ------------------------------------------------------------------------- */
1093 /* mouse pointer functions */
1094 /* ------------------------------------------------------------------------- */
1096 #if !defined(PLATFORM_MSDOS)
1097 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1098 /* XPM image definitions */
1099 static const char *cursor_image_none[] =
1101 /* width height num_colors chars_per_pixel */
1130 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1131 static const char *cursor_image_dot[] =
1133 /* width height num_colors chars_per_pixel */
1162 static const char **cursor_image_playfield = cursor_image_dot;
1164 /* some people complained about a "white dot" on the screen and thought it
1165 was a graphical error... OK, let's just remove the whole pointer :-) */
1166 static const char **cursor_image_playfield = cursor_image_none;
1169 #if defined(TARGET_SDL)
1170 static const int cursor_bit_order = BIT_ORDER_MSB;
1171 #elif defined(TARGET_X11_NATIVE)
1172 static const int cursor_bit_order = BIT_ORDER_LSB;
1175 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1177 struct MouseCursorInfo *cursor;
1178 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1179 int header_lines = 4;
1182 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1184 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1187 for (y = 0; y < cursor->width; y++)
1189 for (x = 0; x < cursor->height; x++)
1192 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1197 cursor->data[i] = cursor->mask[i] = 0;
1200 switch (image[header_lines + y][x])
1203 cursor->data[i] |= bit_mask;
1204 cursor->mask[i] |= bit_mask;
1208 cursor->mask[i] |= bit_mask;
1217 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1221 #endif /* !PLATFORM_MSDOS */
1223 void SetMouseCursor(int mode)
1225 #if !defined(PLATFORM_MSDOS)
1226 static struct MouseCursorInfo *cursor_none = NULL;
1227 static struct MouseCursorInfo *cursor_playfield = NULL;
1228 struct MouseCursorInfo *cursor_new;
1230 if (cursor_none == NULL)
1231 cursor_none = get_cursor_from_image(cursor_image_none);
1233 if (cursor_playfield == NULL)
1234 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1236 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1237 mode == CURSOR_NONE ? cursor_none :
1238 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1240 #if defined(TARGET_SDL)
1241 SDLSetMouseCursor(cursor_new);
1242 #elif defined(TARGET_X11_NATIVE)
1243 X11SetMouseCursor(cursor_new);
1249 /* ========================================================================= */
1250 /* audio functions */
1251 /* ========================================================================= */
1253 void OpenAudio(void)
1255 /* always start with reliable default values */
1256 audio.sound_available = FALSE;
1257 audio.music_available = FALSE;
1258 audio.loops_available = FALSE;
1260 audio.sound_enabled = FALSE;
1261 audio.sound_deactivated = FALSE;
1263 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1264 audio.mixer_pid = 0;
1265 audio.device_name = NULL;
1266 audio.device_fd = -1;
1268 audio.num_channels = 0;
1269 audio.music_channel = 0;
1270 audio.first_sound_channel = 0;
1272 #if defined(TARGET_SDL)
1274 #elif defined(PLATFORM_UNIX)
1276 #elif defined(PLATFORM_MSDOS)
1281 void CloseAudio(void)
1283 #if defined(TARGET_SDL)
1285 #elif defined(PLATFORM_UNIX)
1287 #elif defined(PLATFORM_MSDOS)
1291 audio.sound_enabled = FALSE;
1294 void SetAudioMode(boolean enabled)
1296 if (!audio.sound_available)
1299 audio.sound_enabled = enabled;
1303 /* ========================================================================= */
1304 /* event functions */
1305 /* ========================================================================= */
1307 void InitEventFilter(EventFilter filter_function)
1309 #if defined(TARGET_SDL)
1310 /* set event filter to filter out certain events */
1311 SDL_SetEventFilter(filter_function);
1315 boolean PendingEvent(void)
1317 #if defined(TARGET_SDL)
1318 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1320 return (XPending(display) ? TRUE : FALSE);
1324 void NextEvent(Event *event)
1326 #if defined(TARGET_SDL)
1327 SDLNextEvent(event);
1329 XNextEvent(display, event);
1333 void PeekEvent(Event *event)
1335 #if defined(TARGET_SDL)
1336 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1338 XPeekEvent(display, event);
1342 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1344 #if defined(TARGET_SDL)
1347 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1348 (int)event->keysym.unicode,
1349 (int)event->keysym.sym,
1350 (int)SDL_GetModState());
1353 if (with_modifiers &&
1354 event->keysym.unicode > 0x0000 &&
1355 event->keysym.unicode < 0x2000)
1356 return event->keysym.unicode;
1358 return event->keysym.sym;
1363 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1364 (int)XLookupKeysym(event, event->state),
1365 (int)XLookupKeysym(event, 0));
1369 return XLookupKeysym(event, event->state);
1371 return XLookupKeysym(event, 0);
1375 KeyMod HandleKeyModState(Key key, int key_status)
1377 static KeyMod current_modifiers = KMOD_None;
1379 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1381 KeyMod new_modifier = KMOD_None;
1386 new_modifier = KMOD_Shift_L;
1389 new_modifier = KMOD_Shift_R;
1391 case KSYM_Control_L:
1392 new_modifier = KMOD_Control_L;
1394 case KSYM_Control_R:
1395 new_modifier = KMOD_Control_R;
1398 new_modifier = KMOD_Meta_L;
1401 new_modifier = KMOD_Meta_R;
1404 new_modifier = KMOD_Alt_L;
1407 new_modifier = KMOD_Alt_R;
1413 if (key_status == KEY_PRESSED)
1414 current_modifiers |= new_modifier;
1416 current_modifiers &= ~new_modifier;
1419 return current_modifiers;
1422 KeyMod GetKeyModState()
1424 #if defined(TARGET_SDL)
1425 return (KeyMod)SDL_GetModState();
1427 return HandleKeyModState(KSYM_UNDEFINED, 0);
1431 KeyMod GetKeyModStateFromEvents()
1433 /* always use key modifier state as tracked from key events (this is needed
1434 if the modifier key event was injected into the event queue, but the key
1435 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1436 query the keys as held pressed on the keyboard) -- this case is currently
1437 only used to filter out clipboard insert events from "True X-Mouse" tool */
1439 return HandleKeyModState(KSYM_UNDEFINED, 0);
1442 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1444 if (event->type != EVENT_CLIENTMESSAGE)
1447 #if defined(TARGET_SDL)
1448 return TRUE; /* the only possible message here is SDL_QUIT */
1449 #elif defined(PLATFORM_UNIX)
1450 if ((event->window == window->drawable) &&
1451 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1459 /* ========================================================================= */
1460 /* joystick functions */
1461 /* ========================================================================= */
1463 void InitJoysticks()
1467 #if defined(NO_JOYSTICK)
1468 return; /* joysticks generally deactivated by compile-time directive */
1471 /* always start with reliable default values */
1472 joystick.status = JOYSTICK_NOT_AVAILABLE;
1473 for (i = 0; i < MAX_PLAYERS; i++)
1474 joystick.fd[i] = -1; /* joystick device closed */
1476 #if defined(TARGET_SDL)
1478 #elif defined(PLATFORM_UNIX)
1479 UnixInitJoysticks();
1480 #elif defined(PLATFORM_MSDOS)
1481 MSDOSInitJoysticks();
1485 for (i = 0; i < MAX_PLAYERS; i++)
1486 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1490 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1492 #if defined(TARGET_SDL)
1493 return SDLReadJoystick(nr, x, y, b1, b2);
1494 #elif defined(PLATFORM_UNIX)
1495 return UnixReadJoystick(nr, x, y, b1, b2);
1496 #elif defined(PLATFORM_MSDOS)
1497 return MSDOSReadJoystick(nr, x, y, b1, b2);