X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Ftools.c;h=866870a29d10e2ba5b09daa57836bc5ba06e8139;hb=db796e071bbe21db45ac516e55eaf2ea7cee33d5;hp=130111dc2c8bd10c45826580cf84af5be549c7ed;hpb=113df1c4ad60b24a31ec6498f8cd3b2d4cd9dbfd;p=rocksndiamonds.git diff --git a/src/tools.c b/src/tools.c index 130111dc..866870a2 100644 --- a/src/tools.c +++ b/src/tools.c @@ -20,6 +20,10 @@ #include "network.h" #include "tape.h" + +/* select level set with EMC X11 graphics before activating EM GFX debugging */ +#define DEBUG_EM_GFX 0 + /* tool button identifiers */ #define TOOL_CTRL_ID_YES 0 #define TOOL_CTRL_ID_NO 1 @@ -237,7 +241,8 @@ void BackToFront() if (redraw_mask & REDRAW_ALL) { BlitBitmap(backbuffer, window, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); - redraw_mask = 0; + + redraw_mask = REDRAW_NONE; } if (redraw_mask & REDRAW_FIELD) @@ -409,6 +414,50 @@ void FadeToFront() BackToFront(); } +void FadeIn(int fade_delay) +{ + if (fade_delay == 0) + { + BackToFront(); + + return; + } + + FadeScreen(NULL, FADE_MODE_FADE_IN, fade_delay, 0); + + redraw_mask = REDRAW_NONE; +} + +void FadeOut(int fade_delay, int post_delay) +{ + if (fade_delay == 0) + { + ClearRectangle(backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE); + BackToFront(); + + return; + } + + FadeScreen(NULL, FADE_MODE_FADE_OUT, fade_delay, post_delay); + + redraw_mask = REDRAW_NONE; +} + +void FadeCross(int fade_delay) +{ + if (fade_delay == 0) + { + BlitBitmap(bitmap_db_title, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + BackToFront(); + + return; + } + + FadeScreen(bitmap_db_title, FADE_MODE_CROSSFADE, fade_delay, 0); + + redraw_mask = REDRAW_NONE; +} + void SetMainBackgroundImageIfDefined(int graphic) { if (graphic_info[graphic].bitmap) @@ -499,6 +548,17 @@ inline int getGraphicAnimationFrame(int graphic, int sync_frame) if (graphic_info[graphic].anim_global_sync || sync_frame < 0) sync_frame = FrameCounter; +#if 0 + if (graphic == element_info[EL_CUSTOM_START + 255].graphic[ACTION_DEFAULT] && + sync_frame == 0 && + FrameCounter > 10) + { + int x = 1 / 0; + + printf("::: FOO!\n"); + } +#endif + return getAnimationFrame(graphic_info[graphic].anim_frames, graphic_info[graphic].anim_delay, graphic_info[graphic].anim_mode, @@ -1041,6 +1101,8 @@ void DrawLevelFieldCrumbledSand(int x, int y) return; #if 1 + /* !!! CHECK THIS !!! */ + /* if (Feld[x][y] == EL_ELEMENT_SNAPPING && GFX_CRUMBLED(GfxElement[x][y])) @@ -1336,8 +1398,8 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) int font_nr = FONT_ENVELOPE_1 + envelope_nr; int font_width = getFontWidth(font_nr); int font_height = getFontHeight(font_nr); - int max_xsize = level.envelope_xsize[envelope_nr]; - int max_ysize = level.envelope_ysize[envelope_nr]; + int max_xsize = level.envelope[envelope_nr].xsize; + int max_ysize = level.envelope[envelope_nr].ysize; int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0); int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0); int xend = max_xsize; @@ -1364,7 +1426,7 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr); DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height, - level.envelope_text[envelope_nr], font_nr, max_xsize, + level.envelope[envelope_nr].text, font_nr, max_xsize, xsize - 2, ysize - 2, mask_mode); redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; @@ -1390,7 +1452,7 @@ void ShowEnvelope(int envelope_nr) game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */ - PlaySoundStereo(sound_opening, SOUND_MIDDLE); + PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE); if (anim_mode == ANIM_DEFAULT) AnimateEnvelope(envelope_nr, ANIM_DEFAULT, ACTION_OPENING); @@ -1402,7 +1464,7 @@ void ShowEnvelope(int envelope_nr) else WaitForEventToContinue(); - PlaySoundStereo(sound_closing, SOUND_MIDDLE); + PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE); if (anim_mode != ANIM_NONE) AnimateEnvelope(envelope_nr, main_anim_mode, ACTION_CLOSING); @@ -1418,28 +1480,45 @@ void ShowEnvelope(int envelope_nr) BackToFront(); } -void getMicroGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) +void getPreviewGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y, + int tilesize) { + struct + { + int width_mult, width_div; + int height_mult, height_div; + } offset_calc[4] = + { + { 0, 1, 0, 1 }, + { 0, 1, 2, 3 }, + { 1, 2, 2, 3 }, + { 3, 4, 2, 3 }, + }; + int offset_calc_pos = (tilesize < MICRO_TILESIZE || tilesize > TILESIZE ? 3 : + 5 - log_2(tilesize)); Bitmap *src_bitmap = graphic_info[graphic].bitmap; - int mini_startx = src_bitmap->width * 3 / 4; - int mini_starty = src_bitmap->height * 2 / 3; - int src_x = mini_startx + graphic_info[graphic].src_x / 8; - int src_y = mini_starty + graphic_info[graphic].src_y / 8; + int width_mult = offset_calc[offset_calc_pos].width_mult; + int width_div = offset_calc[offset_calc_pos].width_div; + int height_mult = offset_calc[offset_calc_pos].height_mult; + int height_div = offset_calc[offset_calc_pos].height_div; + int mini_startx = src_bitmap->width * width_mult / width_div; + int mini_starty = src_bitmap->height * height_mult / height_div; + int src_x = mini_startx + graphic_info[graphic].src_x * tilesize / TILESIZE; + int src_y = mini_starty + graphic_info[graphic].src_y * tilesize / TILESIZE; *bitmap = src_bitmap; *x = src_x; *y = src_y; } -void DrawMicroElement(int xpos, int ypos, int element) +void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize) { Bitmap *src_bitmap; int src_x, src_y; int graphic = el2preimg(element); - getMicroGraphicSource(graphic, &src_bitmap, &src_x, &src_y); - BlitBitmap(src_bitmap, drawto, src_x, src_y, MICRO_TILEX, MICRO_TILEY, - xpos, ypos); + getPreviewGraphicSource(graphic, &src_bitmap, &src_x, &src_y, tilesize); + BlitBitmap(src_bitmap, drawto, src_x, src_y, tilesize, tilesize, dst_x,dst_y); } void DrawLevel() @@ -1467,33 +1546,36 @@ void DrawMiniLevel(int size_x, int size_y, int scroll_x, int scroll_y) redraw_mask |= REDRAW_FIELD; } -static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y) +static void DrawPreviewLevelExt(int from_x, int from_y) { + boolean show_level_border = (BorderElement != EL_EMPTY); + int dst_x = preview.x; + int dst_y = preview.y; + int level_xsize = lev_fieldx + (show_level_border ? 2 : 0); + int level_ysize = lev_fieldy + (show_level_border ? 2 : 0); + int tile_size = preview.tile_size; + int preview_width = preview.xsize * tile_size; + int preview_height = preview.ysize * tile_size; + int real_preview_xsize = MIN(level_xsize, preview.xsize); + int real_preview_ysize = MIN(level_ysize, preview.ysize); int x, y; - DrawBackground(xpos, ypos, MICROLEVEL_XSIZE, MICROLEVEL_YSIZE); - - if (lev_fieldx < STD_LEV_FIELDX) - xpos += (STD_LEV_FIELDX - lev_fieldx) / 2 * MICRO_TILEX; - if (lev_fieldy < STD_LEV_FIELDY) - ypos += (STD_LEV_FIELDY - lev_fieldy) / 2 * MICRO_TILEY; + DrawBackground(dst_x, dst_y, preview_width, preview_height); - xpos += MICRO_TILEX; - ypos += MICRO_TILEY; + dst_x += (preview_width - real_preview_xsize * tile_size) / 2; + dst_y += (preview_height - real_preview_ysize * tile_size) / 2; - for (x = -1; x <= STD_LEV_FIELDX; x++) + for (x = 0; x < real_preview_xsize; x++) { - for (y = -1; y <= STD_LEV_FIELDY; y++) + for (y = 0; y < real_preview_ysize; y++) { - int lx = from_x + x, ly = from_y + y; - - if (lx >= 0 && lx < lev_fieldx && ly >= 0 && ly < lev_fieldy) - DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY, - level.field[lx][ly]); - else if (lx >= -1 && lx < lev_fieldx+1 && ly >= -1 && ly < lev_fieldy+1 - && BorderElement != EL_EMPTY) - DrawMicroElement(xpos + x * MICRO_TILEX, ypos + y * MICRO_TILEY, - getBorderElement(lx, ly)); + int lx = from_x + x + (show_level_border ? -1 : 0); + int ly = from_y + y + (show_level_border ? -1 : 0); + int element = (IN_LEV_FIELD(lx, ly) ? level.field[lx][ly] : + getBorderElement(lx, ly)); + + DrawPreviewElement(dst_x + x * tile_size, dst_y + y * tile_size, + element, tile_size); } } @@ -1509,7 +1591,7 @@ static void DrawMicroLevelExt(int xpos, int ypos, int from_x, int from_y) #define MICROLABEL_IMPORTED_BY_HEAD 6 #define MICROLABEL_IMPORTED_BY 7 -static void DrawMicroLevelLabelExt(int mode) +static void DrawPreviewLevelLabelExt(int mode) { char label_text[MAX_OUTPUT_LINESIZE + 1]; int max_len_label_text; @@ -1557,13 +1639,17 @@ static void DrawMicroLevelLabelExt(int mode) redraw_mask |= REDRAW_MICROLEVEL; } -void DrawMicroLevel(int xpos, int ypos, boolean restart) +void DrawPreviewLevel(boolean restart) { static unsigned long scroll_delay = 0; static unsigned long label_delay = 0; static int from_x, from_y, scroll_direction; static int label_state, label_counter; - int last_game_status = game_status; /* save current game status */ + unsigned long scroll_delay_value = preview.step_delay; + boolean show_level_border = (BorderElement != EL_EMPTY); + int level_xsize = lev_fieldx + (show_level_border ? 2 : 0); + int level_ysize = lev_fieldy + (show_level_border ? 2 : 0); + int last_game_status = game_status; /* save current game status */ /* force PREVIEW font on preview level */ game_status = GAME_MODE_PSEUDO_PREVIEW; @@ -1575,8 +1661,8 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) label_state = 1; label_counter = 0; - DrawMicroLevelExt(xpos, ypos, from_x, from_y); - DrawMicroLevelLabelExt(label_state); + DrawPreviewLevelExt(from_x, from_y); + DrawPreviewLevelLabelExt(label_state); /* initialize delay counters */ DelayReached(&scroll_delay, 0); @@ -1603,36 +1689,50 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) return; } - /* scroll micro level, if needed */ - if ((lev_fieldx > STD_LEV_FIELDX || lev_fieldy > STD_LEV_FIELDY) && - DelayReached(&scroll_delay, MICROLEVEL_SCROLL_DELAY)) + /* scroll preview level, if needed */ + if ((level_xsize > preview.xsize || level_ysize > preview.ysize) && + DelayReached(&scroll_delay, scroll_delay_value)) { switch (scroll_direction) { case MV_LEFT: if (from_x > 0) - from_x--; + { + from_x -= preview.step_offset; + from_x = (from_x < 0 ? 0 : from_x); + } else scroll_direction = MV_UP; break; case MV_RIGHT: - if (from_x < lev_fieldx - STD_LEV_FIELDX) - from_x++; + if (from_x < level_xsize - preview.xsize) + { + from_x += preview.step_offset; + from_x = (from_x > level_xsize - preview.xsize ? + level_xsize - preview.xsize : from_x); + } else scroll_direction = MV_DOWN; break; case MV_UP: if (from_y > 0) - from_y--; + { + from_y -= preview.step_offset; + from_y = (from_y < 0 ? 0 : from_y); + } else scroll_direction = MV_RIGHT; break; case MV_DOWN: - if (from_y < lev_fieldy - STD_LEV_FIELDY) - from_y++; + if (from_y < level_ysize - preview.ysize) + { + from_y += preview.step_offset; + from_y = (from_y > level_ysize - preview.ysize ? + level_ysize - preview.ysize : from_y); + } else scroll_direction = MV_LEFT; break; @@ -1641,14 +1741,14 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) break; } - DrawMicroLevelExt(xpos, ypos, from_x, from_y); + DrawPreviewLevelExt(from_x, from_y); } /* !!! THIS ALL SUCKS -- SHOULD BE CLEANLY REWRITTEN !!! */ /* redraw micro level label, if needed */ - if (strcmp(level.name, NAMELESS_LEVEL_NAME) != 0 && - strcmp(level.author, ANONYMOUS_NAME) != 0 && - strcmp(level.author, leveldir_current->name) != 0 && + if (!strEqual(level.name, NAMELESS_LEVEL_NAME) && + !strEqual(level.author, ANONYMOUS_NAME) && + !strEqual(level.author, leveldir_current->name) && DelayReached(&label_delay, MICROLEVEL_LABEL_DELAY)) { int max_label_counter = 23; @@ -1682,7 +1782,7 @@ void DrawMicroLevel(int xpos, int ypos, boolean restart) label_state = (label_state == MICROLABEL_IMPORTED_FROM_HEAD ? MICROLABEL_IMPORTED_BY_HEAD : MICROLABEL_IMPORTED_BY); - DrawMicroLevelLabelExt(label_state); + DrawPreviewLevelLabelExt(label_state); } game_status = last_game_status; /* restore current game status */ @@ -1898,8 +1998,17 @@ void DrawPlayer(struct PlayerInfo *player) last_element == EL_EM_DYNAMITE_ACTIVE || last_element == EL_SP_DISK_RED_ACTIVE) DrawDynamite(last_jx, last_jy); +#if 0 + /* !!! this is not enough to prevent flickering of players which are + moving next to each others without a free tile between them -- this + can only be solved by drawing all players layer by layer (first the + background, then the foreground etc.) !!! => TODO */ + else if (!IS_PLAYER(last_jx, last_jy)) + DrawLevelField(last_jx, last_jy); +#else else DrawLevelField(last_jx, last_jy); +#endif if (player->is_pushing && IN_SCR_FIELD(SCREENX(next_jx), SCREENY(next_jy))) DrawLevelElement(next_jx, next_jy, EL_EMPTY); @@ -2496,7 +2605,7 @@ unsigned int MoveDoor(unsigned int door_state) door_2.height = VYSIZE; if (door_state == DOOR_GET_STATE) - return(door1 | door2); + return (door1 | door2); if (door_state & DOOR_SET_STATE) { @@ -2505,17 +2614,20 @@ unsigned int MoveDoor(unsigned int door_state) if (door_state & DOOR_ACTION_2) door2 = door_state & DOOR_ACTION_2; - return(door1 | door2); + return (door1 | door2); } - if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1) - door_state &= ~DOOR_OPEN_1; - else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1) - door_state &= ~DOOR_CLOSE_1; - if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2) - door_state &= ~DOOR_OPEN_2; - else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2) - door_state &= ~DOOR_CLOSE_2; + if (!(door_state & DOOR_FORCE_REDRAW)) + { + if (door1 == DOOR_OPEN_1 && door_state & DOOR_OPEN_1) + door_state &= ~DOOR_OPEN_1; + else if (door1 == DOOR_CLOSE_1 && door_state & DOOR_CLOSE_1) + door_state &= ~DOOR_CLOSE_1; + if (door2 == DOOR_OPEN_2 && door_state & DOOR_OPEN_2) + door_state &= ~DOOR_OPEN_2; + else if (door2 == DOOR_CLOSE_2 && door_state & DOOR_CLOSE_2) + door_state &= ~DOOR_CLOSE_2; + } door_delay_value = (door_state & DOOR_ACTION_1 ? door_1.step_delay : door_2.step_delay); @@ -2550,8 +2662,8 @@ unsigned int MoveDoor(unsigned int door_state) #if 1 int end = door_size; #else - int end = (door_state & DOOR_ACTION_1 && - door_1.anim_mode & ANIM_VERTICAL ? DYSIZE : DXSIZE); + int end = (door_state & DOOR_ACTION_1 && door_1.anim_mode & ANIM_VERTICAL ? + DYSIZE : DXSIZE); #endif #if 1 int start = ((door_state & DOOR_NO_DELAY) ? end : 0); @@ -2564,9 +2676,9 @@ unsigned int MoveDoor(unsigned int door_state) { /* opening door sound has priority over simultaneously closing door */ if (door_state & (DOOR_OPEN_1 | DOOR_OPEN_2)) - PlaySoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE); + PlayMenuSoundStereo(SND_DOOR_OPENING, SOUND_MIDDLE); else if (door_state & (DOOR_CLOSE_1 | DOOR_CLOSE_2)) - PlaySoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE); + PlayMenuSoundStereo(SND_DOOR_CLOSING, SOUND_MIDDLE); } for (k = start; k <= end && !(door_1_done && door_2_done); k += stepsize) @@ -2669,9 +2781,15 @@ unsigned int MoveDoor(unsigned int door_state) if (door_state & DOOR_ACTION_2) { +#if 1 + int a = MIN(x * door_2.step_offset, door_size); + int p = (door_state & DOOR_OPEN_2 ? door_size - a : a); + int i = p + door_skip; +#else int a = MIN(x * door_2.step_offset, door_size_2); int p = (door_state & DOOR_OPEN_2 ? door_size_2 - a : a); int i = p + door_skip; +#endif if (door_2.anim_mode & ANIM_STATIC_PANEL) { @@ -2748,13 +2866,15 @@ unsigned int MoveDoor(unsigned int door_state) door_2_done = (a == VXSIZE); } - BackToFront(); + if (!(door_state & DOOR_NO_DELAY)) + { + BackToFront(); - if (game_status == GAME_MODE_MAIN) - DoAnimation(); + if (game_status == GAME_MODE_MAIN) + DoAnimation(); - if (!(door_state & DOOR_NO_DELAY)) WaitUntilDelayReached(&door_delay, door_delay_value); + } } } @@ -4171,19 +4291,19 @@ em_object_mapping_list[] = EL_QUICKSAND_FULL, -1, -1 }, { - Xsand_stonein_1, FALSE, FALSE, + Xsand_stonein_1, FALSE, TRUE, EL_ROCK, ACTION_FILLING, -1 }, { - Xsand_stonein_2, FALSE, FALSE, + Xsand_stonein_2, FALSE, TRUE, EL_ROCK, ACTION_FILLING, -1 }, { - Xsand_stonein_3, FALSE, FALSE, + Xsand_stonein_3, FALSE, TRUE, EL_ROCK, ACTION_FILLING, -1 }, { - Xsand_stonein_4, FALSE, FALSE, + Xsand_stonein_4, FALSE, TRUE, EL_ROCK, ACTION_FILLING, -1 }, { @@ -5200,8 +5320,6 @@ unsigned int InitRND(long seed) return InitEngineRND(seed); } -#define DEBUG_EM_GFX 0 - void InitGraphicInfo_EM(void) { struct Mapping_EM_to_RND_object object_mapping[TILE_MAX]; @@ -5209,12 +5327,16 @@ 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 */ @@ -5308,12 +5430,12 @@ void InitGraphicInfo_EM(void) i == Ymagnify_eat ? element : i == Ygrass_eat ? element : i == Ydirt_eat ? element : - i == Yspring_kill_e ? EL_SPRING : - i == Yspring_kill_w ? EL_SPRING : i == Yemerald_stone ? EL_EMERALD : i == Ydiamond_stone ? EL_ROCK : - i == Xsand_stonein_4 ? EL_EMPTY : - i == Xsand_stoneout_2 ? EL_ROCK : + i == Xsand_stonein_1 ? element : + i == Xsand_stonein_2 ? element : + i == Xsand_stonein_3 ? element : + i == Xsand_stonein_4 ? element : is_backside ? EL_EMPTY : action_removing ? EL_EMPTY : element); @@ -5355,6 +5477,7 @@ void InitGraphicInfo_EM(void) direction)); int base_graphic = el_act2img(effective_element, ACTION_DEFAULT); int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT); + 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]; @@ -5522,23 +5645,43 @@ void InitGraphicInfo_EM(void) g_em->crumbled_border_size = graphic_info[crumbled].border_size; } - if (!g->double_movement && (effective_action == ACTION_FALLING || - effective_action == ACTION_MOVING || - effective_action == ACTION_PUSHING || - effective_action == ACTION_EATING)) +#if 0 + if (element == EL_ROCK && + effective_action == ACTION_FILLING) + printf("::: has_action_graphics == %d\n", has_action_graphics); +#endif + + if ((!g->double_movement && (effective_action == ACTION_FALLING || + effective_action == ACTION_MOVING || + effective_action == ACTION_PUSHING || + effective_action == ACTION_EATING)) || + (!has_action_graphics && (effective_action == ACTION_FILLING || + effective_action == ACTION_EMPTYING))) { int move_dir = - (effective_action == ACTION_FALLING ? MV_DOWN : direction); + (effective_action == ACTION_FALLING || + effective_action == ACTION_FILLING || + 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 || - i == Ydrip_s1B || - i == Ydrip_s2 || - i == Ydrip_s2B ? 16 : 8); + int num_steps = (i == Ydrip_s1 ? 16 : + i == Ydrip_s1B ? 16 : + i == Ydrip_s2 ? 16 : + i == Ydrip_s2B ? 16 : + i == Xsand_stonein_1 ? 32 : + i == Xsand_stonein_2 ? 32 : + i == Xsand_stonein_3 ? 32 : + i == Xsand_stonein_4 ? 32 : + i == Xsand_stoneout_1 ? 16 : + 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 || - i == Ydrip_s2B ? j + 8 : j) + 1; + int step_frame = (i == Ydrip_s2 ? j + 8 : + i == Ydrip_s2B ? j + 8 : + i == Xsand_stonein_2 ? j + 8 : + i == Xsand_stonein_3 ? j + 16 : + i == Xsand_stonein_4 ? j + 24 : + i == Xsand_stoneout_2 ? j + 8 : j) + 1; int step = (is_backside ? step_frame : num_steps - step_frame); if (is_backside) /* tile where movement starts */ @@ -5660,6 +5803,8 @@ void InitGraphicInfo_EM(void) 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 @@ -5806,6 +5951,8 @@ void InitGraphicInfo_EM(void) 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 @@ -5814,6 +5961,96 @@ void InitGraphicInfo_EM(void) } #if DEBUG_EM_GFX + printf("\n"); + printf("::: [%d errors found]\n", num_em_gfx_errors); + exit(0); #endif } + +void PlayMenuSound() +{ + int sound = menu.sound[game_status]; + + if (sound == SND_UNDEFINED) + return; + + if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) || + (!setup.sound_loops && IS_LOOP_SOUND(sound))) + return; + + if (IS_LOOP_SOUND(sound)) + PlaySoundLoop(sound); + else + PlaySound(sound); +} + +void PlayMenuSoundStereo(int sound, int stereo_position) +{ + if (sound == SND_UNDEFINED) + return; + + if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) || + (!setup.sound_loops && IS_LOOP_SOUND(sound))) + return; + + if (IS_LOOP_SOUND(sound)) + PlaySoundExt(sound, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_LOOP); + else + PlaySoundStereo(sound, stereo_position); +} + +void PlayMenuSoundIfLoop() +{ + int sound = menu.sound[game_status]; + + if (sound == SND_UNDEFINED) + return; + + if ((!setup.sound_simple && !IS_LOOP_SOUND(sound)) || + (!setup.sound_loops && IS_LOOP_SOUND(sound))) + return; + + if (IS_LOOP_SOUND(sound)) + PlaySoundLoop(sound); +} + +void PlayMenuMusic() +{ + int music = menu.music[game_status]; + + if (music == MUS_UNDEFINED) + return; + + PlayMusic(music); +} + +void ToggleFullscreenIfNeeded() +{ + if (setup.fullscreen != video.fullscreen_enabled || + setup.fullscreen_mode != video.fullscreen_mode_current) + { + Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); + + /* save backbuffer content which gets lost when toggling fullscreen mode */ + BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + + if (setup.fullscreen && video.fullscreen_enabled) + { + /* keep fullscreen mode, but change screen mode */ + video.fullscreen_mode_current = setup.fullscreen_mode; + video.fullscreen_enabled = FALSE; + } + + /* toggle fullscreen */ + ChangeVideoModeIfNeeded(setup.fullscreen); + setup.fullscreen = video.fullscreen_enabled; + + /* restore backbuffer content from temporary backbuffer backup bitmap */ + BlitBitmap(tmp_backbuffer, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + + FreeBitmap(tmp_backbuffer); + + redraw_mask = REDRAW_ALL; + } +}