added optional button to restart game (door, panel and touch variants)
[rocksndiamonds.git] / src / libgame / system.c
index edae9c60944407647aa230587271253dba7938fd..c1abb8a41ab1d11d7d43f34f5c128dea14694e99 100644 (file)
@@ -69,22 +69,23 @@ int                 FrameCounter = 0;
 // init/close functions
 // ============================================================================
 
-void InitProgramInfo(char *argv0, char *config_filename, char *userdata_subdir,
-                    char *program_title, char *icon_title,
+void InitProgramInfo(char *command_filename,
+                    char *config_filename, char *userdata_subdir,
+                    char *program_basename, char *program_title,
                     char *icon_filename, char *cookie_prefix,
                     char *program_version_string, int program_version)
 {
-  program.command_basepath = getBasePath(argv0);
-  program.command_basename = getBaseName(argv0);
+  program.command_basepath = getBasePath(command_filename);
+  program.command_basename = getBaseName(command_filename);
 
   program.config_filename = config_filename;
 
   program.userdata_subdir = userdata_subdir;
   program.userdata_path = getMainUserGameDataDir();
 
+  program.program_basename = program_basename;
   program.program_title = program_title;
   program.window_title = "(undefined)";
-  program.icon_title = icon_title;
 
   program.icon_filename = icon_filename;
 
@@ -98,10 +99,10 @@ void InitProgramInfo(char *argv0, char *config_filename, char *userdata_subdir,
 
   program.version_string = program_version_string;
 
-  program.log_filename[LOG_OUT_ID] = getLogFilename(LOG_OUT_BASENAME);
-  program.log_filename[LOG_ERR_ID] = getLogFilename(LOG_ERR_BASENAME);
-  program.log_file[LOG_OUT_ID] = program.log_file_default[LOG_OUT_ID] = stdout;
-  program.log_file[LOG_ERR_ID] = program.log_file_default[LOG_ERR_ID] = stderr;
+  program.log_filename = getLogFilename(getLogBasename(program_basename));
+  program.log_file = program.log_file_default = stdout;
+
+  program.api_thread_count = 0;
 
   program.headless = FALSE;
 }
@@ -128,34 +129,7 @@ void InitRuntimeInfo()
   runtime.uses_touch_device = FALSE;
 #endif
 
-  runtime.api_server = setup.api_server;
-}
-
-void InitScoresInfo(void)
-{
-  char *global_scores_dir = getPath2(getCommonDataDir(), SCORES_DIRECTORY);
-
-  program.global_scores = directoryExists(global_scores_dir);
-  program.many_scores_per_name = !program.global_scores;
-
-#if 0
-  if (options.debug)
-  {
-    if (program.global_scores)
-    {
-      Debug("internal:path", "Using global, multi-user scores directory '%s'.",
-           global_scores_dir);
-      Debug("internal:path", "Remove to enable single-user scores directory.");
-      Debug("internal:path", "(This enables multipe score entries per user.)");
-    }
-    else
-    {
-      Debug("internal:path", "Using private, single-user scores directory.");
-    }
-  }
-#endif
-
-  free(global_scores_dir);
+  runtime.use_api_server = setup.use_api_server;
 }
 
 void SetWindowTitle(void)
@@ -194,7 +168,7 @@ void InitPlatformDependentStuff(void)
   // this is initialized in GetOptions(), but may already be used before
   options.verbose = TRUE;
 
-  OpenLogFiles();
+  OpenLogFile();
 
   int sdl_init_flags = SDL_INIT_EVENTS | SDL_INIT_NOPARACHUTE;
 
@@ -206,7 +180,7 @@ void InitPlatformDependentStuff(void)
 
 void ClosePlatformDependentStuff(void)
 {
-  CloseLogFiles();
+  CloseLogFile();
 }
 
 void InitGfxFieldInfo(int sx, int sy, int sxsize, int sysize,
@@ -298,7 +272,7 @@ void InitGfxClipRegion(boolean enabled, int x, int y, int width, int height)
   gfx.clip_height = height;
 }
 
-void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(void))
+void InitGfxDrawBusyAnimFunction(void (*draw_busy_anim_function)(boolean))
 {
   gfx.draw_busy_anim_function = draw_busy_anim_function;
 }
