X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ftools.c;h=79cf0885135681310694fdc4dc562fd40dfa5cf0;hp=e33344dd6b23cd1a64bd06a2f84d4d8924836fc0;hb=1d7ec87196d24515b3d6e9400c689d9cd48c49f5;hpb=3ea7bc006da99f1b13d817285820023b30ce2e38 diff --git a/src/tools.c b/src/tools.c index e33344dd..79cf0885 100644 --- a/src/tools.c +++ b/src/tools.c @@ -4,7 +4,7 @@ // (c) 1995-2014 by Artsoft Entertainment // Holger Schemel // info@artsoft.org -// http://www.artsoft.org/ +// https://www.artsoft.org/ // ---------------------------------------------------------------------------- // tools.c // ============================================================================ @@ -23,8 +23,6 @@ #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 @@ -35,8 +33,11 @@ #define TOOL_CTRL_ID_PLAYER_2 4 #define TOOL_CTRL_ID_PLAYER_3 5 #define TOOL_CTRL_ID_PLAYER_4 6 +#define TOOL_CTRL_ID_TOUCH_YES 7 +#define TOOL_CTRL_ID_TOUCH_NO 8 +#define TOOL_CTRL_ID_TOUCH_CONFIRM 9 -#define NUM_TOOL_BUTTONS 7 +#define NUM_TOOL_BUTTONS 10 // constants for number of doors and door parts #define NUM_DOORS 2 @@ -192,22 +193,6 @@ static char *print_if_not_empty(int element) 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); @@ -296,7 +281,7 @@ static int getLevelFromScreenY_RND(int sy) 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); @@ -306,14 +291,12 @@ static int getLevelFromScreenX_EM(int sx) 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); @@ -323,8 +306,6 @@ static int getLevelFromScreenY_EM(int sy) int py = sy - SY; int ly = LEVELY((py + dy) / TILESIZE_VAR); - ly = correctLevelPosY_EM(ly); - return ly; } @@ -410,41 +391,51 @@ int getLevelFromScreenY(int y) 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) @@ -481,6 +472,11 @@ void SetDrawtoField(int mode) } } +int GetDrawtoField(void) +{ + return (drawto_field == fieldbuffer ? DRAW_TO_FIELDBUFFER : DRAW_TO_BACKBUFFER); +} + static void RedrawPlayfield_RND(void) { if (game.envelope_active) @@ -516,6 +512,10 @@ static void DrawMaskedBorderExt_Rect(int x, int y, int width, int height, 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; @@ -635,60 +635,7 @@ void DrawMaskedBorderToTarget(int draw_target) 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) @@ -771,7 +718,7 @@ static void PrintFrameTimeDebugging(void) 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), @@ -970,19 +917,13 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) 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); @@ -998,8 +939,7 @@ static void SetScreenStates_BeforeFadingIn(void) 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; @@ -1022,8 +962,7 @@ static void SetScreenStates_BeforeFadingOut(void) 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) @@ -1156,6 +1095,13 @@ void FadeSkipNextFadeOut(void) 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) @@ -1178,14 +1124,14 @@ static Bitmap *getGlobalBorderBitmap(int graphic) 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); @@ -1364,6 +1310,9 @@ static void RedrawGlobalBorderIfNeeded(void) #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) @@ -1461,15 +1410,15 @@ void SetBorderElement(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) @@ -1478,39 +1427,42 @@ void SetBorderElement(void) } } -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, @@ -1540,6 +1492,40 @@ int getGraphicAnimationFrame(int graphic, int sync_frame) 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]; @@ -1548,7 +1534,7 @@ void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap) 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)]; } @@ -1594,7 +1580,7 @@ void getSizedGraphicSourceExt(int graphic, int frame, int tilesize, *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); @@ -1621,6 +1607,24 @@ void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) 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) { @@ -1638,8 +1642,9 @@ void DrawGraphic(int x, int y, int graphic, int frame) #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 @@ -1655,8 +1660,10 @@ void DrawFixedGraphic(int x, int y, int graphic, int frame) #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 @@ -1692,8 +1699,10 @@ void DrawGraphicThruMask(int x, int y, int graphic, int frame) #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 @@ -1709,8 +1718,10 @@ void DrawFixedGraphicThruMask(int x, int y, int graphic, int frame) #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 @@ -1871,8 +1882,10 @@ static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy, #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 @@ -2002,31 +2015,37 @@ void DrawScreenElementExt(int x, int y, int dx, int dy, int element, 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) @@ -2078,7 +2097,7 @@ void DrawLevelElementThruMask(int x, int y, int element) 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 !!! @@ -2131,8 +2150,27 @@ static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy, 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, @@ -2151,6 +2189,15 @@ 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); @@ -2158,9 +2205,23 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame, 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) || @@ -2206,10 +2267,23 @@ static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame, 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); } } } @@ -2285,8 +2359,8 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame) 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); @@ -2315,7 +2389,7 @@ static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame) !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); @@ -2341,7 +2415,7 @@ void DrawLevelFieldCrumbled(int x, int y) 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])) { @@ -2364,7 +2438,7 @@ void DrawLevelFieldCrumbledDigging(int x, int y, int direction, 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); } @@ -2390,7 +2464,7 @@ void DrawLevelFieldCrumbledNeighbours(int x, int 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; @@ -2409,7 +2483,7 @@ void DrawLevelFieldCrumbledNeighbours(int x, int 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; @@ -2445,9 +2519,43 @@ static int getBorderElement(int x, int y) 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)); } @@ -2474,7 +2582,7 @@ void DrawScreenField(int x, int y) return; } - element = Feld[lx][ly]; + element = Tile[lx][ly]; content = Store[lx][ly]; if (IS_MOVING(lx, ly)) @@ -2501,6 +2609,16 @@ void DrawScreenField(int x, int y) 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) @@ -2541,7 +2659,7 @@ void DrawScreenField(int x, int y) 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 || @@ -2694,7 +2812,7 @@ void DrawSizedElementOrWall(int sx, int sy, int scroll_x, int scroll_y, 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); } @@ -2706,7 +2824,7 @@ void DrawMiniElementOrWall(int sx, int sy, int scroll_x, int scroll_y) 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))); } @@ -2807,11 +2925,11 @@ static void AnimateEnvelope(int envelope_nr, int anim_mode, int action) 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(); @@ -2835,9 +2953,13 @@ void ShowEnvelope(int envelope_nr) 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) @@ -2846,10 +2968,13 @@ void ShowEnvelope(int envelope_nr) AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_OPENING); if (tape.playing) - Delay(wait_delay_value); + Delay_WithScreenUpdates(wait_delay_value); else WaitForEventToContinue(); + RemapAllGadgets(); + SetOverlayEnabled(overlay_enabled); + PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE); if (anim_mode != ANIM_NONE) @@ -2866,6 +2991,53 @@ void ShowEnvelope(int envelope_nr) 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; @@ -3016,6 +3188,8 @@ static void DrawEnvelopeRequest(char *text) // 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); } @@ -3097,6 +3271,8 @@ static void AnimateEnvelopeRequest(int anim_mode, int action) } } + PrepareEnvelopeRequestToScreen(backbuffer, dst_x, dst_y, width, height); + redraw_mask |= REDRAW_FIELD; BackToFront(); @@ -3133,10 +3309,13 @@ static void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) { MapGadget(tool_gadget[TOOL_CTRL_ID_YES]); MapGadget(tool_gadget[TOOL_CTRL_ID_NO]); + MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_YES]); + MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_NO]); } else if (req_state & REQ_CONFIRM) { MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]); + MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_CONFIRM]); } else if (req_state & REQ_PLAYER) { @@ -3405,8 +3584,8 @@ static void DrawPreviewLevelExt(boolean restart) 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) { @@ -3549,7 +3728,7 @@ void DrawPreviewPlayers(void) { int element = level.field[x][y]; - if (ELEM_IS_PLAYER(element)) + if (IS_PLAYER_ELEMENT(element)) { int player_nr = GET_PLAYER_NR(element); @@ -3714,10 +3893,10 @@ void ClearNetworkPlayers(void) } 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); @@ -3739,12 +3918,23 @@ void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, 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); } @@ -3752,12 +3942,24 @@ static void DrawGraphicAnimation(int x, int y, int graphic) 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); } @@ -3780,16 +3982,22 @@ void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic) 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 } @@ -3893,8 +4101,8 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage) #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; @@ -3920,8 +4128,8 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage) 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 : @@ -4016,7 +4224,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage) 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; @@ -4047,7 +4255,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage) 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]; } @@ -4081,7 +4289,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage) // 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 @@ -4128,7 +4336,7 @@ static void DrawPlayerExt(struct PlayerInfo *player, int drawing_stage) 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); @@ -4208,6 +4416,7 @@ void DrawPlayerField(int x, int y) void WaitForEventToContinue(void) { + boolean first_wait = TRUE; boolean still_wait = TRUE; if (program.headless) @@ -4220,6 +4429,7 @@ void WaitForEventToContinue(void) button_status = MB_RELEASED; ClearEventQueue(); + ClearPlayerAction(); while (still_wait) { @@ -4229,17 +4439,22 @@ void WaitForEventToContinue(void) { 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; @@ -4250,7 +4465,8 @@ void WaitForEventToContinue(void) still_wait = FALSE; } - BackToFront(); + if (!PendingEvent()) + BackToFront(); } } @@ -4258,10 +4474,11 @@ void WaitForEventToContinue(void) #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; @@ -4282,11 +4499,11 @@ static int RequestHandleEvents(unsigned int req_state) 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(); @@ -4305,6 +4522,8 @@ static int RequestHandleEvents(unsigned int req_state) while (NextValidEvent(&event)) { + event_handled = TRUE; + switch (event.type) { case EVENT_BUTTONPRESS: @@ -4339,12 +4558,15 @@ static int RequestHandleEvents(unsigned int req_state) switch (request_gadget_id) { case TOOL_CTRL_ID_YES: + case TOOL_CTRL_ID_TOUCH_YES: result = TRUE; break; case TOOL_CTRL_ID_NO: + case TOOL_CTRL_ID_TOUCH_NO: result = FALSE; break; case TOOL_CTRL_ID_CONFIRM: + case TOOL_CTRL_ID_TOUCH_CONFIRM: result = TRUE | FALSE; break; @@ -4362,6 +4584,8 @@ static int RequestHandleEvents(unsigned int req_state) break; default: + // only check clickable animations if no request gadget clicked + HandleGlobalAnimClicks(mx, my, button_status, FALSE); break; } @@ -4457,6 +4681,7 @@ static int RequestHandleEvents(unsigned int req_state) break; } + case EVENT_FINGERRELEASE: case EVENT_KEYRELEASE: ClearPlayerAction(); break; @@ -4553,18 +4778,25 @@ static int RequestHandleEvents(unsigned int req_state) } } - 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; @@ -4572,6 +4804,7 @@ static int RequestHandleEvents(unsigned int req_state) 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; @@ -4674,10 +4907,13 @@ static boolean RequestDoor(char *text, unsigned int req_state) { MapGadget(tool_gadget[TOOL_CTRL_ID_YES]); MapGadget(tool_gadget[TOOL_CTRL_ID_NO]); + MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_YES]); + MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_NO]); } else if (req_state & REQ_CONFIRM) { MapGadget(tool_gadget[TOOL_CTRL_ID_CONFIRM]); + MapGadget(tool_gadget[TOOL_CTRL_ID_TOUCH_CONFIRM]); } else if (req_state & REQ_PLAYER) { @@ -4710,7 +4946,7 @@ static boolean RequestDoor(char *text, unsigned int req_state) SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1); // ---------- handle request buttons ---------- - result = RequestHandleEvents(req_state); + result = RequestHandleEvents(req_state, draw_buffer_last); UnmapToolButtons(); @@ -4751,6 +4987,7 @@ static boolean RequestDoor(char *text, unsigned int req_state) static boolean RequestEnvelope(char *text, unsigned int req_state) { + int draw_buffer_last = GetDrawtoField(); int result; if (game_status == GAME_MODE_PLAYING) @@ -4802,7 +5039,7 @@ static boolean RequestEnvelope(char *text, unsigned int req_state) SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1); // ---------- handle request buttons ---------- - result = RequestHandleEvents(req_state); + result = RequestHandleEvents(req_state, draw_buffer_last); UnmapToolButtons(); @@ -4839,6 +5076,8 @@ boolean Request(char *text, unsigned int req_state) boolean overlay_enabled = GetOverlayEnabled(); boolean result; + game.request_active_or_moving = TRUE; + SetOverlayEnabled(FALSE); if (global.use_envelope_request) @@ -4848,6 +5087,8 @@ boolean Request(char *text, unsigned int req_state) SetOverlayEnabled(overlay_enabled); + game.request_active_or_moving = FALSE; + return result; } @@ -5162,7 +5403,6 @@ unsigned int MoveDoor(unsigned int door_state) 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; @@ -5355,7 +5595,7 @@ unsigned int MoveDoor(unsigned int door_state) 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 @@ -5422,8 +5662,6 @@ unsigned int MoveDoor(unsigned int door_state) 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(); } @@ -5549,36 +5787,49 @@ static struct int graphic; struct TextPosInfo *pos; int gadget_id; + boolean is_touch_button; char *infotext; } toolbutton_info[NUM_TOOL_BUTTONS] = { { IMG_GFX_REQUEST_BUTTON_YES, &request.button.yes, - TOOL_CTRL_ID_YES, "yes" + TOOL_CTRL_ID_YES, FALSE, "yes" }, { IMG_GFX_REQUEST_BUTTON_NO, &request.button.no, - TOOL_CTRL_ID_NO, "no" + TOOL_CTRL_ID_NO, FALSE, "no" }, { IMG_GFX_REQUEST_BUTTON_CONFIRM, &request.button.confirm, - TOOL_CTRL_ID_CONFIRM, "confirm" + TOOL_CTRL_ID_CONFIRM, FALSE, "confirm" }, { IMG_GFX_REQUEST_BUTTON_PLAYER_1, &request.button.player_1, - TOOL_CTRL_ID_PLAYER_1, "player 1" + TOOL_CTRL_ID_PLAYER_1, FALSE, "player 1" }, { IMG_GFX_REQUEST_BUTTON_PLAYER_2, &request.button.player_2, - TOOL_CTRL_ID_PLAYER_2, "player 2" + TOOL_CTRL_ID_PLAYER_2, FALSE, "player 2" }, { IMG_GFX_REQUEST_BUTTON_PLAYER_3, &request.button.player_3, - TOOL_CTRL_ID_PLAYER_3, "player 3" + TOOL_CTRL_ID_PLAYER_3, FALSE, "player 3" }, { IMG_GFX_REQUEST_BUTTON_PLAYER_4, &request.button.player_4, - TOOL_CTRL_ID_PLAYER_4, "player 4" + TOOL_CTRL_ID_PLAYER_4, FALSE, "player 4" + }, + { + IMG_GFX_REQUEST_BUTTON_TOUCH_YES, &request.button.touch_yes, + TOOL_CTRL_ID_TOUCH_YES, TRUE, "yes" + }, + { + IMG_GFX_REQUEST_BUTTON_TOUCH_NO, &request.button.touch_no, + TOOL_CTRL_ID_TOUCH_NO, TRUE, "no" + }, + { + IMG_GFX_REQUEST_BUTTON_TOUCH_CONFIRM, &request.button.touch_confirm, + TOOL_CTRL_ID_TOUCH_CONFIRM, TRUE, "confirm" } }; @@ -5595,8 +5846,9 @@ void CreateToolButtons(void) Bitmap *deco_bitmap = None; int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0; unsigned int event_mask = GD_EVENT_RELEASED; - int dx = DX; - int dy = DY; + boolean is_touch_button = toolbutton_info[i].is_touch_button; + int base_x = (is_touch_button ? 0 : DX); + int base_y = (is_touch_button ? 0 : DY); int gd_x = gfx->src_x; int gd_y = gfx->src_y; int gd_xp = gfx->src_x + gfx->pressed_xoffset; @@ -5605,9 +5857,13 @@ void CreateToolButtons(void) int y = pos->y; int id = i; - if (global.use_envelope_request) + // 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(&dx, &dy, TRUE); + setRequestPosition(&base_x, &base_y, TRUE); // check if request buttons are outside of envelope and fix, if needed if (x < 0 || x + gfx->width > request.width || @@ -5654,8 +5910,8 @@ void CreateToolButtons(void) gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_IMAGE_ID, graphic, GDI_INFO_TEXT, toolbutton_info[i].infotext, - GDI_X, dx + x, - GDI_Y, dy + y, + GDI_X, base_x + x, + GDI_Y, base_y + y, GDI_WIDTH, gfx->width, GDI_HEIGHT, gfx->height, GDI_TYPE, GD_TYPE_NORMAL_BUTTON, @@ -5667,12 +5923,13 @@ void CreateToolButtons(void) GDI_DECORATION_SIZE, pos->size, pos->size, GDI_DECORATION_SHIFTING, 1, 1, GDI_DIRECT_DRAW, FALSE, + GDI_OVERLAY_TOUCH_BUTTON, is_touch_button, GDI_EVENT_MASK, event_mask, GDI_CALLBACK_ACTION, HandleToolButtons, GDI_END); if (gi == NULL) - Error(ERR_EXIT, "cannot create gadget"); + Fail("cannot create gadget"); tool_gadget[id] = gi; } @@ -5709,352 +5966,227 @@ static struct Mapping_EM_to_RND_object int action; int direction; } -em_object_mapping_list[] = +em_object_mapping_list[GAME_TILE_MAX + 1] = { { - Xblank, TRUE, FALSE, + Zborder, FALSE, FALSE, EL_EMPTY, -1, -1 }, { - Yacid_splash_eB, FALSE, FALSE, - EL_ACID_SPLASH_RIGHT, -1, -1 - }, - { - Yacid_splash_wB, FALSE, FALSE, - EL_ACID_SPLASH_LEFT, -1, -1 + Zplayer, FALSE, FALSE, + EL_EMPTY, -1, -1 }, -#ifdef EM_ENGINE_BAD_ROLL { - Xstone_force_e, FALSE, FALSE, - EL_ROCK, -1, MV_BIT_RIGHT + Zbug, FALSE, FALSE, + EL_EMPTY, -1, -1 }, { - Xstone_force_w, FALSE, FALSE, - EL_ROCK, -1, MV_BIT_LEFT + Ztank, FALSE, FALSE, + EL_EMPTY, -1, -1 }, { - Xnut_force_e, FALSE, FALSE, - EL_NUT, -1, MV_BIT_RIGHT + Zeater, FALSE, FALSE, + EL_EMPTY, -1, -1 }, { - Xnut_force_w, FALSE, FALSE, - EL_NUT, -1, MV_BIT_LEFT + Zdynamite, FALSE, FALSE, + EL_EMPTY, -1, -1 }, { - Xspring_force_e, FALSE, FALSE, - EL_SPRING, -1, MV_BIT_RIGHT + Zboom, FALSE, FALSE, + EL_EMPTY, -1, -1 }, + { - Xspring_force_w, FALSE, FALSE, - EL_SPRING, -1, MV_BIT_LEFT + Xchain, FALSE, FALSE, + EL_DEFAULT, ACTION_EXPLODING, -1 }, { - Xemerald_force_e, FALSE, FALSE, - EL_EMERALD, -1, MV_BIT_RIGHT + Xboom_bug, FALSE, FALSE, + EL_BUG, ACTION_EXPLODING, -1 }, { - Xemerald_force_w, FALSE, FALSE, - EL_EMERALD, -1, MV_BIT_LEFT + Xboom_tank, FALSE, FALSE, + EL_SPACESHIP, ACTION_EXPLODING, -1 }, { - Xdiamond_force_e, FALSE, FALSE, - EL_DIAMOND, -1, MV_BIT_RIGHT + Xboom_android, FALSE, FALSE, + EL_EMC_ANDROID, ACTION_OTHER, -1 }, { - Xdiamond_force_w, FALSE, FALSE, - EL_DIAMOND, -1, MV_BIT_LEFT + Xboom_1, FALSE, FALSE, + EL_DEFAULT, ACTION_EXPLODING, -1 }, { - Xbomb_force_e, FALSE, FALSE, - EL_BOMB, -1, MV_BIT_RIGHT + Xboom_2, FALSE, FALSE, + EL_DEFAULT, ACTION_EXPLODING, -1 }, + { - Xbomb_force_w, FALSE, FALSE, - EL_BOMB, -1, MV_BIT_LEFT + Xblank, TRUE, FALSE, + EL_EMPTY, -1, -1 }, -#endif // EM_ENGINE_BAD_ROLL { - Xstone, TRUE, FALSE, - EL_ROCK, -1, -1 + Xsplash_e, FALSE, FALSE, + EL_ACID_SPLASH_RIGHT, -1, -1 }, { - Xstone_pause, FALSE, FALSE, - EL_ROCK, -1, -1 - }, - { - Xstone_fall, FALSE, FALSE, - EL_ROCK, -1, -1 - }, - { - Ystone_s, FALSE, FALSE, - EL_ROCK, ACTION_FALLING, -1 - }, - { - Ystone_sB, FALSE, TRUE, - EL_ROCK, ACTION_FALLING, -1 - }, - { - Ystone_e, FALSE, FALSE, - EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Ystone_eB, FALSE, TRUE, - EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Ystone_w, FALSE, FALSE, - EL_ROCK, ACTION_MOVING, MV_BIT_LEFT - }, - { - Ystone_wB, FALSE, TRUE, - EL_ROCK, ACTION_MOVING, MV_BIT_LEFT - }, - { - Xnut, TRUE, FALSE, - EL_NUT, -1, -1 - }, - { - Xnut_pause, FALSE, FALSE, - EL_NUT, -1, -1 - }, - { - Xnut_fall, FALSE, FALSE, - EL_NUT, -1, -1 - }, - { - Ynut_s, FALSE, FALSE, - EL_NUT, ACTION_FALLING, -1 - }, - { - Ynut_sB, FALSE, TRUE, - EL_NUT, ACTION_FALLING, -1 - }, - { - Ynut_e, FALSE, FALSE, - EL_NUT, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Ynut_eB, FALSE, TRUE, - EL_NUT, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Ynut_w, FALSE, FALSE, - EL_NUT, ACTION_MOVING, MV_BIT_LEFT - }, - { - Ynut_wB, FALSE, TRUE, - EL_NUT, ACTION_MOVING, MV_BIT_LEFT - }, - { - Xbug_n, TRUE, FALSE, - EL_BUG_UP, -1, -1 - }, - { - Xbug_e, TRUE, FALSE, - EL_BUG_RIGHT, -1, -1 - }, - { - Xbug_s, TRUE, FALSE, - EL_BUG_DOWN, -1, -1 - }, - { - Xbug_w, TRUE, FALSE, - EL_BUG_LEFT, -1, -1 - }, - { - Xbug_gon, FALSE, FALSE, - EL_BUG_UP, -1, -1 - }, - { - Xbug_goe, FALSE, FALSE, - EL_BUG_RIGHT, -1, -1 - }, - { - Xbug_gos, FALSE, FALSE, - EL_BUG_DOWN, -1, -1 - }, - { - Xbug_gow, FALSE, FALSE, - EL_BUG_LEFT, -1, -1 - }, - { - Ybug_n, FALSE, FALSE, - EL_BUG, ACTION_MOVING, MV_BIT_UP - }, - { - Ybug_nB, FALSE, TRUE, - EL_BUG, ACTION_MOVING, MV_BIT_UP - }, - { - Ybug_e, FALSE, FALSE, - EL_BUG, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Ybug_eB, FALSE, TRUE, - EL_BUG, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Ybug_s, FALSE, FALSE, - EL_BUG, ACTION_MOVING, MV_BIT_DOWN - }, - { - Ybug_sB, FALSE, TRUE, - EL_BUG, ACTION_MOVING, MV_BIT_DOWN - }, - { - Ybug_w, FALSE, FALSE, - EL_BUG, ACTION_MOVING, MV_BIT_LEFT - }, - { - Ybug_wB, FALSE, TRUE, - EL_BUG, ACTION_MOVING, MV_BIT_LEFT + Xsplash_w, FALSE, FALSE, + EL_ACID_SPLASH_LEFT, -1, -1 }, + { - Ybug_w_n, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP + Xplant, TRUE, FALSE, + EL_EMC_PLANT, -1, -1 }, { - Ybug_n_e, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT + Yplant, FALSE, FALSE, + EL_EMC_PLANT, -1, -1 }, + { - Ybug_e_s, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN + Xacid_1, TRUE, FALSE, + EL_ACID, -1, -1 }, { - Ybug_s_w, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT + Xacid_2, FALSE, FALSE, + EL_ACID, -1, -1 }, { - Ybug_e_n, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP + Xacid_3, FALSE, FALSE, + EL_ACID, -1, -1 }, { - Ybug_s_e, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT + Xacid_4, FALSE, FALSE, + EL_ACID, -1, -1 }, { - Ybug_w_s, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN + Xacid_5, FALSE, FALSE, + EL_ACID, -1, -1 }, { - Ybug_n_w, FALSE, FALSE, - EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT + Xacid_6, FALSE, FALSE, + EL_ACID, -1, -1 }, { - Ybug_stone, FALSE, FALSE, - EL_BUG, ACTION_SMASHED_BY_ROCK, -1 + Xacid_7, FALSE, FALSE, + EL_ACID, -1, -1 }, { - Ybug_spring, FALSE, FALSE, - EL_BUG, ACTION_SMASHED_BY_SPRING, -1 + Xacid_8, FALSE, FALSE, + EL_ACID, -1, -1 }, + { - Xtank_n, TRUE, FALSE, - EL_SPACESHIP_UP, -1, -1 + Xfake_acid_1, TRUE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Xtank_e, TRUE, FALSE, - EL_SPACESHIP_RIGHT, -1, -1 + Xfake_acid_2, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Xtank_s, TRUE, FALSE, - EL_SPACESHIP_DOWN, -1, -1 + Xfake_acid_3, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Xtank_w, TRUE, FALSE, - EL_SPACESHIP_LEFT, -1, -1 + Xfake_acid_4, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Xtank_gon, FALSE, FALSE, - EL_SPACESHIP_UP, -1, -1 + Xfake_acid_5, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Xtank_goe, FALSE, FALSE, - EL_SPACESHIP_RIGHT, -1, -1 + Xfake_acid_6, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Xtank_gos, FALSE, FALSE, - EL_SPACESHIP_DOWN, -1, -1 + Xfake_acid_7, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Xtank_gow, FALSE, FALSE, - EL_SPACESHIP_LEFT, -1, -1 + Xfake_acid_8, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, + { - Ytank_n, FALSE, FALSE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP + Xfake_acid_1_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Ytank_nB, FALSE, TRUE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP + Xfake_acid_2_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Ytank_e, FALSE, FALSE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT + Xfake_acid_3_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Ytank_eB, FALSE, TRUE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT + Xfake_acid_4_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Ytank_s, FALSE, FALSE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN + Xfake_acid_5_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Ytank_sB, FALSE, TRUE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN + Xfake_acid_6_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Ytank_w, FALSE, FALSE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT + Xfake_acid_7_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, { - Ytank_wB, FALSE, TRUE, - EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT + Xfake_acid_8_player, FALSE, FALSE, + EL_EMC_FAKE_ACID, -1, -1 }, + { - Ytank_w_n, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP + Xgrass, TRUE, FALSE, + EL_EMC_GRASS, -1, -1 }, { - Ytank_n_e, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT + Ygrass_nB, FALSE, FALSE, + EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP }, { - Ytank_e_s, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN + Ygrass_eB, FALSE, FALSE, + EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT }, { - Ytank_s_w, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT + Ygrass_sB, FALSE, FALSE, + EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN }, { - Ytank_e_n, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP + Ygrass_wB, FALSE, FALSE, + EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT }, + { - Ytank_s_e, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT + Xdirt, TRUE, FALSE, + EL_SAND, -1, -1 }, { - Ytank_w_s, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN + Ydirt_nB, FALSE, FALSE, + EL_SAND, ACTION_DIGGING, MV_BIT_UP }, { - Ytank_n_w, FALSE, FALSE, - EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT + Ydirt_eB, FALSE, FALSE, + EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT }, { - Ytank_stone, FALSE, FALSE, - EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1 + Ydirt_sB, FALSE, FALSE, + EL_SAND, ACTION_DIGGING, MV_BIT_DOWN }, { - Ytank_spring, FALSE, FALSE, - EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1 + Ydirt_wB, FALSE, FALSE, + EL_SAND, ACTION_DIGGING, MV_BIT_LEFT }, + { Xandroid, TRUE, FALSE, EL_EMC_ANDROID, ACTION_ACTIVE, -1 @@ -6155,66 +6287,7 @@ em_object_mapping_list[] = Yandroid_nwB, FALSE, TRUE, EL_EMC_ANDROID, ACTION_SHRINKING, MV_BIT_UPLEFT }, - { - Xspring, TRUE, FALSE, - EL_SPRING, -1, -1 - }, - { - Xspring_pause, FALSE, FALSE, - EL_SPRING, -1, -1 - }, - { - Xspring_e, FALSE, FALSE, - EL_SPRING, -1, -1 - }, - { - Xspring_w, FALSE, FALSE, - EL_SPRING, -1, -1 - }, - { - Xspring_fall, FALSE, FALSE, - EL_SPRING, -1, -1 - }, - { - Yspring_s, FALSE, FALSE, - EL_SPRING, ACTION_FALLING, -1 - }, - { - Yspring_sB, FALSE, TRUE, - EL_SPRING, ACTION_FALLING, -1 - }, - { - Yspring_e, FALSE, FALSE, - EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Yspring_eB, FALSE, TRUE, - EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT - }, - { - Yspring_w, FALSE, FALSE, - EL_SPRING, ACTION_MOVING, MV_BIT_LEFT - }, - { - Yspring_wB, FALSE, TRUE, - EL_SPRING, ACTION_MOVING, MV_BIT_LEFT - }, - { - Yspring_kill_e, FALSE, FALSE, - EL_SPRING, ACTION_EATING, MV_BIT_RIGHT - }, - { - Yspring_kill_eB, FALSE, TRUE, - EL_SPRING, ACTION_EATING, MV_BIT_RIGHT - }, - { - Yspring_kill_w, FALSE, FALSE, - EL_SPRING, ACTION_EATING, MV_BIT_LEFT - }, - { - Yspring_kill_wB, FALSE, TRUE, - EL_SPRING, ACTION_EATING, MV_BIT_LEFT - }, + { Xeater_n, TRUE, FALSE, EL_YAMYAM_UP, -1, -1 @@ -6271,6 +6344,7 @@ em_object_mapping_list[] = Yeater_spring, FALSE, FALSE, EL_YAMYAM, ACTION_SMASHED_BY_SPRING, -1 }, + { Xalien, TRUE, FALSE, EL_ROBOT, -1, -1 @@ -6319,536 +6393,546 @@ em_object_mapping_list[] = Yalien_spring, FALSE, FALSE, EL_ROBOT, ACTION_SMASHED_BY_SPRING, -1 }, + { - Xemerald, TRUE, FALSE, - EL_EMERALD, -1, -1 + Xbug_1_n, TRUE, FALSE, + EL_BUG_UP, -1, -1 }, { - Xemerald_pause, FALSE, FALSE, - EL_EMERALD, -1, -1 + Xbug_1_e, TRUE, FALSE, + EL_BUG_RIGHT, -1, -1 }, { - Xemerald_fall, FALSE, FALSE, - EL_EMERALD, -1, -1 + Xbug_1_s, TRUE, FALSE, + EL_BUG_DOWN, -1, -1 }, { - Xemerald_shine, FALSE, FALSE, - EL_EMERALD, ACTION_TWINKLING, -1 + Xbug_1_w, TRUE, FALSE, + EL_BUG_LEFT, -1, -1 }, { - Yemerald_s, FALSE, FALSE, - EL_EMERALD, ACTION_FALLING, -1 + Xbug_2_n, FALSE, FALSE, + EL_BUG_UP, -1, -1 }, { - Yemerald_sB, FALSE, TRUE, - EL_EMERALD, ACTION_FALLING, -1 + Xbug_2_e, FALSE, FALSE, + EL_BUG_RIGHT, -1, -1 }, { - Yemerald_e, FALSE, FALSE, - EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT + Xbug_2_s, FALSE, FALSE, + EL_BUG_DOWN, -1, -1 }, { - Yemerald_eB, FALSE, TRUE, - EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT + Xbug_2_w, FALSE, FALSE, + EL_BUG_LEFT, -1, -1 }, { - Yemerald_w, FALSE, FALSE, - EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT + Ybug_n, FALSE, FALSE, + EL_BUG, ACTION_MOVING, MV_BIT_UP }, { - Yemerald_wB, FALSE, TRUE, - EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT + Ybug_nB, FALSE, TRUE, + EL_BUG, ACTION_MOVING, MV_BIT_UP }, { - Yemerald_eat, FALSE, FALSE, - EL_EMERALD, ACTION_COLLECTING, -1 + Ybug_e, FALSE, FALSE, + EL_BUG, ACTION_MOVING, MV_BIT_RIGHT }, { - Yemerald_stone, FALSE, FALSE, - EL_NUT, ACTION_BREAKING, -1 + Ybug_eB, FALSE, TRUE, + EL_BUG, ACTION_MOVING, MV_BIT_RIGHT }, { - Xdiamond, TRUE, FALSE, - EL_DIAMOND, -1, -1 + Ybug_s, FALSE, FALSE, + EL_BUG, ACTION_MOVING, MV_BIT_DOWN }, { - Xdiamond_pause, FALSE, FALSE, - EL_DIAMOND, -1, -1 + Ybug_sB, FALSE, TRUE, + EL_BUG, ACTION_MOVING, MV_BIT_DOWN }, { - Xdiamond_fall, FALSE, FALSE, - EL_DIAMOND, -1, -1 + Ybug_w, FALSE, FALSE, + EL_BUG, ACTION_MOVING, MV_BIT_LEFT }, { - Xdiamond_shine, FALSE, FALSE, - EL_DIAMOND, ACTION_TWINKLING, -1 + Ybug_wB, FALSE, TRUE, + EL_BUG, ACTION_MOVING, MV_BIT_LEFT }, { - Ydiamond_s, FALSE, FALSE, - EL_DIAMOND, ACTION_FALLING, -1 + Ybug_w_n, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_UP }, { - Ydiamond_sB, FALSE, TRUE, - EL_DIAMOND, ACTION_FALLING, -1 + Ybug_n_e, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT }, { - Ydiamond_e, FALSE, FALSE, - EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT + Ybug_e_s, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN }, { - Ydiamond_eB, FALSE, TRUE, - EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT + Ybug_s_w, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT }, { - Ydiamond_w, FALSE, FALSE, - EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT + Ybug_e_n, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP }, { - Ydiamond_wB, FALSE, TRUE, - EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT + Ybug_s_e, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT }, { - Ydiamond_eat, FALSE, FALSE, - EL_DIAMOND, ACTION_COLLECTING, -1 + Ybug_w_s, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN }, { - Ydiamond_stone, FALSE, FALSE, - EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1 + Ybug_n_w, FALSE, FALSE, + EL_BUG, ACTION_TURNING_FROM_UP, MV_BIT_LEFT }, { - Xdrip_fall, TRUE, FALSE, - EL_AMOEBA_DROP, -1, -1 + Ybug_stone, FALSE, FALSE, + EL_BUG, ACTION_SMASHED_BY_ROCK, -1 }, { - Xdrip_stretch, FALSE, FALSE, - EL_AMOEBA_DROP, ACTION_FALLING, -1 + Ybug_spring, FALSE, FALSE, + EL_BUG, ACTION_SMASHED_BY_SPRING, -1 }, + { - Xdrip_stretchB, FALSE, TRUE, - EL_AMOEBA_DROP, ACTION_FALLING, -1 + Xtank_1_n, TRUE, FALSE, + EL_SPACESHIP_UP, -1, -1 }, { - Xdrip_eat, FALSE, FALSE, - EL_AMOEBA_DROP, ACTION_GROWING, -1 + Xtank_1_e, TRUE, FALSE, + EL_SPACESHIP_RIGHT, -1, -1 }, { - Ydrip_s1, FALSE, FALSE, - EL_AMOEBA_DROP, ACTION_FALLING, -1 + Xtank_1_s, TRUE, FALSE, + EL_SPACESHIP_DOWN, -1, -1 }, { - Ydrip_s1B, FALSE, TRUE, - EL_AMOEBA_DROP, ACTION_FALLING, -1 + Xtank_1_w, TRUE, FALSE, + EL_SPACESHIP_LEFT, -1, -1 }, { - Ydrip_s2, FALSE, FALSE, - EL_AMOEBA_DROP, ACTION_FALLING, -1 + Xtank_2_n, FALSE, FALSE, + EL_SPACESHIP_UP, -1, -1 }, { - Ydrip_s2B, FALSE, TRUE, - EL_AMOEBA_DROP, ACTION_FALLING, -1 + Xtank_2_e, FALSE, FALSE, + EL_SPACESHIP_RIGHT, -1, -1 }, { - Xbomb, TRUE, FALSE, - EL_BOMB, -1, -1 + Xtank_2_s, FALSE, FALSE, + EL_SPACESHIP_DOWN, -1, -1 }, { - Xbomb_pause, FALSE, FALSE, - EL_BOMB, -1, -1 + Xtank_2_w, FALSE, FALSE, + EL_SPACESHIP_LEFT, -1, -1 }, { - Xbomb_fall, FALSE, FALSE, - EL_BOMB, -1, -1 + Ytank_n, FALSE, FALSE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP }, { - Ybomb_s, FALSE, FALSE, - EL_BOMB, ACTION_FALLING, -1 + Ytank_nB, FALSE, TRUE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_UP }, { - Ybomb_sB, FALSE, TRUE, - EL_BOMB, ACTION_FALLING, -1 + Ytank_e, FALSE, FALSE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT }, { - Ybomb_e, FALSE, FALSE, - EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT + Ytank_eB, FALSE, TRUE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_RIGHT }, { - Ybomb_eB, FALSE, TRUE, - EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT + Ytank_s, FALSE, FALSE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN }, { - Ybomb_w, FALSE, FALSE, - EL_BOMB, ACTION_MOVING, MV_BIT_LEFT + Ytank_sB, FALSE, TRUE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_DOWN }, { - Ybomb_wB, FALSE, TRUE, - EL_BOMB, ACTION_MOVING, MV_BIT_LEFT + Ytank_w, FALSE, FALSE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT }, { - Ybomb_eat, FALSE, FALSE, - EL_BOMB, ACTION_ACTIVATING, -1 + Ytank_wB, FALSE, TRUE, + EL_SPACESHIP, ACTION_MOVING, MV_BIT_LEFT }, { - Xballoon, TRUE, FALSE, - EL_BALLOON, -1, -1 + Ytank_w_n, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_UP }, { - Yballoon_n, FALSE, FALSE, - EL_BALLOON, ACTION_MOVING, MV_BIT_UP + Ytank_n_e, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_RIGHT }, { - Yballoon_nB, FALSE, TRUE, - EL_BALLOON, ACTION_MOVING, MV_BIT_UP + Ytank_e_s, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_DOWN }, { - Yballoon_e, FALSE, FALSE, - EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT + Ytank_s_w, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_LEFT }, { - Yballoon_eB, FALSE, TRUE, - EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT + Ytank_e_n, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_RIGHT, MV_BIT_UP }, { - Yballoon_s, FALSE, FALSE, - EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN + Ytank_s_e, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_DOWN, MV_BIT_RIGHT }, { - Yballoon_sB, FALSE, TRUE, - EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN + Ytank_w_s, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_LEFT, MV_BIT_DOWN }, { - Yballoon_w, FALSE, FALSE, - EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT + Ytank_n_w, FALSE, FALSE, + EL_SPACESHIP, ACTION_TURNING_FROM_UP, MV_BIT_LEFT }, { - Yballoon_wB, FALSE, TRUE, - EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT + Ytank_stone, FALSE, FALSE, + EL_SPACESHIP, ACTION_SMASHED_BY_ROCK, -1 }, { - Xgrass, TRUE, FALSE, - EL_EMC_GRASS, -1, -1 + Ytank_spring, FALSE, FALSE, + EL_SPACESHIP, ACTION_SMASHED_BY_SPRING, -1 }, + { - Ygrass_nB, FALSE, FALSE, - EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_UP + Xemerald, TRUE, FALSE, + EL_EMERALD, -1, -1 }, { - Ygrass_eB, FALSE, FALSE, - EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_RIGHT + Xemerald_pause, FALSE, FALSE, + EL_EMERALD, -1, -1 }, { - Ygrass_sB, FALSE, FALSE, - EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_DOWN + Xemerald_fall, FALSE, FALSE, + EL_EMERALD, -1, -1 }, { - Ygrass_wB, FALSE, FALSE, - EL_EMC_GRASS, ACTION_DIGGING, MV_BIT_LEFT + Xemerald_shine, FALSE, FALSE, + EL_EMERALD, ACTION_TWINKLING, -1 }, { - Xdirt, TRUE, FALSE, - EL_SAND, -1, -1 + Yemerald_s, FALSE, FALSE, + EL_EMERALD, ACTION_FALLING, -1 }, { - Ydirt_nB, FALSE, FALSE, - EL_SAND, ACTION_DIGGING, MV_BIT_UP + Yemerald_sB, FALSE, TRUE, + EL_EMERALD, ACTION_FALLING, -1 }, { - Ydirt_eB, FALSE, FALSE, - EL_SAND, ACTION_DIGGING, MV_BIT_RIGHT + Yemerald_e, FALSE, FALSE, + EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT }, { - Ydirt_sB, FALSE, FALSE, - EL_SAND, ACTION_DIGGING, MV_BIT_DOWN + Yemerald_eB, FALSE, TRUE, + EL_EMERALD, ACTION_MOVING, MV_BIT_RIGHT }, { - Ydirt_wB, FALSE, FALSE, - EL_SAND, ACTION_DIGGING, MV_BIT_LEFT + Yemerald_w, FALSE, FALSE, + EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT }, { - Xacid_ne, TRUE, FALSE, - EL_ACID_POOL_TOPRIGHT, -1, -1 + Yemerald_wB, FALSE, TRUE, + EL_EMERALD, ACTION_MOVING, MV_BIT_LEFT }, { - Xacid_se, TRUE, FALSE, - EL_ACID_POOL_BOTTOMRIGHT, -1, -1 + Yemerald_blank, FALSE, FALSE, + EL_EMERALD, ACTION_COLLECTING, -1 }, + { - Xacid_s, TRUE, FALSE, - EL_ACID_POOL_BOTTOM, -1, -1 + Xdiamond, TRUE, FALSE, + EL_DIAMOND, -1, -1 }, { - Xacid_sw, TRUE, FALSE, - EL_ACID_POOL_BOTTOMLEFT, -1, -1 + Xdiamond_pause, FALSE, FALSE, + EL_DIAMOND, -1, -1 }, { - Xacid_nw, TRUE, FALSE, - EL_ACID_POOL_TOPLEFT, -1, -1 + Xdiamond_fall, FALSE, FALSE, + EL_DIAMOND, -1, -1 }, { - Xacid_1, TRUE, FALSE, - EL_ACID, -1, -1 + Xdiamond_shine, FALSE, FALSE, + EL_DIAMOND, ACTION_TWINKLING, -1 }, { - Xacid_2, FALSE, FALSE, - EL_ACID, -1, -1 + Ydiamond_s, FALSE, FALSE, + EL_DIAMOND, ACTION_FALLING, -1 }, { - Xacid_3, FALSE, FALSE, - EL_ACID, -1, -1 + Ydiamond_sB, FALSE, TRUE, + EL_DIAMOND, ACTION_FALLING, -1 }, { - Xacid_4, FALSE, FALSE, - EL_ACID, -1, -1 + Ydiamond_e, FALSE, FALSE, + EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT }, { - Xacid_5, FALSE, FALSE, - EL_ACID, -1, -1 + Ydiamond_eB, FALSE, TRUE, + EL_DIAMOND, ACTION_MOVING, MV_BIT_RIGHT }, { - Xacid_6, FALSE, FALSE, - EL_ACID, -1, -1 + Ydiamond_w, FALSE, FALSE, + EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT }, { - Xacid_7, FALSE, FALSE, - EL_ACID, -1, -1 + Ydiamond_wB, FALSE, TRUE, + EL_DIAMOND, ACTION_MOVING, MV_BIT_LEFT }, { - Xacid_8, FALSE, FALSE, - EL_ACID, -1, -1 + Ydiamond_blank, FALSE, FALSE, + EL_DIAMOND, ACTION_COLLECTING, -1 }, { - Xball_1, TRUE, FALSE, - EL_EMC_MAGIC_BALL, -1, -1 + Ydiamond_stone, FALSE, FALSE, + EL_DIAMOND, ACTION_SMASHED_BY_ROCK, -1 }, + { - Xball_1B, FALSE, FALSE, - EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1 + Xstone, TRUE, FALSE, + EL_ROCK, -1, -1 }, { - Xball_2, FALSE, FALSE, - EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1 + Xstone_pause, FALSE, FALSE, + EL_ROCK, -1, -1 }, { - Xball_2B, FALSE, FALSE, - EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1 + Xstone_fall, FALSE, FALSE, + EL_ROCK, -1, -1 }, { - Yball_eat, FALSE, FALSE, - EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1 + Ystone_s, FALSE, FALSE, + EL_ROCK, ACTION_FALLING, -1 }, { - Ykey_1_eat, FALSE, FALSE, - EL_EM_KEY_1, ACTION_COLLECTING, -1 + Ystone_sB, FALSE, TRUE, + EL_ROCK, ACTION_FALLING, -1 }, { - Ykey_2_eat, FALSE, FALSE, - EL_EM_KEY_2, ACTION_COLLECTING, -1 + Ystone_e, FALSE, FALSE, + EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT }, { - Ykey_3_eat, FALSE, FALSE, - EL_EM_KEY_3, ACTION_COLLECTING, -1 + Ystone_eB, FALSE, TRUE, + EL_ROCK, ACTION_MOVING, MV_BIT_RIGHT }, { - Ykey_4_eat, FALSE, FALSE, - EL_EM_KEY_4, ACTION_COLLECTING, -1 + Ystone_w, FALSE, FALSE, + EL_ROCK, ACTION_MOVING, MV_BIT_LEFT }, { - Ykey_5_eat, FALSE, FALSE, - EL_EMC_KEY_5, ACTION_COLLECTING, -1 + Ystone_wB, FALSE, TRUE, + EL_ROCK, ACTION_MOVING, MV_BIT_LEFT }, + { - Ykey_6_eat, FALSE, FALSE, - EL_EMC_KEY_6, ACTION_COLLECTING, -1 + Xbomb, TRUE, FALSE, + EL_BOMB, -1, -1 }, { - Ykey_7_eat, FALSE, FALSE, - EL_EMC_KEY_7, ACTION_COLLECTING, -1 + Xbomb_pause, FALSE, FALSE, + EL_BOMB, -1, -1 }, { - Ykey_8_eat, FALSE, FALSE, - EL_EMC_KEY_8, ACTION_COLLECTING, -1 + Xbomb_fall, FALSE, FALSE, + EL_BOMB, -1, -1 }, { - Ylenses_eat, FALSE, FALSE, - EL_EMC_LENSES, ACTION_COLLECTING, -1 + Ybomb_s, FALSE, FALSE, + EL_BOMB, ACTION_FALLING, -1 }, { - Ymagnify_eat, FALSE, FALSE, - EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1 + Ybomb_sB, FALSE, TRUE, + EL_BOMB, ACTION_FALLING, -1 }, { - Ygrass_eat, FALSE, FALSE, - EL_EMC_GRASS, ACTION_SNAPPING, -1 + Ybomb_e, FALSE, FALSE, + EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT }, { - Ydirt_eat, FALSE, FALSE, - EL_SAND, ACTION_SNAPPING, -1 + Ybomb_eB, FALSE, TRUE, + EL_BOMB, ACTION_MOVING, MV_BIT_RIGHT }, { - Xgrow_ns, TRUE, FALSE, - EL_EXPANDABLE_WALL_VERTICAL, -1, -1 + Ybomb_w, FALSE, FALSE, + EL_BOMB, ACTION_MOVING, MV_BIT_LEFT }, { - Ygrow_ns_eat, FALSE, FALSE, - EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1 + Ybomb_wB, FALSE, TRUE, + EL_BOMB, ACTION_MOVING, MV_BIT_LEFT }, { - Xgrow_ew, TRUE, FALSE, - EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1 + Ybomb_blank, FALSE, FALSE, + EL_BOMB, ACTION_ACTIVATING, -1 }, + { - Ygrow_ew_eat, FALSE, FALSE, - EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1 + Xnut, TRUE, FALSE, + EL_NUT, -1, -1 }, { - Xwonderwall, TRUE, FALSE, - EL_MAGIC_WALL, -1, -1 + Xnut_pause, FALSE, FALSE, + EL_NUT, -1, -1 }, { - XwonderwallB, FALSE, FALSE, - EL_MAGIC_WALL, ACTION_ACTIVE, -1 + Xnut_fall, FALSE, FALSE, + EL_NUT, -1, -1 }, { - Xamoeba_1, TRUE, FALSE, - EL_AMOEBA_DRY, ACTION_OTHER, -1 + Ynut_s, FALSE, FALSE, + EL_NUT, ACTION_FALLING, -1 }, { - Xamoeba_2, FALSE, FALSE, - EL_AMOEBA_DRY, ACTION_OTHER, -1 + Ynut_sB, FALSE, TRUE, + EL_NUT, ACTION_FALLING, -1 }, { - Xamoeba_3, FALSE, FALSE, - EL_AMOEBA_DRY, ACTION_OTHER, -1 + Ynut_e, FALSE, FALSE, + EL_NUT, ACTION_MOVING, MV_BIT_RIGHT }, { - Xamoeba_4, FALSE, FALSE, - EL_AMOEBA_DRY, ACTION_OTHER, -1 + Ynut_eB, FALSE, TRUE, + EL_NUT, ACTION_MOVING, MV_BIT_RIGHT }, { - Xamoeba_5, TRUE, FALSE, - EL_AMOEBA_WET, ACTION_OTHER, -1 + Ynut_w, FALSE, FALSE, + EL_NUT, ACTION_MOVING, MV_BIT_LEFT }, { - Xamoeba_6, FALSE, FALSE, - EL_AMOEBA_WET, ACTION_OTHER, -1 + Ynut_wB, FALSE, TRUE, + EL_NUT, ACTION_MOVING, MV_BIT_LEFT }, { - Xamoeba_7, FALSE, FALSE, - EL_AMOEBA_WET, ACTION_OTHER, -1 + Ynut_stone, FALSE, FALSE, + EL_NUT, ACTION_BREAKING, -1 }, + { - Xamoeba_8, FALSE, FALSE, - EL_AMOEBA_WET, ACTION_OTHER, -1 + Xspring, TRUE, FALSE, + EL_SPRING, -1, -1 }, { - Xdoor_1, TRUE, FALSE, - EL_EM_GATE_1, -1, -1 + Xspring_pause, FALSE, FALSE, + EL_SPRING, -1, -1 }, { - Xdoor_2, TRUE, FALSE, - EL_EM_GATE_2, -1, -1 + Xspring_e, TRUE, FALSE, + EL_SPRING_RIGHT, -1, -1 }, { - Xdoor_3, TRUE, FALSE, - EL_EM_GATE_3, -1, -1 + Xspring_w, TRUE, FALSE, + EL_SPRING_LEFT, -1, -1 }, { - Xdoor_4, TRUE, FALSE, - EL_EM_GATE_4, -1, -1 + Xspring_fall, FALSE, FALSE, + EL_SPRING, -1, -1 }, { - Xdoor_5, TRUE, FALSE, - EL_EMC_GATE_5, -1, -1 + Yspring_s, FALSE, FALSE, + EL_SPRING, ACTION_FALLING, -1 }, { - Xdoor_6, TRUE, FALSE, - EL_EMC_GATE_6, -1, -1 + Yspring_sB, FALSE, TRUE, + EL_SPRING, ACTION_FALLING, -1 }, { - Xdoor_7, TRUE, FALSE, - EL_EMC_GATE_7, -1, -1 + Yspring_e, FALSE, FALSE, + EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT }, { - Xdoor_8, TRUE, FALSE, - EL_EMC_GATE_8, -1, -1 + Yspring_eB, FALSE, TRUE, + EL_SPRING, ACTION_MOVING, MV_BIT_RIGHT }, { - Xkey_1, TRUE, FALSE, - EL_EM_KEY_1, -1, -1 + Yspring_w, FALSE, FALSE, + EL_SPRING, ACTION_MOVING, MV_BIT_LEFT }, { - Xkey_2, TRUE, FALSE, - EL_EM_KEY_2, -1, -1 + Yspring_wB, FALSE, TRUE, + EL_SPRING, ACTION_MOVING, MV_BIT_LEFT }, { - Xkey_3, TRUE, FALSE, - EL_EM_KEY_3, -1, -1 + Yspring_alien_e, FALSE, FALSE, + EL_SPRING, ACTION_EATING, MV_BIT_RIGHT }, { - Xkey_4, TRUE, FALSE, - EL_EM_KEY_4, -1, -1 + Yspring_alien_eB, FALSE, TRUE, + EL_SPRING, ACTION_EATING, MV_BIT_RIGHT }, { - Xkey_5, TRUE, FALSE, - EL_EMC_KEY_5, -1, -1 + Yspring_alien_w, FALSE, FALSE, + EL_SPRING, ACTION_EATING, MV_BIT_LEFT }, { - Xkey_6, TRUE, FALSE, - EL_EMC_KEY_6, -1, -1 + Yspring_alien_wB, FALSE, TRUE, + EL_SPRING, ACTION_EATING, MV_BIT_LEFT }, + { - Xkey_7, TRUE, FALSE, - EL_EMC_KEY_7, -1, -1 + Xpush_emerald_e, FALSE, FALSE, + EL_EMERALD, -1, MV_BIT_RIGHT }, { - Xkey_8, TRUE, FALSE, - EL_EMC_KEY_8, -1, -1 + Xpush_emerald_w, FALSE, FALSE, + EL_EMERALD, -1, MV_BIT_LEFT }, { - Xwind_n, TRUE, FALSE, - EL_BALLOON_SWITCH_UP, -1, -1 + Xpush_diamond_e, FALSE, FALSE, + EL_DIAMOND, -1, MV_BIT_RIGHT }, { - Xwind_e, TRUE, FALSE, - EL_BALLOON_SWITCH_RIGHT, -1, -1 + Xpush_diamond_w, FALSE, FALSE, + EL_DIAMOND, -1, MV_BIT_LEFT }, { - Xwind_s, TRUE, FALSE, - EL_BALLOON_SWITCH_DOWN, -1, -1 + Xpush_stone_e, FALSE, FALSE, + EL_ROCK, -1, MV_BIT_RIGHT }, { - Xwind_w, TRUE, FALSE, - EL_BALLOON_SWITCH_LEFT, -1, -1 + Xpush_stone_w, FALSE, FALSE, + EL_ROCK, -1, MV_BIT_LEFT }, { - Xwind_nesw, TRUE, FALSE, - EL_BALLOON_SWITCH_ANY, -1, -1 + Xpush_bomb_e, FALSE, FALSE, + EL_BOMB, -1, MV_BIT_RIGHT }, { - Xwind_stop, TRUE, FALSE, - EL_BALLOON_SWITCH_NONE, -1, -1 + Xpush_bomb_w, FALSE, FALSE, + EL_BOMB, -1, MV_BIT_LEFT }, { - Xexit, TRUE, FALSE, - EL_EM_EXIT_CLOSED, -1, -1 + Xpush_nut_e, FALSE, FALSE, + EL_NUT, -1, MV_BIT_RIGHT }, { - Xexit_1, TRUE, FALSE, - EL_EM_EXIT_OPEN, -1, -1 + Xpush_nut_w, FALSE, FALSE, + EL_NUT, -1, MV_BIT_LEFT }, { - Xexit_2, FALSE, FALSE, - EL_EM_EXIT_OPEN, -1, -1 + Xpush_spring_e, FALSE, FALSE, + EL_SPRING_RIGHT, -1, MV_BIT_RIGHT }, { - Xexit_3, FALSE, FALSE, - EL_EM_EXIT_OPEN, -1, -1 + Xpush_spring_w, FALSE, FALSE, + EL_SPRING_LEFT, -1, MV_BIT_LEFT }, + { Xdynamite, TRUE, FALSE, EL_EM_DYNAMITE, -1, -1 }, { - Ydynamite_eat, FALSE, FALSE, + Ydynamite_blank, FALSE, FALSE, EL_EM_DYNAMITE, ACTION_COLLECTING, -1 }, { @@ -6867,222 +6951,461 @@ em_object_mapping_list[] = Xdynamite_4, FALSE, FALSE, EL_EM_DYNAMITE_ACTIVE, -1, -1 }, + { - Xbumper, TRUE, FALSE, - EL_EMC_SPRING_BUMPER, -1, -1 + Xkey_1, TRUE, FALSE, + EL_EM_KEY_1, -1, -1 }, { - XbumperB, FALSE, FALSE, - EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1 + Xkey_2, TRUE, FALSE, + EL_EM_KEY_2, -1, -1 }, { - Xwheel, TRUE, FALSE, - EL_ROBOT_WHEEL, -1, -1 + Xkey_3, TRUE, FALSE, + EL_EM_KEY_3, -1, -1 }, { - XwheelB, FALSE, FALSE, - EL_ROBOT_WHEEL, ACTION_ACTIVE, -1 + Xkey_4, TRUE, FALSE, + EL_EM_KEY_4, -1, -1 }, { - Xswitch, TRUE, FALSE, - EL_EMC_MAGIC_BALL_SWITCH, -1, -1 + Xkey_5, TRUE, FALSE, + EL_EMC_KEY_5, -1, -1 }, { - XswitchB, FALSE, FALSE, - EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1 + Xkey_6, TRUE, FALSE, + EL_EMC_KEY_6, -1, -1 }, { - Xsand, TRUE, FALSE, - EL_QUICKSAND_EMPTY, -1, -1 + Xkey_7, TRUE, FALSE, + EL_EMC_KEY_7, -1, -1 }, { - Xsand_stone, TRUE, FALSE, - EL_QUICKSAND_FULL, -1, -1 + Xkey_8, TRUE, FALSE, + EL_EMC_KEY_8, -1, -1 }, + { - Xsand_stonein_1, FALSE, TRUE, - EL_ROCK, ACTION_FILLING, -1 + Xdoor_1, TRUE, FALSE, + EL_EM_GATE_1, -1, -1 }, { - Xsand_stonein_2, FALSE, TRUE, - EL_ROCK, ACTION_FILLING, -1 + Xdoor_2, TRUE, FALSE, + EL_EM_GATE_2, -1, -1 }, { - Xsand_stonein_3, FALSE, TRUE, - EL_ROCK, ACTION_FILLING, -1 + Xdoor_3, TRUE, FALSE, + EL_EM_GATE_3, -1, -1 }, { - Xsand_stonein_4, FALSE, TRUE, - EL_ROCK, ACTION_FILLING, -1 + Xdoor_4, TRUE, FALSE, + EL_EM_GATE_4, -1, -1 }, { - Xsand_stonesand_1, FALSE, FALSE, - EL_QUICKSAND_EMPTYING, -1, -1 + Xdoor_5, TRUE, FALSE, + EL_EMC_GATE_5, -1, -1 }, { - Xsand_stonesand_2, FALSE, FALSE, - EL_QUICKSAND_EMPTYING, -1, -1 + Xdoor_6, TRUE, FALSE, + EL_EMC_GATE_6, -1, -1 }, { - Xsand_stonesand_3, FALSE, FALSE, - EL_QUICKSAND_EMPTYING, -1, -1 + Xdoor_7, TRUE, FALSE, + EL_EMC_GATE_7, -1, -1 }, { - Xsand_stonesand_4, FALSE, FALSE, - EL_QUICKSAND_EMPTYING, -1, -1 + Xdoor_8, TRUE, FALSE, + EL_EMC_GATE_8, -1, -1 }, + { - Xsand_stonesand_quickout_1, FALSE, FALSE, - EL_QUICKSAND_EMPTYING, -1, -1 + Xfake_door_1, TRUE, FALSE, + EL_EM_GATE_1_GRAY, -1, -1 }, { - Xsand_stonesand_quickout_2, FALSE, FALSE, - EL_QUICKSAND_EMPTYING, -1, -1 + Xfake_door_2, TRUE, FALSE, + EL_EM_GATE_2_GRAY, -1, -1 }, { - Xsand_stoneout_1, FALSE, FALSE, - EL_ROCK, ACTION_EMPTYING, -1 + Xfake_door_3, TRUE, FALSE, + EL_EM_GATE_3_GRAY, -1, -1 }, { - Xsand_stoneout_2, FALSE, FALSE, - EL_ROCK, ACTION_EMPTYING, -1 + Xfake_door_4, TRUE, FALSE, + EL_EM_GATE_4_GRAY, -1, -1 }, { - Xsand_sandstone_1, FALSE, FALSE, - EL_QUICKSAND_FILLING, -1, -1 + Xfake_door_5, TRUE, FALSE, + EL_EMC_GATE_5_GRAY, -1, -1 }, { - Xsand_sandstone_2, FALSE, FALSE, - EL_QUICKSAND_FILLING, -1, -1 + Xfake_door_6, TRUE, FALSE, + EL_EMC_GATE_6_GRAY, -1, -1 }, { - Xsand_sandstone_3, FALSE, FALSE, - EL_QUICKSAND_FILLING, -1, -1 + Xfake_door_7, TRUE, FALSE, + EL_EMC_GATE_7_GRAY, -1, -1 }, { - Xsand_sandstone_4, FALSE, FALSE, - EL_QUICKSAND_FILLING, -1, -1 + Xfake_door_8, TRUE, FALSE, + EL_EMC_GATE_8_GRAY, -1, -1 }, + { - Xplant, TRUE, FALSE, - EL_EMC_PLANT, -1, -1 + Xballoon, TRUE, FALSE, + EL_BALLOON, -1, -1 }, { - Yplant, FALSE, FALSE, - EL_EMC_PLANT, -1, -1 + Yballoon_n, FALSE, FALSE, + EL_BALLOON, ACTION_MOVING, MV_BIT_UP }, { - Xlenses, TRUE, FALSE, - EL_EMC_LENSES, -1, -1 + Yballoon_nB, FALSE, TRUE, + EL_BALLOON, ACTION_MOVING, MV_BIT_UP }, { - Xmagnify, TRUE, FALSE, - EL_EMC_MAGNIFIER, -1, -1 + Yballoon_e, FALSE, FALSE, + EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT }, { - Xdripper, TRUE, FALSE, - EL_EMC_DRIPPER, -1, -1 + Yballoon_eB, FALSE, TRUE, + EL_BALLOON, ACTION_MOVING, MV_BIT_RIGHT }, { - XdripperB, FALSE, FALSE, - EL_EMC_DRIPPER, ACTION_ACTIVE, -1 + Yballoon_s, FALSE, FALSE, + EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN + }, + { + Yballoon_sB, FALSE, TRUE, + EL_BALLOON, ACTION_MOVING, MV_BIT_DOWN }, + { + Yballoon_w, FALSE, FALSE, + EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT + }, + { + Yballoon_wB, FALSE, TRUE, + EL_BALLOON, ACTION_MOVING, MV_BIT_LEFT + }, + + { + Xball_1, TRUE, FALSE, + EL_EMC_MAGIC_BALL, -1, -1 + }, + { + Yball_1, FALSE, FALSE, + EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1 + }, + { + Xball_2, FALSE, FALSE, + EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1 + }, + { + Yball_2, FALSE, FALSE, + EL_EMC_MAGIC_BALL, ACTION_ACTIVE, -1 + }, + { + Yball_blank, FALSE, FALSE, + EL_EMC_MAGIC_BALL, ACTION_DROPPING, -1 + }, + + { + Xamoeba_1, TRUE, FALSE, + EL_AMOEBA_DRY, ACTION_OTHER, -1 + }, + { + Xamoeba_2, FALSE, FALSE, + EL_AMOEBA_DRY, ACTION_OTHER, -1 + }, + { + Xamoeba_3, FALSE, FALSE, + EL_AMOEBA_DRY, ACTION_OTHER, -1 + }, + { + Xamoeba_4, FALSE, FALSE, + EL_AMOEBA_DRY, ACTION_OTHER, -1 + }, + { + Xamoeba_5, TRUE, FALSE, + EL_AMOEBA_WET, ACTION_OTHER, -1 + }, + { + Xamoeba_6, FALSE, FALSE, + EL_AMOEBA_WET, ACTION_OTHER, -1 + }, + { + Xamoeba_7, FALSE, FALSE, + EL_AMOEBA_WET, ACTION_OTHER, -1 + }, + { + Xamoeba_8, FALSE, FALSE, + EL_AMOEBA_WET, ACTION_OTHER, -1 + }, + + { + Xdrip, TRUE, FALSE, + EL_AMOEBA_DROP, ACTION_GROWING, -1 + }, + { + Xdrip_fall, FALSE, FALSE, + EL_AMOEBA_DROP, -1, -1 + }, + { + Xdrip_stretch, FALSE, FALSE, + EL_AMOEBA_DROP, ACTION_FALLING, -1 + }, + { + Xdrip_stretchB, FALSE, TRUE, + EL_AMOEBA_DROP, ACTION_FALLING, -1 + }, + { + Ydrip_1_s, FALSE, FALSE, + EL_AMOEBA_DROP, ACTION_FALLING, -1 + }, + { + Ydrip_1_sB, FALSE, TRUE, + EL_AMOEBA_DROP, ACTION_FALLING, -1 + }, + { + Ydrip_2_s, FALSE, FALSE, + EL_AMOEBA_DROP, ACTION_FALLING, -1 + }, + { + Ydrip_2_sB, FALSE, TRUE, + EL_AMOEBA_DROP, ACTION_FALLING, -1 + }, + + { + Xwonderwall, TRUE, FALSE, + EL_MAGIC_WALL, -1, -1 + }, + { + Ywonderwall, FALSE, FALSE, + EL_MAGIC_WALL, ACTION_ACTIVE, -1 + }, + + { + Xwheel, TRUE, FALSE, + EL_ROBOT_WHEEL, -1, -1 + }, + { + Ywheel, FALSE, FALSE, + EL_ROBOT_WHEEL, ACTION_ACTIVE, -1 + }, + + { + Xswitch, TRUE, FALSE, + EL_EMC_MAGIC_BALL_SWITCH, -1, -1 + }, + { + Yswitch, FALSE, FALSE, + EL_EMC_MAGIC_BALL_SWITCH, ACTION_ACTIVE, -1 + }, + + { + Xbumper, TRUE, FALSE, + EL_EMC_SPRING_BUMPER, -1, -1 + }, + { + Ybumper, FALSE, FALSE, + EL_EMC_SPRING_BUMPER, ACTION_ACTIVE, -1 + }, + + { + Xacid_nw, TRUE, FALSE, + EL_ACID_POOL_TOPLEFT, -1, -1 + }, + { + Xacid_ne, TRUE, FALSE, + EL_ACID_POOL_TOPRIGHT, -1, -1 + }, + { + Xacid_sw, TRUE, FALSE, + EL_ACID_POOL_BOTTOMLEFT, -1, -1 + }, + { + Xacid_s, TRUE, FALSE, + EL_ACID_POOL_BOTTOM, -1, -1 + }, + { + Xacid_se, TRUE, FALSE, + EL_ACID_POOL_BOTTOMRIGHT, -1, -1 + }, + { Xfake_blank, TRUE, FALSE, EL_INVISIBLE_WALL, -1, -1 }, { - Xfake_blankB, FALSE, FALSE, + Yfake_blank, FALSE, FALSE, EL_INVISIBLE_WALL, ACTION_ACTIVE, -1 }, + { Xfake_grass, TRUE, FALSE, EL_EMC_FAKE_GRASS, -1, -1 }, { - Xfake_grassB, FALSE, FALSE, + Yfake_grass, FALSE, FALSE, EL_EMC_FAKE_GRASS, ACTION_ACTIVE, -1 }, + { - Xfake_door_1, TRUE, FALSE, - EL_EM_GATE_1_GRAY, -1, -1 + Xfake_amoeba, TRUE, FALSE, + EL_EMC_DRIPPER, -1, -1 }, { - Xfake_door_2, TRUE, FALSE, - EL_EM_GATE_2_GRAY, -1, -1 + Yfake_amoeba, FALSE, FALSE, + EL_EMC_DRIPPER, ACTION_ACTIVE, -1 }, + { - Xfake_door_3, TRUE, FALSE, - EL_EM_GATE_3_GRAY, -1, -1 + Xlenses, TRUE, FALSE, + EL_EMC_LENSES, -1, -1 }, + { - Xfake_door_4, TRUE, FALSE, - EL_EM_GATE_4_GRAY, -1, -1 + Xmagnify, TRUE, FALSE, + EL_EMC_MAGNIFIER, -1, -1 }, + { - Xfake_door_5, TRUE, FALSE, - EL_EMC_GATE_5_GRAY, -1, -1 + Xsand, TRUE, FALSE, + EL_QUICKSAND_EMPTY, -1, -1 }, { - Xfake_door_6, TRUE, FALSE, - EL_EMC_GATE_6_GRAY, -1, -1 + Xsand_stone, TRUE, FALSE, + EL_QUICKSAND_FULL, -1, -1 }, { - Xfake_door_7, TRUE, FALSE, - EL_EMC_GATE_7_GRAY, -1, -1 + Xsand_stonein_1, FALSE, TRUE, + EL_ROCK, ACTION_FILLING, -1 }, { - Xfake_door_8, TRUE, FALSE, - EL_EMC_GATE_8_GRAY, -1, -1 + Xsand_stonein_2, FALSE, TRUE, + EL_ROCK, ACTION_FILLING, -1 }, { - Xfake_acid_1, TRUE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_stonein_3, FALSE, TRUE, + EL_ROCK, ACTION_FILLING, -1 }, { - Xfake_acid_2, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_stonein_4, FALSE, TRUE, + EL_ROCK, ACTION_FILLING, -1 }, { - Xfake_acid_3, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_sandstone_1, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 }, { - Xfake_acid_4, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_sandstone_2, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 }, { - Xfake_acid_5, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_sandstone_3, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 }, { - Xfake_acid_6, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_sandstone_4, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 }, { - Xfake_acid_7, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_stonesand_1, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 }, { - Xfake_acid_8, FALSE, FALSE, - EL_EMC_FAKE_ACID, -1, -1 + Xsand_stonesand_2, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 }, { - Xsteel_1, TRUE, FALSE, - EL_STEELWALL, -1, -1 + Xsand_stonesand_3, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 }, { - Xsteel_2, TRUE, FALSE, - EL_EMC_STEELWALL_2, -1, -1 + Xsand_stonesand_4, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + { + Xsand_stoneout_1, FALSE, FALSE, + EL_ROCK, ACTION_EMPTYING, -1 + }, + { + Xsand_stoneout_2, FALSE, FALSE, + EL_ROCK, ACTION_EMPTYING, -1 + }, + { + Xsand_stonesand_quickout_1, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + { + Xsand_stonesand_quickout_2, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + + { + Xslide_ns, TRUE, FALSE, + EL_EXPANDABLE_WALL_VERTICAL, -1, -1 + }, + { + Yslide_ns_blank, FALSE, FALSE, + EL_EXPANDABLE_WALL_VERTICAL, ACTION_GROWING, -1 + }, + { + Xslide_ew, TRUE, FALSE, + EL_EXPANDABLE_WALL_HORIZONTAL, -1, -1 + }, + { + Yslide_ew_blank, FALSE, FALSE, + EL_EXPANDABLE_WALL_HORIZONTAL, ACTION_GROWING, -1 + }, + + { + Xwind_n, TRUE, FALSE, + EL_BALLOON_SWITCH_UP, -1, -1 + }, + { + Xwind_e, TRUE, FALSE, + EL_BALLOON_SWITCH_RIGHT, -1, -1 + }, + { + Xwind_s, TRUE, FALSE, + EL_BALLOON_SWITCH_DOWN, -1, -1 + }, + { + Xwind_w, TRUE, FALSE, + EL_BALLOON_SWITCH_LEFT, -1, -1 + }, + { + Xwind_any, TRUE, FALSE, + EL_BALLOON_SWITCH_ANY, -1, -1 + }, + { + Xwind_stop, TRUE, FALSE, + EL_BALLOON_SWITCH_NONE, -1, -1 + }, + + { + Xexit, TRUE, FALSE, + EL_EM_EXIT_CLOSED, -1, -1 + }, + { + Xexit_1, TRUE, FALSE, + EL_EM_EXIT_OPEN, -1, -1 + }, + { + Xexit_2, FALSE, FALSE, + EL_EM_EXIT_OPEN, -1, -1 }, { - Xsteel_3, TRUE, FALSE, - EL_EMC_STEELWALL_3, -1, -1 + Xexit_3, FALSE, FALSE, + EL_EM_EXIT_OPEN, -1, -1 }, + { - Xsteel_4, TRUE, FALSE, - EL_EMC_STEELWALL_4, -1, -1 + Xpause, FALSE, FALSE, + EL_EMPTY, -1, -1 }, + { Xwall_1, TRUE, FALSE, EL_WALL, -1, -1 @@ -7099,22 +7422,41 @@ em_object_mapping_list[] = Xwall_4, TRUE, FALSE, EL_EMC_WALL_16, -1, -1 }, + { - Xround_wall_1, TRUE, FALSE, + Xroundwall_1, TRUE, FALSE, EL_WALL_SLIPPERY, -1, -1 }, { - Xround_wall_2, TRUE, FALSE, + Xroundwall_2, TRUE, FALSE, EL_EMC_WALL_SLIPPERY_2, -1, -1 }, { - Xround_wall_3, TRUE, FALSE, + Xroundwall_3, TRUE, FALSE, EL_EMC_WALL_SLIPPERY_3, -1, -1 }, { - Xround_wall_4, TRUE, FALSE, + Xroundwall_4, TRUE, FALSE, EL_EMC_WALL_SLIPPERY_4, -1, -1 }, + + { + Xsteel_1, TRUE, FALSE, + EL_STEELWALL, -1, -1 + }, + { + Xsteel_2, TRUE, FALSE, + EL_EMC_STEELWALL_2, -1, -1 + }, + { + Xsteel_3, TRUE, FALSE, + EL_EMC_STEELWALL_3, -1, -1 + }, + { + Xsteel_4, TRUE, FALSE, + EL_EMC_STEELWALL_4, -1, -1 + }, + { Xdecor_1, TRUE, FALSE, EL_EMC_WALL_8, -1, -1 @@ -7163,6 +7505,7 @@ em_object_mapping_list[] = Xdecor_12, TRUE, FALSE, EL_EMC_WALL_12, -1, -1 }, + { Xalpha_0, TRUE, FALSE, EL_CHAR('0'), -1, -1 @@ -7208,8 +7551,8 @@ em_object_mapping_list[] = EL_CHAR('!'), -1, -1 }, { - Xalpha_quote, TRUE, FALSE, - EL_CHAR('"'), -1, -1 + Xalpha_apost, TRUE, FALSE, + EL_CHAR('\''), -1, -1 }, { Xalpha_comma, TRUE, FALSE, @@ -7349,40 +7692,52 @@ em_object_mapping_list[] = }, { - Xboom_bug, FALSE, FALSE, - EL_BUG, ACTION_EXPLODING, -1 + Ykey_1_blank, FALSE, FALSE, + EL_EM_KEY_1, ACTION_COLLECTING, -1 }, { - Xboom_bomb, FALSE, FALSE, - EL_BOMB, ACTION_EXPLODING, -1 + Ykey_2_blank, FALSE, FALSE, + EL_EM_KEY_2, ACTION_COLLECTING, -1 }, { - Xboom_android, FALSE, FALSE, - EL_EMC_ANDROID, ACTION_OTHER, -1 + Ykey_3_blank, FALSE, FALSE, + EL_EM_KEY_3, ACTION_COLLECTING, -1 }, { - Xboom_1, FALSE, FALSE, - EL_DEFAULT, ACTION_EXPLODING, -1 + Ykey_4_blank, FALSE, FALSE, + EL_EM_KEY_4, ACTION_COLLECTING, -1 }, { - Xboom_2, FALSE, FALSE, - EL_DEFAULT, ACTION_EXPLODING, -1 + Ykey_5_blank, FALSE, FALSE, + EL_EMC_KEY_5, ACTION_COLLECTING, -1 }, { - Znormal, FALSE, FALSE, - EL_EMPTY, -1, -1 + Ykey_6_blank, FALSE, FALSE, + EL_EMC_KEY_6, ACTION_COLLECTING, -1 }, { - Zdynamite, FALSE, FALSE, - EL_EMPTY, -1, -1 + Ykey_7_blank, FALSE, FALSE, + EL_EMC_KEY_7, ACTION_COLLECTING, -1 }, { - Zplayer, FALSE, FALSE, - EL_EMPTY, -1, -1 + Ykey_8_blank, FALSE, FALSE, + EL_EMC_KEY_8, ACTION_COLLECTING, -1 }, { - ZBORDER, FALSE, FALSE, - EL_EMPTY, -1, -1 + Ylenses_blank, FALSE, FALSE, + EL_EMC_LENSES, ACTION_COLLECTING, -1 + }, + { + Ymagnify_blank, FALSE, FALSE, + EL_EMC_MAGNIFIER, ACTION_COLLECTING, -1 + }, + { + Ygrass_blank, FALSE, FALSE, + EL_EMC_GRASS, ACTION_SNAPPING, -1 + }, + { + Ydirt_blank, FALSE, FALSE, + EL_SAND, ACTION_SNAPPING, -1 }, { @@ -7400,214 +7755,214 @@ static struct Mapping_EM_to_RND_player int action; int direction; } -em_player_mapping_list[] = +em_player_mapping_list[MAX_PLAYERS * PLY_MAX + 1] = { { - SPR_walk + 0, 0, + PLY_walk_n, 0, EL_PLAYER_1, ACTION_MOVING, MV_BIT_UP, }, { - SPR_walk + 1, 0, + PLY_walk_e, 0, EL_PLAYER_1, ACTION_MOVING, MV_BIT_RIGHT, }, { - SPR_walk + 2, 0, + PLY_walk_s, 0, EL_PLAYER_1, ACTION_MOVING, MV_BIT_DOWN, }, { - SPR_walk + 3, 0, + PLY_walk_w, 0, EL_PLAYER_1, ACTION_MOVING, MV_BIT_LEFT, }, { - SPR_push + 0, 0, + PLY_push_n, 0, EL_PLAYER_1, ACTION_PUSHING, MV_BIT_UP, }, { - SPR_push + 1, 0, + PLY_push_e, 0, EL_PLAYER_1, ACTION_PUSHING, MV_BIT_RIGHT, }, { - SPR_push + 2, 0, + PLY_push_s, 0, EL_PLAYER_1, ACTION_PUSHING, MV_BIT_DOWN, }, { - SPR_push + 3, 0, + PLY_push_w, 0, EL_PLAYER_1, ACTION_PUSHING, MV_BIT_LEFT, }, { - SPR_spray + 0, 0, + PLY_shoot_n, 0, EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_UP, }, { - SPR_spray + 1, 0, + PLY_shoot_e, 0, EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_RIGHT, }, { - SPR_spray + 2, 0, + PLY_shoot_s, 0, EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_DOWN, }, { - SPR_spray + 3, 0, + PLY_shoot_w, 0, EL_PLAYER_1, ACTION_SNAPPING, MV_BIT_LEFT, }, { - SPR_walk + 0, 1, + PLY_walk_n, 1, EL_PLAYER_2, ACTION_MOVING, MV_BIT_UP, }, { - SPR_walk + 1, 1, + PLY_walk_e, 1, EL_PLAYER_2, ACTION_MOVING, MV_BIT_RIGHT, }, { - SPR_walk + 2, 1, + PLY_walk_s, 1, EL_PLAYER_2, ACTION_MOVING, MV_BIT_DOWN, }, { - SPR_walk + 3, 1, + PLY_walk_w, 1, EL_PLAYER_2, ACTION_MOVING, MV_BIT_LEFT, }, { - SPR_push + 0, 1, + PLY_push_n, 1, EL_PLAYER_2, ACTION_PUSHING, MV_BIT_UP, }, { - SPR_push + 1, 1, + PLY_push_e, 1, EL_PLAYER_2, ACTION_PUSHING, MV_BIT_RIGHT, }, { - SPR_push + 2, 1, + PLY_push_s, 1, EL_PLAYER_2, ACTION_PUSHING, MV_BIT_DOWN, }, { - SPR_push + 3, 1, + PLY_push_w, 1, EL_PLAYER_2, ACTION_PUSHING, MV_BIT_LEFT, }, { - SPR_spray + 0, 1, + PLY_shoot_n, 1, EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_UP, }, { - SPR_spray + 1, 1, + PLY_shoot_e, 1, EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_RIGHT, }, { - SPR_spray + 2, 1, + PLY_shoot_s, 1, EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_DOWN, }, { - SPR_spray + 3, 1, + PLY_shoot_w, 1, EL_PLAYER_2, ACTION_SNAPPING, MV_BIT_LEFT, }, { - SPR_still, 0, + PLY_still, 0, EL_PLAYER_1, ACTION_DEFAULT, -1, }, { - SPR_still, 1, + PLY_still, 1, EL_PLAYER_2, ACTION_DEFAULT, -1, }, { - SPR_walk + 0, 2, + PLY_walk_n, 2, EL_PLAYER_3, ACTION_MOVING, MV_BIT_UP, }, { - SPR_walk + 1, 2, + PLY_walk_e, 2, EL_PLAYER_3, ACTION_MOVING, MV_BIT_RIGHT, }, { - SPR_walk + 2, 2, + PLY_walk_s, 2, EL_PLAYER_3, ACTION_MOVING, MV_BIT_DOWN, }, { - SPR_walk + 3, 2, + PLY_walk_w, 2, EL_PLAYER_3, ACTION_MOVING, MV_BIT_LEFT, }, { - SPR_push + 0, 2, + PLY_push_n, 2, EL_PLAYER_3, ACTION_PUSHING, MV_BIT_UP, }, { - SPR_push + 1, 2, + PLY_push_e, 2, EL_PLAYER_3, ACTION_PUSHING, MV_BIT_RIGHT, }, { - SPR_push + 2, 2, + PLY_push_s, 2, EL_PLAYER_3, ACTION_PUSHING, MV_BIT_DOWN, }, { - SPR_push + 3, 2, + PLY_push_w, 2, EL_PLAYER_3, ACTION_PUSHING, MV_BIT_LEFT, }, { - SPR_spray + 0, 2, + PLY_shoot_n, 2, EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_UP, }, { - SPR_spray + 1, 2, + PLY_shoot_e, 2, EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_RIGHT, }, { - SPR_spray + 2, 2, + PLY_shoot_s, 2, EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_DOWN, }, { - SPR_spray + 3, 2, + PLY_shoot_w, 2, EL_PLAYER_3, ACTION_SNAPPING, MV_BIT_LEFT, }, { - SPR_walk + 0, 3, + PLY_walk_n, 3, EL_PLAYER_4, ACTION_MOVING, MV_BIT_UP, }, { - SPR_walk + 1, 3, + PLY_walk_e, 3, EL_PLAYER_4, ACTION_MOVING, MV_BIT_RIGHT, }, { - SPR_walk + 2, 3, + PLY_walk_s, 3, EL_PLAYER_4, ACTION_MOVING, MV_BIT_DOWN, }, { - SPR_walk + 3, 3, + PLY_walk_w, 3, EL_PLAYER_4, ACTION_MOVING, MV_BIT_LEFT, }, { - SPR_push + 0, 3, + PLY_push_n, 3, EL_PLAYER_4, ACTION_PUSHING, MV_BIT_UP, }, { - SPR_push + 1, 3, + PLY_push_e, 3, EL_PLAYER_4, ACTION_PUSHING, MV_BIT_RIGHT, }, { - SPR_push + 2, 3, + PLY_push_s, 3, EL_PLAYER_4, ACTION_PUSHING, MV_BIT_DOWN, }, { - SPR_push + 3, 3, + PLY_push_w, 3, EL_PLAYER_4, ACTION_PUSHING, MV_BIT_LEFT, }, { - SPR_spray + 0, 3, + PLY_shoot_n, 3, EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_UP, }, { - SPR_spray + 1, 3, + PLY_shoot_e, 3, EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_RIGHT, }, { - SPR_spray + 2, 3, + PLY_shoot_s, 3, EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_DOWN, }, { - SPR_spray + 3, 3, + PLY_shoot_w, 3, EL_PLAYER_4, ACTION_SNAPPING, MV_BIT_LEFT, }, { - SPR_still, 2, + PLY_still, 2, EL_PLAYER_3, ACTION_DEFAULT, -1, }, { - SPR_still, 3, + PLY_still, 3, EL_PLAYER_4, ACTION_DEFAULT, -1, }, @@ -7617,7 +7972,7 @@ em_player_mapping_list[] = } }; -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; @@ -7638,17 +7993,49 @@ int map_element_RND_to_EM(int element_rnd) 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; + + 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; + + mapping_initialized = TRUE; + } + + if (element_em_cave < 0 || element_em_cave >= CAVE_TILE_MAX) + { + Warn("invalid EM cave element %d", element_em_cave); - Error(ERR_WARN, "invalid RND level element %d", element_rnd); + return EL_UNKNOWN; + } - 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) @@ -7656,7 +8043,7 @@ int map_element_EM_to_RND(int element_em) 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++) @@ -7666,52 +8053,55 @@ int map_element_EM_to_RND(int element_em) 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) @@ -8140,24 +8530,19 @@ int getBeltSwitchElementFromBeltNrAndBeltDir(int belt_nr, int belt_dir) 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) @@ -8172,8 +8557,8 @@ 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_player player_mapping[MAX_PLAYERS][SPR_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) { @@ -8188,8 +8573,8 @@ static int get_effective_element_EM(int tile, int frame_em) { switch (tile) { - case Yacid_splash_eB: - case Yacid_splash_wB: + case Xsplash_e: + case Xsplash_w: return (frame_em > 5 ? EL_EMPTY : element); default: @@ -8200,11 +8585,11 @@ static int get_effective_element_EM(int tile, int frame_em) { switch (tile) { - case Yacid_splash_eB: - case Yacid_splash_wB: + case Xsplash_e: + case Xsplash_w: return EL_EMPTY; - case Yemerald_stone: + case Ynut_stone: return EL_EMERALD; case Ydiamond_stone: @@ -8212,24 +8597,24 @@ static int get_effective_element_EM(int tile, int frame_em) case Xdrip_stretch: case Xdrip_stretchB: - case Ydrip_s1: - case Ydrip_s1B: - case Xball_1B: + case Ydrip_1_s: + case Ydrip_1_sB: + case Yball_1: case Xball_2: - case Xball_2B: - case Yball_eat: - case Ykey_1_eat: - case Ykey_2_eat: - case Ykey_3_eat: - case Ykey_4_eat: - case Ykey_5_eat: - case Ykey_6_eat: - case Ykey_7_eat: - case Ykey_8_eat: - case Ylenses_eat: - case Ymagnify_eat: - case Ygrass_eat: - case Ydirt_eat: + case Yball_2: + case Yball_blank: + case Ykey_1_blank: + case Ykey_2_blank: + case Ykey_3_blank: + case Ykey_4_blank: + case Ykey_5_blank: + case Ykey_6_blank: + case Ykey_7_blank: + case Ykey_8_blank: + case Ylenses_blank: + case Ymagnify_blank: + case Ygrass_blank: + case Ydirt_blank: case Xsand_stonein_1: case Xsand_stonein_2: case Xsand_stonein_3: @@ -8269,9 +8654,9 @@ static boolean check_linear_animation_EM(int tile) case Ytank_s_e: case Ytank_w_s: case Ytank_n_w: - case Yacid_splash_eB: - case Yacid_splash_wB: - case Yemerald_stone: + case Xsplash_e: + case Xsplash_w: + case Ynut_stone: return TRUE; } @@ -8517,21 +8902,8 @@ void InitGraphicInfo_EM(void) { 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; @@ -8542,7 +8914,7 @@ void InitGraphicInfo_EM(void) // always start with reliable default values for (p = 0; p < MAX_PLAYERS; p++) { - for (i = 0; i < SPR_MAX; i++) + for (i = 0; i < PLY_MAX; i++) { player_mapping[p][i].element_rnd = EL_UNKNOWN; player_mapping[p][i].action = ACTION_DEFAULT; @@ -8580,7 +8952,7 @@ void InitGraphicInfo_EM(void) 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; @@ -8599,24 +8971,24 @@ void InitGraphicInfo_EM(void) int effective_action = (j < 7 ? action : i == Xdrip_stretch ? action : i == Xdrip_stretchB ? action : - i == Ydrip_s1 ? action : - i == Ydrip_s1B ? action : - i == Xball_1B ? action : + i == Ydrip_1_s ? action : + i == Ydrip_1_sB ? action : + i == Yball_1 ? action : i == Xball_2 ? action : - i == Xball_2B ? action : - i == Yball_eat ? action : - i == Ykey_1_eat ? action : - i == Ykey_2_eat ? action : - i == Ykey_3_eat ? action : - i == Ykey_4_eat ? action : - i == Ykey_5_eat ? action : - i == Ykey_6_eat ? action : - i == Ykey_7_eat ? action : - i == Ykey_8_eat ? action : - i == Ylenses_eat ? action : - i == Ymagnify_eat ? action : - i == Ygrass_eat ? action : - i == Ydirt_eat ? action : + i == Yball_2 ? action : + i == Yball_blank ? action : + i == Ykey_1_blank ? action : + i == Ykey_2_blank ? action : + i == Ykey_3_blank ? action : + i == Ykey_4_blank ? action : + i == Ykey_5_blank ? action : + i == Ykey_6_blank ? action : + i == Ykey_7_blank ? action : + i == Ykey_8_blank ? action : + i == Ylenses_blank ? action : + i == Ymagnify_blank ? action : + i == Ygrass_blank ? action : + i == Ydirt_blank ? action : i == Xsand_stonein_1 ? action : i == Xsand_stonein_2 ? action : i == Xsand_stonein_3 ? action : @@ -8637,7 +9009,7 @@ void InitGraphicInfo_EM(void) 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 @@ -8647,8 +9019,8 @@ void InitGraphicInfo_EM(void) g->anim_mode & ANIM_LINEAR); int sync_frame = (i == Xdrip_stretch ? 7 : i == Xdrip_stretchB ? 7 : - i == Ydrip_s2 ? j + 8 : - i == Ydrip_s2B ? j + 8 : + i == Ydrip_2_s ? j + 8 : + i == Ydrip_2_sB ? j + 8 : i == Xacid_1 ? 0 : i == Xacid_2 ? 10 : i == Xacid_3 ? 20 : @@ -8665,21 +9037,29 @@ void InitGraphicInfo_EM(void) 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 == Xball_2B ? j + 8 : - i == Yball_eat ? j + 1 : - i == Ykey_1_eat ? j + 1 : - i == Ykey_2_eat ? j + 1 : - i == Ykey_3_eat ? j + 1 : - i == Ykey_4_eat ? j + 1 : - i == Ykey_5_eat ? j + 1 : - i == Ykey_6_eat ? j + 1 : - i == Ykey_7_eat ? j + 1 : - i == Ykey_8_eat ? j + 1 : - i == Ylenses_eat ? j + 1 : - i == Ymagnify_eat ? j + 1 : - i == Ygrass_eat ? j + 1 : - i == Ydirt_eat ? j + 1 : + i == Yball_2 ? j + 8 : + i == Yball_blank ? j + 1 : + i == Ykey_1_blank ? j + 1 : + i == Ykey_2_blank ? j + 1 : + i == Ykey_3_blank ? j + 1 : + i == Ykey_4_blank ? j + 1 : + i == Ykey_5_blank ? j + 1 : + i == Ykey_6_blank ? j + 1 : + i == Ykey_7_blank ? j + 1 : + i == Ykey_8_blank ? j + 1 : + i == Ylenses_blank ? j + 1 : + i == Ymagnify_blank ? j + 1 : + i == Ygrass_blank ? j + 1 : + i == Ydirt_blank ? j + 1 : i == Xamoeba_1 ? 0 : i == Xamoeba_2 ? 1 : i == Xamoeba_3 ? 2 : @@ -8721,13 +9101,13 @@ void InitGraphicInfo_EM(void) 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 : @@ -8747,13 +9127,6 @@ void InitGraphicInfo_EM(void) 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, @@ -8791,10 +9164,10 @@ void InitGraphicInfo_EM(void) effective_action == ACTION_EMPTYING ? MV_DOWN : direction); int dx = (move_dir == MV_LEFT ? -1 : move_dir == MV_RIGHT ? 1 : 0); int dy = (move_dir == MV_UP ? -1 : move_dir == MV_DOWN ? 1 : 0); - int num_steps = (i == Ydrip_s1 ? 16 : - i == Ydrip_s1B ? 16 : - i == Ydrip_s2 ? 16 : - i == Ydrip_s2B ? 16 : + int num_steps = (i == Ydrip_1_s ? 16 : + i == Ydrip_1_sB ? 16 : + i == Ydrip_2_s ? 16 : + i == Ydrip_2_sB ? 16 : i == Xsand_stonein_1 ? 32 : i == Xsand_stonein_2 ? 32 : i == Xsand_stonein_3 ? 32 : @@ -8803,8 +9176,8 @@ void InitGraphicInfo_EM(void) i == Xsand_stoneout_2 ? 16 : 8); int cx = ABS(dx) * (TILEX / num_steps); int cy = ABS(dy) * (TILEY / num_steps); - int step_frame = (i == Ydrip_s2 ? j + 8 : - i == Ydrip_s2B ? j + 8 : + int step_frame = (i == Ydrip_2_s ? j + 8 : + i == Ydrip_2_sB ? j + 8 : i == Xsand_stonein_2 ? j + 8 : i == Xsand_stonein_3 ? j + 16 : i == Xsand_stonein_4 ? j + 24 : @@ -8849,78 +9222,10 @@ void InitGraphicInfo_EM(void) 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++) { @@ -8943,8 +9248,8 @@ void InitGraphicInfo_EM(void) 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; @@ -8965,7 +9270,7 @@ void InitGraphicInfo_EM(void) for (p = 0; p < MAX_PLAYERS; p++) { - for (i = 0; i < SPR_MAX; i++) + for (i = 0; i < PLY_MAX; i++) { int element = player_mapping[p][i].element_rnd; int action = player_mapping[p][i].action; @@ -8980,17 +9285,10 @@ void InitGraphicInfo_EM(void) 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, @@ -9008,64 +9306,9 @@ void InitGraphicInfo_EM(void) 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, @@ -9073,7 +9316,7 @@ 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) { @@ -9125,17 +9368,19 @@ static void CheckSaveEngineSnapshot_MM(boolean element_clicked, } } -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 == 0 && !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, @@ -9299,51 +9544,59 @@ void PlaySoundSelecting(void) #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; + + // when creating new renderer, destroy textures linked to old renderer + FreeAllImageTextures(); // needs old renderer to free the textures - // toggle fullscreen + // re-create screen and renderer (including change of vsync mode) ChangeVideoModeIfNeeded(setup.fullscreen); // set setup value according to successfully changed fullscreen mode @@ -9351,12 +9604,17 @@ void ToggleFullscreenOrChangeWindowScalingIfNeeded(void) // 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, @@ -9376,6 +9634,8 @@ void SetAnimStatus(int anim_status_new) { 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; @@ -9385,7 +9645,11 @@ void SetAnimStatus(int anim_status_new) 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; } @@ -9486,9 +9750,9 @@ void ChangeViewportPropertiesIfNeeded(void) { 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]; @@ -9542,7 +9806,7 @@ void ChangeViewportPropertiesIfNeeded(void) 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 || @@ -9553,7 +9817,7 @@ void ChangeViewportPropertiesIfNeeded(void) 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 || @@ -9623,7 +9887,7 @@ void ChangeViewportPropertiesIfNeeded(void) 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(); @@ -9657,13 +9921,13 @@ void ChangeViewportPropertiesIfNeeded(void) 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; @@ -9679,7 +9943,7 @@ void ChangeViewportPropertiesIfNeeded(void) if (init_video_buffer) { - // printf("::: init_video_buffer\n"); + // Debug("tools:viewport", "init_video_buffer"); FreeAllImageTextures(); // needs old renderer to free the textures @@ -9689,7 +9953,7 @@ void ChangeViewportPropertiesIfNeeded(void) if (init_gadgets_and_anims) { - // printf("::: init_gadgets_and_anims\n"); + // Debug("tools:viewport", "init_gadgets_and_anims"); InitGadgets(); InitGlobalAnimations(); @@ -9697,6 +9961,209 @@ void ChangeViewportPropertiesIfNeeded(void) if (init_em_graphics) { - InitGraphicInfo_EM(); + 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); }