// (c) 1995-2014 by Artsoft Entertainment
// Holger Schemel
// info@artsoft.org
-// http://www.artsoft.org/
+// https://www.artsoft.org/
// ----------------------------------------------------------------------------
// tools.c
// ============================================================================
#include "screens.h"
-// select level set with EMC X11 graphics before activating EM GFX debugging
-#define DEBUG_EM_GFX FALSE
#define DEBUG_FRAME_TIME FALSE
// tool button identifiers
return s;
}
-int correctLevelPosX_EM(int lx)
-{
- lx -= 1;
- lx -= (BorderElement != EL_EMPTY ? 1 : 0);
-
- return lx;
-}
-
-int correctLevelPosY_EM(int ly)
-{
- ly -= 1;
- ly -= (BorderElement != EL_EMPTY ? 1 : 0);
-
- return ly;
-}
-
int getFieldbufferOffsetX_RND(int dir, int pos)
{
int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0);
static int getLevelFromScreenX_EM(int sx)
{
- int level_xsize = level.native_em_level->lev->width;
+ int level_xsize = level.native_em_level->cav->width;
int full_xsize = level_xsize * TILESIZE_VAR;
sx -= (full_xsize < SXSIZE ? (SXSIZE - full_xsize) / 2 : 0);
int px = sx - SX;
int lx = LEVELX((px + dx) / TILESIZE_VAR);
- lx = correctLevelPosX_EM(lx);
-
return lx;
}
static int getLevelFromScreenY_EM(int sy)
{
- int level_ysize = level.native_em_level->lev->height;
+ int level_ysize = level.native_em_level->cav->height;
int full_ysize = level_ysize * TILESIZE_VAR;
sy -= (full_ysize < SYSIZE ? (SYSIZE - full_ysize) / 2 : 0);
int py = sy - SY;
int ly = LEVELY((py + dy) / TILESIZE_VAR);
- ly = correctLevelPosY_EM(ly);
-
return ly;
}
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(" Tile: %d\t['%s']\n", Tile[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]));
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),
height = WIN_YSIZE;
}
- if (!setup.fade_screens ||
- fade_delay == 0 ||
- fading.fade_mode == FADE_MODE_NONE)
- {
- if (fade_mode == FADE_MODE_FADE_OUT)
- return;
-
- BlitBitmap(backbuffer, window, x, y, width, height, x, y);
-
- redraw_mask &= ~fade_mask;
+ // when switching screens without fading, set fade delay to zero
+ if (!setup.fade_screens || fading.fade_mode == FADE_MODE_NONE)
+ fade_delay = 0;
+ // do not display black frame when fading out without fade delay
+ if (fade_mode == FADE_MODE_FADE_OUT && fade_delay == 0)
return;
- }
FadeRectangle(x, y, width, height, fade_mode, fade_delay, post_delay,
draw_border_function);
global.anim_status = global.anim_status_next;
// store backbuffer with all animations that will be started after fading in
- if (fade_type_skip != FADE_MODE_SKIP_FADE_IN)
- PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
+ PrepareFadeBitmap(DRAW_TO_FADE_TARGET);
// set screen mode for animations back to fading
global.anim_status = GAME_MODE_PSEUDO_FADING;
global.anim_status = GAME_MODE_PSEUDO_FADING;
// store backbuffer with all animations that will be stopped for fading out
- if (fade_type_skip != FADE_MODE_SKIP_FADE_OUT)
- PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
+ PrepareFadeBitmap(DRAW_TO_FADE_SOURCE);
}
static void SetScreenStates_AfterFadingOut(void)
BorderElement = EL_EMPTY;
- // the MM game engine does not use a visible border element
- if (level.game_engine_type == GAME_ENGINE_TYPE_MM)
+ // only the R'n'D game engine may use an additional steelwall border
+ if (level.game_engine_type != GAME_ENGINE_TYPE_RND)
return;
for (y = 0; y < lev_fieldy && BorderElement == EL_EMPTY; y++)
{
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)
{
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 !!!
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]))
{
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;
}
- element = Feld[lx][ly];
+ element = Tile[lx][ly];
content = Store[lx][ly];
if (IS_MOVING(lx, ly))
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)));
}
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
}
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 (!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
int action;
int direction;
}
-em_object_mapping_list[] =
+em_object_mapping_list[GAME_TILE_MAX + 1] =
{
+ {
+ Zborder, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zplayer, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+
+ {
+ Zbug, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Ztank, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zeater, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zdynamite, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+ {
+ Zboom, FALSE, FALSE,
+ EL_EMPTY, -1, -1
+ },
+
+ {
+ Xchain, FALSE, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_bug, FALSE, FALSE,
+ EL_BUG, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_tank, FALSE, FALSE,
+ EL_SPACESHIP, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_android, FALSE, FALSE,
+ EL_EMC_ANDROID, ACTION_OTHER, -1
+ },
+ {
+ Xboom_1, FALSE, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
+ },
+ {
+ Xboom_2, FALSE, FALSE,
+ EL_DEFAULT, ACTION_EXPLODING, -1
+ },
+
{
Xblank, TRUE, FALSE,
EL_EMPTY, -1, -1
},
{
- Xacid_splash_e, FALSE, FALSE,
+ Xsplash_e, FALSE, FALSE,
EL_ACID_SPLASH_RIGHT, -1, -1
},
{
- Xacid_splash_w, FALSE, FALSE,
+ Xsplash_w, FALSE, FALSE,
EL_ACID_SPLASH_LEFT, -1, -1
},
EL_SPRING, -1, -1
},
{
- Xspring_e, FALSE, FALSE,
- EL_SPRING, -1, -1
+ Xspring_e, TRUE, FALSE,
+ EL_SPRING_RIGHT, -1, -1
},
{
- Xspring_w, FALSE, FALSE,
- EL_SPRING, -1, -1
+ Xspring_w, TRUE, FALSE,
+ EL_SPRING_LEFT, -1, -1
},
{
Xspring_fall, FALSE, FALSE,
},
{
Xpush_spring_e, FALSE, FALSE,
- EL_SPRING, -1, MV_BIT_RIGHT
+ EL_SPRING_RIGHT, -1, MV_BIT_RIGHT
},
{
Xpush_spring_w, FALSE, FALSE,
- EL_SPRING, -1, MV_BIT_LEFT
+ EL_SPRING_LEFT, -1, MV_BIT_LEFT
},
{
},
{
- Xdrip, FALSE, FALSE,
+ Xdrip, TRUE, FALSE,
EL_AMOEBA_DROP, ACTION_GROWING, -1
},
{
- Xdrip_fall, TRUE, FALSE,
+ Xdrip_fall, FALSE, FALSE,
EL_AMOEBA_DROP, -1, -1
},
{
EL_MAGIC_WALL, -1, -1
},
{
- XwonderwallB, FALSE, FALSE,
+ Ywonderwall, FALSE, FALSE,
EL_MAGIC_WALL, ACTION_ACTIVE, -1
},
EL_ROBOT_WHEEL, -1, -1
},
{
- XwheelB, FALSE, FALSE,
+ Ywheel, FALSE, FALSE,
EL_ROBOT_WHEEL, ACTION_ACTIVE, -1
},
EL_EMC_MAGIC_BALL_SWITCH, -1, -1
},
{
- XswitchB, FALSE, FALSE,
+ Yswitch, FALSE, FALSE,
EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1
},
EL_EMC_SPRING_BUMPER, -1, -1
},
{
- XbumperB, FALSE, FALSE,
+ Ybumper, FALSE, FALSE,
EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1
},
EL_INVISIBLE_WALL, -1, -1
},
{
- Xfake_blankB, FALSE, FALSE,
+ Yfake_blank, FALSE, FALSE,
EL_INVISIBLE_WALL, ACTION_ACTIVE, -1
},
EL_EMC_FAKE_GRASS, -1, -1
},
{
- Xfake_grassB, FALSE, FALSE,
+ Yfake_grass, FALSE, FALSE,
EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1
},
EL_EMC_DRIPPER, -1, -1
},
{
- Xfake_amoebaB, FALSE, FALSE,
+ Yfake_amoeba, FALSE, FALSE,
EL_EMC_DRIPPER, ACTION_ACTIVE, -1
},
},
{
- Xslidewall_ns, TRUE, FALSE,
+ Xslide_ns, TRUE, FALSE,
EL_EXPANDABLE_WALL_VERTICAL, -1, -1
},
{
- Yslidewall_ns_blank, FALSE, FALSE,
+ Yslide_ns_blank, FALSE, FALSE,
EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1
},
{
- Xslidewall_ew, TRUE, FALSE,
+ Xslide_ew, TRUE, FALSE,
EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1
},
{
- Yslidewall_ew_blank, FALSE, FALSE,
+ Yslide_ew_blank, FALSE, FALSE,
EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1
},
EL_CHAR('!'), -1, -1
},
{
- Xalpha_quote, TRUE, FALSE,
- EL_CHAR('"'), -1, -1
+ Xalpha_apost, TRUE, FALSE,
+ EL_CHAR('\''), -1, -1
},
{
Xalpha_comma, TRUE, FALSE,
EL_SAND, ACTION_SNAPPING, -1
},
- {
- Xboom_bug, FALSE, FALSE,
- EL_BUG, ACTION_EXPLODING, -1
- },
- {
- Xboom_bomb, FALSE, FALSE,
- EL_BOMB, ACTION_EXPLODING, -1
- },
- {
- Xboom_android, FALSE, FALSE,
- EL_EMC_ANDROID, ACTION_OTHER, -1
- },
- {
- Xboom_1, FALSE, FALSE,
- EL_DEFAULT, ACTION_EXPLODING, -1
- },
- {
- Xboom_2, FALSE, FALSE,
- EL_DEFAULT, ACTION_EXPLODING, -1
- },
- {
- Znormal, FALSE, FALSE,
- EL_EMPTY, -1, -1
- },
- {
- Zdynamite, FALSE, FALSE,
- EL_EMPTY, -1, -1
- },
- {
- Zplayer, FALSE, FALSE,
- EL_EMPTY, -1, -1
- },
- {
- Zborder, FALSE, FALSE,
- EL_EMPTY, -1, -1
- },
-
{
-1, FALSE, FALSE,
-1, -1, -1
int action;
int direction;
}
-em_player_mapping_list[] =
+em_player_mapping_list[MAX_PLAYERS * PLY_MAX + 1] =
{
{
PLY_walk_n, 0,
}
};
-int map_element_RND_to_EM(int element_rnd)
+int map_element_RND_to_EM_cave(int element_rnd)
{
static unsigned short mapping_RND_to_EM[NUM_FILE_ELEMENTS];
static boolean mapping_initialized = FALSE;
mapping_initialized = TRUE;
}
- if (element_rnd >= 0 && element_rnd < NUM_FILE_ELEMENTS)
- return mapping_RND_to_EM[element_rnd];
+ if (element_rnd < 0 || element_rnd >= NUM_FILE_ELEMENTS)
+ {
+ Warn("invalid RND level element %d", element_rnd);
+
+ return EL_UNKNOWN;
+ }
+
+ return map_em_element_X_to_C(mapping_RND_to_EM[element_rnd]);
+}
+
+int map_element_EM_to_RND_cave(int element_em_cave)
+{
+ static unsigned short mapping_EM_to_RND[GAME_TILE_MAX];
+ static boolean mapping_initialized = FALSE;
+
+ if (!mapping_initialized)
+ {
+ int i;
+
+ // return "EL_UNKNOWN" for all undefined elements in mapping array
+ for (i = 0; i < GAME_TILE_MAX; i++)
+ mapping_EM_to_RND[i] = EL_UNKNOWN;
- Error(ERR_WARN, "invalid RND level element %d", element_rnd);
+ for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
+ mapping_EM_to_RND[em_object_mapping_list[i].element_em] =
+ em_object_mapping_list[i].element_rnd;
- return EL_UNKNOWN;
+ mapping_initialized = TRUE;
+ }
+
+ if (element_em_cave < 0 || element_em_cave >= CAVE_TILE_MAX)
+ {
+ Warn("invalid EM cave element %d", element_em_cave);
+
+ return EL_UNKNOWN;
+ }
+
+ return mapping_EM_to_RND[map_em_element_C_to_X(element_em_cave)];
}
-int map_element_EM_to_RND(int element_em)
+int map_element_EM_to_RND_game(int element_em_game)
{
- static unsigned short mapping_EM_to_RND[TILE_MAX];
+ static unsigned short mapping_EM_to_RND[GAME_TILE_MAX];
static boolean mapping_initialized = FALSE;
if (!mapping_initialized)
int i;
// return "EL_UNKNOWN" for all undefined elements in mapping array
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
mapping_EM_to_RND[i] = EL_UNKNOWN;
for (i = 0; em_object_mapping_list[i].element_em != -1; i++)
mapping_initialized = TRUE;
}
- if (element_em >= 0 && element_em < TILE_MAX)
- return mapping_EM_to_RND[element_em];
+ if (element_em_game < 0 || element_em_game >= GAME_TILE_MAX)
+ {
+ Warn("invalid EM game element %d", element_em_game);
- Error(ERR_WARN, "invalid EM level element %d", element_em);
+ return EL_UNKNOWN;
+ }
- return EL_UNKNOWN;
+ return mapping_EM_to_RND[element_em_game];
}
void map_android_clone_elements_RND_to_EM(struct LevelInfo *level)
{
struct LevelInfo_EM *level_em = level->native_em_level;
- struct LEVEL *lev = level_em->lev;
+ struct CAVE *cav = level_em->cav;
int i, j;
- for (i = 0; i < TILE_MAX; i++)
- lev->android_array[i] = Xblank;
+ for (i = 0; i < GAME_TILE_MAX; i++)
+ cav->android_array[i] = Cblank;
for (i = 0; i < level->num_android_clone_elements; i++)
{
int element_rnd = level->android_clone_element[i];
- int element_em = map_element_RND_to_EM(element_rnd);
+ int element_em_cave = map_element_RND_to_EM_cave(element_rnd);
for (j = 0; em_object_mapping_list[j].element_em != -1; j++)
if (em_object_mapping_list[j].element_rnd == element_rnd)
- lev->android_array[em_object_mapping_list[j].element_em] = element_em;
+ cav->android_array[em_object_mapping_list[j].element_em] =
+ element_em_cave;
}
}
void map_android_clone_elements_EM_to_RND(struct LevelInfo *level)
{
struct LevelInfo_EM *level_em = level->native_em_level;
- struct LEVEL *lev = level_em->lev;
+ struct CAVE *cav = level_em->cav;
int i, j;
level->num_android_clone_elements = 0;
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
- int element_em = lev->android_array[i];
+ int element_em_cave = cav->android_array[i];
int element_rnd;
boolean element_found = FALSE;
- if (element_em == Xblank)
+ if (element_em_cave == Cblank)
continue;
- element_rnd = map_element_EM_to_RND(element_em);
+ element_rnd = map_element_EM_to_RND_cave(element_em_cave);
for (j = 0; j < level->num_android_clone_elements; j++)
if (level->android_clone_element[j] == element_rnd)
return getBeltSwitchElementFromBeltNrAndBeltDirNr(belt_nr, belt_dir_nr);
}
+boolean swapTiles_EM(boolean is_pre_emc_cave)
+{
+ return is_pre_emc_cave && leveldir_current->use_emc_tiles;
+}
+
boolean getTeamMode_EM(void)
{
return game.team_mode || network_playing;
}
-int getGameFrameDelay_EM(int native_em_game_frame_delay)
+boolean isActivePlayer_EM(int player_nr)
{
- int game_frame_delay_value;
-
- game_frame_delay_value =
- (tape.playing && tape.fast_forward ? FfwdFrameDelay :
- GameFrameDelay == GAME_FRAME_DELAY ? native_em_game_frame_delay :
- GameFrameDelay);
-
- if (tape.playing && tape.warp_forward && !tape.pausing)
- game_frame_delay_value = 0;
-
- return game_frame_delay_value;
+ return stored_player[player_nr].active;
}
unsigned int InitRND(int seed)
return InitEngineRandom_RND(seed);
}
-static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX];
+static struct Mapping_EM_to_RND_object object_mapping[GAME_TILE_MAX];
static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][PLY_MAX];
static int get_effective_element_EM(int tile, int frame_em)
{
switch (tile)
{
- case Xacid_splash_e:
- case Xacid_splash_w:
+ case Xsplash_e:
+ case Xsplash_w:
return (frame_em > 5 ? EL_EMPTY : element);
default:
{
switch (tile)
{
- case Xacid_splash_e:
- case Xacid_splash_w:
+ case Xsplash_e:
+ case Xsplash_w:
return EL_EMPTY;
case Ynut_stone:
case Ytank_s_e:
case Ytank_w_s:
case Ytank_n_w:
- case Xacid_splash_e:
- case Xacid_splash_w:
+ case Xsplash_e:
+ case Xsplash_w:
case Ynut_stone:
return TRUE;
}
{
int i, j, p;
-#if DEBUG_EM_GFX
- int num_em_gfx_errors = 0;
-
- if (graphic_info_em_object[0][0].bitmap == NULL)
- {
- // EM graphics not yet initialized in em_open_all()
-
- return;
- }
-
- printf("::: [4 errors can be ignored (1 x 'bomb', 3 x 'em_dynamite']\n");
-#endif
-
// always start with reliable default values
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
object_mapping[i].element_rnd = EL_UNKNOWN;
object_mapping[i].is_backside = FALSE;
MV_DIR_FROM_BIT(em_player_mapping_list[i].direction);
}
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
int element = object_mapping[i].element_rnd;
int action = object_mapping[i].action;
boolean has_action_graphics = (graphic != base_graphic);
boolean has_crumbled_graphics = (base_crumbled != base_graphic);
struct GraphicInfo *g = &graphic_info[graphic];
- struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
+ struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][j];
Bitmap *src_bitmap;
int src_x, src_y;
// ensure to get symmetric 3-frame, 2-delay animations as used in EM
i == Xboom_bug && j == 5 ? 2 :
i == Xboom_bug && j == 6 ? 2 :
i == Xboom_bug && j == 7 ? 0 :
- i == Xboom_bomb && j == 1 ? 2 :
- i == Xboom_bomb && j == 2 ? 2 :
- i == Xboom_bomb && j == 3 ? 4 :
- i == Xboom_bomb && j == 4 ? 4 :
- i == Xboom_bomb && j == 5 ? 2 :
- i == Xboom_bomb && j == 6 ? 2 :
- i == Xboom_bomb && j == 7 ? 0 :
+ i == Xboom_tank && j == 1 ? 2 :
+ i == Xboom_tank && j == 2 ? 2 :
+ i == Xboom_tank && j == 3 ? 4 :
+ i == Xboom_tank && j == 4 ? 4 :
+ i == Xboom_tank && j == 5 ? 2 :
+ i == Xboom_tank && j == 6 ? 2 :
+ i == Xboom_tank && j == 7 ? 0 :
i == Xboom_android && j == 7 ? 6 :
i == Xboom_1 && j == 1 ? 2 :
i == Xboom_1 && j == 2 ? 2 :
special_animation && j == 4 ? 3 :
effective_action != action ? 0 :
j);
-
-#if DEBUG_EM_GFX
- Bitmap *debug_bitmap = g_em->bitmap;
- int debug_src_x = g_em->src_x;
- int debug_src_y = g_em->src_y;
-#endif
-
int frame = getAnimationFrame(g->anim_frames,
g->anim_delay,
g->anim_mode,
bit 5 - 0 ( 6 bit): graphic height */
g_em->unique_identifier =
(graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height;
-
-#if DEBUG_EM_GFX
-
- // skip check for EMC elements not contained in original EMC artwork
- if (element == EL_EMC_FAKE_ACID)
- continue;
-
- if (g_em->bitmap != debug_bitmap ||
- g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y ||
- g_em->src_offset_x != 0 ||
- g_em->src_offset_y != 0 ||
- g_em->dst_offset_x != 0 ||
- g_em->dst_offset_y != 0 ||
- g_em->width != TILEX ||
- g_em->height != TILEY)
- {
- static int last_i = -1;
-
- if (i != last_i)
- {
- printf("\n");
- last_i = i;
- }
-
- printf("::: EMC GFX ERROR for element %d -> %d ('%s', '%s', %d)",
- i, element, element_info[element].token_name,
- element_action_info[effective_action].suffix, direction);
-
- if (element != effective_element)
- printf(" [%d ('%s')]",
- effective_element,
- element_info[effective_element].token_name);
-
- printf("\n");
-
- if (g_em->bitmap != debug_bitmap)
- printf(" %d (%d): different bitmap! (0x%08x != 0x%08x)\n",
- j, is_backside, (int)(g_em->bitmap), (int)(debug_bitmap));
-
- if (g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y)
- printf(" frame %d (%c): %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
- j, (is_backside ? 'B' : 'F'),
- g_em->src_x, g_em->src_y,
- g_em->src_x / 32, g_em->src_y / 32,
- debug_src_x, debug_src_y,
- debug_src_x / 32, debug_src_y / 32);
-
- if (g_em->src_offset_x != 0 ||
- g_em->src_offset_y != 0 ||
- g_em->dst_offset_x != 0 ||
- g_em->dst_offset_y != 0)
- printf(" %d (%d): offsets %d,%d and %d,%d should be all 0\n",
- j, is_backside,
- g_em->src_offset_x, g_em->src_offset_y,
- g_em->dst_offset_x, g_em->dst_offset_y);
-
- if (g_em->width != TILEX ||
- g_em->height != TILEY)
- printf(" %d (%d): size %d,%d should be %d,%d\n",
- j, is_backside,
- g_em->width, g_em->height, TILEX, TILEY);
-
- num_em_gfx_errors++;
- }
-#endif
-
}
}
- for (i = 0; i < TILE_MAX; i++)
+ for (i = 0; i < GAME_TILE_MAX; i++)
{
for (j = 0; j < 8; j++)
{
Xspring);
// no separate animation for "smashed by rock" -- use rock instead
- struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j];
- struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][7 - j];
+ struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][j];
+ struct GraphicInfo_EM *g_xx = &graphic_info_em_object[e][j];
g_em->bitmap = g_xx->bitmap;
g_em->src_x = g_xx->src_x;
el_act_dir2img(effective_element, effective_action,
direction));
struct GraphicInfo *g = &graphic_info[graphic];
- struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][7 - j];
+ struct GraphicInfo_EM *g_em = &graphic_info_em_player[p][i][j];
Bitmap *src_bitmap;
int src_x, src_y;
int sync_frame = j;
-
-#if DEBUG_EM_GFX
- Bitmap *debug_bitmap = g_em->bitmap;
- int debug_src_x = g_em->src_x;
- int debug_src_y = g_em->src_y;
-#endif
-
int frame = getAnimationFrame(g->anim_frames,
g->anim_delay,
g->anim_mode,
g_em->dst_offset_y = 0;
g_em->width = TILEX;
g_em->height = TILEY;
-
-#if DEBUG_EM_GFX
-
- // skip check for EMC elements not contained in original EMC artwork
- if (element == EL_PLAYER_3 ||
- element == EL_PLAYER_4)
- continue;
-
- if (g_em->bitmap != debug_bitmap ||
- g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y)
- {
- static int last_i = -1;
-
- if (i != last_i)
- {
- printf("\n");
- last_i = i;
- }
-
- printf("::: EMC GFX ERROR for p/a %d/%d -> %d ('%s', '%s', %d)",
- p, i, element, element_info[element].token_name,
- element_action_info[effective_action].suffix, direction);
-
- if (element != effective_element)
- printf(" [%d ('%s')]",
- effective_element,
- element_info[effective_element].token_name);
-
- printf("\n");
-
- if (g_em->bitmap != debug_bitmap)
- printf(" %d: different bitmap! (0x%08x != 0x%08x)\n",
- j, (int)(g_em->bitmap), (int)(debug_bitmap));
-
- if (g_em->src_x != debug_src_x ||
- g_em->src_y != debug_src_y)
- printf(" frame %d: %d,%d (%d,%d) should be %d,%d (%d,%d)\n",
- j,
- g_em->src_x, g_em->src_y,
- g_em->src_x / 32, g_em->src_y / 32,
- debug_src_x, debug_src_y,
- debug_src_x / 32, debug_src_y / 32);
-
- num_em_gfx_errors++;
- }
-#endif
-
}
}
}
-
-#if DEBUG_EM_GFX
- printf("\n");
- printf("::: [%d errors found]\n", num_em_gfx_errors);
-
- exit(0);
-#endif
}
static void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame,
boolean any_player_snapping,
boolean any_player_dropping)
{
- if (frame == 0 && !any_player_dropping)
+ if (frame == 7 && !any_player_dropping)
{
if (!local_player->was_waiting)
{
boolean any_player_dropping)
{
if (tape.single_step && tape.recording && !tape.pausing)
- if (frame == 0 && !any_player_dropping)
+ if (frame == 7 && !any_player_dropping)
TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
CheckSaveEngineSnapshot_EM(action, frame, any_player_moving,
#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);
+
+ // set setup value according to successfully changed window scaling
+ setup.window_scaling_percent = video.window_scaling_percent;
+}
+void ChangeVsyncModeIfNeeded(void)
+{
+ int setup_vsync_mode = VSYNC_MODE_STR_TO_INT(setup.vsync_mode);
+ int video_vsync_mode = video.vsync_mode;
+
+ // if setup and video vsync mode are already matching, nothing do do
+ if (setup_vsync_mode == video_vsync_mode)
return;
- }
- if (change_fullscreen ||
- change_window_scaling_percent)
+ // if renderer is using OpenGL, vsync mode can directly be changed
+ SDLSetScreenVsyncMode(setup.vsync_mode);
+
+ // if vsync mode unchanged, try re-creating renderer to set vsync mode
+ if (video.vsync_mode == video_vsync_mode)
{
Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH);
- // save backbuffer content which gets lost when toggling fullscreen mode
+ // save backbuffer content which gets lost when re-creating screen
BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
- if (change_window_scaling_percent)
- {
- // keep window mode, but change window scaling
- video.fullscreen_enabled = TRUE; // force new window scaling
- }
+ // force re-creating screen and renderer to set new vsync mode
+ video.fullscreen_enabled = !setup.fullscreen;
- // toggle fullscreen
+ // when creating new renderer, destroy textures linked to old renderer
+ FreeAllImageTextures(); // needs old renderer to free the textures
+
+ // re-create screen and renderer (including change of vsync mode)
ChangeVideoModeIfNeeded(setup.fullscreen);
// set setup value according to successfully changed fullscreen mode
// restore backbuffer content from temporary backbuffer backup bitmap
BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
-
FreeBitmap(tmp_backbuffer);
// update visible window/screen
BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0);
+
+ // when changing vsync mode, re-create textures for new renderer
+ InitImageTextures();
}
+
+ // set setup value according to successfully changed vsync mode
+ setup.vsync_mode = VSYNC_MODE_INT_TO_STR(video.vsync_mode);
}
static void JoinRectangles(int *x, int *y, int *width, int *height,
if (init_em_graphics)
{
- InitGraphicInfo_EM();
+ InitGraphicInfo_EM();
}
}