rnd-20111007-1-src
[rocksndiamonds.git] / src / libgame / msdos.c
index 53a0b08fe24e8d370bee631ddf8520b51f6f4990..c4c6ff4f4cceca78a66b418d0a00ed3ba78eff67 100644 (file)
@@ -1,21 +1,27 @@
 /***********************************************************
-*  Rocks'n'Diamonds -- McDuffin Strikes Back!              *
+* Artsoft Retro-Game Library                               *
 *----------------------------------------------------------*
-*  ©1995 Artsoft Development                               *
-*        Holger Schemel                                    *
-*        33659 Bielefeld-Senne                             *
-*        Telefon: (0521) 493245                            *
-*        eMail: aeglos@valinor.owl.de                      *
-*               aeglos@uni-paderborn.de                    *
-*               q99492@pbhrzx.uni-paderborn.de             *
+* (c) 1994-2006 Artsoft Entertainment                      *
+*               Holger Schemel                             *
+*               Detmolder Strasse 189                      *
+*               33604 Bielefeld                            *
+*               Germany                                    *
+*               e-mail: info@artsoft.org                   *
 *----------------------------------------------------------*
-*  msdos.c                                                 *
+* msdos.c                                                  *
 ***********************************************************/
 
-#include "libgame.h"
+#include "system.h"
+
 
 #if defined(PLATFORM_MSDOS)
 
+#include "sound.h"
+#include "joystick.h"
+#include "misc.h"
+#include "setup.h"
+#include "pcx.h"
+
 #define AllegroDefaultScreen() (display->screens[display->default_screen])
 
 /* allegro driver declarations */
@@ -48,22 +54,16 @@ static int global_colormap_entries_used = 0;
 
 boolean wait_for_vsync;
 
-/*
-extern int playing_sounds;
-extern struct SoundControl playlist[MAX_SOUNDS_PLAYING];
-extern struct SoundControl emptySoundControl;
-*/
-
 static BITMAP *Read_PCX_to_AllegroBitmap(char *);
 
 static void allegro_init_drivers()
 {
   int i;
 
-  for (i=0; i<MAX_EVENT_BUFFER; i++)
+  for (i = 0; i < MAX_EVENT_BUFFER; i++)
     event_buffer[i].type = 0;
 
-  for (i=0; i<MAX_SCANCODES; i++)
+  for (i = 0; i < MAX_SCANCODES; i++)
     key_press_state[i] = KeyReleaseMask;
 
   last_mouse_pos = mouse_pos;
@@ -86,7 +86,7 @@ static void allegro_init_drivers()
 
 static boolean allegro_init_audio()
 {
-  reserve_voices(MAX_SOUNDS_PLAYING, 0);
+  reserve_voices(NUM_MIXER_CHANNELS, 0);
 
   if (install_sound(DIGI_AUTODETECT, MIDI_NONE, NULL) == -1)
     if (install_sound(DIGI_SB, MIDI_NONE, NULL) == -1)
@@ -234,25 +234,7 @@ static KeySym ScancodeToKeySym(byte scancode)
   }
 }
 