@@ -313,11 +287,16 @@ void InitGfxDrawGlobalBorderFunction(void (*draw_global_border_function)(int))
   gfx.draw_global_border_function = draw_global_border_function;
 }
 
-void InitGfxDrawTileCursorFunction(void (*draw_tile_cursor_function)(int))
+void InitGfxDrawTileCursorFunction(void (*draw_tile_cursor_function)(int, int))
 {
   gfx.draw_tile_cursor_function = draw_tile_cursor_function;
 }
 
+void InitGfxDrawEnvelopeRequestFunction(void (*draw_envelope_request_function)(int))
+{
+  gfx.draw_envelope_request_function = draw_envelope_request_function;
+}
+
 void InitGfxCustomArtworkInfo(void)
 {
   gfx.override_level_graphics = FALSE;
@@ -474,7 +453,8 @@ void SetDrawBackgroundMask(int draw_background_mask)
   gfx.draw_background_mask = draw_background_mask;
 }
 
-static void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
+void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask,
+                        int x, int y, int width, int height)
 {
   if (background_bitmap_tile != NULL)
     gfx.background_bitmap_mask |= mask;
@@ -485,40 +465,19 @@ static void SetBackgroundBitmap(Bitmap *background_bitmap_tile, int mask)
     return;
 
   if (mask == REDRAW_ALL)
-    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
+    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap,
+                   x, y, width, height,
                    0, 0, video.width, video.height);
   else if (mask == REDRAW_FIELD)
-    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
+    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap,
+                   x, y, width, height,
                    gfx.real_sx, gfx.real_sy, gfx.full_sxsize, gfx.full_sysize);
   else if (mask == REDRAW_DOOR_1)
-    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap, 0, 0, 0, 0,
+    BlitBitmapTiled(background_bitmap_tile, gfx.background_bitmap,
+                   x, y, width, height,
                    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
@@ -592,14 +551,14 @@ void InitVideoBuffer(int width, int height, int depth, boolean fullscreen)
   video.window_scaling_available = WINDOW_SCALING_STATUS;
 
   video.frame_counter = 0;
-  video.frame_delay = 0;
-  video.frame_delay_value = GAME_FRAME_DELAY;
+  video.frame_delay.count = 0;
+  video.frame_delay.value = GAME_FRAME_DELAY;
 
   video.shifted_up = FALSE;
   video.shifted_up_pos = 0;
   video.shifted_up_pos_last = 0;
-  video.shifted_up_delay = 0;
-  video.shifted_up_delay_value = ONE_SECOND_DELAY / 4;
+  video.shifted_up_delay.count = 0;
+  video.shifted_up_delay.value = ONE_SECOND_DELAY / 4;
 
   SDLInitVideoBuffer(fullscreen);
 
@@ -640,9 +599,22 @@ void FreeBitmap(Bitmap *bitmap)
   free(bitmap);
 }
 
+void ResetBitmapAlpha(Bitmap *bitmap)
+{
+  bitmap->alpha[0][0] = -1;
+  bitmap->alpha[0][1] = -1;
+  bitmap->alpha[1][0] = -1;
+  bitmap->alpha[1][1] = -1;
+  bitmap->alpha_next_blit = -1;
+}
+
 Bitmap *CreateBitmapStruct(void)
 {
-  return checked_calloc(sizeof(Bitmap));
+  Bitmap *new_bitmap = checked_calloc(sizeof(Bitmap));
+
+  ResetBitmapAlpha(new_bitmap);
+
+  return new_bitmap;
 }
 
 Bitmap *CreateBitmap(int width, int height, int depth)
@@ -715,8 +687,7 @@ void SetRedrawMaskFromArea(int x, int y, int width, int height)
     redraw_mask = REDRAW_ALL;
 }
 
