+ program.sdl_icon_filename = sdl_icon_filename;
+ program.msdos_cursor_filename = msdos_cursor_filename;
+
+ program.cookie_prefix = cookie_prefix;
+ program.filename_prefix = filename_prefix;
+
+ program.version_major = VERSION_MAJOR(program_version);
+ program.version_minor = VERSION_MINOR(program_version);
+ program.version_patch = VERSION_PATCH(program_version);
+
+ program.error_filename = getErrorFilename(ERROR_BASENAME);
+ program.error_file = stderr;
+}
+
+void InitExitFunction(void (*exit_function)(int))
+{
+ program.exit_function = exit_function;
+
+ /* set signal handlers to custom exit function */
+ signal(SIGINT, exit_function);
+ signal(SIGTERM, exit_function);
+
+#if defined(TARGET_SDL)
+ /* set exit function to automatically cleanup SDL stuff after exit() */
+ atexit(SDL_Quit);
+#endif
+}
+
+void InitPlatformDependentStuff(void)
+{
+#if defined(PLATFORM_MSDOS)
+ _fmode = O_BINARY;
+#endif
+
+#if defined(PLATFORM_MACOSX)
+ updateUserGameDataDir();
+#endif
+
+#if !defined(PLATFORM_UNIX) || defined(PLATFORM_MACOSX)
+ openErrorFile();
+#endif
+
+#if defined(TARGET_SDL)
+ if (SDL_Init(SDL_INIT_EVENTTHREAD | SDL_INIT_NOPARACHUTE) < 0)
+ Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
+
+ SDLNet_Init();
+#endif
+}
+
+void ClosePlatformDependentStuff(void)
+{
+#if defined(PLATFORM_WIN32) || defined(PLATFORM_MSDOS)
+ closeErrorFile();
+#endif
+
+#if defined(PLATFORM_MSDOS)
+ dumpErrorFile();
+#endif
+}
+
+void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
+ int real_sx, int real_sy,
+ int full_sxsize, int full_sysize,
+ Bitmap *field_save_buffer)
+{
+ gfx.sx = sx;
+ gfx.sy = sy;
+ gfx.sxsize = sxsize;
+ gfx.sysize = sysize;
+ gfx.real_sx = real_sx;
+ gfx.real_sy = real_sy;
+ gfx.full_sxsize = full_sxsize;
+ gfx.full_sysize = full_sysize;
+
+ gfx.field_save_buffer = field_save_buffer;
+
+#if 0
+ gfx.background_bitmap = NULL;
+ gfx.background_bitmap_mask = REDRAW_NONE;
+#endif
+
+ SetDrawDeactivationMask(REDRAW_NONE); /* do not deactivate drawing */
+ SetDrawBackgroundMask(REDRAW_NONE); /* deactivate masked drawing */
+}
+
+void InitGfxDoor1Info(int dx, int dy, int dxsize, int dysize)
+{
+ gfx.dx = dx;
+ gfx.dy = dy;
+ gfx.dxsize = dxsize;
+ gfx.dysize = dysize;
+}
+
+void InitGfxDoor2Info(int vx, int vy, int vxsize, int vysize)
+{
+ gfx.vx = vx;
+ gfx.vy = vy;
+ gfx.vxsize = vxsize;
+ gfx.vysize = vysize;
+}
+
+void InitGfxWindowInfo(int win_xsize, int win_ysize)
+{
+ gfx.win_xsize = win_xsize;
+ gfx.win_ysize = win_ysize;
+
+#if 1
+ gfx.background_bitmap_mask = REDRAW_NONE;
+
+ ReCreateBitmap(&gfx.background_bitmap, win_xsize, win_ysize, DEFAULT_DEPTH);
+#endif
+}
+
+void InitGfxScrollbufferInfo(int scrollbuffer_width, int scrollbuffer_height)
+{
+ /* currently only used by MSDOS code to alloc VRAM buffer, if available */
+ /* 2009-03-24: also (temporarily?) used for overlapping blit workaround */
+ gfx.scrollbuffer_width = scrollbuffer_width;
+ gfx.scrollbuffer_height = scrollbuffer_height;
+}
+
+void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
+{
+ gfx.clipping_enabled = enabled;
+ gfx.clip_x = x;
+ gfx.clip_y = y;
+ gfx.clip_width = width;
+ gfx.clip_height = height;
+}
+
+void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
+{
+ gfx.draw_busy_anim_function = draw_busy_anim_function;
+}
+
+void InitGfxCustomArtworkInfo()
+{
+ gfx.override_level_graphics = FALSE;
+ gfx.override_level_sounds = FALSE;
+ gfx.override_level_music = FALSE;
+
+ gfx.draw_init_text = TRUE;
+}
+
+void SetDrawDeactivationMask(int draw_deactivation_mask)
+{
+ gfx.draw_deactivation_mask = draw_deactivation_mask;
+}
+
+void SetDrawBackgroundMask(int draw_background_mask)
+{
+ gfx.draw_background_mask = draw_background_mask;
+}
+
+static void DrawBitmapFromTile(Bitmap *bitmap, Bitmap *tile,
+ int dest_x, int dest_y, int width, int height)
+{
+ int bitmap_xsize = width;
+ int bitmap_ysize = height;
+ int tile_xsize = tile->width;
+ int tile_ysize = tile->height;
+ int tile_xsteps = (bitmap_xsize + tile_xsize - 1) / tile_xsize;
+ int tile_ysteps = (bitmap_ysize + tile_ysize - 1) / tile_ysize;
+ int x, y;
+
+ for (y = 0; y < tile_ysteps; y++)
+ {
+ for (x = 0; x < tile_xsteps; x++)
+ {
+ int draw_x = dest_x + x * tile_xsize;
+ int draw_y = dest_y + y * tile_ysize;
+ int draw_xsize = MIN(tile_xsize, bitmap_xsize - x * tile_xsize);
+ int draw_ysize = MIN(tile_ysize, bitmap_ysize - y * tile_ysize);
+
+ BlitBitmap(tile, bitmap, 0, 0, draw_xsize, draw_ysize, draw_x, draw_y);
+ }
+ }
+}
+
+void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
+{
+ if (background_bitmap_tile != NULL)
+ gfx.background_bitmap_mask |= mask;
+ else
+ gfx.background_bitmap_mask &= ~mask;
+
+#if 0
+ if (gfx.background_bitmap == NULL)
+ gfx.background_bitmap = CreateBitmap(video.width, video.height,
+ DEFAULT_DEPTH);
+#endif
+
+ if (background_bitmap_tile == NULL) /* empty background requested */
+ return;
+
+ if (mask == REDRAW_ALL)
+ DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
+ 0, 0, video.width, video.height);
+ else if (mask == REDRAW_FIELD)
+ DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
+ gfx.real_sx, gfx.real_sy,
+ gfx.full_sxsize, gfx.full_sysize);
+ else if (mask == REDRAW_DOOR_1)
+ {
+ DrawBitmapFromTile(gfx.background_bitmap, background_bitmap_tile,
+ gfx.dx, gfx.dy,
+ gfx.dxsize, gfx.dysize);
+ }
+}
+
+void SetWindowBackgroundBitmap(Bitmap *background_bitmap_tile)
+{
+ /* remove every mask before setting mask for window */
+ /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
+ SetBackgroundBitmap(NULL, 0xffff); /* !!! FIX THIS !!! */
+ SetBackgroundBitmap(background_bitmap_tile, REDRAW_ALL);
+}
+
+void SetMainBackgroundBitmap(Bitmap *background_bitmap_tile)
+{
+ /* remove window area mask before setting mask for main area */
+ /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
+ SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
+ SetBackgroundBitmap(background_bitmap_tile, REDRAW_FIELD);
+}
+
+void SetDoorBackgroundBitmap(Bitmap *background_bitmap_tile)
+{
+ /* remove window area mask before setting mask for door area */
+ /* (!!! TO BE FIXED: The whole REDRAW_* system really sucks! !!!) */
+ SetBackgroundBitmap(NULL, REDRAW_ALL); /* !!! FIX THIS !!! */
+ SetBackgroundBitmap(background_bitmap_tile, REDRAW_DOOR_1);
+}
+
+
+/* ========================================================================= */
+/* video functions */
+/* ========================================================================= */
+
+inline static int GetRealDepth(int depth)
+{
+ return (depth == DEFAULT_DEPTH ? video.default_depth : depth);
+}
+
+inline static void sysFillRectangle(Bitmap *bitmap, int x, int y,
+ int width, int height, Pixel color)
+{
+#if defined(TARGET_SDL)
+ SDLFillRectangle(bitmap, x, y, width, height, color);
+#else
+ X11FillRectangle(bitmap, x, y, width, height, color);
+#endif
+}
+
+inline static void sysCopyArea(Bitmap *src_bitmap, Bitmap *dst_bitmap,
+ int src_x, int src_y, int width, int height,
+ int dst_x, int dst_y, int mask_mode)
+{
+#if defined(TARGET_SDL)
+ SDLCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
+ dst_x, dst_y, mask_mode);
+#else
+ X11CopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
+ dst_x, dst_y, mask_mode);
+#endif
+}
+
+void InitVideoDisplay(void)
+{
+#if defined(TARGET_SDL)
+ SDLInitVideoDisplay();
+#else
+ X11InitVideoDisplay();
+#endif
+}
+
+void CloseVideoDisplay(void)
+{
+ KeyboardAutoRepeatOn();
+
+#if defined(TARGET_SDL)
+ SDL_QuitSubSystem(SDL_INIT_VIDEO);
+#else
+ if (display)
+ XCloseDisplay(display);
+#endif
+}
+
+void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
+{
+ video.width = width;
+ video.height = height;
+ video.depth = GetRealDepth(depth);
+
+ video.fullscreen_available = FULLSCREEN_STATUS;
+ video.fullscreen_enabled = FALSE;
+#if 0
+ video.fullscreen_mode_current = NULL;
+ video.fullscreen_modes = NULL;
+#endif
+
+#if defined(TARGET_SDL)
+ SDLInitVideoBuffer(&backbuffer, &window, fullscreen);
+#else
+ X11InitVideoBuffer(&backbuffer, &window);
+#endif
+
+ drawto = backbuffer;
+}
+
+inline static void FreeBitmapPointers(Bitmap *bitmap)
+{
+ if (bitmap == NULL)
+ return;
+
+#if defined(TARGET_SDL)
+ SDLFreeBitmapPointers(bitmap);
+#else
+ X11FreeBitmapPointers(bitmap);
+#endif
+
+ checked_free(bitmap->source_filename);
+ bitmap->source_filename = NULL;
+}
+
+inline static void TransferBitmapPointers(Bitmap *src_bitmap,
+ Bitmap *dst_bitmap)
+{
+ if (src_bitmap == NULL || dst_bitmap == NULL)
+ return;
+
+ FreeBitmapPointers(dst_bitmap);
+
+ *dst_bitmap = *src_bitmap;
+}
+
+void FreeBitmap(Bitmap *bitmap)
+{
+ if (bitmap == NULL)
+ return;
+
+ FreeBitmapPointers(bitmap);
+
+ free(bitmap);
+}
+
+Bitmap *CreateBitmapStruct(void)
+{
+#if defined(TARGET_SDL)
+ return checked_calloc(sizeof(struct SDLSurfaceInfo));
+#else
+ return checked_calloc(sizeof(struct X11DrawableInfo));
+#endif
+}
+
+Bitmap *CreateBitmap(int width, int height, int depth)
+{
+ Bitmap *new_bitmap = CreateBitmapStruct();
+ int real_width = MAX(1, width); /* prevent zero bitmap width */
+ int real_height = MAX(1, height); /* prevent zero bitmap height */
+ int real_depth = GetRealDepth(depth);
+
+#if defined(TARGET_SDL)
+ SDLCreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
+#else
+ X11CreateBitmapContent(new_bitmap, real_width, real_height, real_depth);
+#endif
+
+ new_bitmap->width = real_width;
+ new_bitmap->height = real_height;
+
+ return new_bitmap;
+}
+
+void ReCreateBitmap(Bitmap **bitmap, int width, int height, int depth)
+{
+ Bitmap *new_bitmap = CreateBitmap(width, height, depth);
+
+ if (*bitmap == NULL)
+ {
+ *bitmap = new_bitmap;
+ }
+ else
+ {
+ TransferBitmapPointers(new_bitmap, *bitmap);
+ free(new_bitmap);
+ }
+}
+
+void CloseWindow(DrawWindow *window)
+{
+#if defined(TARGET_X11)
+ X11CloseWindow(window);
+#endif
+}
+
+inline static boolean CheckDrawingArea(int x, int y, int width, int height,
+ int draw_mask)
+{
+ if (draw_mask == REDRAW_NONE)
+ return FALSE;
+
+ if (draw_mask & REDRAW_ALL)
+ return TRUE;
+
+ if ((draw_mask & REDRAW_FIELD) &&
+ x >= gfx.real_sx && x < gfx.real_sx + gfx.full_sxsize)
+ return TRUE;
+
+ if ((draw_mask & REDRAW_DOOR_1) &&
+ x >= gfx.dx && y < gfx.dy + gfx.dysize)
+ return TRUE;
+
+ if ((draw_mask & REDRAW_DOOR_2) &&
+ x >= gfx.dx && y >= gfx.vy)
+ return TRUE;
+
+ return FALSE;