-void XMapWindow(Display *display, Window window)
-{
-  int x, y;
-  unsigned int width, height;
-  boolean mouse_off;
-
-  x = AllegroDefaultScreen().x;
-  y = AllegroDefaultScreen().y;
-  width = AllegroDefaultScreen().width;
-  height = AllegroDefaultScreen().height;
-
-  mouse_off = hide_mouse(display, x, y, width, height);
-  blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
-
-  if (mouse_off)
-    unhide_mouse(display);
-}
-
-static unsigned long AllocColorCell(int r, int g, int b)
+Pixel AllegroAllocColorCell(int r, int g, int b)
 {
   byte pixel_mapping = 0;
   int i;
@@ -262,7 +244,7 @@ static unsigned long AllocColorCell(int r, int g, int b)
   b >>= 10;
 
   /* try to use existing colors from the global colormap */
-  for (i=0; i<global_colormap_entries_used; i++)
+  for (i = 0; i < global_colormap_entries_used; i++)
   {
     if (r == global_colormap[i].r &&
        g == global_colormap[i].g &&
@@ -278,24 +260,46 @@ static unsigned long AllocColorCell(int r, int g, int b)
     if (global_colormap_entries_used < MAX_COLORS)
       global_colormap_entries_used++;
 
+    i = global_colormap_entries_used - 1;
+
     global_colormap[i].r = r;
     global_colormap[i].g = g;
     global_colormap[i].b = b;
 
+    set_palette(global_colormap);
+
     pixel_mapping = i;
   }
 
   return pixel_mapping;
 }
 
+void XMapWindow(Display *display, Window window)
+{
+  int x, y;
+  unsigned int width, height;
+  boolean mouse_off;
+
+  x = AllegroDefaultScreen().x;
+  y = AllegroDefaultScreen().y;
+  width = AllegroDefaultScreen().width;
+  height = AllegroDefaultScreen().height;
+
+  mouse_off = hide_mouse(display, x, y, width, height);
+  blit((BITMAP *)window, video_bitmap, 0, 0, x, y, width, height);
+
+  if (mouse_off)
+    unhide_mouse(display);
+}
+
 Display *XOpenDisplay(char *display_name)
 {
   Screen *screen;
   Display *display;
   BITMAP *mouse_bitmap = NULL;
+  char *mouse_filename = getCustomImageFilename(program.msdos_cursor_filename);
 
-  mouse_bitmap = Read_PCX_to_AllegroBitmap(program.msdos_pointer_filename);
-  if (mouse_bitmap == NULL)
+  if ((mouse_bitmap = Read_PCX_to_AllegroBitmap(mouse_filename)) == NULL)
     return NULL;
 
   screen = malloc(sizeof(Screen));
@@ -303,13 +307,8 @@ Display *XOpenDisplay(char *display_name)
 
   screen[0].cmap = 0;
   screen[0].root = 0;
-#if 0
-  screen[0].white_pixel = 0xFF;
-  screen[0].black_pixel = 0x00;
-#else
-  screen[0].white_pixel = AllocColorCell(0xFFFF, 0xFFFF, 0xFFFF);
-  screen[0].black_pixel = AllocColorCell(0x0000, 0x0000, 0x0000);
-#endif
+  screen[0].white_pixel = AllegroAllocColorCell(0xFFFF, 0xFFFF, 0xFFFF);
+  screen[0].black_pixel = AllegroAllocColorCell(0x0000, 0x0000, 0x0000);
   screen[0].video_bitmap = NULL;
 
   display->default_screen = 0;
@@ -330,8 +329,8 @@ Display *XOpenDisplay(char *display_name)
 
 Window XCreateSimpleWindow(Display *display, Window parent, int x, int y,
                           unsigned int width, unsigned int height,
-                          unsigned int border_width, unsigned long border,
-                          unsigned long background)
+                          unsigned int border_width, unsigned int border,
+                          unsigned int background)
 {
   video_bitmap = create_video_bitmap(XRES, YRES);
   clear_to_color(video_bitmap, background);
@@ -379,11 +378,10 @@ Status XStringListToTextProperty(char **list, int count,
 
 void XFree(void *data)
 {
-  if (data)
-    free(data);
+  checked_free(data);
 }
 
-GC XCreateGC(Display *display, Drawable d, unsigned long value_mask,
+GC XCreateGC(Display *display, Drawable d, unsigned int value_mask,
             XGCValues *values)
 {
   XGCValues *gcv;
@@ -442,8 +440,7 @@ Pixmap XCreatePixmap(Display *display, Drawable d, unsigned int width,
   BITMAP *bitmap = NULL;
 
   if (gfx_capabilities & GFX_HW_VRAM_BLIT &&
-      width  == playfield.scrollbuffer_width &&
-      height == playfield.scrollbuffer_height)
+      width == gfx.scrollbuffer_width && height == gfx.scrollbuffer_height)
     bitmap = create_video_bitmap(width, height);
 
   if (bitmap == NULL)
@@ -503,12 +500,10 @@ static BITMAP *Image_to_AllegroBitmap(Image *image)
   byte *src_ptr = image->data;
   byte pixel_mapping[MAX_COLORS];
   unsigned int depth = 8;
-
-#if 0
-  int i, j, x, y;
-#else
   int i, x, y;
-#endif
+
+  if (image->type == IMAGETYPE_TRUECOLOR && depth == 8)
+    Error(ERR_EXIT, "cannot handle true-color images on 8-bit display");
 
   /* allocate new allegro bitmap structure */
   if ((bitmap = create_bitmap_ex(depth, image->width, image->height)) == NULL)
@@ -520,55 +515,19 @@ static BITMAP *Image_to_AllegroBitmap(Image *image)
   clear(bitmap);
 
   /* try to use existing colors from the global colormap */
-  for (i=0; i<MAX_COLORS; i++)
+  for (i = 0; i < MAX_COLORS; i++)
   {
-
-#if 0
-    int r, g, b;
-#endif
-
     if (!image->rgb.color_used[i])
       continue;
 
-
-#if 0
-    r = image->rgb.red[i] >> 10;
-    g = image->rgb.green[i] >> 10;
-    b = image->rgb.blue[i] >> 10;
-
-    for (j=0; j<global_colormap_entries_used; j++)
-    {
-      if (r == global_colormap[j].r &&
-         g == global_colormap[j].g &&
-         b == global_colormap[j].b)            /* color found */
-      {
-       pixel_mapping[i] = j;
-       break;
-      }
-    }
-
-    if (j == global_colormap_entries_used)     /* color not found */
-    {
-      if (global_colormap_entries_used < MAX_COLORS)
-       global_colormap_entries_used++;
-
-      global_colormap[j].r = r;
-      global_colormap[j].g = g;
-      global_colormap[j].b = b;
-
-      pixel_mapping[i] = j;
-    }
-#else
-    pixel_mapping[i] = AllocColorCell(image->rgb.red[i],
-                                     image->rgb.green[i],
-                                     image->rgb.blue[i]);
-#endif
-
+    pixel_mapping[i] = AllegroAllocColorCell(image->rgb.red[i],
+                                            image->rgb.green[i],
+                                            image->rgb.blue[i]);
   }
 
   /* copy bitmap data */
-  for (y=0; y<image->height; y++)
-    for (x=0; x<image->width; x++)
+  for (y = 0; y < image->height; y++)
+    for (x = 0; x < image->width; x++)
       putpixel(bitmap, x, y, pixel_mapping[*src_ptr++]);
 
   return bitmap;
@@ -601,7 +560,10 @@ int Read_PCX_to_Pixmap(Display *display, Window window, GC gc, char *filename,
     return errno_pcx;
 
   *pixmap = (Pixmap)bitmap;
-  *pixmap_mask = (Pixmap)bitmap;
+
+  /* pixmap_mask will never be used in Allegro (which uses masked_blit()),
+     so use non-NULL dummy pointer to empty Pixmap */
+  *pixmap_mask = (Pixmap)DUMMY_MASK;
 
   return PCX_Success;
 }
@@ -635,11 +597,13 @@ void XFreePixmap(Display *display, Pixmap pixmap)
 
 void XFreeGC(Display *display, GC gc)
 {
-  XGCValues *gcv;
+  XGCValues *gcv = (XGCValues *)gc;
+
+  checked_free(gcv);
+}
 
-  gcv = (XGCValues *)gc;
-  if (gcv)
-    free(gcv);
+void XUnmapWindow(Display *display, Window window)
+{
 }
 
 void XCloseDisplay(Display *display)
@@ -649,11 +613,8 @@ void XCloseDisplay(Display *display)
   if (is_screen_bitmap(bitmap))
     destroy_bitmap(bitmap);
 
-  if (display->screens)
-    free(display->screens);
-
-  if (display)
-    free(display);
+  checked_free(display->screens);
+  checked_free(display);
 
   /* return to text mode (or DOS box on Windows screen) */
   set_gfx_mode(GFX_TEXT, 0, 0, 0, 0);
@@ -704,7 +665,7 @@ static void HandleKeyboardRaw(int mode)
 {
   int i;
 
-  for (i=0; i<MAX_SCANCODES; i++)
+  for (i = 0; i < MAX_SCANCODES; i++)
   {
     int scancode, new_state, event_type;
     char key_pressed;
@@ -816,7 +777,7 @@ int XPending(Display *display)
   /* mouse button event */
   if (mouse_b != last_mouse_b)
   {
-    for (i=0; i<3; i++)                /* check all three mouse buttons */
+    for (i = 0; i < 3; i++)    /* check all three mouse buttons */
     {
       int bitmask = (1 << i);
 
@@ -850,7 +811,7 @@ int XLookupString(XKeyEvent *key_event, char *buffer, int buffer_size,
   return 0;
 }
 
-void XSetForeground(Display *display, GC gc, unsigned long pixel)
+void XSetForeground(Display *display, GC gc, unsigned int pixel)
 {
   XGCValues *gcv = (XGCValues *)gc;
 
@@ -887,6 +848,10 @@ void XDestroyImage(XImage *ximage)
 {
 }
 
+void XDestroyWindow(Display *display, Window window)
+{
+}
+
 Bool XQueryPointer(Display *display, Window window,
                   Window *root, Window *child, int *root_x, int *root_y,
                   int *win_x, int *win_y, unsigned int *mask)
@@ -908,9 +873,67 @@ void XAutoRepeatOff(Display *display)
   keyboard_auto_repeat = FALSE;
 }
 
-boolean MSDOSOpenAudio(void)
+void AllegroDrawLine(Drawable d, int from_x, int from_y, int to_x, int to_y,
+                    Pixel color)
+{
+  boolean mouse_off = FALSE;
+
+  if ((BITMAP *)d == video_bitmap)
+  {
+    int dx = AllegroDefaultScreen().x;
+    int dy = AllegroDefaultScreen().y;
+    int x1, y1, x2, y2;
+
+    from_x += dx;
+    from_y += dy;
+    to_x += dx;
+    to_y += dy;
+
+    x1 = (from_x < to_x ? from_x : to_x);
+    y1 = (from_y < to_y ? from_y : to_y);
+    x2 = (from_x < to_x ? to_x : from_x);
+    y2 = (from_y < to_y ? to_y : from_y);
+
+    freeze_mouse_flag = TRUE;
+    mouse_off = hide_mouse(display, x1, y1, x2 - x1 + 1, y2 - y1 + 1);
+  }
+
+  line((BITMAP *)d, from_x, from_y, to_x, to_y, color);
+
+  if (mouse_off)
+    unhide_mouse(display);
+
+  freeze_mouse_flag = FALSE;
+}
+
+Pixel AllegroGetPixel(Drawable d, int x, int y)
 {
-  return allegro_init_audio();
+  return getpixel((BITMAP *)d, x, y);
+}
+
+void AllegroZoomBitmap(Drawable src, Drawable dst,
+                      int src_width, int src_height,
+                      int dst_width, int dst_height)
+{
+  stretch_blit((BITMAP *)src, (BITMAP *)dst,
+              0, 0, src_width, src_height, 0, 0, dst_width, dst_height);
+}
+
+void MSDOSOpenAudio(void)
+{
+  if (allegro_init_audio())
+  {
+    audio.sound_available = TRUE;
+    audio.music_available = TRUE;
+    audio.loops_available = TRUE;
+    audio.sound_enabled = TRUE;
+
+    audio.num_channels = NUM_MIXER_CHANNELS;
+    audio.music_channel = MUSIC_CHANNEL;
+    audio.first_sound_channel = FIRST_SOUND_CHANNEL;
+
+    Mixer_InitChannels();
+  }
 }
 
 void MSDOSCloseAudio(void)
@@ -923,4 +946,57 @@ void NetworkServer(int port, int serveronly)
   Error(ERR_WARN, "networking not supported in DOS version");
 }
 
+
+/* ========================================================================= */
+/* joystick functions                                                        */
+/* ========================================================================= */
+
+void MSDOSInitJoysticks()
+{
+  int i;
+
+  /* start from scratch */
+  remove_joystick();
+
+  /* try to access two joysticks; if that fails, try to access just one */
+  if (install_joystick(JOY_TYPE_2PADS) == 0 ||
+      install_joystick(JOY_TYPE_AUTODETECT) == 0)
+    joystick.status = JOYSTICK_ACTIVATED;
+
+  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 >= num_joysticks)
+      joystick_nr = -1;
+
+    /* misuse joystick file descriptor variable to store joystick number */
+    joystick.fd[i] = joystick_nr;
+  }
+}
+
+boolean MSDOSReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
+{
+  /* the allegro global variable 'num_joysticks' contains the number
+     of joysticks found at initialization under MS-DOS / Windows */
+
+  if (nr < 0 || nr >= num_joysticks)
+    return FALSE;
+
+  poll_joystick();
+
+  if (x != NULL)
+    *x = joy[nr].stick[0].axis[0].pos;
+  if (y != NULL)
+    *y = joy[nr].stick[0].axis[1].pos;
+
+  if (b1 != NULL)
+    *b1 = joy[nr].button[0].b;
+  if (b2 != NULL)
+    *b2 = joy[nr].button[1].b;
+
+  return TRUE;
+}
+
 #endif /* PLATFORM_MSDOS */