SDL_CFLAGS := -DUSE_SDL_LIBRARY $(shell sdl-config --cflags)
SDL_LDFLAGS := $(SDL_EXTRA_LIBS) $(shell sdl-config --libs)
-X11_CFLAGS = $(X11_INCL)
+X11_CFLAGS = -DUSE_X11_LIBRARY $(X11_INCL)
X11_LDFLAGS = $(X11_LIBS) -lX11
ifeq ($(USE_SDL),true)
delay problems with lots of mouse motion events when mouse
button not pressed */
-int EventFilter(const Event *event)
+int FilterMouseMotionEvents(const Event *event)
{
if (event->type != EVENT_MOTIONNOTIFY)
return 1;
NextEvent(&event);
- if (EventFilter(&event))
+ if (FilterMouseMotionEvents(&event))
{
switch(event.type)
{
#include "main.h"
-int EventFilter(const Event *);
+int FilterMouseMotionEvents(const Event *);
void EventLoop(void);
void HandleOtherEvents(Event *);
void ClearEventQueue(void);
boolean picture_with_mask;
};
+#if 0
struct IconFileInfo
{
char *picture_filename;
char *picturemask_filename;
};
+#endif
#ifndef USE_SDL_LIBRARY
static int sound_process_id = 0;
static void InitPlayerInfo(void);
static void InitLevelInfo(void);
static void InitNetworkServer(void);
+#if 0
static void InitDisplay(void);
+#endif
static void InitSound(void);
static void InitSoundServer(void);
+#if 0
static void InitWindow(int, char **);
+#endif
static void InitGfx(void);
static void InitGfxBackground(void);
static void LoadGfx(int, struct PictureFileInfo *);
signal(SIGINT, CloseAllAndExit);
signal(SIGTERM, CloseAllAndExit);
+
+ InitBufferedDisplay(&backbuffer, &window);
+ InitEventFilter(FilterMouseMotionEvents);
+
+
+
+#if 0
+
InitDisplay();
InitWindow(argc, argv);
+#if 0
#ifndef USE_SDL_LIBRARY
XMapWindow(display, window);
FlushDisplay();
#endif
+#endif
+
+#endif
+
+
InitGfx();
InitElementProperties(); /* initializes IS_CHAR() for el2gfx() */
#endif /* !USE_SDL_LIBRARY */
}
+
+
+#if 0
+
void InitDisplay()
{
#ifdef USE_SDL_LIBRARY
#endif /* !USE_SDL_LIBRARY */
}
+#endif
+
+
+
void InitGfx()
{
int i, j;
/* create additional image buffers for double-buffering */
-#ifdef USE_SDL_LIBRARY
-
- /* create some native image surfaces for double-buffer purposes */
-
- /* create double-buffer surface for background image */
- if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
- WIN_XSIZE, WIN_YSIZE,
- WIN_SDL_DEPTH, 0, 0, 0, 0))
- == NULL)
- Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
- if ((pix[PIX_DB_BACK] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
- Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
-
- SDL_FreeSurface(sdl_image_tmp);
-
- /* create double-buffer surface for door image */
- if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
- 3 * DXSIZE, DYSIZE + VYSIZE,
- WIN_SDL_DEPTH, 0, 0, 0, 0))
- == NULL)
- Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
-
- if ((pix[PIX_DB_DOOR] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
- Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+#if 0
+ pix[PIX_DB_BACK] = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+#endif
+ pix[PIX_DB_DOOR] = CreateBitmap(3 * DXSIZE, DYSIZE + VYSIZE, DEFAULT_DEPTH);
+ pix[PIX_DB_FIELD] = CreateBitmap(FXSIZE, FYSIZE, DEFAULT_DEPTH);
- SDL_FreeSurface(sdl_image_tmp);
- /* create double-buffer surface for field image */
- if ((sdl_image_tmp = SDL_CreateRGBSurface(SDL_SWSURFACE,
- FXSIZE, FYSIZE,
- WIN_SDL_DEPTH, 0, 0, 0, 0))
- == NULL)
- Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
- if ((pix[PIX_DB_FIELD] = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
- Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+#if 0
- SDL_FreeSurface(sdl_image_tmp);
+#ifdef USE_SDL_LIBRARY
/* SDL cannot directly draw to the visible video framebuffer like X11,
but always uses a backbuffer, which is then blitted to the visible
window = pix[PIX_DB_BACK]; /* 'window' is only symbolic buffer */
pix[PIX_DB_BACK] = backbuffer; /* 'backbuffer' is SDL screen buffer */
-#else /* !USE_SDL_LIBRARY */
+#endif /* !USE_SDL_LIBRARY */
- pix[PIX_DB_BACK] = XCreatePixmap(display, window,
- WIN_XSIZE,WIN_YSIZE,
- XDefaultDepth(display,screen));
- pix[PIX_DB_DOOR] = XCreatePixmap(display, window,
- 3*DXSIZE,DYSIZE+VYSIZE,
- XDefaultDepth(display,screen));
- pix[PIX_DB_FIELD] = XCreatePixmap(display, window,
- FXSIZE,FYSIZE,
- XDefaultDepth(display,screen));
+#endif
- if (!pix[PIX_DB_BACK] || !pix[PIX_DB_DOOR] || !pix[PIX_DB_FIELD])
- Error(ERR_EXIT, "cannot create additional pixmaps");
-#endif /* !USE_SDL_LIBRARY */
#if DEBUG_TIMING
debug_print_timestamp(0, NULL); /* initialize timestamp function */
/* needed if last screen was the setup screen and fullscreen state changed */
ChangeVideoModeIfNeeded();
+#ifdef USE_SDL_LIBRARY
+ SetDrawtoField(DRAW_BACKBUFFER);
+#endif
/* map gadgets for main menu screen */
MapTapeButtons();
#include "main.h"
#include "misc.h"
+inline void SDLInitBufferedDisplay(DrawBuffer *backbuffer, DrawWindow *window)
+{
+ /* initialize SDL video */
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
+
+ /* automatically cleanup SDL stuff after exit() */
+ atexit(SDL_Quit);
+
+ /* open SDL video output device (window or fullscreen mode) */
+ if (!SDLSetVideoMode(backbuffer, window))
+ Error(ERR_EXIT, "setting video mode failed");
+
+ /* set window and icon title */
+ SDL_WM_SetCaption(WINDOW_TITLE_STRING, WINDOW_TITLE_STRING);
+
+ /* create additional buffer for double-buffering */
+
+ pix[PIX_DB_BACK] = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+
+ /* SDL cannot directly draw to the visible video framebuffer like X11,
+ but always uses a backbuffer, which is then blitted to the visible
+ video framebuffer with 'SDL_UpdateRect' (or replaced with the current
+ visible video framebuffer with 'SDL_Flip', if the hardware supports
+ this). Therefore do not use an additional backbuffer for drawing, but
+ use a symbolic buffer (distinguishable from the SDL backbuffer) called
+ 'window', which indicates that the SDL backbuffer should be updated to
+ the visible video framebuffer when attempting to blit to it.
+
+ For convenience, it seems to be a good idea to create this symbolic
+ buffer 'window' at the same size as the SDL backbuffer. Although it
+ should never be drawn to directly, it would do no harm nevertheless. */
+
+ *window = pix[PIX_DB_BACK]; /* 'window' is only symbolic buffer */
+ pix[PIX_DB_BACK] = *backbuffer; /* 'backbuffer' is SDL screen buffer */
+}
+
+inline boolean SDLSetVideoMode(DrawBuffer *backbuffer, DrawWindow *window)
+{
+ boolean success = TRUE;
+
+ if (setup.fullscreen && !fullscreen_enabled && fullscreen_available)
+ {
+ /* switch display to fullscreen mode, if available */
+ DrawWindow window_old = *backbuffer;
+ DrawWindow window_new;
+
+ if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
+ SDL_HWSURFACE|SDL_FULLSCREEN))
+ == NULL)
+ {
+ /* switching display to fullscreen mode failed */
+ Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+
+ /* do not try it again */
+ fullscreen_available = FALSE;
+ success = FALSE;
+ }
+ else
+ {
+ if (window_old)
+ SDL_FreeSurface(window_old);
+ *backbuffer = window_new;
+
+ fullscreen_enabled = TRUE;
+ success = TRUE;
+ }
+ }
+
+ if ((!setup.fullscreen && fullscreen_enabled) || !*backbuffer)
+ {
+ /* switch display to window mode */
+ DrawWindow window_old = *backbuffer;
+ DrawWindow window_new;
+
+ if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
+ SDL_HWSURFACE))
+ == NULL)
+ {
+ /* switching display to window mode failed -- should not happen */
+ Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
+
+ success = FALSE;
+ }
+ else
+ {
+ if (window_old)
+ SDL_FreeSurface(window_old);
+ *backbuffer = window_new;
+
+ fullscreen_enabled = FALSE;
+ success = TRUE;
+ }
+ }
+
+ return success;
+}
+
inline void SDLCopyArea(SDL_Surface *src_surface, SDL_Surface *dst_surface,
int src_x, int src_y,
int width, int height,
#endif
+/* definitions needed for "system.c" */
+
+#define SURFACE_FLAGS (SDL_SWSURFACE)
+
+
/* system dependent definitions */
#define PLATFORM_STRING "SDL"
/* SDL function definitions */
+inline void SDLInitBufferedDisplay(DrawBuffer *, DrawWindow *);
+inline boolean SDLSetVideoMode(Bitmap *, DrawWindow *);
inline void SDLCopyArea(SDL_Surface *, SDL_Surface *,
int, int, int, int, int, int);
inline void SDLFillRectangle(SDL_Surface *, int, int, int, int, unsigned int);
#include "main.h"
#include "misc.h"
-#include "tools.h"
+
+inline void InitEventFilter(EventFilter filter_function)
+{
+#ifdef USE_SDL_LIBRARY
+ /* set event filter to filter out certain events */
+ SDL_SetEventFilter(filter_function);
+#endif
+}
+
+inline void InitBufferedDisplay(DrawBuffer *backbuffer, DrawWindow *window)
+{
+#ifdef USE_SDL_LIBRARY
+ SDLInitBufferedDisplay(backbuffer, window);
+#else
+ X11InitBufferedDisplay(backbuffer, window);
+#endif
+}
+
+inline int GetDisplayDepth(void)
+{
+#ifdef USE_SDL_LIBRARY
+ return SDL_GetVideoSurface()->format->BitsPerPixel;
+#else
+ return XDefaultDepth(display, screen);
+#endif
+}
+
+inline Bitmap CreateBitmap(int width, int height, int depth)
+{
+ int real_depth = (depth == DEFAULT_DEPTH ? GetDisplayDepth() : depth);
+
+#ifdef USE_SDL_LIBRARY
+ SDL_Surface *surface_tmp, *surface_native;
+
+ if ((surface_tmp = SDL_CreateRGBSurface(SURFACE_FLAGS, width, height,
+ real_depth, 0, 0, 0, 0))
+ == NULL)
+ Error(ERR_EXIT, "SDL_CreateRGBSurface() failed: %s", SDL_GetError());
+
+ if ((surface_native = SDL_DisplayFormat(surface_tmp)) == NULL)
+ Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+
+ SDL_FreeSurface(surface_tmp);
+
+ return surface_native;
+#else
+ Pixmap pixmap;
+
+ if (!(pixmap = XCreatePixmap(display, window, width, height, real_depth)))
+ Error(ERR_EXIT, "cannot create pixmap");
+
+ return pixmap;
+#endif
+}
inline void ClearRectangle(Bitmap bitmap, int x, int y, int width, int height)
{
inline boolean SetVideoMode(void)
{
- boolean success = TRUE;
-
#ifdef USE_SDL_LIBRARY
- if (setup.fullscreen && !fullscreen_enabled && fullscreen_available)
- {
- /* switch display to fullscreen mode, if available */
- DrawWindow window_old = backbuffer;
- DrawWindow window_new;
-
- if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
- SDL_HWSURFACE|SDL_FULLSCREEN))
- == NULL)
- {
- /* switching display to fullscreen mode failed */
- Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
-
- /* do not try it again */
- fullscreen_available = FALSE;
- success = FALSE;
- }
- else
- {
- if (window_old)
- SDL_FreeSurface(window_old);
- backbuffer = window_new;
-
- fullscreen_enabled = TRUE;
- success = TRUE;
- }
- }
-
- if ((!setup.fullscreen && fullscreen_enabled) || !backbuffer)
- {
- /* switch display to window mode */
- DrawWindow window_old = backbuffer;
- DrawWindow window_new;
-
- if ((window_new = SDL_SetVideoMode(WIN_XSIZE, WIN_YSIZE, WIN_SDL_DEPTH,
- SDL_HWSURFACE))
- == NULL)
- {
- /* switching display to window mode failed -- should not happen */
- Error(ERR_WARN, "SDL_SetVideoMode() failed: %s", SDL_GetError());
-
- success = FALSE;
- }
- else
- {
- if (window_old)
- SDL_FreeSurface(window_old);
- backbuffer = window_new;
-
- fullscreen_enabled = FALSE;
- success = TRUE;
- }
- }
+ return SDLSetVideoMode(&backbuffer, &window);
#else
+ boolean success = TRUE;
+
if (setup.fullscreen && fullscreen_available)
{
Error(ERR_WARN, "fullscreen not available in X11 version");
success = FALSE;
}
-#endif
return success;
+#endif
}
inline void ChangeVideoModeIfNeeded(void)
if ((setup.fullscreen && !fullscreen_enabled && fullscreen_available) ||
(!setup.fullscreen && fullscreen_enabled))
SetVideoMode();
- SetDrawtoField(DRAW_BACKBUFFER);
#endif
}
#ifndef SYSTEM_H
#define SYSTEM_H
-#if !defined(USE_SDL_LIBRARY)
-#define USE_X11_LIBRARY
-#endif
-
#if defined(XPM_INCLUDE_FILE) && !defined(MSDOS)
#define USE_XPM_LIBRARY
#include XPM_INCLUDE_FILE
#include "msdos.h"
#endif
-#define FULLSCREEN_NOT_AVAILABLE FALSE
-#define FULLSCREEN_AVAILABLE TRUE
-
#if defined(USE_SDL_LIBRARY)
#include "sdl.h"
#elif defined(USE_X11_LIBRARY)
#include "x11.h"
#endif
+
+/* system-wide contant definitions */
+
+#define DEFAULT_DEPTH 0
+
+#define FULLSCREEN_NOT_AVAILABLE FALSE
+#define FULLSCREEN_AVAILABLE TRUE
+
+
+/* system-wide type definitions */
+
+typedef int (*EventFilter)(const Event *);
+
+
+/* system-wide function definitions */
+
+inline void InitEventFilter(EventFilter);
+inline void InitBufferedDisplay(DrawBuffer *, DrawWindow *);
+inline int GetDisplayDepth(void);
+inline Bitmap CreateBitmap(int, int, int);
inline void ClearRectangle(Bitmap, int, int, int, int);
inline void BlitBitmap(Bitmap, Bitmap, int, int, int, int, int, int);
inline void SetClipMask(GC, Pixmap);
#ifdef USE_X11_LIBRARY
+#include "main.h"
+#include "misc.h"
+
+struct IconFileInfo
+{
+ char *picture_filename;
+ char *picturemask_filename;
+};
+
+static void X11InitDisplay()
+{
+#ifndef MSDOS
+ XVisualInfo vinfo_template, *vinfo;
+ int num_visuals;
+#endif
+ unsigned int depth;
+
+ /* connect to X server */
+ if (!(display = XOpenDisplay(options.display_name)))
+ Error(ERR_EXIT, "cannot connect to X server %s",
+ XDisplayName(options.display_name));
+
+ screen = DefaultScreen(display);
+ visual = DefaultVisual(display, screen);
+ depth = DefaultDepth(display, screen);
+ cmap = DefaultColormap(display, screen);
+
+#ifndef MSDOS
+ /* look for good enough visual */
+ vinfo_template.screen = screen;
+ vinfo_template.class = (depth == 8 ? PseudoColor : TrueColor);
+ vinfo_template.depth = depth;
+ if ((vinfo = XGetVisualInfo(display, VisualScreenMask | VisualClassMask |
+ VisualDepthMask, &vinfo_template, &num_visuals)))
+ {
+ visual = vinfo->visual;
+ XFree((void *)vinfo);
+ }
+
+ /* got appropriate visual? */
+ if (depth < 8)
+ {
+ printf("Sorry, displays with less than 8 bits per pixel not supported.\n");
+ exit(-1);
+ }
+ else if ((depth ==8 && visual->class != PseudoColor) ||
+ (depth > 8 && visual->class != TrueColor &&
+ visual->class != DirectColor))
+ {
+ printf("Sorry, cannot get appropriate visual.\n");
+ exit(-1);
+ }
+#endif /* !MSDOS */
+}
+
+static void X11InitWindow()
+{
+ unsigned int border_width = 4;
+ XGCValues gc_values;
+ unsigned long gc_valuemask;
+#ifndef MSDOS
+ XTextProperty windowName, iconName;
+ Pixmap icon_pixmap, iconmask_pixmap;
+ unsigned int icon_width, icon_height;
+ int icon_hot_x, icon_hot_y;
+ char icon_filename[256];
+ XSizeHints size_hints;
+ XWMHints wm_hints;
+ XClassHint class_hints;
+ char *window_name = WINDOW_TITLE_STRING;
+ char *icon_name = WINDOW_TITLE_STRING;
+ long window_event_mask;
+ Atom proto_atom = None, delete_atom = None;
+#endif
+ int screen_width, screen_height;
+ int win_xpos = WIN_XPOS, win_ypos = WIN_YPOS;
+ unsigned long pen_fg = WhitePixel(display,screen);
+ unsigned long pen_bg = BlackPixel(display,screen);
+ const int width = WIN_XSIZE, height = WIN_YSIZE;
+
+#ifndef MSDOS
+ static struct IconFileInfo icon_pic =
+ {
+ "rocks_icon.xbm",
+ "rocks_iconmask.xbm"
+ };
+#endif
+
+ screen_width = XDisplayWidth(display, screen);
+ screen_height = XDisplayHeight(display, screen);
+
+ win_xpos = (screen_width - width) / 2;
+ win_ypos = (screen_height - height) / 2;
+
+ window = XCreateSimpleWindow(display, RootWindow(display, screen),
+ win_xpos, win_ypos, width, height, border_width,
+ pen_fg, pen_bg);
+
+#ifndef MSDOS
+ proto_atom = XInternAtom(display, "WM_PROTOCOLS", FALSE);
+ delete_atom = XInternAtom(display, "WM_DELETE_WINDOW", FALSE);
+ if ((proto_atom != None) && (delete_atom != None))
+ XChangeProperty(display, window, proto_atom, XA_ATOM, 32,
+ PropModePrepend, (unsigned char *) &delete_atom, 1);
+
+ sprintf(icon_filename, "%s/%s/%s",
+ options.ro_base_directory, GRAPHICS_DIRECTORY,
+ icon_pic.picture_filename);
+ XReadBitmapFile(display,window,icon_filename,
+ &icon_width,&icon_height,
+ &icon_pixmap,&icon_hot_x,&icon_hot_y);
+ if (!icon_pixmap)
+ Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
+
+ sprintf(icon_filename, "%s/%s/%s",
+ options.ro_base_directory, GRAPHICS_DIRECTORY,
+ icon_pic.picturemask_filename);
+ XReadBitmapFile(display,window,icon_filename,
+ &icon_width,&icon_height,
+ &iconmask_pixmap,&icon_hot_x,&icon_hot_y);
+ if (!iconmask_pixmap)
+ Error(ERR_EXIT, "cannot read icon bitmap file '%s'", icon_filename);
+
+ size_hints.width = size_hints.min_width = size_hints.max_width = width;
+ size_hints.height = size_hints.min_height = size_hints.max_height = height;
+ size_hints.flags = PSize | PMinSize | PMaxSize;
+
+ if (win_xpos || win_ypos)
+ {
+ size_hints.x = win_xpos;
+ size_hints.y = win_ypos;
+ size_hints.flags |= PPosition;
+ }
+
+ if (!XStringListToTextProperty(&window_name, 1, &windowName))
+ Error(ERR_EXIT, "structure allocation for windowName failed");
+
+ if (!XStringListToTextProperty(&icon_name, 1, &iconName))
+ Error(ERR_EXIT, "structure allocation for iconName failed");
+
+ wm_hints.initial_state = NormalState;
+ wm_hints.input = True;
+ wm_hints.icon_pixmap = icon_pixmap;
+ wm_hints.icon_mask = iconmask_pixmap;
+ wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
+
+ class_hints.res_name = program_name;
+ class_hints.res_class = "Rocks'n'Diamonds";
+
+ XSetWMProperties(display, window, &windowName, &iconName,
+ NULL, 0, &size_hints, &wm_hints,
+ &class_hints);
+
+ XFree(windowName.value);
+ XFree(iconName.value);
+
+ /* Select event types wanted */
+ window_event_mask =
+ ExposureMask | StructureNotifyMask | FocusChangeMask |
+ ButtonPressMask | ButtonReleaseMask | PointerMotionMask |
+ PointerMotionHintMask | KeyPressMask | KeyReleaseMask;
+
+ XSelectInput(display, window, window_event_mask);
+#endif
+
+ /* create GC for drawing with window depth and background color (black) */
+ gc_values.graphics_exposures = False;
+ gc_values.foreground = pen_bg;
+ gc_values.background = pen_bg;
+ gc_valuemask = GCGraphicsExposures | GCForeground | GCBackground;
+ gc = XCreateGC(display, window, gc_valuemask, &gc_values);
+}
+
+inline void X11InitBufferedDisplay(DrawBuffer *unused1, DrawWindow *unused2)
+{
+ X11InitDisplay();
+ X11InitWindow();
+
+ XMapWindow(display, window);
+ FlushDisplay();
+
+ pix[PIX_DB_BACK] = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
+}
+
#endif /* USE_X11_LIBRARY */
#define KEY_F23 XK_F23
#define KEY_F24 XK_F24
+
+/* X11 function definitions */
+
+inline void X11InitBufferedDisplay(DrawBuffer *, DrawWindow *);
+
#endif /* X11_H */