-static boolean CheckDrawingArea(int x, int y, int width, int height,
-                               int draw_mask)
+static boolean CheckDrawingArea(int x, int y, int draw_mask)
 {
   if (draw_mask == REDRAW_NONE)
     return FALSE;
@@ -750,15 +721,15 @@ boolean DrawingDeactivatedField(void)
   return FALSE;
 }
 
-boolean DrawingDeactivated(int x, int y, int width, int height)
+boolean DrawingDeactivated(int x, int y)
 {
-  return CheckDrawingArea(x, y, width, height, gfx.draw_deactivation_mask);
+  return CheckDrawingArea(x, y, gfx.draw_deactivation_mask);
 }
 
 boolean DrawingOnBackground(int x, int y)
 {
-  return (CheckDrawingArea(x, y, 1, 1, gfx.background_bitmap_mask) &&
-         CheckDrawingArea(x, y, 1, 1, gfx.draw_background_mask));
+  return (CheckDrawingArea(x, y, gfx.background_bitmap_mask) &&
+         CheckDrawingArea(x, y, gfx.draw_background_mask));
 }
 
 static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
@@ -814,6 +785,12 @@ static boolean InClippedRectangle(Bitmap *bitmap, int *x, int *y,
   return TRUE;
 }
 
+void SetBitmapAlphaNextBlit(Bitmap *bitmap, int alpha)
+{
+  // set alpha value for next blitting of bitmap
+  bitmap->alpha_next_blit = alpha;
+}
+
 void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
                int src_x, int src_y, int width, int height,
                int dst_x, int dst_y)
