return getLevelFromScreenY_RND(y);
}
+int getScreenFieldSizeX(void)
+{
+ return (tape.playing ? tape.scr_fieldx : SCR_FIELDX);
+}
+
+int getScreenFieldSizeY(void)
+{
+ return (tape.playing ? tape.scr_fieldy : SCR_FIELDY);
+}
+
void DumpTile(int x, int y)
{
int sx = SCREENX(x);
int sy = SCREENY(y);
char *token_name;
- printf_line("-", 79);
- printf("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)\n", sx, sy, x, y);
- printf_line("-", 79);
+ Info("---");
+ Info("Field Info: SCREEN(%d, %d), LEVEL(%d, %d)", sx, sy, x, y);
+ Info("---");
if (!IN_LEV_FIELD(x, y))
{
- printf("(not in level field)\n");
- printf("\n");
+ Info("(not in level field)");
+ Info("");
return;
}
- token_name = element_info[Feld[x][y]].token_name;
+ token_name = element_info[Tile[x][y]].token_name;
- printf(" Feld: %d\t['%s']\n", Feld[x][y], token_name);
- printf(" Back: %s\n", print_if_not_empty(Back[x][y]));
- printf(" Store: %s\n", print_if_not_empty(Store[x][y]));
- printf(" Store2: %s\n", print_if_not_empty(Store2[x][y]));
- printf(" StorePlayer: %s\n", print_if_not_empty(StorePlayer[x][y]));
- printf(" MovPos: %d\n", MovPos[x][y]);
- printf(" MovDir: %d\n", MovDir[x][y]);
- printf(" MovDelay: %d\n", MovDelay[x][y]);
- printf(" ChangeDelay: %d\n", ChangeDelay[x][y]);
- printf(" CustomValue: %d\n", CustomValue[x][y]);
- printf(" GfxElement: %d\n", GfxElement[x][y]);
- printf(" GfxAction: %d\n", GfxAction[x][y]);
- printf(" GfxFrame: %d [%d]\n", GfxFrame[x][y], FrameCounter);
- printf(" Player x/y: %d, %d\n", local_player->jx, local_player->jy);
- printf("\n");
+ Info("Tile: %d\t['%s']", Tile[x][y], token_name);
+ Info("Back: %s", print_if_not_empty(Back[x][y]));
+ Info("Store: %s", print_if_not_empty(Store[x][y]));
+ Info("Store2: %s", print_if_not_empty(Store2[x][y]));
+ Info("StorePlayer: %s", print_if_not_empty(StorePlayer[x][y]));
+ Info("MovPos: %d", MovPos[x][y]);
+ Info("MovDir: %d", MovDir[x][y]);
+ Info("MovDelay: %d", MovDelay[x][y]);
+ Info("ChangeDelay: %d", ChangeDelay[x][y]);
+ Info("CustomValue: %d", CustomValue[x][y]);
+ Info("GfxElement: %d", GfxElement[x][y]);
+ Info("GfxAction: %d", GfxAction[x][y]);
+ Info("GfxFrame: %d [%d]", GfxFrame[x][y], FrameCounter);
+ Info("Player x/y: %d, %d", local_player->jx, local_player->jy);
+ Info("");
}
void DumpTileFromScreen(int sx, int sy)
}
}
+int GetDrawtoField(void)
+{
+ return (drawto_field == fieldbuffer ? DRAW_TO_FIELDBUFFER : DRAW_TO_BACKBUFFER);
+}
+
static void RedrawPlayfield_RND(void)
{
if (game.envelope_active)
Bitmap *src_bitmap = getGlobalBorderBitmapFromStatus(global.border_status);
Bitmap *dst_bitmap = gfx.masked_border_bitmap_ptr;
+ // may happen for "border.draw_masked.*" with undefined "global.border.*"
+ if (src_bitmap == NULL)
+ return;
+
if (x == -1 && y == -1)
return;
void DrawTileCursor(int draw_target)
{
- Bitmap *fade_bitmap;
- Bitmap *src_bitmap;
- int src_x, src_y;
- int dst_x, dst_y;
- int graphic = IMG_GLOBAL_TILE_CURSOR;
- int frame = 0;
- int tilesize = TILESIZE_VAR;
- int width = tilesize;
- int height = tilesize;
-
- if (game_status != GAME_MODE_PLAYING)
- return;
-
- if (!tile_cursor.enabled ||
- !tile_cursor.active)
- return;
-
- if (tile_cursor.moving)
- {
- int step = TILESIZE_VAR / 4;
- int dx = tile_cursor.target_x - tile_cursor.x;
- int dy = tile_cursor.target_y - tile_cursor.y;
-
- if (ABS(dx) < step)
- tile_cursor.x = tile_cursor.target_x;
- else
- tile_cursor.x += SIGN(dx) * step;
-
- if (ABS(dy) < step)
- tile_cursor.y = tile_cursor.target_y;
- else
- tile_cursor.y += SIGN(dy) * step;
-
- if (tile_cursor.x == tile_cursor.target_x &&
- tile_cursor.y == tile_cursor.target_y)
- tile_cursor.moving = FALSE;
- }
-
- dst_x = tile_cursor.x;
- dst_y = tile_cursor.y;
-
- frame = getGraphicAnimationFrame(graphic, -1);
-
- getSizedGraphicSource(graphic, frame, tilesize, &src_bitmap, &src_x, &src_y);
-
- fade_bitmap =
- (draw_target == DRAW_TO_FADE_SOURCE ? gfx.fade_bitmap_source :
- draw_target == DRAW_TO_FADE_TARGET ? gfx.fade_bitmap_target : NULL);
-
- if (draw_target == DRAW_TO_SCREEN)
- BlitToScreenMasked(src_bitmap, src_x, src_y, width, height, dst_x, dst_y);
- else
- BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height,
- dst_x, dst_y);
+ DrawTileCursor_MM(draw_target, game_status == GAME_MODE_PLAYING);
}
void BlitScreenToBitmapExt_RND(Bitmap *target_bitmap, int fx, int fy)
diff_bar[pos++] = '\0';
- Error(ERR_INFO, "%06d [%02d] [%c%02d] %s",
+ Debug("time:frame", "%06d [%02d] [%c%02d] %s",
counter,
diff_1,
(diff_2 < 0 ? '-' : diff_2 > 0 ? '+' : ' '), ABS(diff_2),
FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP);
}
+static int getGlobalGameStatus(int status)
+{
+ return (status == GAME_MODE_PSEUDO_TYPENAME ? GAME_MODE_MAIN :
+ status == GAME_MODE_SCOREINFO ? GAME_MODE_SCORES :
+ status);
+}
+
static Bitmap *getBitmapFromGraphicOrDefault(int graphic, int default_graphic)
{
if (graphic == IMG_UNDEFINED)
return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER);
}
-Bitmap *getGlobalBorderBitmapFromStatus(int status)
+Bitmap *getGlobalBorderBitmapFromStatus(int status_raw)
{
+ int status = getGlobalGameStatus(status_raw);
int graphic =
- (status == GAME_MODE_MAIN ||
- status == GAME_MODE_PSEUDO_TYPENAME ? IMG_GLOBAL_BORDER_MAIN :
- status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES :
- status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR :
- status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING :
+ (status == GAME_MODE_MAIN ? IMG_GLOBAL_BORDER_MAIN :
+ status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES :
+ status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR :
+ status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING :
IMG_GLOBAL_BORDER);
return getGlobalBorderBitmap(graphic);
#if ONLY_REDRAW_GLOBAL_BORDER_IF_NEEDED
if (CheckIfGlobalBorderRedrawIsNeeded())
+#else
+ // determine and store new global border bitmap for current game status
+ global_border_bitmap = getGlobalBorderBitmapFromStatus(game_status);
#endif
{
// redraw global screen border (or clear, if defined to be empty)
{
for (x = 0; x < lev_fieldx; x++)
{
- if (!IS_INDESTRUCTIBLE(Feld[x][y]))
+ if (!IS_INDESTRUCTIBLE(Tile[x][y]))
BorderElement = EL_STEELWALL;
if (y != 0 && y != lev_fieldy - 1 && x != lev_fieldx - 1)
}
}
-void FloodFillLevelExt(int from_x, int from_y, int fill_element,
+void FloodFillLevelExt(int start_x, int start_y, int fill_element,
int max_array_fieldx, int max_array_fieldy,
short field[max_array_fieldx][max_array_fieldy],
int max_fieldx, int max_fieldy)
{
- int i,x,y;
- int old_element;
- static int check[4][2] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
- static int safety = 0;
+ static struct XY stack_buffer[MAX_LEV_FIELDX * MAX_LEV_FIELDY];
+ static struct XY check[4] = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
+ int old_element = field[start_x][start_y];
+ int stack_pos = 0;
- // check if starting field still has the desired content
- if (field[from_x][from_y] == fill_element)
+ // do nothing if start field already has the desired content
+ if (old_element == fill_element)
return;
- safety++;
+ stack_buffer[stack_pos++] = (struct XY){ start_x, start_y };
- if (safety > max_fieldx * max_fieldy)
- Error(ERR_EXIT, "Something went wrong in 'FloodFill()'. Please debug.");
+ while (stack_pos > 0)
+ {
+ struct XY current = stack_buffer[--stack_pos];
+ int i;
- old_element = field[from_x][from_y];
- field[from_x][from_y] = fill_element;
+ field[current.x][current.y] = fill_element;
- for (i = 0; i < 4; i++)
- {
- x = from_x + check[i][0];
- y = from_y + check[i][1];
+ for (i = 0; i < 4; i++)
+ {
+ int x = current.x + check[i].x;
+ int y = current.y + check[i].y;
- if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
- FloodFillLevelExt(x, y, fill_element, max_array_fieldx, max_array_fieldy,
- field, max_fieldx, max_fieldy);
- }
+ // check for stack buffer overflow (should not happen)
+ if (stack_pos >= MAX_LEV_FIELDX * MAX_LEV_FIELDY)
+ Fail("Stack buffer overflow in 'FloodFillLevelExt()'. Please debug.");
- safety--;
+ if (IN_FIELD(x, y, max_fieldx, max_fieldy) && field[x][y] == old_element)
+ stack_buffer[stack_pos++] = (struct XY){ x, y };
+ }
+ }
}
void FloodFillLevel(int from_x, int from_y, int fill_element,
sync_frame);
}
+int getGraphicAnimationFrameXY(int graphic, int lx, int ly)
+{
+ if (graphic_info[graphic].anim_mode & ANIM_TILED)
+ {
+ struct GraphicInfo *g = &graphic_info[graphic];
+ int xsize = MAX(1, g->anim_frames_per_line);
+ int ysize = MAX(1, g->anim_frames / xsize);
+ int xoffset = g->anim_start_frame % xsize;
+ int yoffset = g->anim_start_frame % ysize;
+ // may be needed if screen field is significantly larger than playfield
+ int x = (lx + xoffset + SCR_FIELDX * xsize) % xsize;
+ int y = (ly + yoffset + SCR_FIELDY * ysize) % ysize;
+ int sync_frame = y * xsize + x;
+
+ return sync_frame % g->anim_frames;
+ }
+ else if (graphic_info[graphic].anim_mode & ANIM_RANDOM_STATIC)
+ {
+ struct GraphicInfo *g = &graphic_info[graphic];
+ // may be needed if screen field is significantly larger than playfield
+ int x = (lx + SCR_FIELDX * lev_fieldx) % lev_fieldx;
+ int y = (ly + SCR_FIELDY * lev_fieldy) % lev_fieldy;
+ int sync_frame = GfxRandomStatic[x][y];
+
+ return sync_frame % g->anim_frames;
+ }
+ else
+ {
+ int sync_frame = (IN_LEV_FIELD(lx, ly) ? GfxFrame[lx][ly] : -1);
+
+ return getGraphicAnimationFrame(graphic, sync_frame);
+ }
+}
+
void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap)
{
struct GraphicInfo *g = &graphic_info[graphic];
if (tilesize == gfx.standard_tile_size)
*bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
else if (tilesize == game.tile_size)
- *bitmap = g->bitmaps[IMG_BITMAP_GAME];
+ *bitmap = g->bitmaps[IMG_BITMAP_PTR_GAME];
else
*bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)];
}
*g = graphic_info[IMG_CHAR_EXCLAM];
// if no in-game graphics defined, always use standard graphic size
- if (g->bitmaps[IMG_BITMAP_GAME] == NULL)
+ if (g->bitmaps[IMG_BITMAP_PTR_GAME] == NULL)
tilesize = TILESIZE;
getGraphicSourceBitmap(graphic, tilesize, bitmap);
getSizedGraphicSource(graphic, 0, MINI_TILESIZE, bitmap, x, y);
}
+void getGlobalAnimGraphicSource(int graphic, int frame,
+ Bitmap **bitmap, int *x, int *y)
+{
+ struct GraphicInfo *g = &graphic_info[graphic];
+
+ // if no graphics defined at all, use fallback graphics
+ if (g->bitmaps == NULL)
+ *g = graphic_info[IMG_CHAR_EXCLAM];
+
+ // use original size graphics, if existing, else use standard size graphics
+ if (g->bitmaps[IMG_BITMAP_PTR_ORIGINAL])
+ *bitmap = g->bitmaps[IMG_BITMAP_PTR_ORIGINAL];
+ else
+ *bitmap = g->bitmaps[IMG_BITMAP_STANDARD];
+
+ getGraphicSourceXY(graphic, frame, x, y, FALSE);
+}
+
static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap,
int *x, int *y, boolean get_backside)
{
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
- printf("DrawGraphic(): This should never happen!\n");
+ Debug("draw:DrawGraphic", "x = %d, y = %d, graphic = %d", x, y, graphic);
+ Debug("draw:DrawGraphic", "This should never happen!");
+
return;
}
#endif
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphic(): x = %d, y = %d, graphic = %d\n", x, y, graphic);
- printf("DrawGraphic(): This should never happen!\n");
+ Debug("draw:DrawFixedGraphic", "x = %d, y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawFixedGraphic", "This should never happen!");
+
return;
}
#endif
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
- printf("DrawGraphicThruMask(): This should never happen!\n");
+ Debug("draw:DrawGraphicThruMask", "x = %d,y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawGraphicThruMask", "This should never happen!");
+
return;
}
#endif
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphicThruMask(): x = %d,y = %d, graphic = %d\n",x,y,graphic);
- printf("DrawGraphicThruMask(): This should never happen!\n");
+ Debug("draw:DrawFixedGraphicThruMask", "x = %d,y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawFixedGraphicThruMask", "This should never happen!");
+
return;
}
#endif
#if DEBUG
if (!IN_SCR_FIELD(x, y))
{
- printf("DrawGraphicShifted(): x = %d, y = %d, graphic = %d\n",x,y,graphic);
- printf("DrawGraphicShifted(): This should never happen!\n");
+ Debug("draw:DrawGraphicShiftedNormal", "x = %d, y = %d, graphic = %d",
+ x, y, graphic);
+ Debug("draw:DrawGraphicShiftedNormal", "This should never happen!");
+
return;
}
#endif
if (IN_LEV_FIELD(lx, ly))
{
+ if (element == EL_EMPTY)
+ element = GfxElementEmpty[lx][ly];
+
SetRandomAnimationValue(lx, ly);
graphic = el_act_dir2img(element, GfxAction[lx][ly], GfxDir[lx][ly]);
- frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
+ frame = getGraphicAnimationFrameXY(graphic, lx, ly);
// do not use double (EM style) movement graphic when not moving
if (graphic_info[graphic].double_movement && !dx && !dy)
{
graphic = el_act_dir2img(element, ACTION_DEFAULT, GfxDir[lx][ly]);
- frame = getGraphicAnimationFrame(graphic, GfxFrame[lx][ly]);
+ frame = getGraphicAnimationFrameXY(graphic, lx, ly);
}
+
+ if (game.use_masked_elements && (dx || dy))
+ mask_mode = USE_MASKING;
}
else // border element
{
graphic = el2img(element);
- frame = getGraphicAnimationFrame(graphic, -1);
+ frame = getGraphicAnimationFrameXY(graphic, lx, ly);
}
if (element == EL_EXPANDABLE_WALL)
{
boolean left_stopped = FALSE, right_stopped = FALSE;
- if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Feld[lx - 1][ly]))
+ if (!IN_LEV_FIELD(lx - 1, ly) || IS_WALL(Tile[lx - 1][ly]))
left_stopped = TRUE;
- if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Feld[lx + 1][ly]))
+ if (!IN_LEV_FIELD(lx + 1, ly) || IS_WALL(Tile[lx + 1][ly]))
right_stopped = TRUE;
if (left_stopped && right_stopped)
void DrawLevelFieldThruMask(int x, int y)
{
- DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING);
+ DrawLevelElementExt(x, y, 0, 0, Tile[x][y], NO_CUTTING, USE_MASKING);
}
// !!! implementation of quicksand is totally broken !!!
cx = (dx > 0 ? TILESIZE_VAR - width : 0);
cy = (dy > 0 ? TILESIZE_VAR - height : 0);
- BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
- width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+ if (game.use_masked_elements)
+ {
+ int graphic0 = el2img(EL_EMPTY);
+ int frame0 = getGraphicAnimationFrameXY(graphic0, x, y);
+ Bitmap *src_bitmap0;
+ int src_x0, src_y0;
+
+ getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
+ BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+
+ BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy);
}
static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame,
getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y);
+ // only needed when using masked elements
+ int graphic0 = el2img(EL_EMPTY);
+ int frame0 = getGraphicAnimationFrameXY(graphic0, x, y);
+ Bitmap *src_bitmap0;
+ int src_x0, src_y0;
+
+ if (game.use_masked_elements)
+ getGraphicSource(graphic0, frame0, &src_bitmap0, &src_x0, &src_y0);
+
// draw simple, sloppy, non-corner-accurate crumbled border
width = (dir == 1 || dir == 2 ? crumbled_border_size_var : TILESIZE_VAR);
cx = (dir == 2 ? crumbled_border_pos_var : 0);
cy = (dir == 3 ? crumbled_border_pos_var : 0);
- BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, width, height,
- FX + sx * TILEX_VAR + cx,
- FY + sy * TILEY_VAR + cy);
+ if (game.use_masked_elements)
+ {
+ BlitBitmap(src_bitmap0, drawto_field, src_x0 + cx, src_y0 + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+
+ BlitBitmapMasked(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
// (remaining middle border part must be at least as big as corner part)
if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) ||
by = cy;
}
- BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
- width, height,
- FX + sx * TILEX_VAR + cx,
- FY + sy * TILEY_VAR + cy);
+ if (game.use_masked_elements)
+ {
+ BlitBitmap(src_bitmap0, drawto_field, src_x0 + bx, src_y0 + by,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+
+ BlitBitmapMasked(src_bitmap, drawto_field, src_x + bx, src_y + by,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
+ }
+ else
+ BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by,
+ width, height,
+ FX + sx * TILEX_VAR + cx,
+ FY + sy * TILEY_VAR + cy);
}
}
}
continue;
// do not crumble fields that are being digged or snapped
- if (Feld[xx][yy] == EL_EMPTY ||
- Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+ if (Tile[xx][yy] == EL_EMPTY ||
+ Tile[xx][yy] == EL_ELEMENT_SNAPPING)
continue;
element = TILE_GFX_ELEMENT(xx, yy);
!IN_SCR_FIELD(sxx, syy))
continue;
- if (Feld[xx][yy] == EL_ELEMENT_SNAPPING)
+ if (Tile[xx][yy] == EL_ELEMENT_SNAPPING)
continue;
element = TILE_GFX_ELEMENT(xx, yy);
if (!IN_LEV_FIELD(x, y))
return;
- if (Feld[x][y] == EL_ELEMENT_SNAPPING &&
+ if (Tile[x][y] == EL_ELEMENT_SNAPPING &&
GfxElement[x][y] != EL_UNDEFINED &&
GFX_CRUMBLED(GfxElement[x][y]))
{
int frame2 = getGraphicAnimationFrame(graphic2, step_frame);
int sx = SCREENX(x), sy = SCREENY(y);
- DrawGraphic(sx, sy, graphic1, frame1);
+ DrawScreenGraphic(sx, sy, graphic1, frame1);
DrawLevelFieldCrumbledExt(x, y, graphic2, frame2);
}
if (!IN_LEV_FIELD(xx, yy) ||
!IN_SCR_FIELD(sxx, syy) ||
- !GFX_CRUMBLED(Feld[xx][yy]) ||
+ !GFX_CRUMBLED(Tile[xx][yy]) ||
IS_MOVING(xx, yy))
continue;
if (!IN_LEV_FIELD(xx, yy) ||
!IN_SCR_FIELD(sxx, syy) ||
- !GFX_CRUMBLED(Feld[xx][yy]) ||
+ !GFX_CRUMBLED(Tile[xx][yy]) ||
IS_MOVING(xx, yy))
continue;
return border[steel_position][steel_type];
}
+void DrawScreenGraphic(int x, int y, int graphic, int frame)
+{
+ if (game.use_masked_elements)
+ {
+ if (graphic != el2img(EL_EMPTY))
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ DrawGraphicThruMask(x, y, graphic, frame);
+ }
+ else
+ {
+ DrawGraphic(x, y, graphic, frame);
+ }
+}
+
+void DrawLevelGraphic(int x, int y, int graphic, int frame)
+{
+ DrawScreenGraphic(SCREENX(x), SCREENY(y), graphic, frame);
+}
+
void DrawScreenElement(int x, int y, int element)
{
- DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING);
+ int mask_mode = NO_MASKING;
+
+ if (game.use_masked_elements)
+ {
+ int lx = LEVELX(x), ly = LEVELY(y);
+
+ if (IN_LEV_FIELD(lx, ly) && element != EL_EMPTY)
+ {
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ mask_mode = USE_MASKING;
+ }
+ }
+
+ DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, mask_mode);
DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y));
}
return;
}
- element = Feld[lx][ly];
+ element = Tile[lx][ly];
content = Store[lx][ly];
if (IS_MOVING(lx, ly))
else
DrawScreenElement(x, y, EL_EMPTY);
+ if (cut_mode != CUT_BELOW && game.use_masked_elements)
+ {
+ int dir = MovDir[lx][ly];
+ int newx = x + (dir == MV_LEFT ? -1 : dir == MV_RIGHT ? +1 : 0);
+ int newy = y + (dir == MV_UP ? -1 : dir == MV_DOWN ? +1 : 0);
+
+ if (IN_SCR_FIELD(newx, newy))
+ DrawScreenElement(newx, newy, EL_EMPTY);
+ }
+
if (horiz_move)
DrawScreenElementShifted(x, y, MovPos[lx][ly], 0, element, NO_CUTTING);
else if (cut_mode == NO_CUTTING)
horiz_move = (MovDir[oldx][oldy] == MV_LEFT ||
MovDir[oldx][oldy] == MV_RIGHT);
- element_old = Feld[oldx][oldy];
+ element_old = Tile[oldx][oldy];
content_old = Store[oldx][oldy];
if (element_old == EL_QUICKSAND_EMPTYING ||
if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
DrawSizedElement(sx, sy, EL_EMPTY, tilesize);
else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
- DrawSizedElement(sx, sy, Feld[x][y], tilesize);
+ DrawSizedElement(sx, sy, Tile[x][y], tilesize);
else
DrawSizedGraphic(sx, sy, el2edimg(getBorderElement(x, y)), 0, tilesize);
}
if (x < -1 || x > lev_fieldx || y < -1 || y > lev_fieldy)
DrawMiniElement(sx, sy, EL_EMPTY);
else if (x > -1 && x < lev_fieldx && y > -1 && y < lev_fieldy)
- DrawMiniElement(sx, sy, Feld[x][y]);
+ DrawMiniElement(sx, sy, Tile[x][y]);
else
DrawMiniGraphic(sx, sy, el2edimg(getBorderElement(x, y)));
}
for (xx = 0; xx < xsize; xx++)
DrawEnvelopeBackground(graphic, sx, sy, xx, yy, xsize, ysize, font_nr);
- DrawTextBuffer(sx + font_width, sy + font_height,
- level.envelope[envelope_nr].text, font_nr, max_xsize,
- xsize - 2, ysize - 2, 0, mask_mode,
- level.envelope[envelope_nr].autowrap,
- level.envelope[envelope_nr].centered, FALSE);
+ DrawTextArea(sx + font_width, sy + font_height,
+ level.envelope[envelope_nr].text, font_nr, max_xsize,
+ xsize - 2, ysize - 2, 0, mask_mode,
+ level.envelope[envelope_nr].autowrap,
+ level.envelope[envelope_nr].centered, FALSE);
redraw_mask |= REDRAW_FIELD;
BackToFront();
int anim_mode = graphic_info[graphic].anim_mode;
int main_anim_mode = (anim_mode == ANIM_NONE ? ANIM_VERTICAL|ANIM_HORIZONTAL:
anim_mode == ANIM_DEFAULT ? ANIM_VERTICAL : anim_mode);
+ boolean overlay_enabled = GetOverlayEnabled();
game.envelope_active = TRUE; // needed for RedrawPlayfield() events
+ SetOverlayEnabled(FALSE);
+ UnmapAllGadgets();
+
PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE);
if (anim_mode == ANIM_DEFAULT)
else
WaitForEventToContinue();
+ RemapAllGadgets();
+ SetOverlayEnabled(overlay_enabled);
+
PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE);
if (anim_mode != ANIM_NONE)
BackToFront();
}
+static void PrepareEnvelopeRequestToScreen(Bitmap *bitmap, int sx, int sy,
+ int xsize, int ysize)
+{
+ if (!global.use_envelope_request ||
+ request.sort_priority <= 0)
+ return;
+
+ if (request.bitmap == NULL ||
+ xsize > request.xsize ||
+ ysize > request.ysize)
+ {
+ if (request.bitmap != NULL)
+ FreeBitmap(request.bitmap);
+
+ request.bitmap = CreateBitmap(xsize, ysize, DEFAULT_DEPTH);
+
+ SDL_Surface *surface = request.bitmap->surface;
+
+ if ((request.bitmap->surface_masked = SDLGetNativeSurface(surface)) == NULL)
+ Fail("SDLGetNativeSurface() failed");
+ }
+
+ BlitBitmap(bitmap, request.bitmap, sx, sy, xsize, ysize, 0, 0);
+
+ SDLFreeBitmapTextures(request.bitmap);
+ SDLCreateBitmapTextures(request.bitmap);
+
+ // set envelope request run-time values
+ request.sx = sx;
+ request.sy = sy;
+ request.xsize = xsize;
+ request.ysize = ysize;
+}
+
+void DrawEnvelopeRequestToScreen(int drawing_target, int drawing_stage)
+{
+ if (global.use_envelope_request &&
+ game.request_active_or_moving &&
+ request.sort_priority > 0 &&
+ drawing_target == DRAW_TO_SCREEN &&
+ drawing_stage == DRAW_GLOBAL_ANIM_STAGE_2)
+ {
+ BlitToScreen(request.bitmap, 0, 0, request.xsize, request.ysize,
+ request.sx, request.sy);
+ }
+}
+
static void setRequestBasePosition(int *x, int *y)
{
int sx_base, sy_base;
// store readily prepared envelope request for later use when animating
BlitBitmap(backbuffer, bitmap_db_store_2, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+ PrepareEnvelopeRequestToScreen(bitmap_db_store_2, sx, sy, width, height);
+
if (text_door_style)
free(text_door_style);
}
}
}
+ PrepareEnvelopeRequestToScreen(backbuffer, dst_x, dst_y, width, height);
+
redraw_mask |= REDRAW_FIELD;
BackToFront();
DrawPreviewLevelInfo(MICROLABEL_LEVEL_AUTHOR);
// initialize delay counters
- DelayReached(&scroll_delay, 0);
- DelayReached(&label_delay, 0);
+ ResetDelayCounter(&scroll_delay);
+ ResetDelayCounter(&label_delay);
if (leveldir_current->name)
{
{
int element = level.field[x][y];
- if (ELEM_IS_PLAYER(element))
+ if (IS_PLAYER_ELEMENT(element))
{
int player_nr = GET_PLAYER_NR(element);
}
static void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y,
- int graphic, int sync_frame,
+ int graphic, int lx, int ly,
int mask_mode)
{
- int frame = getGraphicAnimationFrame(graphic, sync_frame);
+ int frame = getGraphicAnimationFrameXY(graphic, lx, ly);
if (mask_mode == USE_MASKING)
DrawGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame);
static void DrawGraphicAnimation(int x, int y, int graphic)
{
int lx = LEVELX(x), ly = LEVELY(y);
+ int mask_mode = NO_MASKING;
if (!IN_SCR_FIELD(x, y))
return;
+ if (game.use_masked_elements)
+ {
+ if (Tile[lx][ly] != EL_EMPTY)
+ {
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ mask_mode = USE_MASKING;
+ }
+ }
+
DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR,
- graphic, GfxFrame[lx][ly], NO_MASKING);
+ graphic, lx, ly, mask_mode);
MarkTileDirty(x, y);
}
void DrawFixedGraphicAnimation(int x, int y, int graphic)
{
int lx = LEVELX(x), ly = LEVELY(y);
+ int mask_mode = NO_MASKING;
if (!IN_SCR_FIELD(x, y))
return;
+ if (game.use_masked_elements)
+ {
+ if (Tile[lx][ly] != EL_EMPTY)
+ {
+ DrawScreenElementExt(x, y, 0, 0, EL_EMPTY, NO_CUTTING, NO_MASKING);
+
+ mask_mode = USE_MASKING;
+ }
+ }
+
DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY,
- graphic, GfxFrame[lx][ly], NO_MASKING);
+ graphic, lx, ly, mask_mode);
+
MarkTileDirty(x, y);
}
if (!IN_LEV_FIELD(x, y) || !IN_SCR_FIELD(sx, sy))
return;
+ if (Tile[x][y] == EL_EMPTY)
+ graphic = el2img(GfxElementEmpty[x][y]);
+
if (!IS_NEW_FRAME(GfxFrame[x][y], graphic))
return;
+ if (ANIM_MODE(graphic) & (ANIM_TILED | ANIM_RANDOM_STATIC))
+ return;
+
DrawGraphicAnimation(sx, sy, graphic);
#if 1
if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y)))
DrawLevelFieldCrumbled(x, y);
#else
- if (GFX_CRUMBLED(Feld[x][y]))
+ if (GFX_CRUMBLED(Tile[x][y]))
DrawLevelFieldCrumbled(x, y);
#endif
}
#if DEBUG
if (!IN_LEV_FIELD(player->jx, player->jy))
{
- printf("DrawPlayerField(): x = %d, y = %d\n", player->jx, player->jy);
- printf("DrawPlayerField(): This should never happen!\n");
+ Debug("draw:DrawPlayerExt", "x = %d, y = %d", player->jx, player->jy);
+ Debug("draw:DrawPlayerExt", "This should never happen!");
draw_player[pnr] = FALSE;
int sy = SCREENY(jy);
int sxx = (move_dir == MV_LEFT || move_dir == MV_RIGHT ? player->GfxPos : 0);
int syy = (move_dir == MV_UP || move_dir == MV_DOWN ? player->GfxPos : 0);
- int element = Feld[jx][jy];
- int last_element = Feld[last_jx][last_jy];
+ int element = Tile[jx][jy];
+ int last_element = Tile[last_jx][last_jy];
int action = (player->is_pushing ? ACTION_PUSHING :
player->is_digging ? ACTION_DIGGING :
player->is_collecting ? ACTION_COLLECTING :
if (GFX_CRUMBLED(old_element))
DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame);
else
- DrawGraphic(sx, sy, old_graphic, frame);
+ DrawScreenGraphic(sx, sy, old_graphic, frame);
if (graphic_info[old_graphic].anim_mode & ANIM_OPAQUE_PLAYER)
static_player_is_opaque[pnr] = TRUE;
if (!IS_MOVING(jx, jy)) // push movement already finished
{
- element = Feld[next_jx][next_jy];
+ element = Tile[next_jx][next_jy];
gfx_frame = GfxFrame[next_jx][next_jy];
}
// do not draw (EM style) pushing animation when pushing is finished
// (two-tile animations usually do not contain start and end frame)
if (graphic_info[graphic].double_movement && !IS_MOVING(jx, jy))
- DrawLevelElement(next_jx, next_jy, Feld[next_jx][next_jy]);
+ DrawLevelElement(next_jx, next_jy, Tile[next_jx][next_jy]);
else
DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING);
#else
if (IS_ACTIVE_BOMB(element))
{
int graphic = el2img(element);
- int frame = getGraphicAnimationFrame(graphic, GfxFrame[jx][jy]);
+ int frame = getGraphicAnimationFrameXY(graphic, jx, jy);
if (game.emulation == EMU_SUPAPLEX)
DrawGraphic(sx, sy, IMG_SP_DISK_RED, frame);
void WaitForEventToContinue(void)
{
+ boolean first_wait = TRUE;
boolean still_wait = TRUE;
if (program.headless)
button_status = MB_RELEASED;
ClearEventQueue();
+ ClearPlayerAction();
while (still_wait)
{
{
switch (event.type)
{
- case EVENT_BUTTONRELEASE:
+ case EVENT_BUTTONPRESS:
+ case EVENT_FINGERPRESS:
+ first_wait = FALSE;
+ break;
+
+ case EVENT_BUTTONRELEASE:
+ case EVENT_FINGERRELEASE:
+ still_wait = first_wait;
+ break;
+
case EVENT_KEYPRESS:
case SDL_CONTROLLERBUTTONDOWN:
case SDL_JOYBUTTONDOWN:
still_wait = FALSE;
break;
- case EVENT_KEYRELEASE:
- ClearPlayerAction();
- break;
-
default:
HandleOtherEvents(&event);
break;
still_wait = FALSE;
}
- BackToFront();
+ if (!PendingEvent())
+ BackToFront();
}
}
#define MAX_REQUEST_LINE_FONT1_LEN 7
#define MAX_REQUEST_LINE_FONT2_LEN 10
-static int RequestHandleEvents(unsigned int req_state)
+static int RequestHandleEvents(unsigned int req_state, int draw_buffer_game)
{
boolean game_just_ended = (game_status == GAME_MODE_PLAYING &&
checkGameEnded());
+ int draw_buffer_last = GetDrawtoField();
int width = request.width;
int height = request.height;
int sx, sy;
while (result < 0)
{
+ boolean event_handled = FALSE;
+
if (game_just_ended)
{
- // the MM game engine does not use a special (scrollable) field buffer
- if (level.game_engine_type != GAME_ENGINE_TYPE_MM)
- SetDrawtoField(DRAW_TO_FIELDBUFFER);
+ SetDrawtoField(draw_buffer_game);
HandleGameActions();
while (NextValidEvent(&event))
{
+ event_handled = TRUE;
+
switch (event.type)
{
case EVENT_BUTTONPRESS:
break;
}
+ case EVENT_FINGERRELEASE:
case EVENT_KEYRELEASE:
ClearPlayerAction();
break;
}
}
- if (game_just_ended)
+ if (event_handled)
{
- if (global.use_envelope_request)
+ if (game_just_ended)
{
- // copy back current state of pressed buttons inside request area
- BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
+ if (global.use_envelope_request)
+ {
+ // copy back current state of pressed buttons inside request area
+ BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy);
+ }
}
+
+ PrepareEnvelopeRequestToScreen(drawto, sx, sy, width, height);
}
BackToFront();
}
+ SetDrawtoField(draw_buffer_last);
+
game.request_active = FALSE;
return result;
static boolean RequestDoor(char *text, unsigned int req_state)
{
+ int draw_buffer_last = GetDrawtoField();
unsigned int old_door_state;
int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN;
int font_nr = FONT_TEXT_2;
SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
// ---------- handle request buttons ----------
- result = RequestHandleEvents(req_state);
+ result = RequestHandleEvents(req_state, draw_buffer_last);
UnmapToolButtons();
static boolean RequestEnvelope(char *text, unsigned int req_state)
{
+ int draw_buffer_last = GetDrawtoField();
int result;
if (game_status == GAME_MODE_PLAYING)
SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1);
// ---------- handle request buttons ----------
- result = RequestHandleEvents(req_state);
+ result = RequestHandleEvents(req_state, draw_buffer_last);
UnmapToolButtons();
boolean overlay_enabled = GetOverlayEnabled();
boolean result;
+ game.request_active_or_moving = TRUE;
+
SetOverlayEnabled(FALSE);
if (global.use_envelope_request)
SetOverlayEnabled(overlay_enabled);
+ game.request_active_or_moving = FALSE;
+
return result;
}
int num_move_steps = 0; // number of animation steps for all doors
int max_move_delay_doors_only = 0; // delay for doors only (no panel)
int num_move_steps_doors_only = 0; // steps for doors only (no panel)
- int current_move_delay = 0;
int start = 0;
int k;
if (width > door_rect->width)
width = door_rect->width;
- // printf("::: k == %d [%d] \n", k, start_step);
+ // Debug("tools:MoveDoor", "k == %d [%d]", k, start_step);
}
if (pos->step_yoffset < 0) // door part on bottom side
SkipUntilDelayReached(&door_delay, door_delay_value, &k, last_frame);
- current_move_delay += max_step_delay;
-
// prevent OS (Windows) from complaining about program not responding
CheckQuitEvent();
}
int y = pos->y;
int id = i;
+ // do not use touch buttons if overlay touch buttons are disabled
+ if (is_touch_button && !setup.touch.overlay_buttons)
+ continue;
+
if (global.use_envelope_request && !is_touch_button)
{
setRequestPosition(&base_x, &base_y, TRUE);
GDI_END);
if (gi == NULL)
- Error(ERR_EXIT, "cannot create gadget");
+ Fail("cannot create gadget");
tool_gadget[id] = gi;
}
EL_EMC_FAKE_ACID, -1, -1
},
+ {
+ Xfake_acid_1_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_2_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_3_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_4_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_5_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_6_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_7_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+ {
+ Xfake_acid_8_player, FALSE, FALSE,
+ EL_EMC_FAKE_ACID, -1, -1
+ },
+
{
Xgrass, TRUE, FALSE,
EL_EMC_GRASS, -1, -1
if (element_rnd < 0 || element_rnd >= NUM_FILE_ELEMENTS)
{
- Error(ERR_WARN, "invalid RND level element %d", element_rnd);
+ Warn("invalid RND level element %d", element_rnd);
return EL_UNKNOWN;
}
if (element_em_cave < 0 || element_em_cave >= CAVE_TILE_MAX)
{
- Error(ERR_WARN, "invalid EM cave element %d", element_em_cave);
+ Warn("invalid EM cave element %d", element_em_cave);
return EL_UNKNOWN;
}
if (element_em_game < 0 || element_em_game >= GAME_TILE_MAX)
{
- Error(ERR_WARN, "invalid EM game element %d", element_em_game);
+ Warn("invalid EM game element %d", element_em_game);
return EL_UNKNOWN;
}
i == Xfake_acid_6 ? 50 :
i == Xfake_acid_7 ? 60 :
i == Xfake_acid_8 ? 70 :
+ i == Xfake_acid_1_player ? 0 :
+ i == Xfake_acid_2_player ? 10 :
+ i == Xfake_acid_3_player ? 20 :
+ i == Xfake_acid_4_player ? 30 :
+ i == Xfake_acid_5_player ? 40 :
+ i == Xfake_acid_6_player ? 50 :
+ i == Xfake_acid_7_player ? 60 :
+ i == Xfake_acid_8_player ? 70 :
i == Xball_2 ? 7 :
i == Yball_2 ? j + 8 :
i == Yball_blank ? j + 1 :
}
}
-void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
- boolean any_player_moving,
- boolean any_player_snapping,
- boolean any_player_dropping)
+boolean CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
+ boolean any_player_moving,
+ boolean any_player_snapping,
+ boolean any_player_dropping)
{
if (tape.single_step && tape.recording && !tape.pausing)
- if (frame == 7 && !any_player_dropping)
+ if (frame == 7 && !any_player_dropping && FrameCounter > 6)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
CheckSaveEngineSnapshot_EM(action, frame, any_player_moving,
any_player_snapping, any_player_dropping);
+
+ return tape.pausing;
}
void CheckSingleStepMode_SP(boolean murphy_is_waiting,
#endif
}
-void ToggleFullscreenOrChangeWindowScalingIfNeeded(void)
+void ToggleFullscreenIfNeeded(void)
{
- boolean change_fullscreen = (setup.fullscreen !=
- video.fullscreen_enabled);
- boolean change_window_scaling_percent = (!video.fullscreen_enabled &&
- setup.window_scaling_percent !=
- video.window_scaling_percent);
-
- if (change_window_scaling_percent && video.fullscreen_enabled)
+ // if setup and video fullscreen state are already matching, nothing do do
+ if (setup.fullscreen == video.fullscreen_enabled ||
+ !video.fullscreen_available)
return;
- if (!change_window_scaling_percent && !video.fullscreen_available)
- return;
+ SDLSetWindowFullscreen(setup.fullscreen);
- if (change_window_scaling_percent)
- {
- SDLSetWindowScaling(setup.window_scaling_percent);
+ // set setup value according to successfully changed fullscreen mode
+ setup.fullscreen = video.fullscreen_enabled;
+}
+void ChangeWindowScalingIfNeeded(void)
+{
+ // if setup and video window scaling are already matching, nothing do do
+ if (setup.window_scaling_percent == video.window_scaling_percent ||
+ video.fullscreen_enabled)
return;
- }
- else if (change_fullscreen)
- {
- SDLSetWindowFullscreen(setup.fullscreen);
- // set setup value according to successfully changed fullscreen mode
- setup.fullscreen = video.fullscreen_enabled;
+ SDLSetWindowScaling(setup.window_scaling_percent);
- return;
- }
+ // set setup value according to successfully changed window scaling
+ setup.window_scaling_percent = video.window_scaling_percent;
}
void ChangeVsyncModeIfNeeded(void)
{
if (anim_status_new == GAME_MODE_MAIN)
anim_status_new = GAME_MODE_PSEUDO_MAINONLY;
+ else if (anim_status_new == GAME_MODE_NAMES)
+ anim_status_new = GAME_MODE_PSEUDO_NAMESONLY;
else if (anim_status_new == GAME_MODE_SCORES)
anim_status_new = GAME_MODE_PSEUDO_SCORESOLD;
if ((global.anim_status == GAME_MODE_PSEUDO_MAINONLY &&
global.anim_status_next == GAME_MODE_PSEUDO_TYPENAME) ||
(global.anim_status == GAME_MODE_PSEUDO_TYPENAME &&
- global.anim_status_next == GAME_MODE_PSEUDO_MAINONLY))
+ global.anim_status_next == GAME_MODE_PSEUDO_MAINONLY) ||
+ (global.anim_status == GAME_MODE_PSEUDO_NAMESONLY &&
+ global.anim_status_next == GAME_MODE_PSEUDO_TYPENAMES) ||
+ (global.anim_status == GAME_MODE_PSEUDO_TYPENAMES &&
+ global.anim_status_next == GAME_MODE_PSEUDO_NAMESONLY))
global.anim_status = global.anim_status_next;
}
{
boolean use_mini_tilesize = (level.game_engine_type == GAME_ENGINE_TYPE_MM ?
FALSE : setup.small_game_graphics);
- int gfx_game_mode = game_status;
- int gfx_game_mode2 = (game_status == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
- game_status);
+ int gfx_game_mode = getGlobalGameStatus(game_status);
+ int gfx_game_mode2 = (gfx_game_mode == GAME_MODE_EDITOR ? GAME_MODE_DEFAULT :
+ gfx_game_mode);
struct RectWithBorder *vp_window = &viewport.window[gfx_game_mode];
struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode];
struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode];
init_gfx_buffers = TRUE;
init_gadgets_and_anims = TRUE;
- // printf("::: video: init_video_buffer, init_gfx_buffers\n");
+ // Debug("tools:viewport", "video: init_video_buffer, init_gfx_buffers");
}
if (new_scr_fieldx != SCR_FIELDX ||
SCR_FIELDX = new_scr_fieldx;
SCR_FIELDY = new_scr_fieldy;
- // printf("::: new_scr_fieldx != SCR_FIELDX ...\n");
+ // Debug("tools:viewport", "new_scr_fieldx != SCR_FIELDX ...");
}
if (new_sx != SX ||
if (new_tilesize_var != TILESIZE_VAR)
{
- // printf("::: new_tilesize_var != TILESIZE_VAR\n");
+ // Debug("tools:viewport", "new_tilesize_var != TILESIZE_VAR");
// changing tile size invalidates scroll values of engine snapshots
FreeEngineSnapshotSingle();
init_gfx_buffers = TRUE;
init_gadgets_and_anims = TRUE;
- // printf("::: viewports: init_gfx_buffers\n");
- // printf("::: viewports: init_gadgets_and_anims\n");
+ // Debug("tools:viewport", "viewports: init_gfx_buffers");
+ // Debug("tools:viewport", "viewports: init_gadgets_and_anims");
}
if (init_gfx_buffers)
{
- // printf("::: init_gfx_buffers\n");
+ // Debug("tools:viewport", "init_gfx_buffers");
SCR_FIELDX = new_scr_fieldx_buffers;
SCR_FIELDY = new_scr_fieldy_buffers;
if (init_video_buffer)
{
- // printf("::: init_video_buffer\n");
+ // Debug("tools:viewport", "init_video_buffer");
FreeAllImageTextures(); // needs old renderer to free the textures
if (init_gadgets_and_anims)
{
- // printf("::: init_gadgets_and_anims\n");
+ // Debug("tools:viewport", "init_gadgets_and_anims");
InitGadgets();
InitGlobalAnimations();
InitGraphicInfo_EM();
}
}
+
+void OpenURL(char *url)
+{
+ SDL_OpenURL(url);
+}
+
+void OpenURLFromHash(SetupFileHash *hash, int hash_key)
+{
+ OpenURL(getHashEntry(hash, int2str(hash_key, 0)));
+}
+
+
+// ============================================================================
+// tests
+// ============================================================================
+
+#if defined(PLATFORM_WINDOWS)
+/* FILETIME of Jan 1 1970 00:00:00. */
+static const unsigned __int64 epoch = ((unsigned __int64) 116444736000000000ULL);
+
+/*
+ * timezone information is stored outside the kernel so tzp isn't used anymore.
+ *
+ * Note: this function is not for Win32 high precision timing purpose. See
+ * elapsed_time().
+ */
+static int gettimeofday_windows(struct timeval * tp, struct timezone * tzp)
+{
+ FILETIME file_time;
+ SYSTEMTIME system_time;
+ ULARGE_INTEGER ularge;
+
+ GetSystemTime(&system_time);
+ SystemTimeToFileTime(&system_time, &file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / 10000000L);
+ tp->tv_usec = (long) (system_time.wMilliseconds * 1000);
+
+ return 0;
+}
+#endif
+
+static char *test_init_uuid_random_function_simple(void)
+{
+ static char seed_text[100];
+ unsigned int seed = InitSimpleRandom(NEW_RANDOMIZE);
+
+ sprintf(seed_text, "%d", seed);
+
+ return seed_text;
+}
+
+static char *test_init_uuid_random_function_better(void)
+{
+ static char seed_text[100];
+ struct timeval current_time;
+
+ gettimeofday(¤t_time, NULL);
+
+ prng_seed_bytes(¤t_time, sizeof(current_time));
+
+ sprintf(seed_text, "%ld.%ld",
+ (long)current_time.tv_sec,
+ (long)current_time.tv_usec);
+
+ return seed_text;
+}
+
+#if defined(PLATFORM_WINDOWS)
+static char *test_init_uuid_random_function_better_windows(void)
+{
+ static char seed_text[100];
+ struct timeval current_time;
+
+ gettimeofday_windows(¤t_time, NULL);
+
+ prng_seed_bytes(¤t_time, sizeof(current_time));
+
+ sprintf(seed_text, "%ld.%ld",
+ (long)current_time.tv_sec,
+ (long)current_time.tv_usec);
+
+ return seed_text;
+}
+#endif
+
+static unsigned int test_uuid_random_function_simple(int max)
+{
+ return GetSimpleRandom(max);
+}
+
+static unsigned int test_uuid_random_function_better(int max)
+{
+ return (max > 0 ? prng_get_uint() % max : 0);
+}
+
+#if defined(PLATFORM_WINDOWS)
+#define NUM_UUID_TESTS 3
+#else
+#define NUM_UUID_TESTS 2
+#endif
+
+static void TestGeneratingUUIDs_RunTest(int nr, int always_seed, int num_uuids)
+{
+ struct hashtable *hash_seeds =
+ create_hashtable(16, 0.75, get_hash_from_key, hash_keys_are_equal);
+ struct hashtable *hash_uuids =
+ create_hashtable(16, 0.75, get_hash_from_key, hash_keys_are_equal);
+ static char message[100];
+ int i;
+
+ char *random_name = (nr == 0 ? "simple" : "better");
+ char *random_type = (always_seed ? "always" : "only once");
+ char *(*init_random_function)(void) =
+ (nr == 0 ?
+ test_init_uuid_random_function_simple :
+ test_init_uuid_random_function_better);
+ unsigned int (*random_function)(int) =
+ (nr == 0 ?
+ test_uuid_random_function_simple :
+ test_uuid_random_function_better);
+ int xpos = 40;
+
+#if defined(PLATFORM_WINDOWS)
+ if (nr == 2)
+ {
+ random_name = "windows";
+ init_random_function = test_init_uuid_random_function_better_windows;
+ }
+#endif
+
+ ClearField();
+
+ DrawTextF(xpos, 40, FC_GREEN, "Test: Generating UUIDs");
+ DrawTextF(xpos, 80, FC_YELLOW, "Test %d.%d:", nr + 1, always_seed + 1);
+
+ DrawTextF(xpos, 100, FC_YELLOW, "Random Generator Name: %s", random_name);
+ DrawTextF(xpos, 120, FC_YELLOW, "Seeding Random Generator: %s", random_type);
+ DrawTextF(xpos, 140, FC_YELLOW, "Number of UUIDs generated: %d", num_uuids);
+
+ DrawTextF(xpos, 180, FC_GREEN, "Please wait ...");
+
+ BackToFront();
+
+ // always initialize random number generator at least once
+ init_random_function();
+
+ unsigned int time_start = SDL_GetTicks();
+
+ for (i = 0; i < num_uuids; i++)
+ {
+ if (always_seed)
+ {
+ char *seed = getStringCopy(init_random_function());
+
+ hashtable_remove(hash_seeds, seed);
+ hashtable_insert(hash_seeds, seed, "1");
+ }
+
+ char *uuid = getStringCopy(getUUIDExt(random_function));
+
+ hashtable_remove(hash_uuids, uuid);
+ hashtable_insert(hash_uuids, uuid, "1");
+ }
+
+ int num_unique_seeds = hashtable_count(hash_seeds);
+ int num_unique_uuids = hashtable_count(hash_uuids);
+
+ unsigned int time_needed = SDL_GetTicks() - time_start;
+
+ DrawTextF(xpos, 220, FC_YELLOW, "Time needed: %d ms", time_needed);
+
+ DrawTextF(xpos, 240, FC_YELLOW, "Number of unique UUIDs: %d", num_unique_uuids);
+
+ if (always_seed)
+ DrawTextF(xpos, 260, FC_YELLOW, "Number of unique seeds: %d", num_unique_seeds);
+
+ if (nr == NUM_UUID_TESTS - 1 && always_seed)
+ DrawTextF(xpos, 300, FC_GREEN, "All tests done!");
+ else
+ DrawTextF(xpos, 300, FC_GREEN, "Confirm dialog for next test ...");
+
+ sprintf(message, "Test %d.%d finished!", nr + 1, always_seed + 1);
+
+ Request(message, REQ_CONFIRM);
+
+ hashtable_destroy(hash_seeds, 0);
+ hashtable_destroy(hash_uuids, 0);
+}
+
+void TestGeneratingUUIDs(void)
+{
+ int num_uuids = 1000000;
+ int i, j;
+
+ for (i = 0; i < NUM_UUID_TESTS; i++)
+ for (j = 0; j < 2; j++)
+ TestGeneratingUUIDs_RunTest(i, j, num_uuids);
+
+ CloseAllAndExit(0);
+}