rnd-20020513-1-src
[rocksndiamonds.git] / src / libgame / sdl.c
index 2441ede36ab217a67d3b8a760c9133fd7c91fcaf..42e6286bf78697605e42c52cef07c04b636c5c60 100644 (file)
@@ -13,6 +13,7 @@
 
 #include "system.h"
 #include "sound.h"
+#include "joystick.h"
 #include "misc.h"
 
 
@@ -320,6 +321,60 @@ inline void SDLDrawLines(SDL_Surface *surface, struct XY *points,
 }
 #endif
 
+inline Pixel SDLGetPixel(Bitmap *dst_bitmap, int x, int y)
+{
+  SDL_Surface *surface = dst_bitmap->surface;
+
+#ifdef FULLSCREEN_BUG
+  if (dst_bitmap == backbuffer || dst_bitmap == window)
+  {
+    x += video_xoffset;
+    y += video_yoffset;
+  }
+#endif
+
+  switch (surface->format->BytesPerPixel)
+  {
+    case 1:            /* assuming 8-bpp */
+    {
+      return *((Uint8 *)surface->pixels + y * surface->pitch + x);
+    }
+    break;
+
+    case 2:            /* probably 15-bpp or 16-bpp */
+    {
+      return *((Uint16 *)surface->pixels + y * surface->pitch / 2 + x);
+    }
+    break;
+
+  case 3:              /* slow 24-bpp mode; usually not used */
+    {
+      /* does this work? */
+      Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x * 3;
+      Uint32 color = 0;
+      int shift;
+
+      shift = surface->format->Rshift;
+      color |= *(pix + shift / 8) >> shift;
+      shift = surface->format->Gshift;
+      color |= *(pix + shift / 8) >> shift;
+      shift = surface->format->Bshift;
+      color |= *(pix + shift / 8) >> shift;
+
+      return color;
+    }
+    break;
+
+  case 4:              /* probably 32-bpp */
+    {
+      return *((Uint32 *)surface->pixels + y * surface->pitch / 4 + x);
+    }
+    break;
+  }
+
+  return 0;
+}
+
 
 /* ========================================================================= */
 /* The following functions have been taken from the SGE library              */
@@ -774,21 +829,33 @@ Bitmap *SDLLoadImage(char *filename)
 
   /* load image to temporary surface */
   if ((sdl_image_tmp = IMG_Load(filename)) == NULL)
-    Error(ERR_EXIT, "IMG_Load() failed: %s", SDL_GetError());
+  {
+    SetError("IMG_Load(): %s", SDL_GetError());
+    return NULL;
+  }
 
   /* create native non-transparent surface for current image */
   if ((new_bitmap->surface = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
-    Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+  {
+    SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+    return NULL;
+  }
 
   /* create native transparent surface for current image */
   SDL_SetColorKey(sdl_image_tmp, SDL_SRCCOLORKEY,
                  SDL_MapRGB(sdl_image_tmp->format, 0x00, 0x00, 0x00));
   if ((new_bitmap->surface_masked = SDL_DisplayFormat(sdl_image_tmp)) == NULL)
-    Error(ERR_EXIT, "SDL_DisplayFormat() failed: %s", SDL_GetError());
+  {
+    SetError("SDL_DisplayFormat(): %s", SDL_GetError());
+    return NULL;
+  }
 
   /* free temporary surface */
   SDL_FreeSurface(sdl_image_tmp);
 
+  new_bitmap->width = new_bitmap->surface->w;
+  new_bitmap->height = new_bitmap->surface->h;
+
   return new_bitmap;
 }
 
@@ -806,7 +873,7 @@ inline void SDLOpenAudio(void)
   }
 
   if (Mix_OpenAudio(DEFAULT_AUDIO_SAMPLE_RATE, AUDIO_S16,
-                   AUDIO_STEREO_CHANNELS,
+                   AUDIO_NUM_CHANNELS_STEREO,
                    DEFAULT_AUDIO_FRAGMENT_SIZE) < 0)
   {
     Error(ERR_WARN, "Mix_OpenAudio() failed: %s", SDL_GetError());
@@ -818,19 +885,12 @@ inline void SDLOpenAudio(void)
   audio.loops_available = TRUE;
   audio.sound_enabled = TRUE;
 
-  /* determine number of available channels */
-  audio.channels = Mix_AllocateChannels(MIX_CHANNELS);
-
-  if (!audio.mods_available)   /* reserve first channel for music loops */
-  {
-    if (Mix_ReserveChannels(1) == 1)
-      audio.music_channel = 0;
-    else
-      audio.music_available = FALSE;
-  }
+  /* set number of available mixer channels */
+  audio.num_channels = Mix_AllocateChannels(NUM_MIXER_CHANNELS);
+  audio.music_channel = MUSIC_CHANNEL;
+  audio.first_sound_channel = FIRST_SOUND_CHANNEL;
 
-  Mix_Volume(-1, SOUND_MAX_VOLUME);
-  Mix_VolumeMusic(SOUND_MAX_VOLUME);
+  Mixer_InitChannels();
 }
 
 inline void SDLCloseAudio(void)
