X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ftools.c;h=e534cc29c3e79c465cd50d0ee79420ed0bd5bc17;hp=6a1306e45e903f9238a6526b4a6a86f68bcc1ce2;hb=aecdc1103c5dff9ef3900c213931d526df0cb3a7;hpb=8ae535c1c76e1c33572afbcd4b2d3d9c3d7ba63e diff --git a/src/tools.c b/src/tools.c index 6a1306e4..e534cc29 100644 --- a/src/tools.c +++ b/src/tools.c @@ -17,14 +17,15 @@ #include "init.h" #include "game.h" #include "events.h" -#include "cartoons.h" +#include "anim.h" #include "network.h" #include "tape.h" #include "screens.h" /* select level set with EMC X11 graphics before activating EM GFX debugging */ -#define DEBUG_EM_GFX 0 +#define DEBUG_EM_GFX FALSE +#define DEBUG_FRAME_TIME FALSE /* tool button identifiers */ #define TOOL_CTRL_ID_YES 0 @@ -65,83 +66,83 @@ static struct DoorPartControlInfo door_part_controls[] = { { DOOR_1, - IMG_DOOR_1_GFX_PART_1, + IMG_GFX_DOOR_1_PART_1, &door_1.part_1 }, { DOOR_1, - IMG_DOOR_1_GFX_PART_2, + IMG_GFX_DOOR_1_PART_2, &door_1.part_2 }, { DOOR_1, - IMG_DOOR_1_GFX_PART_3, + IMG_GFX_DOOR_1_PART_3, &door_1.part_3 }, { DOOR_1, - IMG_DOOR_1_GFX_PART_4, + IMG_GFX_DOOR_1_PART_4, &door_1.part_4 }, { DOOR_1, - IMG_DOOR_1_GFX_PART_5, + IMG_GFX_DOOR_1_PART_5, &door_1.part_5 }, { DOOR_1, - IMG_DOOR_1_GFX_PART_6, + IMG_GFX_DOOR_1_PART_6, &door_1.part_6 }, { DOOR_1, - IMG_DOOR_1_GFX_PART_7, + IMG_GFX_DOOR_1_PART_7, &door_1.part_7 }, { DOOR_1, - IMG_DOOR_1_GFX_PART_8, + IMG_GFX_DOOR_1_PART_8, &door_1.part_8 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_1, + IMG_GFX_DOOR_2_PART_1, &door_2.part_1 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_2, + IMG_GFX_DOOR_2_PART_2, &door_2.part_2 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_3, + IMG_GFX_DOOR_2_PART_3, &door_2.part_3 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_4, + IMG_GFX_DOOR_2_PART_4, &door_2.part_4 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_5, + IMG_GFX_DOOR_2_PART_5, &door_2.part_5 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_6, + IMG_GFX_DOOR_2_PART_6, &door_2.part_6 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_7, + IMG_GFX_DOOR_2_PART_7, &door_2.part_7 }, { DOOR_2, - IMG_DOOR_2_GFX_PART_8, + IMG_GFX_DOOR_2_PART_8, &door_2.part_8 }, @@ -173,9 +174,6 @@ static int el_act2crm(int, int); static struct GadgetInfo *tool_gadget[NUM_TOOL_BUTTONS]; static int request_gadget_id = -1; -static unsigned int sync_frame_delay = 0; -static unsigned int sync_frame_delay_value = GAME_FRAME_DELAY; - static char *print_if_not_empty(int element) { static char *s = NULL; @@ -236,7 +234,7 @@ void DumpTile(int x, int y) void SetDrawtoField(int mode) { - if (mode == DRAW_FIELDBUFFER) + if (mode == DRAW_TO_FIELDBUFFER) { FX = 2 * TILEX_VAR; FY = 2 * TILEY_VAR; @@ -247,7 +245,7 @@ void SetDrawtoField(int mode) drawto_field = fieldbuffer; } - else /* DRAW_BACKBUFFER */ + else /* DRAW_TO_BACKBUFFER */ { FX = SX; FY = SY; @@ -288,96 +286,126 @@ void RedrawPlayfield() } static void DrawMaskedBorderExt_Rect(int x, int y, int width, int height, - boolean blit_to_screen) + int draw_target) { - Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus(); + Bitmap *src_bitmap = getGlobalBorderBitmapFromStatus(global.border_status); + Bitmap *dst_bitmap = gfx.masked_border_bitmap_ptr; + + if (x == -1 && y == -1) + return; - if (blit_to_screen) - BlitToScreenMasked(bitmap, x, y, width, height, x, y); + if (draw_target == DRAW_TO_SCREEN) + BlitToScreenMasked(src_bitmap, x, y, width, height, x, y); else - BlitBitmapMasked(bitmap, backbuffer, x, y, width, height, x, y); + BlitBitmapMasked(src_bitmap, dst_bitmap, x, y, width, height, x, y); } -static void DrawMaskedBorderExt_FIELD(boolean blit_to_screen) +static void DrawMaskedBorderExt_FIELD(int draw_target) { - if (global.border_status >= GAME_MODE_TITLE && + if (global.border_status >= GAME_MODE_MAIN && global.border_status <= GAME_MODE_PLAYING && border.draw_masked[global.border_status]) DrawMaskedBorderExt_Rect(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, - blit_to_screen); + draw_target); } -static void DrawMaskedBorderExt_DOOR_1(boolean blit_to_screen) +static void DrawMaskedBorderExt_DOOR_1(int draw_target) { - // only draw border over closed doors when drawing to backbuffer - if (!blit_to_screen && (GetDoorState() & DOOR_OPEN_1)) + // when drawing to backbuffer, never draw border over open doors + if (draw_target == DRAW_TO_BACKBUFFER && + (GetDoorState() & DOOR_OPEN_1)) return; if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] && (global.border_status != GAME_MODE_EDITOR || border.draw_masked[GFX_SPECIAL_ARG_EDITOR])) - DrawMaskedBorderExt_Rect(DX, DY, DXSIZE, DYSIZE, blit_to_screen); + DrawMaskedBorderExt_Rect(DX, DY, DXSIZE, DYSIZE, draw_target); } -static void DrawMaskedBorderExt_DOOR_2(boolean blit_to_screen) +static void DrawMaskedBorderExt_DOOR_2(int draw_target) { - // only draw border over closed doors when drawing to backbuffer - if (!blit_to_screen && (GetDoorState() & DOOR_OPEN_2)) + // when drawing to backbuffer, never draw border over open doors + if (draw_target == DRAW_TO_BACKBUFFER && + (GetDoorState() & DOOR_OPEN_2)) return; if (border.draw_masked[GFX_SPECIAL_ARG_DOOR] && global.border_status != GAME_MODE_EDITOR) - DrawMaskedBorderExt_Rect(VX, VY, VXSIZE, VYSIZE, blit_to_screen); + DrawMaskedBorderExt_Rect(VX, VY, VXSIZE, VYSIZE, draw_target); } -static void DrawMaskedBorderExt_DOOR_3(boolean blit_to_screen) +static void DrawMaskedBorderExt_DOOR_3(int draw_target) { /* currently not available */ } -static void DrawMaskedBorderExt_ALL(boolean blit_to_screen) +static void DrawMaskedBorderExt_ALL(int draw_target) { - DrawMaskedBorderExt_FIELD(blit_to_screen); - DrawMaskedBorderExt_DOOR_1(blit_to_screen); - DrawMaskedBorderExt_DOOR_2(blit_to_screen); - DrawMaskedBorderExt_DOOR_3(blit_to_screen); + DrawMaskedBorderExt_FIELD(draw_target); + DrawMaskedBorderExt_DOOR_1(draw_target); + DrawMaskedBorderExt_DOOR_2(draw_target); + DrawMaskedBorderExt_DOOR_3(draw_target); } -static void DrawMaskedBorderExt(int redraw_mask, boolean blit_to_screen) +static void DrawMaskedBorderExt(int redraw_mask, int draw_target) { /* never draw masked screen borders on borderless screens */ - if (game_status == GAME_MODE_LOADING || - game_status == GAME_MODE_TITLE) + if (global.border_status == GAME_MODE_LOADING || + global.border_status == GAME_MODE_TITLE) return; if (redraw_mask & REDRAW_ALL) - DrawMaskedBorderExt_ALL(blit_to_screen); + DrawMaskedBorderExt_ALL(draw_target); else { if (redraw_mask & REDRAW_FIELD) - DrawMaskedBorderExt_FIELD(blit_to_screen); + DrawMaskedBorderExt_FIELD(draw_target); if (redraw_mask & REDRAW_DOOR_1) - DrawMaskedBorderExt_DOOR_1(blit_to_screen); + DrawMaskedBorderExt_DOOR_1(draw_target); if (redraw_mask & REDRAW_DOOR_2) - DrawMaskedBorderExt_DOOR_2(blit_to_screen); + DrawMaskedBorderExt_DOOR_2(draw_target); if (redraw_mask & REDRAW_DOOR_3) - DrawMaskedBorderExt_DOOR_3(blit_to_screen); + DrawMaskedBorderExt_DOOR_3(draw_target); } } void DrawMaskedBorder_FIELD() { - DrawMaskedBorderExt_FIELD(FALSE); + DrawMaskedBorderExt_FIELD(DRAW_TO_BACKBUFFER); } void DrawMaskedBorder(int redraw_mask) { - DrawMaskedBorderExt(redraw_mask, FALSE); + DrawMaskedBorderExt(redraw_mask, DRAW_TO_BACKBUFFER); } -void DrawMaskedBorderToScreen(int redraw_mask) +void DrawMaskedBorderToTarget(int draw_target) { - DrawMaskedBorderExt(redraw_mask, TRUE); + if (draw_target == DRAW_TO_BACKBUFFER || + draw_target == DRAW_TO_SCREEN) + { + DrawMaskedBorderExt(REDRAW_ALL, draw_target); + } + else + { + int last_border_status = global.border_status; + + if (draw_target == DRAW_TO_FADE_SOURCE) + { + global.border_status = gfx.fade_border_source_status; + gfx.masked_border_bitmap_ptr = gfx.fade_bitmap_source; + } + else if (draw_target == DRAW_TO_FADE_TARGET) + { + global.border_status = gfx.fade_border_target_status; + gfx.masked_border_bitmap_ptr = gfx.fade_bitmap_target; + } + + DrawMaskedBorderExt(REDRAW_ALL, draw_target); + + global.border_status = last_border_status; + gfx.masked_border_bitmap_ptr = backbuffer; + } } void BlitScreenToBitmap_RND(Bitmap *target_bitmap) @@ -462,10 +490,70 @@ void DrawFramesPerSecond() font_nr, BLIT_OPAQUE); } +#if DEBUG_FRAME_TIME +static void PrintFrameTimeDebugging() +{ + static unsigned int last_counter = 0; + unsigned int counter = Counter(); + int diff_1 = counter - last_counter; + int diff_2 = diff_1 - GAME_FRAME_DELAY; + int diff_2_max = 20; + int diff_2_cut = MIN(ABS(diff_2), diff_2_max); + char diff_bar[2 * diff_2_max + 5]; + int pos = 0; + int i; + + diff_bar[pos++] = (diff_2 < -diff_2_max ? '<' : ' '); + + for (i = 0; i < diff_2_max; i++) + diff_bar[pos++] = (diff_2 >= 0 ? ' ' : + i >= diff_2_max - diff_2_cut ? '-' : ' '); + + diff_bar[pos++] = '|'; + + for (i = 0; i < diff_2_max; i++) + diff_bar[pos++] = (diff_2 <= 0 ? ' ' : i < diff_2_cut ? '+' : ' '); + + diff_bar[pos++] = (diff_2 > diff_2_max ? '>' : ' '); + + diff_bar[pos++] = '\0'; + + Error(ERR_INFO, "%06d [%02d] [%c%02d] %s", + counter, + diff_1, + (diff_2 < 0 ? '-' : diff_2 > 0 ? '+' : ' '), ABS(diff_2), + diff_bar); + + last_counter = counter; +} +#endif + +static int unifiedRedrawMask(int mask) +{ + if (mask & REDRAW_ALL) + return REDRAW_ALL; + + if (mask & REDRAW_FIELD && mask & REDRAW_DOORS) + return REDRAW_ALL; + + return mask; +} + +static boolean equalRedrawMasks(int mask_1, int mask_2) +{ + return unifiedRedrawMask(mask_1) == unifiedRedrawMask(mask_2); +} + void BackToFront() { + static int last_redraw_mask = REDRAW_NONE; + + // force screen redraw in every frame to continue drawing global animations + // (but always use the last redraw mask to prevent unwanted side effects) if (redraw_mask == REDRAW_NONE) - return; + redraw_mask = last_redraw_mask; + + last_redraw_mask = redraw_mask; #if 1 // masked border now drawn immediately when blitting backbuffer to window @@ -478,6 +566,10 @@ void BackToFront() if (redraw_mask & REDRAW_FPS) DrawFramesPerSecond(); + // remove playfield redraw before potentially merging with doors redraw + if (DrawingDeactivated(REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE)) + redraw_mask &= ~REDRAW_FIELD; + // redraw complete window if both playfield and (some) doors need redraw if (redraw_mask & REDRAW_FIELD && redraw_mask & REDRAW_DOORS) redraw_mask = REDRAW_ALL; @@ -498,39 +590,62 @@ void BackToFront() } else if (redraw_mask & REDRAW_DOORS) { + // merge door areas to prevent calling screen redraw more than once + int x1 = WIN_XSIZE; + int y1 = WIN_YSIZE; + int x2 = 0; + int y2 = 0; + if (redraw_mask & REDRAW_DOOR_1) - BlitBitmap(backbuffer, window, DX, DY, DXSIZE, DYSIZE, DX, DY); + { + x1 = MIN(x1, DX); + y1 = MIN(y1, DY); + x2 = MAX(x2, DX + DXSIZE); + y2 = MAX(y2, DY + DYSIZE); + } if (redraw_mask & REDRAW_DOOR_2) - BlitBitmap(backbuffer, window, VX, VY, VXSIZE, VYSIZE, VX, VY); + { + x1 = MIN(x1, VX); + y1 = MIN(y1, VY); + x2 = MAX(x2, VX + VXSIZE); + y2 = MAX(y2, VY + VYSIZE); + } if (redraw_mask & REDRAW_DOOR_3) - BlitBitmap(backbuffer, window, EX, EY, EXSIZE, EYSIZE, EX, EY); + { + x1 = MIN(x1, EX); + y1 = MIN(y1, EY); + x2 = MAX(x2, EX + EXSIZE); + y2 = MAX(y2, EY + EYSIZE); + } + + BlitBitmap(backbuffer, window, x1, y1, x2 - x1, y2 - y1, x1, y1); } redraw_mask = REDRAW_NONE; -} -static void FadeCrossSaveBackbuffer() -{ - BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); +#if DEBUG_FRAME_TIME + PrintFrameTimeDebugging(); +#endif } -static void FadeCrossRestoreBackbuffer() +void BackToFront_WithFrameDelay(unsigned int frame_delay_value) { - int redraw_mask_last = redraw_mask; + unsigned int frame_delay_value_old = GetVideoFrameDelay(); + + SetVideoFrameDelay(frame_delay_value); - BlitBitmap(bitmap_db_cross, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + BackToFront(); - // do not change redraw mask when restoring backbuffer after cross-fading - redraw_mask = redraw_mask_last; + SetVideoFrameDelay(frame_delay_value_old); } +static int fade_type_skip = FADE_TYPE_NONE; + static void FadeExt(int fade_mask, int fade_mode, int fade_type) { - static int fade_type_skip = FADE_TYPE_NONE; void (*draw_border_function)(void) = NULL; - Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL); int x, y, width, height; int fade_delay, post_delay; @@ -545,18 +660,8 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) return; } -#if 1 - FadeCrossSaveBackbuffer(); -#endif - if (fading.fade_mode & FADE_TYPE_TRANSFORM) - { -#if 0 - FadeCrossSaveBackbuffer(); -#endif - return; - } } redraw_mask |= fade_mask; @@ -619,17 +724,55 @@ static void FadeExt(int fade_mask, int fade_mode, int fade_type) return; } - FadeRectangle(bitmap, x, y, width, height, fade_mode, fade_delay, post_delay, + FadeRectangle(x, y, width, height, fade_mode, fade_delay, post_delay, draw_border_function); - if (fade_type == FADE_TYPE_FADE_OUT) - FadeCrossRestoreBackbuffer(); - redraw_mask &= ~fade_mask; } +static void SetScreenStates_BeforeFadingIn() +{ + // temporarily set screen mode for animations to screen after fading in + 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); + + // set screen mode for animations back to fading + global.anim_status = GAME_MODE_PSEUDO_FADING; +} + +static void SetScreenStates_AfterFadingIn() +{ + // store new source screen (to use correct masked border for fading) + gfx.fade_border_source_status = global.border_status; + + global.anim_status = global.anim_status_next; +} + +static void SetScreenStates_BeforeFadingOut() +{ + // store new target screen (to use correct masked border for fading) + gfx.fade_border_target_status = game_status; + + // set screen mode for animations to fading + global.anim_status = GAME_MODE_PSEUDO_FADING; + + // store backbuffer with all animations that will be stopped for fading out + if (fade_type_skip != FADE_MODE_SKIP_FADE_OUT) + PrepareFadeBitmap(DRAW_TO_FADE_SOURCE); +} + +static void SetScreenStates_AfterFadingOut() +{ + global.border_status = game_status; +} + void FadeIn(int fade_mask) { + SetScreenStates_BeforeFadingIn(); + #if 1 DrawMaskedBorder(REDRAW_ALL); #endif @@ -643,10 +786,22 @@ void FadeIn(int fade_mask) FADE_SY = REAL_SY; FADE_SXSIZE = FULL_SXSIZE; FADE_SYSIZE = FULL_SYSIZE; + + SetScreenStates_AfterFadingIn(); + + // force update of global animation status in case of rapid screen changes + redraw_mask = REDRAW_ALL; + BackToFront(); } void FadeOut(int fade_mask) { + // update screen if areas covered by "fade_mask" and "redraw_mask" differ + if (!equalRedrawMasks(fade_mask, redraw_mask)) + BackToFront(); + + SetScreenStates_BeforeFadingOut(); + #if 0 DrawMaskedBorder(REDRAW_ALL); #endif @@ -656,7 +811,7 @@ void FadeOut(int fade_mask) else FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT); - global.border_status = game_status; + SetScreenStates_AfterFadingOut(); } static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set) @@ -750,14 +905,14 @@ Bitmap *getGlobalBorderBitmap(int graphic) return getBitmapFromGraphicOrDefault(graphic, IMG_GLOBAL_BORDER); } -Bitmap *getGlobalBorderBitmapFromGameStatus() +Bitmap *getGlobalBorderBitmapFromStatus(int status) { int graphic = - (game_status == GAME_MODE_MAIN || - game_status == GAME_MODE_PSEUDO_TYPENAME ? IMG_GLOBAL_BORDER_MAIN : - game_status == GAME_MODE_SCORES ? IMG_GLOBAL_BORDER_SCORES : - game_status == GAME_MODE_EDITOR ? IMG_GLOBAL_BORDER_EDITOR : - game_status == GAME_MODE_PLAYING ? IMG_GLOBAL_BORDER_PLAYING : + (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 : IMG_GLOBAL_BORDER); return getGlobalBorderBitmap(graphic); @@ -858,7 +1013,7 @@ boolean CheckIfGlobalBorderHasChanged() return FALSE; // determine and store new global border bitmap for current game status - global_border_bitmap = getGlobalBorderBitmapFromGameStatus(); + global_border_bitmap = getGlobalBorderBitmapFromStatus(game_status); return (global_border_bitmap_last != global_border_bitmap); } @@ -905,7 +1060,7 @@ void RedrawGlobalBorderFromBitmap(Bitmap *bitmap) void RedrawGlobalBorder() { - Bitmap *bitmap = getGlobalBorderBitmapFromGameStatus(); + Bitmap *bitmap = getGlobalBorderBitmapFromStatus(game_status); RedrawGlobalBorderFromBitmap(bitmap); @@ -919,7 +1074,7 @@ static void RedrawGlobalBorderIfNeeded() // copy current draw buffer to later copy back areas that have not changed if (game_status_last != GAME_MODE_TITLE) - BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); if (CheckIfGlobalBorderRedrawIsNeeded()) { @@ -932,20 +1087,20 @@ static void RedrawGlobalBorderIfNeeded() if (real_sx_last != -1 && real_sy_last != -1 && REAL_SX != -1 && REAL_SY != -1 && full_sxsize_last == FULL_SXSIZE && full_sysize_last == FULL_SYSIZE) - BlitBitmap(bitmap_db_store, backbuffer, + BlitBitmap(bitmap_db_store_1, backbuffer, real_sx_last, real_sy_last, FULL_SXSIZE, FULL_SYSIZE, REAL_SX, REAL_SY); if (dx_last != -1 && dy_last != -1 && DX != -1 && DY != -1 && dxsize_last == DXSIZE && dysize_last == DYSIZE) - BlitBitmap(bitmap_db_store, backbuffer, + BlitBitmap(bitmap_db_store_1, backbuffer, dx_last, dy_last, DXSIZE, DYSIZE, DX, DY); if (vx_last != -1 && vy_last != -1 && VX != -1 && VY != -1 && vxsize_last == VXSIZE && vysize_last == VYSIZE) - BlitBitmap(bitmap_db_store, backbuffer, + BlitBitmap(bitmap_db_store_1, backbuffer, vx_last, vy_last, VXSIZE, VYSIZE, VX, VY); redraw_mask = REDRAW_ALL; @@ -981,11 +1136,11 @@ void ClearField() if (game_status == GAME_MODE_PLAYING) { ClearRectangle(fieldbuffer, 0, 0, FXSIZE, FYSIZE); - SetDrawtoField(DRAW_FIELDBUFFER); + SetDrawtoField(DRAW_TO_FIELDBUFFER); } else { - SetDrawtoField(DRAW_BACKBUFFER); + SetDrawtoField(DRAW_TO_BACKBUFFER); } } @@ -1064,52 +1219,64 @@ int getGraphicAnimationFrame(int graphic, int sync_frame) sync_frame); } -void getSizedGraphicSourceExt(int graphic, int frame, int tilesize, - Bitmap **bitmap, int *x, int *y, - boolean get_backside) +void getGraphicSourceBitmap(int graphic, int tilesize, Bitmap **bitmap) { struct GraphicInfo *g = &graphic_info[graphic]; - Bitmap *src_bitmap = g->bitmap; - int src_x = g->src_x + (get_backside ? g->offset2_x : 0); - int src_y = g->src_y + (get_backside ? g->offset2_y : 0); int tilesize_capped = MIN(MAX(1, tilesize), TILESIZE); - // if no in-game graphics defined, always use standard graphic size - if (g->bitmaps[IMG_BITMAP_GAME] == NULL) - tilesize = TILESIZE; - if (tilesize == gfx.standard_tile_size) - src_bitmap = g->bitmaps[IMG_BITMAP_STANDARD]; + *bitmap = g->bitmaps[IMG_BITMAP_STANDARD]; else if (tilesize == game.tile_size) - src_bitmap = g->bitmaps[IMG_BITMAP_GAME]; + *bitmap = g->bitmaps[IMG_BITMAP_GAME]; else - src_bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)]; + *bitmap = g->bitmaps[IMG_BITMAP_1x1 - log_2(tilesize_capped)]; +} + +void getGraphicSourceXY(int graphic, int frame, int *x, int *y, + boolean get_backside) +{ + struct GraphicInfo *g = &graphic_info[graphic]; + int src_x = g->src_x + (get_backside ? g->offset2_x : 0); + int src_y = g->src_y + (get_backside ? g->offset2_y : 0); if (g->offset_y == 0) /* frames are ordered horizontally */ { int max_width = g->anim_frames_per_line * g->width; int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x; - src_x = pos % max_width; - src_y = src_y % g->height + pos / max_width * g->height; + *x = pos % max_width; + *y = src_y % g->height + pos / max_width * g->height; } else if (g->offset_x == 0) /* frames are ordered vertically */ { int max_height = g->anim_frames_per_line * g->height; int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y; - src_x = src_x % g->width + pos / max_height * g->width; - src_y = pos % max_height; + *x = src_x % g->width + pos / max_height * g->width; + *y = pos % max_height; } else /* frames are ordered diagonally */ { - src_x = src_x + frame * g->offset_x; - src_y = src_y + frame * g->offset_y; + *x = src_x + frame * g->offset_x; + *y = src_y + frame * g->offset_y; } +} - *bitmap = src_bitmap; - *x = src_x * tilesize / g->tile_size; - *y = src_y * tilesize / g->tile_size; +void getSizedGraphicSourceExt(int graphic, int frame, int tilesize, + Bitmap **bitmap, int *x, int *y, + boolean get_backside) +{ + struct GraphicInfo *g = &graphic_info[graphic]; + + // if no in-game graphics defined, always use standard graphic size + if (g->bitmaps[IMG_BITMAP_GAME] == NULL) + tilesize = TILESIZE; + + getGraphicSourceBitmap(graphic, tilesize, bitmap); + getGraphicSourceXY(graphic, frame, x, y, get_backside); + + *x = *x * tilesize / g->tile_size; + *y = *y * tilesize / g->tile_size; } void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap, @@ -1139,40 +1306,8 @@ void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) inline static void getGraphicSourceExt(int graphic, int frame, Bitmap **bitmap, int *x, int *y, boolean get_backside) { - struct GraphicInfo *g = &graphic_info[graphic]; - int src_x = g->src_x + (get_backside ? g->offset2_x : 0); - int src_y = g->src_y + (get_backside ? g->offset2_y : 0); - - if (TILESIZE_VAR != TILESIZE) - return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y, - get_backside); - - *bitmap = g->bitmap; - - if (g->offset_y == 0) /* frames are ordered horizontally */ - { - int max_width = g->anim_frames_per_line * g->width; - int pos = (src_y / g->height) * max_width + src_x + frame * g->offset_x; - - *x = pos % max_width; - *y = src_y % g->height + pos / max_width * g->height; - } - else if (g->offset_x == 0) /* frames are ordered vertically */ - { - int max_height = g->anim_frames_per_line * g->height; - int pos = (src_x / g->width) * max_height + src_y + frame * g->offset_y; - - *x = src_x % g->width + pos / max_height * g->width; - *y = pos % max_height; - } - else /* frames are ordered diagonally */ - { - *x = src_x + frame * g->offset_x; - *y = src_y + frame * g->offset_y; - } - - *x = *x * TILESIZE_VAR / g->tile_size; - *y = *y * TILESIZE_VAR / g->tile_size; + getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y, + get_backside); } void getGraphicSource(int graphic, int frame, Bitmap **bitmap, int *x, int *y) @@ -2178,11 +2313,11 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) int sy = SY + (SYSIZE - ysize * font_height) / 2; int xx, yy; - SetDrawtoField(DRAW_FIELDBUFFER); + SetDrawtoField(DRAW_TO_FIELDBUFFER); BlitScreenToBitmap(backbuffer); - SetDrawtoField(DRAW_BACKBUFFER); + SetDrawtoField(DRAW_TO_BACKBUFFER); for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++) @@ -2239,7 +2374,7 @@ void ShowEnvelope(int envelope_nr) game.envelope_active = FALSE; - SetDrawtoField(DRAW_FIELDBUFFER); + SetDrawtoField(DRAW_TO_FIELDBUFFER); redraw_mask |= REDRAW_FIELD; BackToFront(); @@ -2314,7 +2449,6 @@ static void setRequestPosition(int *x, int *y, boolean add_border_size) void DrawEnvelopeRequest(char *text) { - int last_game_status = game_status; /* save current game status */ char *text_final = text; char *text_door_style = NULL; int graphic = IMG_BACKGROUND_REQUEST; @@ -2382,19 +2516,19 @@ void DrawEnvelopeRequest(char *text) tile_size, tile_size); /* force DOOR font inside door area */ - game_status = GAME_MODE_PSEUDO_DOOR; + SetFontStatus(GAME_MODE_PSEUDO_DOOR); DrawTextBuffer(sx + sx_offset, sy + sy_offset, text_final, font_nr, line_length, -1, max_lines, line_spacing, mask_mode, request.autowrap, request.centered, FALSE); - game_status = last_game_status; /* restore current game status */ + ResetFontStatus(); for (i = 0; i < NUM_TOOL_BUTTONS; i++) RedrawGadget(tool_gadget[i]); // store readily prepared envelope request for later use when animating - BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + BlitBitmap(backbuffer, bitmap_db_store_2, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); if (text_door_style) free(text_door_style); @@ -2455,7 +2589,7 @@ void AnimateEnvelopeRequest(int anim_mode, int action) setRequestPosition(&src_x, &src_y, FALSE); setRequestPositionExt(&dst_x, &dst_y, width, height, FALSE); - BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + BlitBitmap(bitmap_db_store_1, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); for (yy = 0; yy < 2; yy++) { @@ -2469,17 +2603,16 @@ void AnimateEnvelopeRequest(int anim_mode, int action) int yy_size = (yy ? tile_size : ysize_size_top); if (draw_masked) - BlitBitmapMasked(bitmap_db_cross, backbuffer, + BlitBitmapMasked(bitmap_db_store_2, backbuffer, src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy); else - BlitBitmap(bitmap_db_cross, backbuffer, + BlitBitmap(bitmap_db_store_2, backbuffer, src_xx, src_yy, xx_size, yy_size, dst_xx, dst_yy); } } redraw_mask |= REDRAW_FIELD; - DoAnimation(); BackToFront(); SkipUntilDelayReached(&anim_delay, anim_delay_value, &i, last_frame); @@ -2500,13 +2633,13 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) if (game_status == GAME_MODE_PLAYING) BlitScreenToBitmap(backbuffer); - SetDrawtoField(DRAW_BACKBUFFER); + SetDrawtoField(DRAW_TO_BACKBUFFER); // SetDrawBackgroundMask(REDRAW_NONE); if (action == ACTION_OPENING) { - BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + BlitBitmap(backbuffer, bitmap_db_store_1, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); if (req_state & REQ_ASK) { @@ -2526,9 +2659,6 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) } DrawEnvelopeRequest(text); - - if (game_status != GAME_MODE_MAIN) - InitAnimation(); } game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */ @@ -2556,26 +2686,18 @@ void ShowEnvelopeRequest(char *text, unsigned int req_state, int action) game.envelope_active = FALSE; if (action == ACTION_CLOSING) - { - if (game_status != GAME_MODE_MAIN) - StopAnimation(); - - BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); - } + BlitBitmap(bitmap_db_store_1, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); // SetDrawBackgroundMask(last_draw_background_mask); redraw_mask |= REDRAW_FIELD; - if (game_status == GAME_MODE_MAIN) - DoAnimation(); - BackToFront(); if (action == ACTION_CLOSING && game_status == GAME_MODE_PLAYING && level.game_engine_type == GAME_ENGINE_TYPE_RND) - SetDrawtoField(DRAW_FIELDBUFFER); + SetDrawtoField(DRAW_TO_FIELDBUFFER); } void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize) @@ -2747,7 +2869,6 @@ static void DrawPreviewLevelExt(boolean restart) 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 */ if (restart) { @@ -2793,8 +2914,6 @@ static void DrawPreviewLevelExt(boolean restart) DrawTextSAligned(pos->x, pos->y, label_text, font_nr, pos->align); } - game_status = last_game_status; /* restore current game status */ - return; } @@ -2894,8 +3013,6 @@ static void DrawPreviewLevelExt(boolean restart) DrawPreviewLevelLabelExt(label_state); } - - game_status = last_game_status; /* restore current game status */ } void DrawPreviewLevelInitial() @@ -3437,9 +3554,7 @@ void WaitForEventToContinue() still_wait = FALSE; } - DoAnimation(); - - WaitUntilDelayReached(&sync_frame_delay, sync_frame_delay_value); + BackToFront(); } } @@ -3467,16 +3582,16 @@ static int RequestHandleEvents(unsigned int req_state) { if (level_solved) { - SetDrawtoField(DRAW_FIELDBUFFER); + SetDrawtoField(DRAW_TO_FIELDBUFFER); HandleGameActions(); - SetDrawtoField(DRAW_BACKBUFFER); + SetDrawtoField(DRAW_TO_BACKBUFFER); if (global.use_envelope_request) { /* copy current state of request area to middle of playfield area */ - BlitBitmap(bitmap_db_cross, drawto, sx, sy, width, height, sx, sy); + BlitBitmap(bitmap_db_store_2, drawto, sx, sy, width, height, sx, sy); } } @@ -3550,7 +3665,10 @@ static int RequestHandleEvents(unsigned int req_state) } case EVENT_KEYPRESS: - switch (GetEventKey((KeyEvent *)&event, TRUE)) + { + Key key = GetEventKey((KeyEvent *)&event, TRUE); + + switch (key) { case KSYM_space: if (req_state & REQ_CONFIRM) @@ -3572,12 +3690,15 @@ static int RequestHandleEvents(unsigned int req_state) break; default: + HandleKeysDebug(key); break; } if (req_state & REQ_PLAYER) result = 0; + break; + } case EVENT_KEYRELEASE: ClearPlayerAction(); @@ -3604,17 +3725,11 @@ static int RequestHandleEvents(unsigned int req_state) if (global.use_envelope_request) { /* copy back current state of pressed buttons inside request area */ - BlitBitmap(drawto, bitmap_db_cross, sx, sy, width, height, sx, sy); + BlitBitmap(drawto, bitmap_db_store_2, sx, sy, width, height, sx, sy); } } - else - { - DoAnimation(); - } BackToFront(); - - WaitUntilDelayReached(&sync_frame_delay, sync_frame_delay_value); } return result; @@ -3623,7 +3738,6 @@ static int RequestHandleEvents(unsigned int req_state) static boolean RequestDoor(char *text, unsigned int req_state) { unsigned int old_door_state; - int last_game_status = game_status; /* save current game status */ int max_request_line_len = MAX_REQUEST_LINE_FONT1_LEN; int font_nr = FONT_TEXT_2; char *text_ptr; @@ -3680,7 +3794,7 @@ static boolean RequestDoor(char *text, unsigned int req_state) DrawBackground(DX, DY, DXSIZE, DYSIZE); /* force DOOR font inside door area */ - game_status = GAME_MODE_PSEUDO_DOOR; + SetFontStatus(GAME_MODE_PSEUDO_DOOR); /* write text for request */ for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++) @@ -3720,7 +3834,7 @@ static boolean RequestDoor(char *text, unsigned int req_state) // text_ptr += tl + (tc == ' ' || tc == '?' || tc == '!' ? 1 : 0); } - game_status = last_game_status; /* restore current game status */ + ResetFontStatus(); if (req_state & REQ_ASK) { @@ -3759,17 +3873,11 @@ static boolean RequestDoor(char *text, unsigned int req_state) return FALSE; } - if (game_status != GAME_MODE_MAIN) - InitAnimation(); - SetDrawBackgroundMask(REDRAW_FIELD | REDRAW_DOOR_1); // ---------- handle request buttons ---------- result = RequestHandleEvents(req_state); - if (game_status != GAME_MODE_MAIN) - StopAnimation(); - UnmapToolButtons(); if (!(req_state & REQ_STAY_OPEN)) @@ -3864,9 +3972,6 @@ static boolean RequestEnvelope(char *text, unsigned int req_state) // ---------- handle request buttons ---------- result = RequestHandleEvents(req_state); - if (game_status != GAME_MODE_MAIN) - StopAnimation(); - UnmapToolButtons(); ShowEnvelopeRequest(text, req_state, ACTION_CLOSING); @@ -3930,8 +4035,8 @@ void InitGraphicCompatibilityInfo_Doors() } doors[] = { - { DOOR_1, IMG_DOOR_1_GFX_PART_1, IMG_DOOR_1_GFX_PART_8, &door_1 }, - { DOOR_2, IMG_DOOR_2_GFX_PART_1, IMG_DOOR_2_GFX_PART_8, &door_2 }, + { DOOR_1, IMG_GFX_DOOR_1_PART_1, IMG_GFX_DOOR_1_PART_8, &door_1 }, + { DOOR_2, IMG_GFX_DOOR_2_PART_1, IMG_GFX_DOOR_2_PART_8, &door_2 }, { -1, -1, -1, NULL } }; @@ -4164,7 +4269,7 @@ unsigned int MoveDoor(unsigned int door_state) { DX, DY, DXSIZE, DYSIZE }, { VX, VY, VXSIZE, VYSIZE } }; - static int door1 = DOOR_OPEN_1; + static int door1 = DOOR_CLOSE_1; static int door2 = DOOR_CLOSE_2; unsigned int door_delay = 0; unsigned int door_delay_value; @@ -4355,7 +4460,8 @@ unsigned int MoveDoor(unsigned int door_state) int sync_frame = kk_door * door_delay_value; int frame = getGraphicAnimationFrame(dpc->graphic, sync_frame); - getGraphicSource(dpc->graphic, frame, &bitmap, &g_src_x, &g_src_y); + getFixedGraphicSource(dpc->graphic, frame, &bitmap, + &g_src_x, &g_src_y); } // draw door panel @@ -4460,9 +4566,6 @@ unsigned int MoveDoor(unsigned int door_state) { BackToFront(); - if (game_status == GAME_MODE_MAIN) - DoAnimation(); - SkipUntilDelayReached(&door_delay, door_delay_value, &k, last_frame); current_move_delay += max_step_delay; @@ -4577,31 +4680,31 @@ static struct } toolbutton_info[NUM_TOOL_BUTTONS] = { { - IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes, + IMG_GFX_REQUEST_BUTTON_YES, &request.button.yes, TOOL_CTRL_ID_YES, "yes" }, { - IMG_REQUEST_BUTTON_GFX_NO, &request.button.no, + IMG_GFX_REQUEST_BUTTON_NO, &request.button.no, TOOL_CTRL_ID_NO, "no" }, { - IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm, + IMG_GFX_REQUEST_BUTTON_CONFIRM, &request.button.confirm, TOOL_CTRL_ID_CONFIRM, "confirm" }, { - IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1, + IMG_GFX_REQUEST_BUTTON_PLAYER_1, &request.button.player_1, TOOL_CTRL_ID_PLAYER_1, "player 1" }, { - IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2, + IMG_GFX_REQUEST_BUTTON_PLAYER_2, &request.button.player_2, TOOL_CTRL_ID_PLAYER_2, "player 2" }, { - IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3, + IMG_GFX_REQUEST_BUTTON_PLAYER_3, &request.button.player_3, TOOL_CTRL_ID_PLAYER_3, "player 3" }, { - IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4, + IMG_GFX_REQUEST_BUTTON_PLAYER_4, &request.button.player_4, TOOL_CTRL_ID_PLAYER_4, "player 4" } }; @@ -7930,42 +8033,38 @@ void CheckSaveEngineSnapshot_EM(byte action[MAX_PLAYERS], int frame, boolean any_player_snapping, boolean any_player_dropping) { - static boolean player_was_waiting = TRUE; - if (frame == 0 && !any_player_dropping) { - if (!player_was_waiting) + if (!local_player->was_waiting) { - if (!SaveEngineSnapshotToList()) + if (!CheckSaveEngineSnapshotToList()) return; - player_was_waiting = TRUE; + local_player->was_waiting = TRUE; } } else if (any_player_moving || any_player_snapping || any_player_dropping) { - player_was_waiting = FALSE; + local_player->was_waiting = FALSE; } } void CheckSaveEngineSnapshot_SP(boolean murphy_is_waiting, boolean murphy_is_dropping) { - static boolean player_was_waiting = TRUE; - if (murphy_is_waiting) { - if (!player_was_waiting) + if (!local_player->was_waiting) { - if (!SaveEngineSnapshotToList()) + if (!CheckSaveEngineSnapshotToList()) return; - player_was_waiting = TRUE; + local_player->was_waiting = TRUE; } } else { - player_was_waiting = FALSE; + local_player->was_waiting = FALSE; } } @@ -8097,9 +8196,6 @@ void ToggleFullscreenOrChangeWindowScalingIfNeeded() { boolean change_fullscreen = (setup.fullscreen != video.fullscreen_enabled); - boolean change_fullscreen_mode = (video.fullscreen_enabled && - !strEqual(setup.fullscreen_mode, - video.fullscreen_mode_current)); boolean change_window_scaling_percent = (!video.fullscreen_enabled && setup.window_scaling_percent != video.window_scaling_percent); @@ -8129,7 +8225,6 @@ void ToggleFullscreenOrChangeWindowScalingIfNeeded() #endif if (change_fullscreen || - change_fullscreen_mode || change_window_scaling_percent) { Bitmap *tmp_backbuffer = CreateBitmap(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH); @@ -8137,12 +8232,6 @@ void ToggleFullscreenOrChangeWindowScalingIfNeeded() /* save backbuffer content which gets lost when toggling fullscreen mode */ BlitBitmap(backbuffer, tmp_backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); - if (change_fullscreen_mode) - { - /* keep fullscreen, but change fullscreen mode (screen resolution) */ - video.fullscreen_enabled = FALSE; /* force new fullscreen mode */ - } - if (change_window_scaling_percent) { /* keep window mode, but change window scaling */ @@ -8178,6 +8267,50 @@ void JoinRectangles(int *x, int *y, int *width, int *height, *height = MAX(*height, height2); } +void SetAnimStatus(int anim_status_new) +{ + if (anim_status_new == GAME_MODE_MAIN) + anim_status_new = GAME_MODE_PSEUDO_MAINONLY; + + global.anim_status_next = anim_status_new; + + // directly set screen modes that are entered without fading + 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 = global.anim_status_next; +} + +void SetGameStatus(int game_status_new) +{ + game_status = game_status_new; + + SetAnimStatus(game_status_new); +} + +void SetFontStatus(int game_status_new) +{ + static int last_game_status = -1; + + if (game_status_new != -1) + { + // set game status for font use after storing last game status + last_game_status = game_status; + game_status = game_status_new; + } + else + { + // reset game status after font use from last stored game status + game_status = last_game_status; + } +} + +void ResetFontStatus() +{ + SetFontStatus(-1); +} + void ChangeViewportPropertiesIfNeeded() { int gfx_game_mode = game_status; @@ -8222,7 +8355,7 @@ void ChangeViewportPropertiesIfNeeded() int new_scr_fieldy_buffers = new_sysize / new_tilesize_var; boolean init_gfx_buffers = FALSE; boolean init_video_buffer = FALSE; - boolean init_gadgets_and_toons = FALSE; + boolean init_gadgets_and_anims = FALSE; boolean init_em_graphics = FALSE; if (new_win_xsize != WIN_XSIZE || @@ -8233,6 +8366,7 @@ void ChangeViewportPropertiesIfNeeded() init_video_buffer = TRUE; init_gfx_buffers = TRUE; + init_gadgets_and_anims = TRUE; // printf("::: video: init_video_buffer, init_gfx_buffers\n"); } @@ -8347,10 +8481,10 @@ void ChangeViewportPropertiesIfNeeded() TILESIZE_VAR = new_tilesize_var; init_gfx_buffers = TRUE; - init_gadgets_and_toons = TRUE; + init_gadgets_and_anims = TRUE; // printf("::: viewports: init_gfx_buffers\n"); - // printf("::: viewports: init_gadgets_and_toons\n"); + // printf("::: viewports: init_gadgets_and_anims\n"); } if (init_gfx_buffers) @@ -8377,12 +8511,12 @@ void ChangeViewportPropertiesIfNeeded() InitImageTextures(); } - if (init_gadgets_and_toons) + if (init_gadgets_and_anims) { - // printf("::: init_gadgets_and_toons\n"); + // printf("::: init_gadgets_and_anims\n"); InitGadgets(); - InitToons(); + InitGlobalAnimations(); } if (init_em_graphics)