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 SetDrawDeactivationMask(int draw_deactivation_mask)
206 gfx.draw_deactivation_mask = draw_deactivation_mask;
209 void SetDrawBackgroundMask(int draw_background_mask)
211 gfx.draw_background_mask = draw_background_mask;
214 static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
215 int dest_x, int dest_y, int width, int height)
217 int bitmap_xsize = width;
218 int bitmap_ysize = height;
219 int tile_xsize = tile->width;
220 int tile_ysize = tile->height;
221 int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
222 int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
225 for (y = 0; y < tile_ysteps; y++)
227 for (x = 0; x < tile_xsteps; x++)
229 int draw_x = dest_x + x * tile_xsize;
230 int draw_y = dest_y + y * tile_ysize;
231 int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
232 int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
234 BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
239 void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
241 if (background_bitmap_tile != NULL)
242 gfx.background_bitmap_mask |= mask;
244 gfx.background_bitmap_mask &= ~mask;
246 if (gfx.background_bitmap == NULL)
247 gfx.background_bitmap = CreateBitmap(video.width, video.height,
250 if (background_bitmap_tile == NULL) /* empty background requested */
253 if (mask == REDRAW_ALL)
254 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
255 0, 0, video.width, video.height);
256 else if (mask == REDRAW_FIELD)
257 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
258 gfx.real_sx, gfx.real_sy,
259 gfx.full_sxsize, gfx.full_sysize);
260 else if (mask == REDRAW_DOOR_1)
262 DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
264 gfx.dxsize, gfx.dysize);
268 void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
270 SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
273 void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
275 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
276 SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
279 void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
281 SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
282 SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
286 /* ========================================================================= */
287 /* video functions */
288 /* ========================================================================= */
290 inline static int GetRealDepth(int depth)
292 return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
295 inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
296 int width, int height, Pixel color)
298 #if defined(TARGET_SDL)
299 SDLFillRectangle(bitmap, x, y, width, height, color);
301 X11FillRectangle(bitmap, x, y, width, height, color);
305 inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
306 int src_x, int src_y, int width, int height,
307 int dst_x, int dst_y, int mask_mode)
309 #if defined(TARGET_SDL)
310 SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
311 dst_x, dst_y, mask_mode);
313 X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
314 dst_x, dst_y, mask_mode);
318 void InitVideoDisplay(void)
320 #if defined(TARGET_SDL)
321 SDLInitVideoDisplay();
323 X11InitVideoDisplay();
327 void CloseVideoDisplay(void)
329 KeyboardAutoRepeatOn();
331 #if defined(TARGET_SDL)
332 SDL_QuitSubSystem(SDL_INIT_VIDEO);
335 XCloseDisplay(display);
339 void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
342 video.height = height;
343 video.depth = GetRealDepth(depth);
345 video.fullscreen_available = FULLSCREEN_STATUS;
346 video.fullscreen_enabled = FALSE;
347 video.fullscreen_modes = NULL;
348 video.fullscreen_mode_current = NULL;
350 #if defined(TARGET_SDL)
351 SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
353 X11InitVideoBuffer(&backbuffer, &window);
359 Bitmap *CreateBitmapStruct(void)
361 #if defined(TARGET_SDL)
362 return checked_calloc(sizeof(struct SDLSurfaceInfo));
364 return checked_calloc(sizeof(struct X11DrawableInfo));
368 Bitmap *CreateBitmap(int width, int height, int depth)
370 Bitmap *new_bitmap = CreateBitmapStruct();
371 int real_depth = GetRealDepth(depth);
373 #if defined(TARGET_SDL)
374 SDLCreateBitmapContent(new_bitmap, width, height, real_depth);
376 X11CreateBitmapContent(new_bitmap, width, height, real_depth);
379 new_bitmap->width = width;
380 new_bitmap->height = height;
385 inline static void FreeBitmapPointers(Bitmap *bitmap)
390 #if defined(TARGET_SDL)
391 SDLFreeBitmapPointers(bitmap);
393 X11FreeBitmapPointers(bitmap);
396 checked_free(bitmap->source_filename);
397 bitmap->source_filename = NULL;
400 inline static void TransferBitmapPointers(Bitmap *src_bitmap,
403 if (src_bitmap == NULL || dst_bitmap == NULL)
406 FreeBitmapPointers(dst_bitmap);
408 *dst_bitmap = *src_bitmap;
411 void FreeBitmap(Bitmap *bitmap)
416 FreeBitmapPointers(bitmap);
421 void CloseWindow(DrawWindow *window)
423 #if defined(TARGET_X11)
424 if (window->drawable)
426 XUnmapWindow(display, window->drawable);
427 XDestroyWindow(display, window->drawable);
430 XFreeGC(display, window->gc);
434 inline static boolean CheckDrawingArea(int x, int y, int width, int height,
437 if (draw_mask == REDRAW_NONE)
440 if (draw_mask & REDRAW_ALL)
443 if ((draw_mask & REDRAW_FIELD) &&
444 x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
447 if ((draw_mask & REDRAW_DOOR_1) &&
448 x >= gfx.dx && y < gfx.dy + gfx.dysize)
451 if ((draw_mask & REDRAW_DOOR_2) &&
452 x >= gfx.dx && y >= gfx.vy)
458 boolean DrawingDeactivated(int x, int y, int width, int height)
460 return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
463 boolean DrawingOnBackground(int x, int y)
465 return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
466 CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
469 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
470 int src_x, int src_y, int width, int height,
471 int dst_x, int dst_y)
473 if (DrawingDeactivated(dst_x, dst_y, width, height))
476 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
477 dst_x, dst_y, BLIT_OPAQUE);
480 void FadeRectangle(Bitmap *bitmap_cross, int x, int y, int width, int height,
481 int fade_mode, int fade_delay, int post_delay,
482 void (*draw_border_function)(void))
484 #if defined(TARGET_SDL)
485 SDLFadeRectangle(bitmap_cross, x, y, width, height,
486 fade_mode, fade_delay, post_delay, draw_border_function);
488 X11FadeRectangle(bitmap_cross, x, y, width, height,
489 fade_mode, fade_delay, post_delay, draw_border_function);
493 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
496 if (DrawingDeactivated(x, y, width, height))
499 sysFillRectangle(bitmap, x, y, width, height, color);
502 void ClearRectangle(Bitmap *bitmap, int x, int y, int width, int height)
504 FillRectangle(bitmap, x, y, width, height, BLACK_PIXEL);
507 void ClearRectangleOnBackground(Bitmap *bitmap, int x, int y,
508 int width, int height)
510 if (DrawingOnBackground(x, y))
511 BlitBitmap(gfx.background_bitmap, bitmap, x, y, width, height, x, y);
513 ClearRectangle(bitmap, x, y, width, height);
516 void SetClipMask(Bitmap *bitmap, GC clip_gc, Pixmap clip_pixmap)
518 #if defined(TARGET_X11)
521 bitmap->clip_gc = clip_gc;
522 XSetClipMask(display, bitmap->clip_gc, clip_pixmap);
527 void SetClipOrigin(Bitmap *bitmap, GC clip_gc, int clip_x, int clip_y)
529 #if defined(TARGET_X11)
532 bitmap->clip_gc = clip_gc;
533 XSetClipOrigin(display, bitmap->clip_gc, clip_x, clip_y);
538 void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
539 int src_x, int src_y, int width, int height,
540 int dst_x, int dst_y)
542 if (DrawingDeactivated(dst_x, dst_y, width, height))
545 sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
546 dst_x, dst_y, BLIT_MASKED);
549 void BlitBitmapOnBackground(Bitmap *src_bitmap, Bitmap *dst_bitmap,
550 int src_x, int src_y, int width, int height,
551 int dst_x, int dst_y)
553 if (DrawingOnBackground(dst_x, dst_y))
555 /* draw background */
556 BlitBitmap(gfx.background_bitmap, dst_bitmap, dst_x, dst_y, width, height,
559 /* draw foreground */
560 SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc,
561 dst_x - src_x, dst_y - src_y);
562 BlitBitmapMasked(src_bitmap, dst_bitmap, src_x, src_y, width, height,
566 BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, width, height,
570 void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
573 #if defined(TARGET_SDL)
574 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
576 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
580 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
583 #if defined(TARGET_SDL)
584 SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
586 X11DrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, WHITE_PIXEL);
590 #if !defined(TARGET_X11_NATIVE)
591 void DrawLine(Bitmap *bitmap, int from_x, int from_y,
592 int to_x, int to_y, Pixel pixel, int line_width)
596 for (x = 0; x < line_width; x++)
598 for (y = 0; y < line_width; y++)
600 int dx = x - line_width / 2;
601 int dy = y - line_width / 2;
603 if ((x == 0 && y == 0) ||
604 (x == 0 && y == line_width - 1) ||
605 (x == line_width - 1 && y == 0) ||
606 (x == line_width - 1 && y == line_width - 1))
609 #if defined(TARGET_SDL)
611 from_x + dx, from_y + dy, to_x + dx, to_y + dy, pixel);
612 #elif defined(TARGET_ALLEGRO)
613 AllegroDrawLine(bitmap->drawable, from_x + dx, from_y + dy,
614 to_x + dx, to_y + dy, pixel);
621 void DrawLines(Bitmap *bitmap, struct XY *points, int num_points, Pixel pixel)
623 #if !defined(TARGET_X11_NATIVE)
627 for (i = 0; i < num_points - 1; i++)
628 DrawLine(bitmap, points[i].x, points[i].y,
629 points[i + 1].x, points[i + 1].y, pixel, line_width);
632 SDLDrawLines(bitmap->surface, points, num_points, pixel);
635 XSetForeground(display, bitmap->line_gc[1], pixel);
636 XDrawLines(display, bitmap->drawable, bitmap->line_gc[1],
637 (XPoint *)points, num_points, CoordModeOrigin);
641 Pixel GetPixel(Bitmap *bitmap, int x, int y)
643 if (x < 0 || x >= bitmap->width ||
644 y < 0 || y >= bitmap->height)
647 #if defined(TARGET_SDL)
648 return SDLGetPixel(bitmap, x, y);
649 #elif defined(TARGET_ALLEGRO)
650 return AllegroGetPixel(bitmap->drawable, x, y);
652 return X11GetPixel(bitmap, x, y);
656 Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
657 unsigned int color_g, unsigned int color_b)
659 #if defined(TARGET_SDL)
660 return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
661 #elif defined(TARGET_ALLEGRO)
662 return AllegroAllocColorCell(color_r << 8, color_g << 8, color_b << 8);
664 return X11GetPixelFromRGB(color_r, color_g, color_b);
668 Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
670 unsigned int color_r = (color >> 16) & 0xff;
671 unsigned int color_g = (color >> 8) & 0xff;
672 unsigned int color_b = (color >> 0) & 0xff;
674 return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
677 /* execute all pending screen drawing operations */
678 void FlushDisplay(void)
685 /* execute and wait for all pending screen drawing operations */
686 void SyncDisplay(void)
689 XSync(display, FALSE);
693 void KeyboardAutoRepeatOn(void)
695 #if defined(TARGET_SDL)
696 SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY / 2,
697 SDL_DEFAULT_REPEAT_INTERVAL / 2);
698 SDL_EnableUNICODE(1);
701 XAutoRepeatOn(display);
705 void KeyboardAutoRepeatOff(void)
707 #if defined(TARGET_SDL)
708 SDL_EnableKeyRepeat(0, SDL_DEFAULT_REPEAT_INTERVAL);
709 SDL_EnableUNICODE(0);
712 XAutoRepeatOff(display);
716 boolean PointerInWindow(DrawWindow *window)
718 #if defined(TARGET_SDL)
726 /* if XQueryPointer() returns False, the pointer
727 is not on the same screen as the specified window */
728 return XQueryPointer(display, window->drawable, &root, &child,
729 &root_x, &root_y, &win_x, &win_y, &mask);
733 boolean SetVideoMode(boolean fullscreen)
735 #if defined(TARGET_SDL)
736 return SDLSetVideoMode(&backbuffer, fullscreen);
738 boolean success = TRUE;
740 if (fullscreen && video.fullscreen_available)
742 Error(ERR_WARN, "fullscreen not available in X11 version");
744 /* display error message only once */
745 video.fullscreen_available = FALSE;
754 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
756 #if defined(TARGET_SDL)
757 if ((fullscreen && !video.fullscreen_enabled && video.fullscreen_available)||
758 (!fullscreen && video.fullscreen_enabled))
759 fullscreen = SetVideoMode(fullscreen);
765 Bitmap *LoadImage(char *filename)
769 #if defined(TARGET_SDL)
770 new_bitmap = SDLLoadImage(filename);
772 new_bitmap = X11LoadImage(filename);
776 new_bitmap->source_filename = getStringCopy(filename);
781 Bitmap *LoadCustomImage(char *basename)
783 char *filename = getCustomImageFilename(basename);
786 if (filename == NULL)
787 Error(ERR_EXIT, "LoadCustomImage(): cannot find file '%s'", basename);
789 if ((new_bitmap = LoadImage(filename)) == NULL)
790 Error(ERR_EXIT, "LoadImage() failed: %s", GetError());
795 void ReloadCustomImage(Bitmap *bitmap, char *basename)
797 char *filename = getCustomImageFilename(basename);
800 if (filename == NULL) /* (should never happen) */
802 Error(ERR_WARN, "ReloadCustomImage(): cannot find file '%s'", basename);
806 if (strEqual(filename, bitmap->source_filename))
808 /* The old and new image are the same (have the same filename and path).
809 This usually means that this image does not exist in this graphic set
810 and a fallback to the existing image is done. */
815 if ((new_bitmap = LoadImage(filename)) == NULL)
817 Error(ERR_WARN, "LoadImage() failed: %s", GetError());
821 if (bitmap->width != new_bitmap->width ||
822 bitmap->height != new_bitmap->height)
824 Error(ERR_WARN, "ReloadCustomImage: new image '%s' has wrong dimensions",
826 FreeBitmap(new_bitmap);
830 TransferBitmapPointers(new_bitmap, bitmap);
834 Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
836 Bitmap *dst_bitmap = CreateBitmap(zoom_width, zoom_height, DEFAULT_DEPTH);
838 #if defined(TARGET_SDL)
839 SDLZoomBitmap(src_bitmap, dst_bitmap);
841 X11ZoomBitmap(src_bitmap, dst_bitmap);
847 static void CreateScaledBitmaps(Bitmap *old_bitmap, int zoom_factor,
848 boolean create_small_bitmaps)
852 Bitmap *tmp_bitmap_1;
853 Bitmap *tmp_bitmap_2;
854 Bitmap *tmp_bitmap_4;
855 Bitmap *tmp_bitmap_8;
856 Bitmap *tmp_bitmap_16;
857 Bitmap *tmp_bitmap_32;
858 int width_1, height_1;
859 int width_2, height_2;
860 int width_4, height_4;
861 int width_8, height_8;
862 int width_16, height_16;
863 int width_32, height_32;
864 int new_width, new_height;
866 /* calculate new image dimensions for normal sized image */
867 width_1 = old_bitmap->width * zoom_factor;
868 height_1 = old_bitmap->height * zoom_factor;
870 /* get image with normal size (this might require scaling up) */
871 if (zoom_factor != 1)
872 tmp_bitmap_1 = ZoomBitmap(old_bitmap, width_1, height_1);
874 tmp_bitmap_1 = old_bitmap;
876 /* this is only needed to make compilers happy */
880 tmp_bitmap_16 = NULL;
881 tmp_bitmap_32 = NULL;
883 if (create_small_bitmaps)
885 /* calculate new image dimensions for small images */
886 width_2 = width_1 / 2;
887 height_2 = height_1 / 2;
888 width_4 = width_1 / 4;
889 height_4 = height_1 / 4;
890 width_8 = width_1 / 8;
891 height_8 = height_1 / 8;
892 width_16 = width_1 / 16;
893 height_16 = height_1 / 16;
894 width_32 = width_1 / 32;
895 height_32 = height_1 / 32;
899 /* get image with 1/2 of normal size (for use in the level editor) */
900 if (zoom_factor != 2)
901 tmp_bitmap_2 = ZoomBitmap(tmp_bitmap_1, width_1 / 2, height_1 / 2);
903 tmp_bitmap_2 = old_bitmap;
907 /* get image with 1/4 of normal size (for use in the level editor) */
908 if (zoom_factor != 4)
909 tmp_bitmap_4 = ZoomBitmap(tmp_bitmap_2, width_2 / 2, height_2 / 2);
911 tmp_bitmap_4 = old_bitmap;
915 /* get image with 1/8 of normal size (for use on the preview screen) */
916 if (zoom_factor != 8)
917 tmp_bitmap_8 = ZoomBitmap(tmp_bitmap_4, width_4 / 2, height_4 / 2);
919 tmp_bitmap_8 = old_bitmap;
923 /* get image with 1/16 of normal size (for use on the preview screen) */
924 if (zoom_factor != 16)
925 tmp_bitmap_16 = ZoomBitmap(tmp_bitmap_8, width_8 / 2, height_8 / 2);
927 tmp_bitmap_16 = old_bitmap;
931 /* get image with 1/32 of normal size (for use on the preview screen) */
932 if (zoom_factor != 32)
933 tmp_bitmap_32 = ZoomBitmap(tmp_bitmap_16, width_16 / 2, height_16 / 2);
935 tmp_bitmap_32 = old_bitmap;
941 /* if image was scaled up, create new clipmask for normal size image */
942 if (zoom_factor != 1)
944 #if defined(TARGET_X11)
945 if (old_bitmap->clip_mask)
946 XFreePixmap(display, old_bitmap->clip_mask);
948 old_bitmap->clip_mask =
949 Pixmap_to_Mask(tmp_bitmap_1->drawable, width_1, height_1);
951 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
953 SDL_Surface *tmp_surface_1 = tmp_bitmap_1->surface;
955 if (old_bitmap->surface_masked)
956 SDL_FreeSurface(old_bitmap->surface_masked);
958 SDL_SetColorKey(tmp_surface_1, SDL_SRCCOLORKEY,
959 SDL_MapRGB(tmp_surface_1->format, 0x00, 0x00, 0x00));
960 if ((old_bitmap->surface_masked = SDL_DisplayFormat(tmp_surface_1)) ==NULL)
961 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
962 SDL_SetColorKey(tmp_surface_1, 0, 0); /* reset transparent pixel */
967 if (create_small_bitmaps)
970 new_height = height_1 + (height_1 + 1) / 2; /* prevent odd height */
972 new_bitmap = CreateBitmap(new_width, new_height, DEFAULT_DEPTH);
974 BlitBitmap(tmp_bitmap_1, new_bitmap, 0, 0, width_1, height_1, 0, 0);
975 BlitBitmap(tmp_bitmap_2, new_bitmap, 0, 0, width_1 / 2, height_1 / 2,
977 BlitBitmap(tmp_bitmap_4, new_bitmap, 0, 0, width_1 / 4, height_1 / 4,
978 width_1 / 2, height_1);
979 BlitBitmap(tmp_bitmap_8, new_bitmap, 0, 0, width_1 / 8, height_1 / 8,
980 3 * width_1 / 4, height_1);
981 BlitBitmap(tmp_bitmap_16, new_bitmap, 0, 0, width_1 / 16, height_1 / 16,
982 7 * width_1 / 8, height_1);
983 BlitBitmap(tmp_bitmap_32, new_bitmap, 0, 0, width_1 / 32, height_1 / 32,
984 15 * width_1 / 16, height_1);
991 new_height = height_1;
993 new_bitmap = tmp_bitmap_1; /* directly use tmp_bitmap_1 as new bitmap */
996 if (create_small_bitmaps)
998 /* if no small bitmaps created, tmp_bitmap_1 is used as new bitmap now */
999 if (zoom_factor != 1)
1000 FreeBitmap(tmp_bitmap_1);
1002 if (zoom_factor != 2)
1003 FreeBitmap(tmp_bitmap_2);
1005 if (zoom_factor != 4)
1006 FreeBitmap(tmp_bitmap_4);
1008 if (zoom_factor != 8)
1009 FreeBitmap(tmp_bitmap_8);
1011 if (zoom_factor != 16)
1012 FreeBitmap(tmp_bitmap_16);
1014 if (zoom_factor != 32)
1015 FreeBitmap(tmp_bitmap_32);
1018 /* replace image with extended image (containing 1/1, 1/2, 1/4, 1/8 size) */
1019 #if defined(TARGET_SDL)
1020 swap_bitmap.surface = old_bitmap->surface;
1021 old_bitmap->surface = new_bitmap->surface;
1022 new_bitmap->surface = swap_bitmap.surface;
1024 swap_bitmap.drawable = old_bitmap->drawable;
1025 old_bitmap->drawable = new_bitmap->drawable;
1026 new_bitmap->drawable = swap_bitmap.drawable;
1029 old_bitmap->width = new_bitmap->width;
1030 old_bitmap->height = new_bitmap->height;
1033 /* this replaces all blit masks created when loading -- maybe optimize this */
1035 #if defined(TARGET_X11)
1036 if (old_bitmap->clip_mask)
1037 XFreePixmap(display, old_bitmap->clip_mask);
1039 old_bitmap->clip_mask =
1040 Pixmap_to_Mask(old_bitmap->drawable, new_width, new_height);
1042 XSetClipMask(display, old_bitmap->stored_clip_gc, old_bitmap->clip_mask);
1044 SDL_Surface *old_surface = old_bitmap->surface;
1046 if (old_bitmap->surface_masked)
1047 SDL_FreeSurface(old_bitmap->surface_masked);
1049 SDL_SetColorKey(old_surface, SDL_SRCCOLORKEY,
1050 SDL_MapRGB(old_surface->format, 0x00, 0x00, 0x00));
1051 if ((old_bitmap->surface_masked = SDL_DisplayFormat(old_surface)) ==NULL)
1052 Error(ERR_EXIT, "SDL_DisplayFormat() failed");
1053 SDL_SetColorKey(old_surface, 0, 0); /* reset transparent pixel */
1058 UPDATE_BUSY_STATE();
1060 FreeBitmap(new_bitmap); /* this actually frees the _old_ bitmap now */
1063 void CreateBitmapWithSmallBitmaps(Bitmap *old_bitmap, int zoom_factor)
1065 CreateScaledBitmaps(old_bitmap, zoom_factor, TRUE);
1068 void ScaleBitmap(Bitmap *old_bitmap, int zoom_factor)
1070 CreateScaledBitmaps(old_bitmap, zoom_factor, FALSE);
1074 /* ------------------------------------------------------------------------- */
1075 /* mouse pointer functions */
1076 /* ------------------------------------------------------------------------- */
1078 #if !defined(PLATFORM_MSDOS)
1079 #define USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER 0
1080 /* XPM image definitions */
1081 static const char *cursor_image_none[] =
1083 /* width height num_colors chars_per_pixel */
1112 #if USE_ONE_PIXEL_PLAYFIELD_MOUSEPOINTER
1113 static const char *cursor_image_dot[] =
1115 /* width height num_colors chars_per_pixel */
1144 static const char **cursor_image_playfield = cursor_image_dot;
1146 /* some people complained about a "white dot" on the screen and thought it
1147 was a graphical error... OK, let's just remove the whole pointer :-) */
1148 static const char **cursor_image_playfield = cursor_image_none;
1151 #if defined(TARGET_SDL)
1152 static const int cursor_bit_order = BIT_ORDER_MSB;
1153 #elif defined(TARGET_X11_NATIVE)
1154 static const int cursor_bit_order = BIT_ORDER_LSB;
1157 static struct MouseCursorInfo *get_cursor_from_image(const char **image)
1159 struct MouseCursorInfo *cursor;
1160 boolean bit_order_msb = (cursor_bit_order == BIT_ORDER_MSB);
1161 int header_lines = 4;
1164 cursor = checked_calloc(sizeof(struct MouseCursorInfo));
1166 sscanf(image[0], " %d %d ", &cursor->width, &cursor->height);
1169 for (y = 0; y < cursor->width; y++)
1171 for (x = 0; x < cursor->height; x++)
1174 int bit_mask = 0x01 << (bit_order_msb ? 7 - bit_nr : bit_nr );
1179 cursor->data[i] = cursor->mask[i] = 0;
1182 switch (image[header_lines + y][x])
1185 cursor->data[i] |= bit_mask;
1186 cursor->mask[i] |= bit_mask;
1190 cursor->mask[i] |= bit_mask;
1199 sscanf(image[header_lines + y], "%d,%d", &cursor->hot_x, &cursor->hot_y);
1203 #endif /* !PLATFORM_MSDOS */
1205 void SetMouseCursor(int mode)
1207 #if !defined(PLATFORM_MSDOS)
1208 static struct MouseCursorInfo *cursor_none = NULL;
1209 static struct MouseCursorInfo *cursor_playfield = NULL;
1210 struct MouseCursorInfo *cursor_new;
1212 if (cursor_none == NULL)
1213 cursor_none = get_cursor_from_image(cursor_image_none);
1215 if (cursor_playfield == NULL)
1216 cursor_playfield = get_cursor_from_image(cursor_image_playfield);
1218 cursor_new = (mode == CURSOR_DEFAULT ? NULL :
1219 mode == CURSOR_NONE ? cursor_none :
1220 mode == CURSOR_PLAYFIELD ? cursor_playfield : NULL);
1222 #if defined(TARGET_SDL)
1223 SDLSetMouseCursor(cursor_new);
1224 #elif defined(TARGET_X11_NATIVE)
1225 X11SetMouseCursor(cursor_new);
1231 /* ========================================================================= */
1232 /* audio functions */
1233 /* ========================================================================= */
1235 void OpenAudio(void)
1237 /* always start with reliable default values */
1238 audio.sound_available = FALSE;
1239 audio.music_available = FALSE;
1240 audio.loops_available = FALSE;
1242 audio.sound_enabled = FALSE;
1243 audio.sound_deactivated = FALSE;
1245 audio.mixer_pipe[0] = audio.mixer_pipe[1] = 0;
1246 audio.mixer_pid = 0;
1247 audio.device_name = NULL;
1248 audio.device_fd = -1;
1250 audio.num_channels = 0;
1251 audio.music_channel = 0;
1252 audio.first_sound_channel = 0;
1254 #if defined(TARGET_SDL)
1256 #elif defined(PLATFORM_UNIX)
1258 #elif defined(PLATFORM_MSDOS)
1263 void CloseAudio(void)
1265 #if defined(TARGET_SDL)
1267 #elif defined(PLATFORM_UNIX)
1269 #elif defined(PLATFORM_MSDOS)
1273 audio.sound_enabled = FALSE;
1276 void SetAudioMode(boolean enabled)
1278 if (!audio.sound_available)
1281 audio.sound_enabled = enabled;
1285 /* ========================================================================= */
1286 /* event functions */
1287 /* ========================================================================= */
1289 void InitEventFilter(EventFilter filter_function)
1291 #if defined(TARGET_SDL)
1292 /* set event filter to filter out certain events */
1293 SDL_SetEventFilter(filter_function);
1297 boolean PendingEvent(void)
1299 #if defined(TARGET_SDL)
1300 return (SDL_PollEvent(NULL) ? TRUE : FALSE);
1302 return (XPending(display) ? TRUE : FALSE);
1306 void NextEvent(Event *event)
1308 #if defined(TARGET_SDL)
1309 SDLNextEvent(event);
1311 XNextEvent(display, event);
1315 void PeekEvent(Event *event)
1317 #if defined(TARGET_SDL)
1318 SDL_PeepEvents(event, 1, SDL_PEEKEVENT, SDL_ALLEVENTS);
1320 XPeekEvent(display, event);
1324 Key GetEventKey(KeyEvent *event, boolean with_modifiers)
1326 #if defined(TARGET_SDL)
1329 printf("unicode == '%d', sym == '%d', mod == '0x%04x'\n",
1330 (int)event->keysym.unicode,
1331 (int)event->keysym.sym,
1332 (int)SDL_GetModState());
1335 if (with_modifiers &&
1336 event->keysym.unicode > 0x0000 &&
1337 event->keysym.unicode < 0x2000)
1338 return event->keysym.unicode;
1340 return event->keysym.sym;
1345 printf("with modifiers == '0x%04x', without modifiers == '0x%04x'\n",
1346 (int)XLookupKeysym(event, event->state),
1347 (int)XLookupKeysym(event, 0));
1351 return XLookupKeysym(event, event->state);
1353 return XLookupKeysym(event, 0);
1357 KeyMod HandleKeyModState(Key key, int key_status)
1359 static KeyMod current_modifiers = KMOD_None;
1361 if (key != KSYM_UNDEFINED) /* new key => check for modifier key change */
1363 KeyMod new_modifier = KMOD_None;
1368 new_modifier = KMOD_Shift_L;
1371 new_modifier = KMOD_Shift_R;
1373 case KSYM_Control_L:
1374 new_modifier = KMOD_Control_L;
1376 case KSYM_Control_R:
1377 new_modifier = KMOD_Control_R;
1380 new_modifier = KMOD_Meta_L;
1383 new_modifier = KMOD_Meta_R;
1386 new_modifier = KMOD_Alt_L;
1389 new_modifier = KMOD_Alt_R;
1395 if (key_status == KEY_PRESSED)
1396 current_modifiers |= new_modifier;
1398 current_modifiers &= ~new_modifier;
1401 return current_modifiers;
1404 KeyMod GetKeyModState()
1406 #if defined(TARGET_SDL)
1407 return (KeyMod)SDL_GetModState();
1409 return HandleKeyModState(KSYM_UNDEFINED, 0);
1413 KeyMod GetKeyModStateFromEvents()
1415 /* always use key modifier state as tracked from key events (this is needed
1416 if the modifier key event was injected into the event queue, but the key
1417 was not really pressed on keyboard -- SDL_GetModState() seems to directly
1418 query the keys as held pressed on the keyboard) -- this case is currently
1419 only used to filter out clipboard insert events from "True X-Mouse" tool */
1421 return HandleKeyModState(KSYM_UNDEFINED, 0);
1424 boolean CheckCloseWindowEvent(ClientMessageEvent *event)
1426 if (event->type != EVENT_CLIENTMESSAGE)
1429 #if defined(TARGET_SDL)
1430 return TRUE; /* the only possible message here is SDL_QUIT */
1431 #elif defined(PLATFORM_UNIX)
1432 if ((event->window == window->drawable) &&
1433 (event->data.l[0] == XInternAtom(display, "WM_DELETE_WINDOW", FALSE)))
1441 /* ========================================================================= */
1442 /* joystick functions */
1443 /* ========================================================================= */
1445 void InitJoysticks()
1449 #if defined(NO_JOYSTICK)
1450 return; /* joysticks generally deactivated by compile-time directive */
1453 /* always start with reliable default values */
1454 joystick.status = JOYSTICK_NOT_AVAILABLE;
1455 for (i = 0; i < MAX_PLAYERS; i++)
1456 joystick.fd[i] = -1; /* joystick device closed */
1458 #if defined(TARGET_SDL)
1460 #elif defined(PLATFORM_UNIX)
1461 UnixInitJoysticks();
1462 #elif defined(PLATFORM_MSDOS)
1463 MSDOSInitJoysticks();
1467 for (i = 0; i < MAX_PLAYERS; i++)
1468 printf("::: Joystick for player %d: %d\n", i, joystick.fd[i]);
1472 boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
1474 #if defined(TARGET_SDL)
1475 return SDLReadJoystick(nr, x, y, b1, b2);
1476 #elif defined(PLATFORM_UNIX)
1477 return UnixReadJoystick(nr, x, y, b1, b2);
1478 #elif defined(PLATFORM_MSDOS)
1479 return MSDOSReadJoystick(nr, x, y, b1, b2);