@@ -878,4 +938,123 @@ inline void SDLNextEvent(Event *event)
 #endif
 }
 
+
+/* ========================================================================= */
+/* joystick functions                                                        */
+/* ========================================================================= */
+
+static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
+static int sdl_js_axis[MAX_PLAYERS][2]   = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+
+static boolean SDLOpenJoystick(int nr)
+{
+  if (nr < 0 || nr > MAX_PLAYERS)
+    return FALSE;
+
+  return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
+}
+
+static void SDLCloseJoystick(int nr)
+{
+  if (nr < 0 || nr > MAX_PLAYERS)
+    return;
+
+  SDL_JoystickClose(sdl_joystick[nr]);
+}
+
+static boolean SDLCheckJoystickOpened(int nr)
+{
+  if (nr < 0 || nr > MAX_PLAYERS)
+    return FALSE;
+
+  return (SDL_JoystickOpened(nr) ? TRUE : FALSE);
+}
+
+void HandleJoystickEvent(Event *event)
+{
+  switch(event->type)
+  {
+    case SDL_JOYAXISMOTION:
+      if (event->jaxis.axis < 2)
+       sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
+      break;
+
+    case SDL_JOYBUTTONDOWN:
+      if (event->jbutton.button < 2)
+       sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
+      break;
+
+    case SDL_JOYBUTTONUP:
+      if (event->jbutton.button < 2)
+       sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
+      break;
+
+    default:
+      break;
+  }
+}
+
+void SDLInitJoysticks()
+{
+  static boolean sdl_joystick_subsystem_initialized = FALSE;
+  int i;
+
+  if (!sdl_joystick_subsystem_initialized)
+  {
+    sdl_joystick_subsystem_initialized = TRUE;
+
+    if (SDL_Init(SDL_INIT_JOYSTICK) < 0)
+    {
+      Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
+      return;
+    }
+  }
+
+  for (i=0; i<MAX_PLAYERS; i++)
+  {
+    char *device_name = setup.input[i].joy.device_name;
+    int joystick_nr = getJoystickNrFromDeviceName(device_name);
+
+    if (joystick_nr >= SDL_NumJoysticks())
+      joystick_nr = -1;
+
+    /* misuse joystick file descriptor variable to store joystick number */
+    joystick.fd[i] = joystick_nr;
+
+    /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
+    if (SDLCheckJoystickOpened(joystick_nr))
+      SDLCloseJoystick(joystick_nr);
+
+    if (!setup.input[i].use_joystick)
+      continue;
+
+    if (!SDLOpenJoystick(joystick_nr))
+    {
+      Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
+      continue;
+    }
+
+    joystick.status = JOYSTICK_ACTIVATED;
+  }
+}
+
+boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
+{
+  if (nr < 0 || nr >= MAX_PLAYERS)
+    return FALSE;
+
+  if (x != NULL)
+    *x = sdl_js_axis[nr][0];
+  if (y != NULL)
+    *y = sdl_js_axis[nr][1];
+
+  if (b1 != NULL)
+    *b1 = sdl_js_button[nr][0];
+  if (b2 != NULL)
+    *b2 = sdl_js_button[nr][1];
+
+  return TRUE;
+}
+
 #endif /* TARGET_SDL */