@@ -827,7 +804,7 @@ void BlitBitmap(Bitmap *src_bitmap, Bitmap *dst_bitmap,
   if (src_bitmap == NULL || dst_bitmap == NULL)
     return;
 
-  if (DrawingDeactivated(dst_x, dst_y, width, height))
+  if (DrawingDeactivated(dst_x, dst_y))
     return;
 
   if (!InClippedRectangle(src_bitmap, &src_x, &src_y, &width, &height, FALSE) ||
@@ -931,7 +908,10 @@ void FadeRectangle(int x, int y, int width, int height,
 void FillRectangle(Bitmap *bitmap, int x, int y, int width, int height,
                   Pixel color)
 {
-  if (DrawingDeactivated(x, y, width, height))
+  if (program.headless)
+    return;
+
+  if (DrawingDeactivated(x, y))
     return;
 
   if (!InClippedRectangle(bitmap, &x, &y, &width, &height, TRUE))
@@ -958,7 +938,7 @@ void BlitBitmapMasked(Bitmap *src_bitmap, Bitmap *dst_bitmap,
                      int src_x, int src_y, int width, int height,
                      int dst_x, int dst_y)
 {
-  if (DrawingDeactivated(dst_x, dst_y, width, height))
+  if (DrawingDeactivated(dst_x, dst_y))
     return;
 
   sysCopyArea(src_bitmap, dst_bitmap, src_x, src_y, width, height,
@@ -1034,12 +1014,6 @@ void BlitToScreenMasked(Bitmap *bitmap,
     BlitTextureMasked(bitmap, src_x, src_y, width, height, dst_x, dst_y);
 }
 
-void DrawSimpleBlackLine(Bitmap *bitmap, int from_x, int from_y,
-                        int to_x, int to_y)
-{
-  SDLDrawSimpleLine(bitmap, from_x, from_y, to_x, to_y, BLACK_PIXEL);
-}
-
 void DrawSimpleWhiteLine(Bitmap *bitmap, int from_x, int from_y,
                         int to_x, int to_y)
 {
@@ -1108,15 +1082,6 @@ Pixel GetPixelFromRGB(Bitmap *bitmap, unsigned int color_r,
   return SDL_MapRGB(bitmap->surface->format, color_r, color_g, color_b);
 }
 
-Pixel GetPixelFromRGBcompact(Bitmap *bitmap, unsigned int color)
-{
-  unsigned int color_r = (color >> 16) & 0xff;
-  unsigned int color_g = (color >>  8) & 0xff;
-  unsigned int color_b = (color >>  0) & 0xff;
-
-  return GetPixelFromRGB(bitmap, color_r, color_g, color_b);
-}
-
 void KeyboardAutoRepeatOn(void)
 {
   keyrepeat_status = TRUE;
@@ -1134,12 +1099,12 @@ boolean SetVideoMode(boolean fullscreen)
 
 void SetVideoFrameDelay(unsigned int frame_delay_value)
 {
-  video.frame_delay_value = frame_delay_value;
+  video.frame_delay.value = frame_delay_value;
 }
 
 unsigned int GetVideoFrameDelay(void)
 {
-  return video.frame_delay_value;
+  return video.frame_delay.value;
 }
 
 boolean ChangeVideoModeIfNeeded(boolean fullscreen)
@@ -1220,7 +1185,7 @@ void ReloadCustomImage(Bitmap *bitmap, char *basename)
   free(new_bitmap);
 }
 
-static Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
+Bitmap *ZoomBitmap(Bitmap *src_bitmap, int zoom_width, int zoom_height)
 {
   return SDLZoomBitmap(src_bitmap, zoom_width, zoom_height);
 }
@@ -1755,7 +1720,7 @@ void CheckQuitEvent(void)
     program.exit_function(0);
 }
 
-Key GetEventKey(KeyEvent *event, boolean with_modifiers)
+Key GetEventKey(KeyEvent *event)
 {
   // key up/down events in SDL2 do not return text characters anymore
   return event->keysym.sym;
@@ -1834,7 +1799,7 @@ void StartTextInput(int x, int y, int width, int height)
   if (y + height > SCREEN_KEYBOARD_POS(video.height))
   {
     video.shifted_up_pos = y + height - SCREEN_KEYBOARD_POS(video.height);
-    video.shifted_up_delay = SDL_GetTicks();
+    video.shifted_up_delay.count = SDL_GetTicks();
     video.shifted_up = TRUE;
   }
 #endif
@@ -1850,7 +1815,7 @@ void StopTextInput(void)
   if (video.shifted_up)
   {
     video.shifted_up_pos = 0;
-    video.shifted_up_delay = SDL_GetTicks();
+    video.shifted_up_delay.count = SDL_GetTicks();
     video.shifted_up = FALSE;
   }
 #endif
@@ -1870,6 +1835,24 @@ void PushUserEvent(int code, int value1, int value2)
   SDL_PushEvent((SDL_Event *)&event);
 }
 
+boolean PendingEscapeKeyEvent(void)
+{
+  if (PendingEvent())
+  {
+    Event event;
+
+    // check if any key press event is pending
+    if (SDL_PeepEvents(&event, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYDOWN) != 1)
+      return FALSE;
+
+    // check if pressed key is "Escape" key
+    if (event.key.keysym.sym == KSYM_Escape)
+      return TRUE;
+  }
+
+  return FALSE;
+}
+
 
 // ============================================================================
 // joystick functions
@@ -1915,17 +1898,19 @@ void InitEmscriptenFilesystem(void)
 {
 #if defined(PLATFORM_EMSCRIPTEN)
   EM_ASM
-  (
+  ({
+    dir = UTF8ToString($0);
+
     Module.sync_done = 0;
 
-    FS.mkdir('/persistent');           // create persistent data directory
-    FS.mount(IDBFS, {}, '/persistent');        // mount with IDBFS filesystem type
+    FS.mkdir(dir);                     // create persistent data directory
+    FS.mount(IDBFS, {}, dir);          // mount with IDBFS filesystem type
     FS.syncfs(true, function(err)      // sync persistent data into memory
     {
       assert(!err);
       Module.sync_done = 1;
     });
-  );
+  }, PERSISTENT_DIRECTORY);
 
   // wait for persistent data to be synchronized to memory
   while (emscripten_run_script_int("Module.sync_done") == 0)