X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Ftools.c;h=f7735c70b012d6d945adeef60a57266b63f955a9;hp=2ae872b475000ea3d2f0bddca41248f332f09f1c;hb=a7c06161253796a30a0237a7f5a044f459c8cf35;hpb=b33f14a8bdad5e3c9547c37b3854025daba761c7 diff --git a/src/tools.c b/src/tools.c index 2ae872b4..f7735c70 100644 --- a/src/tools.c +++ b/src/tools.c @@ -14,6 +14,7 @@ #include "libgame/libgame.h" #include "tools.h" +#include "init.h" #include "game.h" #include "events.h" #include "cartoons.h" @@ -107,6 +108,37 @@ void SetDrawtoField(int mode) { if (mode == DRAW_BUFFERED && setup.soft_scrolling) { +#if NEW_TILESIZE +#if NEW_SCROLL + FX = 2 * TILEX_VAR; + FY = 2 * TILEY_VAR; + BX1 = -2; + BY1 = -2; + BX2 = SCR_FIELDX + 1; + BY2 = SCR_FIELDY + 1; + redraw_x1 = 2; + redraw_y1 = 2; +#else + FX = TILEX_VAR; + FY = TILEY_VAR; + BX1 = -1; + BY1 = -1; + BX2 = SCR_FIELDX; + BY2 = SCR_FIELDY; + redraw_x1 = 1; + redraw_y1 = 1; +#endif +#else +#if NEW_SCROLL + FX = 2 * TILEX; + FY = 2 * TILEY; + BX1 = -2; + BY1 = -2; + BX2 = SCR_FIELDX + 1; + BY2 = SCR_FIELDY + 1; + redraw_x1 = 2; + redraw_y1 = 2; +#else FX = TILEX; FY = TILEY; BX1 = -1; @@ -115,10 +147,12 @@ void SetDrawtoField(int mode) BY2 = SCR_FIELDY; redraw_x1 = 1; redraw_y1 = 1; +#endif +#endif drawto_field = fieldbuffer; } - else /* DRAW_DIRECT, DRAW_BACKBUFFER */ + else /* DRAW_BACKBUFFER */ { FX = SX; FY = SY; @@ -129,7 +163,7 @@ void SetDrawtoField(int mode) redraw_x1 = 0; redraw_y1 = 0; - drawto_field = (mode == DRAW_DIRECT ? window : backbuffer); + drawto_field = backbuffer; } } @@ -144,7 +178,17 @@ void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height) /* blit playfield from scroll buffer to normal back buffer for fading in */ BlitScreenToBitmap_EM(backbuffer); } - else if (game_status == GAME_MODE_PLAYING && !game.envelope_active) + else if (game_status == GAME_MODE_PLAYING && + level.game_engine_type == GAME_ENGINE_TYPE_SP) + { + /* currently there is no partial redraw -- always redraw whole playfield */ + RedrawPlayfield_SP(TRUE); + + /* blit playfield from scroll buffer to normal back buffer for fading in */ + BlitScreenToBitmap_SP(backbuffer); + } + else if (game_status == GAME_MODE_PLAYING && + !game.envelope_active) { if (force_redraw) { @@ -154,23 +198,17 @@ void RedrawPlayfield(boolean force_redraw, int x, int y, int width, int height) height = gfx.sysize + 2 * TILEY; } - if (force_redraw || setup.direct_draw) + if (force_redraw) { int xx, yy; int x1 = (x - SX) / TILEX, y1 = (y - SY) / TILEY; int x2 = (x - SX + width) / TILEX, y2 = (y - SY + height) / TILEY; - if (setup.direct_draw) - SetDrawtoField(DRAW_BACKBUFFER); - for (xx = BX1; xx <= BX2; xx++) for (yy = BY1; yy <= BY2; yy++) if (xx >= x1 && xx <= x2 && yy >= y1 && yy <= y2) DrawScreenField(xx, yy); DrawAllPlayers(); - - if (setup.direct_draw) - SetDrawtoField(DRAW_DIRECT); } if (setup.soft_scrolling) @@ -241,8 +279,14 @@ void DrawMaskedBorder_ALL() void DrawMaskedBorder(int redraw_mask) { - /* do not draw masked screen borders when displaying title screens */ - if (effectiveGameStatus() == GAME_MODE_TITLE) + /* never draw masked screen borders on borderless screens */ + if (effectiveGameStatus() == GAME_MODE_LOADING || + effectiveGameStatus() == GAME_MODE_TITLE) + return; + + /* never draw masked screen borders when displaying request outside door */ + if (effectiveGameStatus() == GAME_MODE_PSEUDO_DOOR && + global.use_envelope_request) return; if (redraw_mask & REDRAW_ALL) @@ -260,23 +304,136 @@ void DrawMaskedBorder(int redraw_mask) } } +void BlitScreenToBitmap(Bitmap *target_bitmap) +{ + DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field); + int fx = FX, fy = FY; + +#if NEW_TILESIZE + int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0); + int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0); + int dx_var = dx * TILESIZE_VAR / TILESIZE; + int dy_var = dy * TILESIZE_VAR / TILESIZE; + int ffx, ffy; + + // fx += dx * TILESIZE_VAR / TILESIZE; + // fy += dy * TILESIZE_VAR / TILESIZE; +#else + fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0); + fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0); +#endif + + ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var; + ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var; + + if (EVEN(SCR_FIELDX)) + { + if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR) + fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR; + else + fx += (dx_var > 0 ? TILEX_VAR : 0); + } + else + { + fx += dx_var; + } + + if (EVEN(SCR_FIELDY)) + { + if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR) + fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR; + else + fy += (dy_var > 0 ? TILEY_VAR : 0); + } + else + { + fy += dy_var; + } + +#if 0 + printf("::: (%d, %d) [(%d / %d, %d / %d)] => %d, %d\n", + scroll_x, scroll_y, + SBX_Left, SBX_Right, + SBY_Upper, SBY_Lower, + fx, fy); +#endif + + if (border.draw_masked[GAME_MODE_PLAYING]) + { + if (buffer != backbuffer) + { + /* copy playfield buffer to backbuffer to add masked border */ + BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY); + DrawMaskedBorder(REDRAW_FIELD); + } + + BlitBitmap(backbuffer, target_bitmap, + REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, + REAL_SX, REAL_SY); + } + else + { + BlitBitmap(buffer, target_bitmap, fx, fy, SXSIZE, SYSIZE, SX, SY); + } +} + void BackToFront() { - int x,y; + int x, y; DrawBuffer *buffer = (drawto_field == window ? backbuffer : drawto_field); - if (setup.direct_draw && game_status == GAME_MODE_PLAYING) - redraw_mask &= ~REDRAW_MAIN; +#if 0 + printf("::: TILES TO REFRESH: %d\n", redraw_tiles); + for (x = 0; x < SCR_FIELDX; x++) + for (y = 0 ; y < SCR_FIELDY; y++) + if (redraw[redraw_x1 + x][redraw_y1 + y]) + printf("::: - %d, %d [%s]\n", + LEVELX(x), LEVELY(y), + EL_NAME(Feld[LEVELX(x)][LEVELY(y)])); +#endif if (redraw_mask & REDRAW_TILES && redraw_tiles > REDRAWTILES_THRESHOLD) redraw_mask |= REDRAW_FIELD; +#if 0 + // never redraw single tiles, always redraw the whole field + // (redrawing single tiles up to a certain threshold was faster on old, + // now legacy graphics, but slows things down on modern graphics now) + // UPDATE: this is now globally defined by value of REDRAWTILES_THRESHOLD + if (redraw_mask & REDRAW_TILES) + redraw_mask |= REDRAW_FIELD; +#endif + +#if 0 + /* !!! TEST ONLY !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */ + /* (force full redraw) */ + if (game_status == GAME_MODE_PLAYING) + redraw_mask |= REDRAW_FIELD; +#endif + if (redraw_mask & REDRAW_FIELD) redraw_mask &= ~REDRAW_TILES; if (redraw_mask == REDRAW_NONE) return; +#if 0 + printf("::: "); + if (redraw_mask & REDRAW_ALL) + printf("[REDRAW_ALL]"); + if (redraw_mask & REDRAW_FIELD) + printf("[REDRAW_FIELD]"); + if (redraw_mask & REDRAW_TILES) + printf("[REDRAW_TILES]"); + if (redraw_mask & REDRAW_DOOR_1) + printf("[REDRAW_DOOR_1]"); + if (redraw_mask & REDRAW_DOOR_2) + printf("[REDRAW_DOOR_2]"); + if (redraw_mask & REDRAW_FROM_BACKBUFFER) + printf("[REDRAW_FROM_BACKBUFFER]"); + printf(" [%d]\n", FrameCounter); +#endif + if (redraw_mask & REDRAW_TILES && game_status == GAME_MODE_PLAYING && border.draw_masked[GAME_MODE_PLAYING]) @@ -319,7 +476,7 @@ void BackToFront() SyncDisplay(); - /* prevent drawing masked border to backbuffer when using playfield buffer */ + /* never draw masked border to backbuffer when using playfield buffer */ if (game_status != GAME_MODE_PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER || buffer == backbuffer) @@ -336,6 +493,10 @@ void BackToFront() if (redraw_mask & REDRAW_FIELD) { +#if 0 + printf("::: REDRAW_FIELD\n"); +#endif + if (game_status != GAME_MODE_PLAYING || redraw_mask & REDRAW_FROM_BACKBUFFER) { @@ -344,51 +505,88 @@ void BackToFront() } else { +#if 1 + BlitScreenToBitmap(window); +#else int fx = FX, fy = FY; - if (setup.soft_scrolling) +#if NEW_TILESIZE + int dx = (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0); + int dy = (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0); + int dx_var = dx * TILESIZE_VAR / TILESIZE; + int dy_var = dy * TILESIZE_VAR / TILESIZE; + int ffx, ffy; + + // fx += dx * TILESIZE_VAR / TILESIZE; + // fy += dy * TILESIZE_VAR / TILESIZE; +#else + fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0); + fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0); +#endif + + /* !!! THIS WORKS !!! */ + + printf("::: %d, %d\n", scroll_x, scroll_y); + + ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var; + ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var; + + if (EVEN(SCR_FIELDX)) { - fx += (ScreenMovDir & (MV_LEFT | MV_RIGHT) ? ScreenGfxPos : 0); - fy += (ScreenMovDir & (MV_UP | MV_DOWN) ? ScreenGfxPos : 0); + if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR) + fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR; + else + fx += (dx > 0 ? TILEX_VAR : 0); } - - if (setup.soft_scrolling || - ABS(ScreenMovPos) + ScrollStepSize == TILEX || - ABS(ScreenMovPos) == ScrollStepSize || - redraw_tiles > REDRAWTILES_THRESHOLD) + else { - if (border.draw_masked[GAME_MODE_PLAYING]) - { - if (buffer != backbuffer) - { - /* copy playfield buffer to backbuffer to add masked border */ - BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY); - DrawMaskedBorder(REDRAW_FIELD); - } + fx += dx; + } - BlitBitmap(backbuffer, window, - REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, - REAL_SX, REAL_SY); - } + if (EVEN(SCR_FIELDY)) + { + if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR) + fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR; else + fy += (dy > 0 ? TILEY_VAR : 0); + } + else + { + fy += dy; + } + + if (border.draw_masked[GAME_MODE_PLAYING]) + { + if (buffer != backbuffer) { - BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY); + /* copy playfield buffer to backbuffer to add masked border */ + BlitBitmap(buffer, backbuffer, fx, fy, SXSIZE, SYSIZE, SX, SY); + DrawMaskedBorder(REDRAW_FIELD); } + BlitBitmap(backbuffer, window, + REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE, + REAL_SX, REAL_SY); + } + else + { + BlitBitmap(buffer, window, fx, fy, SXSIZE, SYSIZE, SX, SY); + } +#endif + #if 0 #ifdef DEBUG - printf("redrawing all (ScreenGfxPos == %d) because %s\n", - ScreenGfxPos, - (setup.soft_scrolling ? - "setup.soft_scrolling" : - ABS(ScreenGfxPos) + ScrollStepSize == TILEX ? - "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" : - ABS(ScreenGfxPos) == ScrollStepSize ? - "ABS(ScreenGfxPos) == ScrollStepSize" : - "redraw_tiles > REDRAWTILES_THRESHOLD")); + printf("redrawing all (ScreenGfxPos == %d) because %s\n", + ScreenGfxPos, + (setup.soft_scrolling ? + "setup.soft_scrolling" : + ABS(ScreenGfxPos) + ScrollStepSize == TILEX ? + "ABS(ScreenGfxPos) + ScrollStepSize == TILEX" : + ABS(ScreenGfxPos) == ScrollStepSize ? + "ABS(ScreenGfxPos) == ScrollStepSize" : + "redraw_tiles > REDRAWTILES_THRESHOLD")); #endif #endif - } } redraw_mask &= ~REDRAW_MAIN; @@ -418,12 +616,97 @@ void BackToFront() if (redraw_mask & REDRAW_TILES) { +#if 0 + printf("::: REDRAW_TILES\n"); +#endif + +#if NEW_TILESIZE + +#if 1 + InitGfxClipRegion(TRUE, SX, SY, SXSIZE, SYSIZE); + + { + int sx = SX; // - (EVEN(SCR_FIELDX) ? TILEX_VAR / 2 : 0); + int sy = SY; // + (EVEN(SCR_FIELDY) ? TILEY_VAR / 2 : 0); + + int dx = 0, dy = 0; + int dx_var = dx * TILESIZE_VAR / TILESIZE; + int dy_var = dy * TILESIZE_VAR / TILESIZE; + int ffx, ffy; + int fx = FX, fy = FY; + + int scr_fieldx = SCR_FIELDX + (EVEN(SCR_FIELDX) ? 2 : 0); + int scr_fieldy = SCR_FIELDY + (EVEN(SCR_FIELDY) ? 2 : 0); + + ffx = (scroll_x - SBX_Left) * TILEX_VAR + dx_var; + ffy = (scroll_y - SBY_Upper) * TILEY_VAR + dy_var; + + if (EVEN(SCR_FIELDX)) + { + if (ffx < SBX_Right * TILEX_VAR + TILEX_VAR / 2 + TILEX_VAR) + { + fx += dx_var - MIN(ffx, TILEX_VAR / 2) + TILEX_VAR; + + if (fx % TILEX_VAR) + sx -= TILEX_VAR / 2; + else + sx -= TILEX_VAR; + } + else + { + fx += (dx_var > 0 ? TILEX_VAR : 0); + } + } + + if (EVEN(SCR_FIELDY)) + { + if (ffy < SBY_Lower * TILEY_VAR + TILEY_VAR / 2 + TILEY_VAR) + { + fy += dy_var - MIN(ffy, TILEY_VAR / 2) + TILEY_VAR; + + if (fy % TILEY_VAR) + sy -= TILEY_VAR / 2; + else + sy -= TILEY_VAR; + } + else + { + fy += (dy_var > 0 ? TILEY_VAR : 0); + } + } + +#if 0 + printf("::: %d, %d, %d, %d\n", sx, sy, SCR_FIELDX, SCR_FIELDY); +#endif + + for (x = 0; x < scr_fieldx; x++) + for (y = 0 ; y < scr_fieldy; y++) + if (redraw[redraw_x1 + x][redraw_y1 + y]) + BlitBitmap(buffer, window, + FX + x * TILEX_VAR, FY + y * TILEY_VAR, + TILEX_VAR, TILEY_VAR, + sx + x * TILEX_VAR, sy + y * TILEY_VAR); + } + + InitGfxClipRegion(FALSE, -1, -1, -1, -1); +#else + for (x = 0; x < SCR_FIELDX; x++) + for (y = 0 ; y < SCR_FIELDY; y++) + if (redraw[redraw_x1 + x][redraw_y1 + y]) + BlitBitmap(buffer, window, + FX + x * TILEX_VAR, FY + y * TILEY_VAR, + TILEX_VAR, TILEY_VAR, + SX + x * TILEX_VAR, SY + y * TILEY_VAR); +#endif + +#else for (x = 0; x < SCR_FIELDX; x++) for (y = 0 ; y < SCR_FIELDY; y++) if (redraw[redraw_x1 + x][redraw_y1 + y]) BlitBitmap(buffer, window, FX + x * TILEX, FY + y * TILEY, TILEX, TILEY, SX + x * TILEX, SY + y * TILEY); +#endif } if (redraw_mask & REDRAW_FPS) /* display frames per second */ @@ -435,8 +718,12 @@ void BackToFront() if (!global.fps_slowdown) info1[0] = '\0'; - sprintf(text, "%.1f fps%s", global.frames_per_second, info1); + sprintf(text, "%04.1f fps%s", global.frames_per_second, info1); +#if 1 + DrawTextExt(window, SX + SXSIZE + SX, 0, text, FONT_TEXT_2, BLIT_OPAQUE); +#else DrawTextExt(window, SX, SY, text, FONT_TEXT_2, BLIT_OPAQUE); +#endif } FlushDisplay(); @@ -448,113 +735,80 @@ void BackToFront() redraw_mask = REDRAW_NONE; } -void FadeToFront() +static void FadeCrossSaveBackbuffer() { -#if 0 - long fading_delay = 300; - - if (setup.fading && (redraw_mask & REDRAW_FIELD)) - { -#endif - -#if 0 - int x,y; + BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); +} - ClearRectangle(window, REAL_SX,REAL_SY,FULL_SXSIZE,FULL_SYSIZE); - FlushDisplay(); +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; - for (i = 0; i < 2 * FULL_SYSIZE; i++) + if (fade_type == FADE_TYPE_FADE_OUT) + { + if (fade_type_skip != FADE_TYPE_NONE) { - for (y = 0; y < FULL_SYSIZE; y++) - { - BlitBitmap(backbuffer, window, - REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i); - } - FlushDisplay(); - Delay(10); - } -#endif - #if 0 - for (i = 1; i < FULL_SYSIZE; i+=2) - BlitBitmap(backbuffer, window, - REAL_SX,REAL_SY+i, FULL_SXSIZE,1, REAL_SX,REAL_SY+i); - FlushDisplay(); - Delay(fading_delay); + printf("::: skipping %d ... [%d] (X)\n", fade_mode, fade_type_skip); #endif -#if 0 - SetClipOrigin(clip_gc[PIX_FADEMASK], 0, 0); - BlitBitmapMasked(backbuffer, window, - REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, - REAL_SX,REAL_SY); - FlushDisplay(); - Delay(fading_delay); - - SetClipOrigin(clip_gc[PIX_FADEMASK], -1, -1); - BlitBitmapMasked(backbuffer, window, - REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, - REAL_SX,REAL_SY); - FlushDisplay(); - Delay(fading_delay); - - SetClipOrigin(clip_gc[PIX_FADEMASK], 0, -1); - BlitBitmapMasked(backbuffer, window, - REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, - REAL_SX,REAL_SY); - FlushDisplay(); - Delay(fading_delay); - - SetClipOrigin(clip_gc[PIX_FADEMASK], -1, 0); - BlitBitmapMasked(backbuffer, window, - REAL_SX,REAL_SY, FULL_SXSIZE,FULL_SYSIZE, - REAL_SX,REAL_SY); - FlushDisplay(); - Delay(fading_delay); + /* skip all fade operations until specified fade operation */ + if (fade_type & fade_type_skip) + fade_type_skip = FADE_TYPE_NONE; - redraw_mask &= ~REDRAW_MAIN; - } -#endif + return; + } - BackToFront(); -} + if (fading.fade_mode & FADE_TYPE_TRANSFORM) + { + FadeCrossSaveBackbuffer(); -void FadeExt(int fade_mask, int fade_mode) -{ - static int fade_mode_skip = FADE_MODE_NONE; - void (*draw_border_function)(void) = NULL; -#if 0 - Bitmap *bitmap = (fade_mode != FADE_MODE_FADE_IN ? bitmap_db_cross : NULL); -#else - Bitmap *bitmap = (fade_mode & FADE_TYPE_TRANSFORM ? bitmap_db_cross : NULL); -#endif - int x, y, width, height; - int fade_delay, post_delay; + return; + } + } redraw_mask |= fade_mask; - if (fade_mode & FADE_TYPE_SKIP) + if (fade_type == FADE_TYPE_SKIP) { #if 0 - printf("::: will skip %d ... [%d]\n", fade_mode, fade_mode_skip); + printf("::: will skip %d ... [%d]\n", fade_mode, fade_type_skip); #endif - fade_mode_skip = fade_mode; + fade_type_skip = fade_mode; return; } - if (fade_mode_skip & FADE_TYPE_SKIP) +#if 0 + printf("::: !!! FADING %d ... [%d] [%d]\n", fade_mode, fade_type, + fade_type_skip); +#endif + +#if 1 + fade_delay = fading.fade_delay; + post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0); +#endif + + if (fade_type_skip != FADE_TYPE_NONE) { #if 0 - printf("::: skipping %d ... [%d]\n", fade_mode, fade_mode_skip); + printf("::: skipping %d ... [%d]\n", fade_mode, fade_type_skip); #endif /* skip all fade operations until specified fade operation */ - if (fade_mode & fade_mode_skip) - fade_mode_skip = FADE_MODE_NONE; + if (fade_type & fade_type_skip) + fade_type_skip = FADE_TYPE_NONE; +#if 1 + fade_delay = 0; +#else return; +#endif } #if 1 @@ -566,7 +820,7 @@ void FadeExt(int fade_mask, int fade_mode) } #endif -#if 1 +#if 0 if (fading.fade_mode == FADE_MODE_NONE) { BackToFront(); @@ -575,17 +829,34 @@ void FadeExt(int fade_mask, int fade_mode) } #endif - if (fade_mask & REDRAW_FIELD) + /* !!! what about fade_mask == REDRAW_FIELD | REDRAW_ALL ??? !!! */ + +#if 0 + printf("::: NOW FADING %d ... [%d]\n", fade_mode, fade_type); +#endif + +#if 0 + if (fade_mask == REDRAW_NONE) + fade_mask = REDRAW_FIELD; +#endif + + // if (fade_mask & REDRAW_FIELD) + if (fade_mask == REDRAW_FIELD) { x = REAL_SX; y = REAL_SY; width = FULL_SXSIZE; height = FULL_SYSIZE; +#if 0 fade_delay = fading.fade_delay; post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0); +#endif - draw_border_function = DrawMaskedBorder_FIELD; + if (border.draw_masked_when_fading) + draw_border_function = DrawMaskedBorder_FIELD; /* update when fading */ + else + DrawMaskedBorder_FIELD(); /* draw once */ } else /* REDRAW_ALL */ { @@ -594,20 +865,35 @@ void FadeExt(int fade_mask, int fade_mode) width = WIN_XSIZE; height = WIN_YSIZE; +#if 0 fade_delay = fading.fade_delay; post_delay = (fade_mode == FADE_MODE_FADE_OUT ? fading.post_delay : 0); +#endif } #if 1 - if (!setup.fade_screens || fade_delay == 0) + if (!setup.fade_screens || + fade_delay == 0 || + fading.fade_mode == FADE_MODE_NONE) #else - if (!setup.fade_screens || fade_delay == 0 || fading.anim_mode == ANIM_NONE) + if (!setup.fade_screens || fade_delay == 0) #endif { if (fade_mode == FADE_MODE_FADE_OUT) + return; + +#if 0 + if (fade_mode == FADE_MODE_FADE_OUT && + fading.fade_mode != FADE_MODE_NONE) ClearRectangle(backbuffer, x, y, width, height); +#endif +#if 1 + BlitBitmap(backbuffer, window, x, y, width, height, x, y); + redraw_mask = REDRAW_NONE; +#else BackToFront(); +#endif return; } @@ -620,124 +906,22 @@ void FadeExt(int fade_mask, int fade_mode) void FadeIn(int fade_mask) { - global.border_status = game_status; - -#if 0 - global.fading_status = game_status; - - if (global.fading_type == TYPE_ENTER_MENU) - fading = menu.enter_menu; - else if (global.fading_type == TYPE_LEAVE_MENU) - fading = menu.leave_menu; - else if (global.fading_type == TYPE_ENTER_SCREEN) - fading = menu.enter_screen[global.fading_status]; - else if (global.fading_type == TYPE_LEAVE_SCREEN) - fading = menu.leave_screen[global.fading_status]; - - printf("::: FadeIn: %s [0x%08x] [%d]\n", - global.fading_type == TYPE_ENTER_MENU ? "enter_menu" : - global.fading_type == TYPE_LEAVE_MENU ? "leave_menu" : - global.fading_type == TYPE_ENTER_SCREEN ? "enter_screen" : - global.fading_type == TYPE_LEAVE_SCREEN ? "leave_screen" : "(?)", - global.fading_type, - global.fading_status); -#endif - -#if 1 - // printf("::: now fading in...\n"); - if (fading.fade_mode & FADE_TYPE_TRANSFORM) - FadeExt(fade_mask, fading.fade_mode); + FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_IN); else - FadeExt(fade_mask, FADE_MODE_FADE_IN); -#else -#if 1 - if (fading.fade_mode == FADE_MODE_CROSSFADE) - FadeExt(fade_mask, FADE_MODE_CROSSFADE); - else - FadeExt(fade_mask, FADE_MODE_FADE_IN); -#else - FadeExt(fade_mask, FADE_MODE_FADE_IN); -#endif -#endif + FadeExt(fade_mask, FADE_MODE_FADE_IN, FADE_TYPE_FADE_IN); } void FadeOut(int fade_mask) { -#if 0 - if (global.fading_type == TYPE_ENTER_MENU) - fading = menu.enter_menu; - else if (global.fading_type == TYPE_LEAVE_MENU) - fading = menu.leave_menu; - else if (global.fading_type == TYPE_ENTER_SCREEN) - fading = menu.enter_screen[global.fading_status]; - else if (global.fading_type == TYPE_LEAVE_SCREEN) - fading = menu.leave_screen[global.fading_status]; - - printf("::: FadeOut: %s [0x%08x] [%d]\n", - global.fading_type == TYPE_ENTER_MENU ? "enter_menu" : - global.fading_type == TYPE_LEAVE_MENU ? "leave_menu" : - global.fading_type == TYPE_ENTER_SCREEN ? "enter_screen" : - global.fading_type == TYPE_LEAVE_SCREEN ? "leave_screen" : "(?)", - global.fading_type, - global.fading_status); -#endif - -#if 1 - // printf("::: fading.fade_mode == %d\n", fading.fade_mode); - if (fading.fade_mode & FADE_TYPE_TRANSFORM) - FadeCrossSaveBackbuffer(); + FadeExt(fade_mask, fading.fade_mode, FADE_TYPE_FADE_OUT); else - FadeExt(fade_mask, FADE_MODE_FADE_OUT); -#else -#if 1 - if (fading.fade_mode == FADE_MODE_CROSSFADE) - FadeCrossSaveBackbuffer(); - else - FadeExt(fade_mask, FADE_MODE_FADE_OUT); -#else - FadeExt(fade_mask, FADE_MODE_FADE_OUT); -#endif -#endif -} - -void FadeCross(int fade_mask) -{ - FadeExt(fade_mask, FADE_MODE_CROSSFADE); -} - -void FadeCrossSaveBackbuffer() -{ - BlitBitmap(backbuffer, bitmap_db_cross, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); -} - -#if 0 -void FadeSetEnterMenu() -{ - global.fading_type = TYPE_ENTER_MENU; -} - -void FadeSetLeaveMenu() -{ - global.fading_type = TYPE_LEAVE_MENU; -} - -void FadeSetEnterScreen() -{ - global.fading_type = TYPE_ENTER_SCREEN; -} - -void FadeSetLeaveScreen() -{ - // global.fading_type = TYPE_LEAVE_SCREEN; + FadeExt(fade_mask, FADE_MODE_FADE_OUT, FADE_TYPE_FADE_OUT); - global.fading_type = (global.fading_type == TYPE_ENTER_SCREEN ? - TYPE_LEAVE_SCREEN : TYPE_LEAVE_MENU); + global.border_status = game_status; } -#else - static void FadeSetLeaveNext(struct TitleFadingInfo fading_leave, boolean set) { static struct TitleFadingInfo fading_leave_stored; @@ -778,15 +962,19 @@ void FadeSetEnterScreen() printf("::: storing leave_screen[%d]\n", game_status); #endif + FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */ +} + +void FadeSetNextScreen() +{ + fading = menu.next_screen; + #if 0 - printf("::: - %d, %d / %d, %d\n", - menu.enter_screen[game_status].fade_mode, - menu.enter_screen[game_status].fade_delay, - menu.leave_screen[game_status].fade_mode, - menu.leave_screen[game_status].fade_delay); + printf("::: storing next_screen\n"); #endif - FadeSetLeaveNext(menu.leave_screen[game_status], TRUE); /* store */ + // (do not overwrite fade mode set by FadeSetEnterScreen) + // FadeSetLeaveNext(fading, TRUE); /* (keep same fade mode) */ } void FadeSetLeaveScreen() @@ -798,8 +986,6 @@ void FadeSetLeaveScreen() FadeSetLeaveNext(menu.leave_screen[game_status], FALSE); /* recall */ } -#endif - void FadeSetFromType(int type) { if (type & TYPE_ENTER_SCREEN) @@ -819,12 +1005,12 @@ void FadeSetDisabled() void FadeSkipNextFadeIn() { - FadeExt(0, FADE_MODE_SKIP_FADE_IN); + FadeExt(0, FADE_MODE_SKIP_FADE_IN, FADE_TYPE_SKIP); } void FadeSkipNextFadeOut() { - FadeExt(0, FADE_MODE_SKIP_FADE_OUT); + FadeExt(0, FADE_MODE_SKIP_FADE_OUT, FADE_TYPE_SKIP); } void SetWindowBackgroundImageIfDefined(int graphic) @@ -871,8 +1057,22 @@ void SetDoorBackgroundImage(int graphic) void SetPanelBackground() { +#if 1 + struct GraphicInfo *gfx = &graphic_info[IMG_BACKGROUND_PANEL]; + +#if 1 + BlitBitmapTiled(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y, + gfx->width, gfx->height, 0, 0, DXSIZE, DYSIZE); +#else + /* (ClearRectangle() only needed if panel bitmap is smaller than panel) */ + ClearRectangle(bitmap_db_panel, DX, DY, DXSIZE, DYSIZE); + BlitBitmap(gfx->bitmap, bitmap_db_panel, gfx->src_x, gfx->src_y, + MIN(gfx->width, DXSIZE), MIN(gfx->height, DYSIZE), 0, 0); +#endif +#else BlitBitmap(graphic_info[IMG_GLOBAL_DOOR].bitmap, bitmap_db_panel, DOOR_GFX_PAGEX5, DOOR_GFX_PAGEY1, DXSIZE, DYSIZE, 0, 0); +#endif SetDoorBackgroundBitmap(bitmap_db_panel); } @@ -887,7 +1087,18 @@ void DrawBackground(int x, int y, int width, int height) ClearRectangleOnBackground(backbuffer, x, y, width, height); #endif +#if 1 + /* (this only works for the current arrangement of playfield and panels) */ + if (x < gfx.dx) + redraw_mask |= REDRAW_FIELD; + else if (y < gfx.vy) + redraw_mask |= REDRAW_DOOR_1; + else + redraw_mask |= REDRAW_DOOR_2; +#else + /* (this is just wrong (when drawing to one of the two door panel areas)) */ redraw_mask |= REDRAW_FIELD; +#endif } void DrawBackgroundForFont(int x, int y, int width, int height, int font_nr) @@ -910,7 +1121,7 @@ void DrawBackgroundForGraphic(int x, int y, int width, int height, int graphic) DrawBackground(x, y, width, height); } -void ClearWindow() +void ClearField() { /* !!! "drawto" might still point to playfield buffer here (see above) !!! */ /* (when entering hall of fame after playing) */ @@ -924,12 +1135,6 @@ void ClearWindow() } else SetDrawtoField(DRAW_BACKBUFFER); - - if (setup.direct_draw && game_status == GAME_MODE_PLAYING) - { - ClearRectangle(window, REAL_SX, REAL_SY, FULL_SXSIZE, FULL_SYSIZE); - SetDrawtoField(DRAW_DIRECT); - } } void MarkTileDirty(int x, int y) @@ -1014,8 +1219,9 @@ inline int getGraphicAnimationFrame(int graphic, int sync_frame) sync_frame); } -void getSizedGraphicSource(int graphic, int frame, int tilesize_raw, - Bitmap **bitmap, int *x, int *y) +void getSizedGraphicSourceExt(int graphic, int frame, int tilesize_raw, + Bitmap **bitmap, int *x, int *y, + boolean get_backside) { struct { @@ -1041,8 +1247,15 @@ void getSizedGraphicSource(int graphic, int frame, int tilesize_raw, int height_div = offset_calc[offset_calc_pos].height_div; int startx = src_bitmap->width * width_mult / width_div; int starty = src_bitmap->height * height_mult / height_div; +#if NEW_TILESIZE + int src_x = (g->src_x + (get_backside ? g->offset2_x : 0)) * + tilesize / TILESIZE; + int src_y = (g->src_y + (get_backside ? g->offset2_y : 0)) * + tilesize / TILESIZE; +#else int src_x = g->src_x * tilesize / TILESIZE; int src_y = g->src_y * tilesize / TILESIZE; +#endif int width = g->width * tilesize / TILESIZE; int height = g->height * tilesize / TILESIZE; int offset_x = g->offset_x * tilesize / TILESIZE; @@ -1075,6 +1288,25 @@ void getSizedGraphicSource(int graphic, int frame, int tilesize_raw, *y = starty + src_y; } +void getFixedGraphicSourceExt(int graphic, int frame, Bitmap **bitmap, + int *x, int *y, boolean get_backside) +{ + getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, + get_backside); +} + +void getSizedGraphicSource(int graphic, int frame, int tilesize_raw, + Bitmap **bitmap, int *x, int *y) +{ + getSizedGraphicSourceExt(graphic, frame, tilesize_raw, bitmap, x, y, FALSE); +} + +void getFixedGraphicSource(int graphic, int frame, + Bitmap **bitmap, int *x, int *y) +{ + getSizedGraphicSourceExt(graphic, frame, TILESIZE, bitmap, x, y, FALSE); +} + void getMiniGraphicSource(int graphic, Bitmap **bitmap, int *x, int *y) { #if 1 @@ -1097,6 +1329,12 @@ inline void getGraphicSourceExt(int graphic, int frame, Bitmap **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); +#if NEW_TILESIZE + if (TILESIZE_VAR != TILESIZE) + return getSizedGraphicSourceExt(graphic, frame, TILESIZE_VAR, bitmap, x, y, + get_backside); +#endif + *bitmap = g->bitmap; if (g->offset_y == 0) /* frames are ordered horizontally */ @@ -1138,7 +1376,28 @@ void DrawGraphic(int x, int y, int graphic, int frame) } #endif +#if NEW_TILESIZE + DrawGraphicExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, graphic, + frame); +#else DrawGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame); +#endif + MarkTileDirty(x, y); +} + +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"); + return; + } +#endif + + DrawFixedGraphicExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, + frame); MarkTileDirty(x, y); } @@ -1149,6 +1408,20 @@ void DrawGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic, int src_x, src_y; getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); +#if NEW_TILESIZE + BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX_VAR, TILEY_VAR, x, y); +#else + BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y); +#endif +} + +void DrawFixedGraphicExt(DrawBuffer *dst_bitmap, int x, int y, int graphic, + int frame) +{ + Bitmap *src_bitmap; + int src_x, src_y; + + getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); BlitBitmap(src_bitmap, dst_bitmap, src_x, src_y, TILEX, TILEY, x, y); } @@ -1163,8 +1436,29 @@ void DrawGraphicThruMask(int x, int y, int graphic, int frame) } #endif - DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y *TILEY, graphic, +#if NEW_TILESIZE + DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, + graphic, frame); +#else + DrawGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, frame); +#endif + MarkTileDirty(x, y); +} + +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"); + return; + } +#endif + + DrawFixedGraphicThruMaskExt(drawto_field, FX + x * TILEX, FY + y * TILEY, + graphic, frame); MarkTileDirty(x, y); } @@ -1176,6 +1470,24 @@ void DrawGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, int graphic, getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); + SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc, + dst_x - src_x, dst_y - src_y); +#if NEW_TILESIZE + BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX_VAR, TILEY_VAR, + dst_x, dst_y); +#else + BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y); +#endif +} + +void DrawFixedGraphicThruMaskExt(DrawBuffer *d, int dst_x, int dst_y, + int graphic, int frame) +{ + Bitmap *src_bitmap; + int src_x, src_y; + + getFixedGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); + SetClipOrigin(src_bitmap, src_bitmap->stored_clip_gc, dst_x - src_x, dst_y - src_y); BlitBitmapMasked(src_bitmap, d, src_x, src_y, TILEX, TILEY, dst_x, dst_y); @@ -1296,6 +1608,15 @@ inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy, } #endif +#if NEW_TILESIZE + width = width * TILESIZE_VAR / TILESIZE; + height = height * TILESIZE_VAR / TILESIZE; + cx = cx * TILESIZE_VAR / TILESIZE; + cy = cy * TILESIZE_VAR / TILESIZE; + dx = dx * TILESIZE_VAR / TILESIZE; + dy = dy * TILESIZE_VAR / TILESIZE; +#endif + if (width > 0 && height > 0) { getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); @@ -1303,8 +1624,13 @@ inline static void DrawGraphicShiftedNormal(int x, int y, int dx, int dy, src_x += cx; src_y += cy; +#if NEW_TILESIZE + dst_x = FX + x * TILEX_VAR + dx; + dst_y = FY + y * TILEY_VAR + dy; +#else dst_x = FX + x * TILEX + dx; dst_y = FY + y * TILEY + dy; +#endif if (mask_mode == USE_MASKING) { @@ -1328,26 +1654,64 @@ inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy, Bitmap *src_bitmap; int src_x, src_y; int dst_x, dst_y; +#if NEW_TILESIZE + int width = TILEX_VAR, height = TILEY_VAR; +#else int width = TILEX, height = TILEY; +#endif int x1 = x; int y1 = y; int x2 = x + SIGN(dx); int y2 = y + SIGN(dy); +#if 0 + /* !!! DOES NOT WORK FOR SLOW MOVEMENT !!! */ + int sync_frame = GfxFrame[LEVELX(x)][LEVELY(y)]; +#else + /* movement with two-tile animations must be sync'ed with movement position, + not with current GfxFrame (which can be higher when using slow movement) */ + int anim_pos = (dx ? ABS(dx) : ABS(dy)); int anim_frames = graphic_info[graphic].anim_frames; - int sync_frame = (dx ? ABS(dx) : ABS(dy)) * anim_frames / TILESIZE; +#if 1 + /* (we also need anim_delay here for movement animations with less frames) */ + int anim_delay = graphic_info[graphic].anim_delay; + int sync_frame = anim_pos * anim_frames * anim_delay / TILESIZE; +#else + int sync_frame = anim_pos * anim_frames / TILESIZE; +#endif +#endif boolean draw_start_tile = (cut_mode != CUT_ABOVE); /* only for falling! */ boolean draw_end_tile = (cut_mode != CUT_BELOW); /* only for falling! */ /* re-calculate animation frame for two-tile movement animation */ frame = getGraphicAnimationFrame(graphic, sync_frame); +#if 0 +#if 0 + printf("::: %d, %d, %d => %d [%d]\n", + anim_pos, anim_frames, anim_delay, sync_frame, graphic); +#else + printf("::: %d, %d => %d\n", + anim_pos, anim_frames, sync_frame); +#endif +#endif + +#if 0 + printf("::: %d [%d, %d] [%d] [%d]\n", frame, sync_frame, dy, + GfxFrame[LEVELX(x)][LEVELY(y)], mask_mode); +#endif + /* check if movement start graphic inside screen area and should be drawn */ if (draw_start_tile && IN_SCR_FIELD(x1, y1)) { getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, TRUE); +#if NEW_TILESIZE + dst_x = FX + x1 * TILEX_VAR; + dst_y = FY + y1 * TILEY_VAR; +#else dst_x = FX + x1 * TILEX; dst_y = FY + y1 * TILEY; +#endif if (mask_mode == USE_MASKING) { @@ -1368,8 +1732,13 @@ inline static void DrawGraphicShiftedDouble(int x, int y, int dx, int dy, { getGraphicSourceExt(graphic, frame, &src_bitmap, &src_x, &src_y, FALSE); +#if NEW_TILESIZE + dst_x = FX + x2 * TILEX_VAR; + dst_y = FY + y2 * TILEY_VAR; +#else dst_x = FX + x2 * TILEX; dst_y = FY + y2 * TILEY; +#endif if (mask_mode == USE_MASKING) { @@ -1497,14 +1866,242 @@ void DrawLevelFieldThruMask(int x, int y) DrawLevelElementExt(x, y, 0, 0, Feld[x][y], NO_CUTTING, USE_MASKING); } -static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) +/* !!! implementation of quicksand is totally broken !!! */ +#define IS_CRUMBLED_TILE(x, y, e) \ + (GFX_CRUMBLED(e) && (!IN_LEV_FIELD(x, y) || \ + !IS_MOVING(x, y) || \ + (e) == EL_QUICKSAND_EMPTYING || \ + (e) == EL_QUICKSAND_FAST_EMPTYING)) + +static void DrawLevelFieldCrumbledInnerCorners(int x, int y, int dx, int dy, + int graphic) { Bitmap *src_bitmap; int src_x, src_y; + int width, height, cx, cy; + int sx = SCREENX(x), sy = SCREENY(y); + int crumbled_border_size = graphic_info[graphic].border_size; + int i; + + getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); + + for (i = 1; i < 4; i++) + { + int dxx = (i & 1 ? dx : 0); + int dyy = (i & 2 ? dy : 0); + int xx = x + dxx; + int yy = y + dyy; + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + boolean same = (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class); + + /* return if check prevents inner corner */ + if (same == (dxx == dx && dyy == dy)) + return; + } + + /* if we reach this point, we have an inner corner */ + + getGraphicSource(graphic, 1, &src_bitmap, &src_x, &src_y); + +#if NEW_TILESIZE + width = crumbled_border_size * TILESIZE_VAR / TILESIZE; + height = crumbled_border_size * TILESIZE_VAR / TILESIZE; + cx = (dx > 0 ? TILEX - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE; + cy = (dy > 0 ? TILEY - crumbled_border_size : 0) * TILESIZE_VAR / TILESIZE; + + BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, + width, height, FX + sx * TILEX_VAR + cx, FY + sy * TILEY_VAR + cy); +#else + width = crumbled_border_size; + height = crumbled_border_size; + cx = (dx > 0 ? TILEX - crumbled_border_size : 0); + cy = (dy > 0 ? TILEY - crumbled_border_size : 0); + + BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); +#endif +} + +static void DrawLevelFieldCrumbledBorders(int x, int y, int graphic, int frame, + int dir) +{ + Bitmap *src_bitmap; + int src_x, src_y; + int width, height, bx, by, cx, cy; int sx = SCREENX(x), sy = SCREENY(y); - int element; - int width, height, cx, cy, i; int crumbled_border_size = graphic_info[graphic].border_size; + int i; + + getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); + + /* draw simple, sloppy, non-corner-accurate crumbled border */ + +#if 1 + width = (dir == 1 || dir == 2 ? crumbled_border_size : TILEX); + height = (dir == 0 || dir == 3 ? crumbled_border_size : TILEY); + cx = (dir == 2 ? TILEX - crumbled_border_size : 0); + cy = (dir == 3 ? TILEY - crumbled_border_size : 0); +#else + if (dir == 1 || dir == 2) /* left or right crumbled border */ + { + width = crumbled_border_size; + height = TILEY; + cx = (dir == 2 ? TILEX - crumbled_border_size : 0); + cy = 0; + } + else /* top or bottom crumbled border */ + { + width = TILEX; + height = crumbled_border_size; + cx = 0; + cy = (dir == 3 ? TILEY - crumbled_border_size : 0); + } +#endif + +#if NEW_TILESIZE + BlitBitmap(src_bitmap, drawto_field, + src_x + cx * TILESIZE_VAR / TILESIZE, + src_y + cy * TILESIZE_VAR / TILESIZE, + width * TILESIZE_VAR / TILESIZE, + height * TILESIZE_VAR / TILESIZE, + FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE, + FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE); +#else + BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); +#endif + + /* (remaining middle border part must be at least as big as corner part) */ + if (!(graphic_info[graphic].style & STYLE_ACCURATE_BORDERS) || + crumbled_border_size >= TILESIZE / 3) + return; + + /* correct corners of crumbled border, if needed */ + +#if 1 + for (i = -1; i <= 1; i+=2) + { + int xx = x + (dir == 0 || dir == 3 ? i : 0); + int yy = y + (dir == 1 || dir == 2 ? i : 0); + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) + { + /* no crumbled corner, but continued crumbled border */ + + int c1 = (dir == 2 || dir == 3 ? TILESIZE - crumbled_border_size : 0); + int c2 = (i == 1 ? TILESIZE - crumbled_border_size : 0); + int b1 = (i == 1 ? crumbled_border_size : + TILESIZE - 2 * crumbled_border_size); + + width = crumbled_border_size; + height = crumbled_border_size; + + if (dir == 1 || dir == 2) + { + cx = c1; + cy = c2; + bx = cx; + by = b1; + } + else + { + cx = c2; + cy = c1; + bx = b1; + by = cy; + } + +#if NEW_TILESIZE + BlitBitmap(src_bitmap, drawto_field, + src_x + bx * TILESIZE_VAR / TILESIZE, + src_y + by * TILESIZE_VAR / TILESIZE, + width * TILESIZE_VAR / TILESIZE, + height * TILESIZE_VAR / TILESIZE, + FX + sx * TILEX_VAR + cx * TILESIZE_VAR / TILESIZE, + FY + sy * TILEY_VAR + cy * TILESIZE_VAR / TILESIZE); +#else + BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); +#endif + } + } +#else + if (dir == 1 || dir == 2) /* left or right crumbled border */ + { + for (i = -1; i <= 1; i+=2) + { + int xx = x; + int yy = y + i; + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) + { + /* no crumbled corner, but continued crumbled border */ + + width = crumbled_border_size; + height = crumbled_border_size; + cx = (dir == 2 ? TILEX - crumbled_border_size : 0); + cy = (i == 1 ? TILEY - crumbled_border_size : 0); + bx = cx; + by = (i == 1 ? crumbled_border_size : + TILEY - 2 * crumbled_border_size); + + BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + } + } + } + else /* top or bottom crumbled border */ + { + for (i = -1; i <= 1; i+=2) + { + int xx = x + i; + int yy = y; + int element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : + BorderElement); + + /* check if neighbour field is of same crumble type */ + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) + { + /* no crumbled corner, but continued crumbled border */ + + width = crumbled_border_size; + height = crumbled_border_size; + cx = (i == 1 ? TILEX - crumbled_border_size : 0); + cy = (dir == 3 ? TILEY - crumbled_border_size : 0); + bx = (i == 1 ? crumbled_border_size : + TILEX - 2 * crumbled_border_size); + by = cy; + + BlitBitmap(src_bitmap, drawto_field, src_x + bx, src_y + by, + width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + } + } + } +#endif +} + +static void DrawLevelFieldCrumbledExt(int x, int y, int graphic, int frame) +{ + int sx = SCREENX(x), sy = SCREENY(y); + int element; + int i; static int xy[4][2] = { { 0, -1 }, @@ -1519,13 +2116,11 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) element = TILE_GFX_ELEMENT(x, y); /* crumble field itself */ - if (GFX_CRUMBLED(element) && !IS_MOVING(x, y)) + if (IS_CRUMBLED_TILE(x, y, element)) { if (!IN_SCR_FIELD(sx, sy)) return; - getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); - for (i = 0; i < 4; i++) { int xx = x + xy[i][0]; @@ -1534,32 +2129,35 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) element = (IN_LEV_FIELD(xx, yy) ? TILE_GFX_ELEMENT(xx, yy) : BorderElement); - /* check if neighbour field is of same type */ - if (GFX_CRUMBLED(element) && !IS_MOVING(xx, yy)) + /* check if neighbour field is of same crumble type */ +#if 1 + if (IS_CRUMBLED_TILE(xx, yy, element) && + graphic_info[graphic].class == + graphic_info[el_act2crm(element, ACTION_DEFAULT)].class) continue; +#else + if (IS_CRUMBLED_TILE(xx, yy, element)) + continue; +#endif - if (i == 1 || i == 2) - { - width = crumbled_border_size; - height = TILEY; - cx = (i == 2 ? TILEX - crumbled_border_size : 0); - cy = 0; - } - else + DrawLevelFieldCrumbledBorders(x, y, graphic, frame, i); + } + + if ((graphic_info[graphic].style & STYLE_INNER_CORNERS) && + graphic_info[graphic].anim_frames == 2) + { + for (i = 0; i < 4; i++) { - width = TILEX; - height = crumbled_border_size; - cx = 0; - cy = (i == 3 ? TILEY - crumbled_border_size : 0); - } + int dx = (i & 1 ? +1 : -1); + int dy = (i & 2 ? +1 : -1); - BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, - width, height, FX + sx * TILEX + cx, FY + sy * TILEY + cy); + DrawLevelFieldCrumbledInnerCorners(x, y, dx, dy, graphic); + } } MarkTileDirty(sx, sy); } - else /* crumble neighbour fields */ + else /* center field not crumbled -- crumble neighbour fields */ { for (i = 0; i < 4; i++) { @@ -1569,8 +2167,7 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) int syy = sy + xy[i][1]; if (!IN_LEV_FIELD(xx, yy) || - !IN_SCR_FIELD(sxx, syy) || - IS_MOVING(xx, yy)) + !IN_SCR_FIELD(sxx, syy)) continue; if (Feld[xx][yy] == EL_ELEMENT_SNAPPING) @@ -1578,38 +2175,19 @@ static void DrawLevelFieldCrumbledSandExt(int x, int y, int graphic, int frame) element = TILE_GFX_ELEMENT(xx, yy); - if (!GFX_CRUMBLED(element)) + if (!IS_CRUMBLED_TILE(xx, yy, element)) continue; graphic = el_act2crm(element, ACTION_DEFAULT); - crumbled_border_size = graphic_info[graphic].border_size; - getGraphicSource(graphic, frame, &src_bitmap, &src_x, &src_y); - - if (i == 1 || i == 2) - { - width = crumbled_border_size; - height = TILEY; - cx = (i == 1 ? TILEX - crumbled_border_size : 0); - cy = 0; - } - else - { - width = TILEX; - height = crumbled_border_size; - cx = 0; - cy = (i == 0 ? TILEY - crumbled_border_size : 0); - } - - BlitBitmap(src_bitmap, drawto_field, src_x + cx, src_y + cy, - width, height, FX + sxx * TILEX + cx, FY + syy * TILEY + cy); + DrawLevelFieldCrumbledBorders(xx, yy, graphic, 0, 3 - i); MarkTileDirty(sxx, syy); } } } -void DrawLevelFieldCrumbledSand(int x, int y) +void DrawLevelFieldCrumbled(int x, int y) { int graphic; @@ -1628,7 +2206,7 @@ void DrawLevelFieldCrumbledSand(int x, int y) GfxElement[x][y] != EL_UNDEFINED && GFX_CRUMBLED(GfxElement[x][y])) { - DrawLevelFieldCrumbledSandDigging(x, y, GfxDir[x][y], GfxFrame[x][y]); + DrawLevelFieldCrumbledDigging(x, y, GfxDir[x][y], GfxFrame[x][y]); return; } @@ -1640,11 +2218,11 @@ void DrawLevelFieldCrumbledSand(int x, int y) graphic = el_act2crm(Feld[x][y], ACTION_DEFAULT); #endif - DrawLevelFieldCrumbledSandExt(x, y, graphic, 0); + DrawLevelFieldCrumbledExt(x, y, graphic, 0); } -void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction, - int step_frame) +void DrawLevelFieldCrumbledDigging(int x, int y, int direction, + int step_frame) { int graphic1 = el_act_dir2img(GfxElement[x][y], ACTION_DIGGING, direction); int graphic2 = el_act_dir2crm(GfxElement[x][y], ACTION_DIGGING, direction); @@ -1653,10 +2231,10 @@ void DrawLevelFieldCrumbledSandDigging(int x, int y, int direction, int sx = SCREENX(x), sy = SCREENY(y); DrawGraphic(sx, sy, graphic1, frame1); - DrawLevelFieldCrumbledSandExt(x, y, graphic2, frame2); + DrawLevelFieldCrumbledExt(x, y, graphic2, frame2); } -void DrawLevelFieldCrumbledSandNeighbours(int x, int y) +void DrawLevelFieldCrumbledNeighbours(int x, int y) { int sx = SCREENX(x), sy = SCREENY(y); static int xy[4][2] = @@ -1711,7 +2289,7 @@ static int getBorderElement(int x, int y) void DrawScreenElement(int x, int y, int element) { DrawScreenElementExt(x, y, 0, 0, element, NO_CUTTING, NO_MASKING); - DrawLevelFieldCrumbledSand(LEVELX(x), LEVELY(y)); + DrawLevelFieldCrumbled(LEVELX(x), LEVELY(y)); } void DrawLevelElement(int x, int y, int element) @@ -1733,6 +2311,7 @@ void DrawScreenField(int x, int y) element = getBorderElement(lx, ly); DrawScreenElement(x, y, element); + return; } @@ -1758,8 +2337,22 @@ void DrawScreenField(int x, int y) element == EL_DC_MAGIC_WALL_FILLING) cut_mode = CUT_BELOW; +#if 0 + if (lx == 9 && ly == 1) + printf("::: %s [%d] [%d, %d] [%d]\n", + EL_NAME(TILE_GFX_ELEMENT(lx, ly)), + el_act2crm(TILE_GFX_ELEMENT(lx, ly), ACTION_DEFAULT), + element_info[EL_QUICKSAND_EMPTYING].graphic[ACTION_DEFAULT], + element_info[EL_QUICKSAND_EMPTYING].crumbled[ACTION_DEFAULT], + GFX_CRUMBLED(TILE_GFX_ELEMENT(lx, ly))); +#endif + if (cut_mode == CUT_ABOVE) +#if 1 + DrawScreenElement(x, y, element); +#else DrawScreenElementShifted(x, y, 0, 0, element, NO_CUTTING); +#endif else DrawScreenElement(x, y, EL_EMPTY); @@ -1768,8 +2361,16 @@ void DrawScreenField(int x, int y) else if (cut_mode == NO_CUTTING) DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], element, cut_mode); else + { DrawScreenElementShifted(x, y, 0, MovPos[lx][ly], content, cut_mode); +#if 1 + if (cut_mode == CUT_BELOW && + IN_LEV_FIELD(lx, ly + 1) && IN_SCR_FIELD(x, y + 1)) + DrawLevelElement(lx, ly + 1, element); +#endif + } + if (content == EL_ACID) { int dir = MovDir[lx][ly]; @@ -1882,7 +2483,7 @@ void DrawEnvelopeBackground(int envelope_nr, int startx, int starty, int inner_sy = (height >= 3 * font_height ? font_height : 0); boolean draw_masked = graphic_info[graphic].draw_masked; - getGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); + getFixedGraphicSource(graphic, 0, &src_bitmap, &src_x, &src_y); if (src_bitmap == NULL || width < font_width || height < font_height) { @@ -1914,14 +2515,97 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND); boolean ffwd_delay = (tape.playing && tape.fast_forward); boolean no_delay = (tape.warp_forward); - unsigned long anim_delay = 0; + unsigned int anim_delay = 0; + int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay); + int anim_delay_value = (no_delay ? 0 : frame_delay_value); + 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[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; + int yend = (anim_mode != ANIM_DEFAULT ? max_ysize : 0); + int xstep = (xstart < xend ? 1 : 0); + int ystep = (ystart < yend || xstep == 0 ? 1 : 0); + int x, y; + + for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep) + { + int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2; + int ysize = (action == ACTION_CLOSING ? yend - (y - ystart) : y) + 2; + int sx = (SXSIZE - xsize * font_width) / 2; + int sy = (SYSIZE - ysize * font_height) / 2; + int xx, yy; + + SetDrawtoField(DRAW_BUFFERED); + +#if 1 + BlitScreenToBitmap(backbuffer); +#else + BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY); +#endif + + SetDrawtoField(DRAW_BACKBUFFER); + + for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++) + DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr); + +#if 1 + DrawTextBuffer(SX + sx + font_width, SY + 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); +#else + DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height, + level.envelope[envelope_nr].text, font_nr, max_xsize, + xsize - 2, ysize - 2, mask_mode); +#endif + + redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + BackToFront(); + + WaitUntilDelayReached(&anim_delay, anim_delay_value / 2); + } +} + +void AnimateEnvelopeDoor(char *text, int anim_mode, int action) +{ +#if 1 + int envelope_nr = 0; +#endif + int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr; + Bitmap *src_bitmap = graphic_info[graphic].bitmap; + int mask_mode = (src_bitmap != NULL ? BLIT_MASKED : BLIT_ON_BACKGROUND); + boolean ffwd_delay = (tape.playing && tape.fast_forward); + boolean no_delay = (tape.warp_forward); + unsigned int anim_delay = 0; int frame_delay_value = (ffwd_delay ? FfwdFrameDelay : GameFrameDelay); int anim_delay_value = (no_delay ? 0 : frame_delay_value); +#if 1 + int max_word_len = maxWordLengthInString(text); + int font_nr = (max_word_len > 7 ? FONT_TEXT_1 : FONT_TEXT_2); +#else int font_nr = FONT_ENVELOPE_1 + envelope_nr; +#endif int font_width = getFontWidth(font_nr); int font_height = getFontHeight(font_nr); +#if 1 + +#if 1 + int max_xsize = DXSIZE / font_width; + int max_ysize = DYSIZE / font_height; +#else + int max_xsize = 7; /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */ + int max_ysize = 13; /* tools.c: MAX_REQUEST_LINES == 13 */ +#endif + +#else int max_xsize = level.envelope[envelope_nr].xsize; int max_ysize = level.envelope[envelope_nr].ysize; +#endif int xstart = (anim_mode & ANIM_VERTICAL ? max_xsize : 0); int ystart = (anim_mode & ANIM_HORIZONTAL ? max_ysize : 0); int xend = max_xsize; @@ -1930,6 +2614,54 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) int ystep = (ystart < yend || xstep == 0 ? 1 : 0); int x, y; +#if 1 + char *text_ptr; + char *text_copy = getStringCopy(text); +#else +#if 1 + font_nr = FONT_TEXT_2; + + if (maxWordLengthInString(text) > 7) /* MAX_REQUEST_LINE_FONT1_LEN == 7 */ + { + max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */ + font_nr = FONT_TEXT_1; + } +#else + int max_word_len = 0; + char *text_ptr; + char *text_copy = getStringCopy(text); + + font_nr = FONT_TEXT_2; + + for (text_ptr = text; *text_ptr; text_ptr++) + { + max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0); + + if (max_word_len > 7) /* tools.c: MAX_REQUEST_LINE_FONT1_LEN == 7 */ + { + max_xsize = 10; /* tools.c: MAX_REQUEST_LINE_FONT2_LEN == 10 */ + font_nr = FONT_TEXT_1; + + break; + } + } +#endif +#endif + +#if 1 + for (text_ptr = text_copy; *text_ptr; text_ptr++) + if (*text_ptr == ' ') + *text_ptr = '\n'; +#endif + +#if 1 + dDX = SX + (SXSIZE - DXSIZE) / 2 - DX; + dDY = SY + (SYSIZE - DYSIZE) / 2 - DY; +#else + dDX = SX + SXSIZE / 2 - max_xsize * font_width / 2 - DX; + dDY = SY + SYSIZE / 2 - max_ysize * font_height / 2 - DY; +#endif + for (x = xstart, y = ystart; x <= xend && y <= yend; x += xstep, y += ystep) { int xsize = (action == ACTION_CLOSING ? xend - (x - xstart) : x) + 2; @@ -1938,32 +2670,85 @@ void AnimateEnvelope(int envelope_nr, int anim_mode, int action) int sy = (SYSIZE - ysize * font_height) / 2; int xx, yy; +#if 1 + BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); +#else SetDrawtoField(DRAW_BUFFERED); +#if 1 + BlitScreenToBitmap(backbuffer); +#else BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY); +#endif SetDrawtoField(DRAW_BACKBUFFER); +#endif for (yy = 0; yy < ysize; yy++) for (xx = 0; xx < xsize; xx++) DrawEnvelopeBackground(envelope_nr, sx,sy, xx,yy, xsize, ysize, font_nr); #if 1 + +#if 1 + DrawTextBuffer(SX + sx + font_width, SY + sy + font_height + 8, + text_copy, font_nr, max_xsize, + xsize - 2, ysize - 2, 2, mask_mode, + FALSE, TRUE, FALSE); +#else DrawTextBuffer(SX + sx + font_width, SY + sy + font_height, level.envelope[envelope_nr].text, font_nr, max_xsize, - xsize - 2, ysize - 2, mask_mode, + xsize - 2, ysize - 2, 0, mask_mode, level.envelope[envelope_nr].autowrap, level.envelope[envelope_nr].centered, FALSE); +#endif + #else DrawTextToTextArea(SX + sx + font_width, SY + sy + font_height, level.envelope[envelope_nr].text, font_nr, max_xsize, xsize - 2, ysize - 2, mask_mode); #endif + /* copy request gadgets to door backbuffer */ +#if 1 + if ((ysize - 2) > 13) + BlitBitmap(bitmap_db_door, drawto, + DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2, + DOOR_GFX_PAGEY1 + 13 * font_height, + (xsize - 2) * font_width, + (ysize - 2 - 13) * font_height, + SX + sx + font_width, + SY + sy + font_height * (1 + 13)); +#else + if ((ysize - 2) > 13) + BlitBitmap(bitmap_db_door, drawto, + DOOR_GFX_PAGEX1 + (DXSIZE - (xsize - 2) * font_width) / 2, + DOOR_GFX_PAGEY1 + 13 * font_height, + (xsize - 2) * font_width, + (ysize - 2 - 13) * font_height, + SX + sx + font_width, + SY + sy + font_height * (1 + 13)); +#endif + +#if 1 + redraw_mask = REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; + // redraw_mask |= REDRAW_ALL | REDRAW_FROM_BACKBUFFER; +#else redraw_mask |= REDRAW_FIELD | REDRAW_FROM_BACKBUFFER; +#endif + +#if 1 + DoAnimation(); BackToFront(); +#else + BackToFront(); +#endif WaitUntilDelayReached(&anim_delay, anim_delay_value / 2); } + +#if 1 + free(text_copy); +#endif } void ShowEnvelope(int envelope_nr) @@ -2010,6 +2795,127 @@ void ShowEnvelope(int envelope_nr) BackToFront(); } +void ShowEnvelopeDoor(char *text, int action) +{ +#if 1 + int last_game_status = game_status; /* save current game status */ + // int last_draw_background_mask = gfx.draw_background_mask; + int envelope_nr = 0; +#endif + int element = EL_ENVELOPE_1 + envelope_nr; + int graphic = IMG_BACKGROUND_ENVELOPE_1 + envelope_nr; + int sound_opening = element_info[element].sound[ACTION_OPENING]; + int sound_closing = element_info[element].sound[ACTION_CLOSING]; +#if 0 + boolean ffwd_delay = (tape.playing && tape.fast_forward); + boolean no_delay = (tape.warp_forward); + int normal_delay_value = ONE_SECOND_DELAY / (ffwd_delay ? 2 : 1); + int wait_delay_value = (no_delay ? 0 : normal_delay_value); +#endif + 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); + +#if 1 + if (game_status == GAME_MODE_PLAYING) + { + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + BlitScreenToBitmap_EM(backbuffer); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + BlitScreenToBitmap_SP(backbuffer); + else + { + BlitBitmap(fieldbuffer, backbuffer, FX, FY, SXSIZE, SYSIZE, SX, SY); + } + } + + SetDrawtoField(DRAW_BACKBUFFER); + + // SetDrawBackgroundMask(REDRAW_NONE); + + if (action == ACTION_OPENING) + { + BlitBitmap(backbuffer, bitmap_db_store, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + + if (game_status != GAME_MODE_MAIN) + InitAnimation(); + } + + /* force DOOR font inside door area */ + game_status = GAME_MODE_PSEUDO_DOOR; +#endif + + game.envelope_active = TRUE; /* needed for RedrawPlayfield() events */ + + if (action == ACTION_OPENING) + { + PlayMenuSoundStereo(sound_opening, SOUND_MIDDLE); + + if (anim_mode == ANIM_DEFAULT) + AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_OPENING); + + AnimateEnvelopeDoor(text, main_anim_mode, ACTION_OPENING); + +#if 0 + if (tape.playing) + Delay(wait_delay_value); + else + WaitForEventToContinue(); +#endif + } + else + { + PlayMenuSoundStereo(sound_closing, SOUND_MIDDLE); + + if (anim_mode != ANIM_NONE) + AnimateEnvelopeDoor(text, main_anim_mode, ACTION_CLOSING); + + if (anim_mode == ANIM_DEFAULT) + AnimateEnvelopeDoor(text, ANIM_DEFAULT, ACTION_CLOSING); + } + + game.envelope_active = FALSE; + +#if 1 + // game_status = last_game_status; /* restore current game status */ + + if (action == ACTION_CLOSING) + { + if (game_status != GAME_MODE_MAIN) + StopAnimation(); + + BlitBitmap(bitmap_db_store, backbuffer, 0, 0, WIN_XSIZE, WIN_YSIZE, 0, 0); + } +#else + SetDrawtoField(DRAW_BUFFERED); +#endif + + // SetDrawBackgroundMask(last_draw_background_mask); + +#if 1 + redraw_mask = REDRAW_FIELD; + // redraw_mask |= REDRAW_ALL; +#else + redraw_mask |= REDRAW_FIELD; +#endif + +#if 1 + if (game_status == GAME_MODE_MAIN) + DoAnimation(); + + BackToFront(); + + /* (important: after "BackToFront()", but before "SetDrawtoField()") */ + game_status = last_game_status; /* restore current game status */ + + if (game_status == GAME_MODE_PLAYING && + level.game_engine_type == GAME_ENGINE_TYPE_RND) + SetDrawtoField(DRAW_BUFFERED); +#else + BackToFront(); +#endif +} + void DrawPreviewElement(int dst_x, int dst_y, int element, int tilesize) { Bitmap *src_bitmap; @@ -2024,8 +2930,14 @@ void DrawLevel() { int x,y; +#if 1 + SetMainBackgroundImage(IMG_BACKGROUND_PLAYING); + SetDrawBackgroundMask(REDRAW_FIELD); +#else SetDrawBackgroundMask(REDRAW_NONE); - ClearWindow(); +#endif + + ClearField(); for (x = BX1; x <= BX2; x++) for (y = BY1; y <= BY2; y++) @@ -2183,11 +3095,11 @@ static void DrawPreviewLevelLabelExt(int mode) void DrawPreviewLevel(boolean restart) { - static unsigned long scroll_delay = 0; - static unsigned long label_delay = 0; + static unsigned int scroll_delay = 0; + static unsigned int label_delay = 0; static int from_x, from_y, scroll_direction; static int label_state, label_counter; - unsigned long scroll_delay_value = preview.step_delay; + unsigned int 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); @@ -2378,6 +3290,18 @@ inline void DrawGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, DrawGraphicExt(dst_bitmap, x, y, graphic, frame); } +inline void DrawFixedGraphicAnimationExt(DrawBuffer *dst_bitmap, int x, int y, + int graphic, int sync_frame, + int mask_mode) +{ + int frame = getGraphicAnimationFrame(graphic, sync_frame); + + if (mask_mode == USE_MASKING) + DrawFixedGraphicThruMaskExt(dst_bitmap, x, y, graphic, frame); + else + DrawFixedGraphicExt(dst_bitmap, x, y, graphic, frame); +} + inline void DrawGraphicAnimation(int x, int y, int graphic) { int lx = LEVELX(x), ly = LEVELY(y); @@ -2385,19 +3309,36 @@ inline void DrawGraphicAnimation(int x, int y, int graphic) if (!IN_SCR_FIELD(x, y)) return; +#if NEW_TILESIZE + DrawGraphicAnimationExt(drawto_field, FX + x * TILEX_VAR, FY + y * TILEY_VAR, + graphic, GfxFrame[lx][ly], NO_MASKING); +#else DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY, graphic, GfxFrame[lx][ly], NO_MASKING); +#endif MarkTileDirty(x, y); } -void DrawLevelGraphicAnimation(int x, int y, int graphic) +inline void DrawFixedGraphicAnimation(int x, int y, int graphic) { - DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic); -} + int lx = LEVELX(x), ly = LEVELY(y); -void DrawLevelElementAnimation(int x, int y, int element) -{ - int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); + if (!IN_SCR_FIELD(x, y)) + return; + + DrawGraphicAnimationExt(drawto_field, FX + x * TILEX, FY + y * TILEY, + graphic, GfxFrame[lx][ly], NO_MASKING); + MarkTileDirty(x, y); +} + +void DrawLevelGraphicAnimation(int x, int y, int graphic) +{ + DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic); +} + +void DrawLevelElementAnimation(int x, int y, int element) +{ + int graphic = el_act_dir2img(element, GfxAction[x][y], GfxDir[x][y]); DrawGraphicAnimation(SCREENX(x), SCREENY(y), graphic); } @@ -2416,10 +3357,10 @@ inline void DrawLevelGraphicAnimationIfNeeded(int x, int y, int graphic) #if 1 if (GFX_CRUMBLED(TILE_GFX_ELEMENT(x, y))) - DrawLevelFieldCrumbledSand(x, y); + DrawLevelFieldCrumbled(x, y); #else if (GFX_CRUMBLED(Feld[x][y])) - DrawLevelFieldCrumbledSand(x, y); + DrawLevelFieldCrumbled(x, y); #endif } @@ -2439,7 +3380,7 @@ void DrawLevelElementAnimationIfNeeded(int x, int y, int element) DrawGraphicAnimation(sx, sy, graphic); if (GFX_CRUMBLED(element)) - DrawLevelFieldCrumbledSand(x, y); + DrawLevelFieldCrumbled(x, y); } static int getPlayerGraphic(struct PlayerInfo *player, int move_dir) @@ -2496,6 +3437,8 @@ void DrawPlayerField(int x, int y) DrawPlayer(PLAYERINFO(x, y)); } +#define DRAW_PLAYER_OVER_PUSHED_ELEMENT 1 + void DrawPlayer(struct PlayerInfo *player) { int jx = player->jx; @@ -2592,9 +3535,6 @@ void DrawPlayer(struct PlayerInfo *player) if (!IN_SCR_FIELD(sx, sy)) return; - if (setup.direct_draw) - SetDrawtoField(DRAW_BUFFERED); - /* ----------------------------------------------------------------------- */ /* draw things behind the player, if needed */ /* ----------------------------------------------------------------------- */ @@ -2612,7 +3552,7 @@ void DrawPlayer(struct PlayerInfo *player) int frame = getGraphicAnimationFrame(old_graphic, player->StepFrame); if (GFX_CRUMBLED(old_element)) - DrawLevelFieldCrumbledSandDigging(jx, jy, move_dir, player->StepFrame); + DrawLevelFieldCrumbledDigging(jx, jy, move_dir, player->StepFrame); else DrawGraphic(sx, sy, old_graphic, frame); @@ -2638,6 +3578,7 @@ void DrawPlayer(struct PlayerInfo *player) } } +#if !DRAW_PLAYER_OVER_PUSHED_ELEMENT /* ----------------------------------------------------------------------- */ /* draw player himself */ /* ----------------------------------------------------------------------- */ @@ -2675,6 +3616,17 @@ void DrawPlayer(struct PlayerInfo *player) DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); } +#endif + +#if DRAW_PLAYER_OVER_PUSHED_ELEMENT + if (player->GfxPos) + { + if (move_dir == MV_LEFT || move_dir == MV_RIGHT) + sxx = player->GfxPos; + else + syy = player->GfxPos; + } +#endif /* ----------------------------------------------------------------------- */ /* draw things the player is pushing, if needed */ @@ -2714,11 +3666,90 @@ void DrawPlayer(struct PlayerInfo *player) #endif /* draw background element under pushed element (like the Sokoban field) */ +#if 1 + if (game.use_masked_pushing && IS_MOVING(jx, jy)) + { + /* this allows transparent pushing animation over non-black background */ + + if (Back[jx][jy]) + DrawLevelElement(jx, jy, Back[jx][jy]); + else + DrawLevelElement(jx, jy, EL_EMPTY); + + if (Back[next_jx][next_jy]) + DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]); + else + DrawLevelElement(next_jx, next_jy, EL_EMPTY); + } + else if (Back[next_jx][next_jy]) + DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]); +#else if (Back[next_jx][next_jy]) DrawLevelElement(next_jx, next_jy, Back[next_jx][next_jy]); +#endif + +#if 0 + printf("::: %d, %d, %d, %d [%d] [%d, %d, %d] [%d] [%d, %d] [%d, %d]\n", + jx, px, player->GfxPos, player->StepFrame, + player->is_pushing, + dx, sxx, pxx, + IS_MOVING(jx, jy), + graphic, frame, + GfxFrame[jx][jy], GfxFrame[next_jx][next_jy]); +#endif +#if 1 + /* 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]); + else + DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING); +#else /* masked drawing is needed for EMC style (double) movement graphics */ + /* !!! (ONLY WHEN DRAWING PUSHED ELEMENT OVER THE PLAYER) !!! */ DrawGraphicShiftedThruMask(px, py, pxx, pyy, graphic, frame, NO_CUTTING); +#endif + } +#endif + +#if DRAW_PLAYER_OVER_PUSHED_ELEMENT + /* ----------------------------------------------------------------------- */ + /* draw player himself */ + /* ----------------------------------------------------------------------- */ + + graphic = getPlayerGraphic(player, move_dir); + + /* in the case of changed player action or direction, prevent the current + animation frame from being restarted for identical animations */ + if (player->Frame == 0 && equalGraphics(graphic, last_player_graphic)) + player->Frame = last_player_frame; + + frame = getGraphicAnimationFrame(graphic, player->Frame); + + if (player->GfxPos) + { + if (move_dir == MV_LEFT || move_dir == MV_RIGHT) + sxx = player->GfxPos; + else + syy = player->GfxPos; + } + + if (!setup.soft_scrolling && ScreenMovPos) + sxx = syy = 0; + + if (player_is_opaque) + DrawGraphicShifted(sx, sy, sxx, syy, graphic, frame,NO_CUTTING,NO_MASKING); + else + DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); + + if (SHIELD_ON(player)) + { + int graphic = (player->shield_deadly_time_left ? IMG_SHIELD_DEADLY_ACTIVE : + IMG_SHIELD_NORMAL_ACTIVE); + int frame = getGraphicAnimationFrame(graphic, -1); + + DrawGraphicShiftedThruMask(sx, sy, sxx, syy, graphic, frame, NO_CUTTING); } #endif @@ -2773,18 +3804,6 @@ void DrawPlayer(struct PlayerInfo *player) DrawLevelFieldThruMask(jx, jy); } - if (setup.direct_draw) - { - int dst_x = SX + SCREENX(MIN(jx, last_jx)) * TILEX; - int dst_y = SY + SCREENY(MIN(jy, last_jy)) * TILEY; - int x_size = TILEX * (1 + ABS(jx - last_jx)); - int y_size = TILEY * (1 + ABS(jy - last_jy)); - - BlitBitmap(drawto_field, window, - dst_x, dst_y, x_size, y_size, dst_x, dst_y); - SetDrawtoField(DRAW_DIRECT); - } - MarkTileDirty(sx, sy); } @@ -2851,9 +3870,23 @@ boolean Request(char *text, unsigned int req_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; +#if 0 int max_word_len = 0; +#endif char *text_ptr; + int i; + +#if 1 + global.use_envelope_request = 0; +#endif +#if 1 + if (maxWordLengthInString(text) > MAX_REQUEST_LINE_FONT1_LEN) + { + max_request_line_len = MAX_REQUEST_LINE_FONT2_LEN; + font_nr = FONT_TEXT_1; + } +#else for (text_ptr = text; *text_ptr; text_ptr++) { max_word_len = (*text_ptr != ' ' ? max_word_len + 1 : 0); @@ -2870,10 +3903,15 @@ boolean Request(char *text, unsigned int req_state) break; } } +#endif - if (game_status == GAME_MODE_PLAYING && - level.game_engine_type == GAME_ENGINE_TYPE_EM) - BlitScreenToBitmap_EM(backbuffer); + if (game_status == GAME_MODE_PLAYING) + { + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) + BlitScreenToBitmap_EM(backbuffer); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + BlitScreenToBitmap_SP(backbuffer); + } /* disable deactivated drawing when quick-loading level tape recording */ if (tape.playing && tape.deactivate_display) @@ -2897,9 +3935,21 @@ boolean Request(char *text, unsigned int req_state) UnmapAllGadgets(); + /* draw released gadget before proceeding */ + // BackToFront(); + +#if 0 + if (old_door_state & DOOR_OPEN_1 && !global.use_envelope_request) +#else if (old_door_state & DOOR_OPEN_1) +#endif { +#if 1 + if (!global.use_envelope_request) + CloseDoor(DOOR_CLOSE_1); +#else CloseDoor(DOOR_CLOSE_1); +#endif /* save old door content */ BlitBitmap(bitmap_db_door, bitmap_db_door, @@ -2920,40 +3970,49 @@ boolean Request(char *text, unsigned int req_state) game_status = GAME_MODE_PSEUDO_DOOR; /* write text for request */ - for (ty = 0; ty < MAX_REQUEST_LINES; ty++) + for (text_ptr = text, ty = 0; ty < MAX_REQUEST_LINES; ty++) { char text_line[max_request_line_len + 1]; int tx, tl, tc = 0; - if (!*text) + if (!*text_ptr) break; for (tl = 0, tx = 0; tx < max_request_line_len; tl++, tx++) { - tc = *(text + tx); + tc = *(text_ptr + tx); if (!tc || tc == ' ') break; } if (!tl) { - text++; + text_ptr++; ty--; continue; } - strncpy(text_line, text, tl); + strncpy(text_line, text_ptr, tl); text_line[tl] = 0; DrawText(DX + (DXSIZE - tl * getFontWidth(font_nr)) / 2, DY + 8 + ty * (getFontHeight(font_nr) + 2), text_line, font_nr); - text += tl + (tc == ' ' ? 1 : 0); + text_ptr += tl + (tc == ' ' ? 1 : 0); } game_status = last_game_status; /* restore current game status */ +#if 1 + if (global.use_envelope_request) + { + /* !!! TMP !!! */ + FreeToolButtons(); + CreateToolButtons(); + } +#endif + if (req_state & REQ_ASK) { MapGadget(tool_gadget[TOOL_CTRL_ID_YES]); @@ -2976,7 +4035,36 @@ boolean Request(char *text, unsigned int req_state) DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); +#if 1 + if (global.use_envelope_request) + { + ShowEnvelopeDoor(text, ACTION_OPENING); + + for (i = 0; i < NUM_TOOL_BUTTONS; i++) + { + if ((req_state & REQ_ASK && (i == TOOL_CTRL_ID_YES || + i == TOOL_CTRL_ID_NO)) || + (req_state & REQ_CONFIRM && i == TOOL_CTRL_ID_CONFIRM) || + (req_state & REQ_PLAYER && (i == TOOL_CTRL_ID_PLAYER_1 && + i == TOOL_CTRL_ID_PLAYER_2 && + i == TOOL_CTRL_ID_PLAYER_3 && + i == TOOL_CTRL_ID_PLAYER_4))) + { + int x = tool_gadget[i]->x + dDX; + int y = tool_gadget[i]->y + dDY; + + ModifyGadget(tool_gadget[i], GDI_X, x, GDI_Y, y, GDI_END); + } + } + } +#endif + +#if 1 + if (!global.use_envelope_request) + OpenDoor(DOOR_OPEN_1); +#else OpenDoor(DOOR_OPEN_1); +#endif if (!(req_state & REQUEST_WAIT_FOR_INPUT)) { @@ -2993,8 +4081,13 @@ boolean Request(char *text, unsigned int req_state) return FALSE; } +#if 1 + if (game_status != GAME_MODE_MAIN && !global.use_envelope_request) + InitAnimation(); +#else if (game_status != GAME_MODE_MAIN) InitAnimation(); +#endif button_status = MB_RELEASED; @@ -3087,6 +4180,9 @@ boolean Request(char *text, unsigned int req_state) break; case KSYM_Escape: +#if defined(TARGET_SDL2) + case KSYM_Back: +#endif result = 0; break; @@ -3131,8 +4227,16 @@ boolean Request(char *text, unsigned int req_state) Delay(10); } +#if 1 + game_status = GAME_MODE_PSEUDO_DOOR; +#endif + BackToFront(); +#if 1 + game_status = last_game_status; /* restore current game status */ +#endif + #else DoAnimation(); @@ -3153,7 +4257,16 @@ boolean Request(char *text, unsigned int req_state) UnmapToolButtons(); +#if 1 + if (global.use_envelope_request) + ShowEnvelopeDoor(text, ACTION_CLOSING); +#endif + +#if 1 + if (!(req_state & REQ_STAY_OPEN) && !global.use_envelope_request) +#else if (!(req_state & REQ_STAY_OPEN)) +#endif { CloseDoor(DOOR_CLOSE_1); @@ -3243,8 +4356,8 @@ unsigned int MoveDoor(unsigned int door_state) { static int door1 = DOOR_OPEN_1; static int door2 = DOOR_CLOSE_2; - unsigned long door_delay = 0; - unsigned long door_delay_value; + unsigned int door_delay = 0; + unsigned int door_delay_value; int stepsize = 1; if (door_1.width < 0 || door_1.width > DXSIZE) @@ -3296,6 +4409,11 @@ unsigned int MoveDoor(unsigned int door_state) door_state &= ~DOOR_CLOSE_ALL; } +#if 1 + if (game_status == GAME_MODE_EDITOR) + door_state |= DOOR_NO_DELAY; +#endif + if (door_state & DOOR_ACTION) { boolean handle_door_1 = (door_state & DOOR_ACTION_1); @@ -3549,6 +4667,102 @@ void UndrawSpecialEditorDoor() /* ---------- new tool button stuff ---------------------------------------- */ +#if 1 + +static struct +{ + int graphic; + struct TextPosInfo *pos; + int gadget_id; + char *infotext; +} toolbutton_info[NUM_TOOL_BUTTONS] = +{ + { + IMG_REQUEST_BUTTON_GFX_YES, &request.button.yes, + TOOL_CTRL_ID_YES, "yes" + }, + { + IMG_REQUEST_BUTTON_GFX_NO, &request.button.no, + TOOL_CTRL_ID_NO, "no" + }, + { + IMG_REQUEST_BUTTON_GFX_CONFIRM, &request.button.confirm, + TOOL_CTRL_ID_CONFIRM, "confirm" + }, + { + IMG_REQUEST_BUTTON_GFX_PLAYER_1, &request.button.player_1, + TOOL_CTRL_ID_PLAYER_1, "player 1" + }, + { + IMG_REQUEST_BUTTON_GFX_PLAYER_2, &request.button.player_2, + TOOL_CTRL_ID_PLAYER_2, "player 2" + }, + { + IMG_REQUEST_BUTTON_GFX_PLAYER_3, &request.button.player_3, + TOOL_CTRL_ID_PLAYER_3, "player 3" + }, + { + IMG_REQUEST_BUTTON_GFX_PLAYER_4, &request.button.player_4, + TOOL_CTRL_ID_PLAYER_4, "player 4" + } +}; + +void CreateToolButtons() +{ + int i; + + for (i = 0; i < NUM_TOOL_BUTTONS; i++) + { + struct GraphicInfo *gfx = &graphic_info[toolbutton_info[i].graphic]; + struct TextPosInfo *pos = toolbutton_info[i].pos; + struct GadgetInfo *gi; + 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 gd_x = gfx->src_x; + int gd_y = gfx->src_y; + int gd_xp = gfx->src_x + gfx->pressed_xoffset; + int gd_yp = gfx->src_y + gfx->pressed_yoffset; + int id = i; + + if (id >= TOOL_CTRL_ID_PLAYER_1 && id <= TOOL_CTRL_ID_PLAYER_4) + { + int player_nr = id - TOOL_CTRL_ID_PLAYER_1; + + getSizedGraphicSource(PLAYER_NR_GFX(IMG_PLAYER_1, player_nr), 0, + pos->size, &deco_bitmap, &deco_x, &deco_y); + deco_xpos = (gfx->width - pos->size) / 2; + deco_ypos = (gfx->height - pos->size) / 2; + } + + gi = CreateGadget(GDI_CUSTOM_ID, id, + GDI_INFO_TEXT, toolbutton_info[i].infotext, + GDI_X, DX + pos->x, + GDI_Y, DY + pos->y, + GDI_WIDTH, gfx->width, + GDI_HEIGHT, gfx->height, + GDI_TYPE, GD_TYPE_NORMAL_BUTTON, + GDI_STATE, GD_BUTTON_UNPRESSED, + GDI_DESIGN_UNPRESSED, gfx->bitmap, gd_x, gd_y, + GDI_DESIGN_PRESSED, gfx->bitmap, gd_xp, gd_yp, + GDI_DECORATION_DESIGN, deco_bitmap, deco_x, deco_y, + GDI_DECORATION_POSITION, deco_xpos, deco_ypos, + GDI_DECORATION_SIZE, pos->size, pos->size, + GDI_DECORATION_SHIFTING, 1, 1, + GDI_DIRECT_DRAW, FALSE, + GDI_EVENT_MASK, event_mask, + GDI_CALLBACK_ACTION, HandleToolButtons, + GDI_END); + + if (gi == NULL) + Error(ERR_EXIT, "cannot create gadget"); + + tool_gadget[id] = gi; + } +} + +#else + /* graphic position values for tool buttons */ #define TOOL_BUTTON_YES_XPOS 2 #define TOOL_BUTTON_YES_YPOS 250 @@ -3658,7 +4872,7 @@ void CreateToolButtons() Bitmap *deco_bitmap = None; int deco_x = 0, deco_y = 0, deco_xpos = 0, deco_ypos = 0; struct GadgetInfo *gi; - unsigned long event_mask; + unsigned int event_mask; int gd_xoffset, gd_yoffset; int gd_x1, gd_x2, gd_y; int id = i; @@ -3707,6 +4921,8 @@ void CreateToolButtons() } } +#endif + void FreeToolButtons() { int i; @@ -4944,6 +6160,32 @@ em_object_mapping_list[] = Xsand_stonein_4, FALSE, TRUE, EL_ROCK, ACTION_FILLING, -1 }, +#if 1 + { + Xsand_stonesand_1, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + { + Xsand_stonesand_2, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + { + Xsand_stonesand_3, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + { + Xsand_stonesand_4, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + { + Xsand_stonesand_quickout_1, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, + { + Xsand_stonesand_quickout_2, FALSE, FALSE, + EL_QUICKSAND_EMPTYING, -1, -1 + }, +#else { Xsand_stonesand_1, FALSE, FALSE, EL_QUICKSAND_FULL, -1, -1 @@ -4960,6 +6202,7 @@ em_object_mapping_list[] = Xsand_stonesand_4, FALSE, FALSE, EL_QUICKSAND_FULL, -1, -1 }, +#endif { Xsand_stoneout_1, FALSE, FALSE, EL_ROCK, ACTION_EMPTYING, -1 @@ -4968,6 +6211,24 @@ em_object_mapping_list[] = Xsand_stoneout_2, FALSE, FALSE, EL_ROCK, ACTION_EMPTYING, -1 }, +#if 1 + { + Xsand_sandstone_1, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 + }, + { + Xsand_sandstone_2, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 + }, + { + Xsand_sandstone_3, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 + }, + { + Xsand_sandstone_4, FALSE, FALSE, + EL_QUICKSAND_FILLING, -1, -1 + }, +#else { Xsand_sandstone_1, FALSE, FALSE, EL_QUICKSAND_FULL, -1, -1 @@ -4984,6 +6245,7 @@ em_object_mapping_list[] = Xsand_sandstone_4, FALSE, FALSE, EL_QUICKSAND_FULL, -1, -1 }, +#endif { Xplant, TRUE, FALSE, EL_EMC_PLANT, -1, -1 @@ -5773,12 +7035,58 @@ int map_direction_EM_to_RND(int direction) MV_NONE); } -int get_next_element(int element) +int map_element_RND_to_SP(int element_rnd) { - switch (element) - { - case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL; - case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY; + int element_sp = 0x20; /* map unknown elements to yellow "hardware" */ + + if (element_rnd >= EL_SP_START && + element_rnd <= EL_SP_END) + element_sp = element_rnd - EL_SP_START; + else if (element_rnd == EL_EMPTY_SPACE) + element_sp = 0x00; + else if (element_rnd == EL_INVISIBLE_WALL) + element_sp = 0x28; + + return element_sp; +} + +int map_element_SP_to_RND(int element_sp) +{ + int element_rnd = EL_UNKNOWN; + + if (element_sp >= 0x00 && + element_sp <= 0x27) + element_rnd = EL_SP_START + element_sp; + else if (element_sp == 0x28) + element_rnd = EL_INVISIBLE_WALL; + + return element_rnd; +} + +int map_action_SP_to_RND(int action_sp) +{ + switch (action_sp) + { + case actActive: return ACTION_ACTIVE; + case actImpact: return ACTION_IMPACT; + case actExploding: return ACTION_EXPLODING; + case actDigging: return ACTION_DIGGING; + case actSnapping: return ACTION_SNAPPING; + case actCollecting: return ACTION_COLLECTING; + case actPassing: return ACTION_PASSING; + case actPushing: return ACTION_PUSHING; + case actDropping: return ACTION_DROPPING; + + default: return ACTION_DEFAULT; + } +} + +int get_next_element(int element) +{ + switch (element) + { + case EL_QUICKSAND_FILLING: return EL_QUICKSAND_FULL; + case EL_QUICKSAND_EMPTYING: return EL_QUICKSAND_EMPTY; case EL_QUICKSAND_FAST_FILLING: return EL_QUICKSAND_FAST_FULL; case EL_QUICKSAND_FAST_EMPTYING: return EL_QUICKSAND_FAST_EMPTY; case EL_MAGIC_WALL_FILLING: return EL_MAGIC_WALL_FULL; @@ -6049,10 +7357,12 @@ int getGameFrameDelay_EM(int native_em_game_frame_delay) return game_frame_delay_value; } -unsigned int InitRND(long seed) +unsigned int InitRND(int seed) { if (level.game_engine_type == GAME_ENGINE_TYPE_EM) return InitEngineRandom_EM(seed); + else if (level.game_engine_type == GAME_ENGINE_TYPE_SP) + return InitEngineRandom_SP(seed); else return InitEngineRandom_RND(seed); } @@ -6062,50 +7372,877 @@ static struct Mapping_EM_to_RND_object object_mapping[TILE_MAX]; static struct Mapping_EM_to_RND_player player_mapping[MAX_PLAYERS][SPR_MAX]; #endif +inline static int get_effective_element_EM(int tile, int frame_em) +{ + int element = object_mapping[tile].element_rnd; + int action = object_mapping[tile].action; + boolean is_backside = object_mapping[tile].is_backside; + boolean action_removing = (action == ACTION_DIGGING || + action == ACTION_SNAPPING || + action == ACTION_COLLECTING); + + if (frame_em < 7) + { + switch (tile) + { + case Yacid_splash_eB: + case Yacid_splash_wB: + return (frame_em > 5 ? EL_EMPTY : element); + +#if 0 + /* !!! FIX !!! */ + case Ydiamond_stone: + // if (!game.use_native_emc_graphics_engine) + return EL_ROCK; +#endif + + default: + return element; + } + } + else /* frame_em == 7 */ + { + switch (tile) + { + case Yacid_splash_eB: + case Yacid_splash_wB: + return EL_EMPTY; + + case Yemerald_stone: + return EL_EMERALD; + + case Ydiamond_stone: + return EL_ROCK; + + case Xdrip_stretch: + case Xdrip_stretchB: + case Ydrip_s1: + case Ydrip_s1B: + case Xball_1B: + 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 Xsand_stonein_1: + case Xsand_stonein_2: + case Xsand_stonein_3: + case Xsand_stonein_4: + return element; + + default: + return (is_backside || action_removing ? EL_EMPTY : element); + } + } +} + +inline static boolean check_linear_animation_EM(int tile) +{ + switch (tile) + { + case Xsand_stonesand_1: + case Xsand_stonesand_quickout_1: + case Xsand_sandstone_1: + case Xsand_stonein_1: + case Xsand_stoneout_1: + case Xboom_1: + case Xdynamite_1: + case Ybug_w_n: + case Ybug_n_e: + case Ybug_e_s: + case Ybug_s_w: + case Ybug_e_n: + case Ybug_s_e: + case Ybug_w_s: + case Ybug_n_w: + case Ytank_w_n: + case Ytank_n_e: + case Ytank_e_s: + case Ytank_s_w: + case Ytank_e_n: + case Ytank_s_e: + case Ytank_w_s: + case Ytank_n_w: +#if 1 + case Yacid_splash_eB: + case Yacid_splash_wB: + case Yemerald_stone: +#endif + return TRUE; + } + + return FALSE; +} + +inline static void set_crumbled_graphics_EM(struct GraphicInfo_EM *g_em, + boolean has_crumbled_graphics, + int crumbled, int sync_frame) +{ + /* if element can be crumbled, but certain action graphics are just empty + space (like instantly snapping sand to empty space in 1 frame), do not + treat these empty space graphics as crumbled graphics in EMC engine */ + if (crumbled == IMG_EMPTY_SPACE) + has_crumbled_graphics = FALSE; + + if (has_crumbled_graphics) + { + struct GraphicInfo *g_crumbled = &graphic_info[crumbled]; + int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames, + g_crumbled->anim_delay, + g_crumbled->anim_mode, + g_crumbled->anim_start_frame, + sync_frame); + + getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap, + &g_em->crumbled_src_x, &g_em->crumbled_src_y); + + g_em->crumbled_border_size = graphic_info[crumbled].border_size; + + g_em->has_crumbled_graphics = TRUE; + } + else + { + g_em->crumbled_bitmap = NULL; + g_em->crumbled_src_x = 0; + g_em->crumbled_src_y = 0; + g_em->crumbled_border_size = 0; + + g_em->has_crumbled_graphics = FALSE; + } +} + void ResetGfxAnimation_EM(int x, int y, int tile) { GfxFrame[x][y] = 0; } -void getGraphicSourceObjectExt_EM(int tile, int frame_em, - Bitmap **src_bitmap, int *src_x, int *src_y, - int x, int y) -{ - int element = object_mapping[tile].element_rnd; - int action = object_mapping[tile].action; - int direction = object_mapping[tile].direction; - boolean is_backside = object_mapping[tile].is_backside; - boolean action_removing = (action == ACTION_DIGGING || - action == ACTION_SNAPPING || - action == ACTION_COLLECTING); - int effective_element = (frame_em > 0 ? element : - is_backside ? EL_EMPTY : - action_removing ? EL_EMPTY : - element); - int graphic = (direction == MV_NONE ? - el_act2img(effective_element, action) : - el_act_dir2img(effective_element, action, direction)); - struct GraphicInfo *g = &graphic_info[graphic]; - int sync_frame; +void SetGfxAnimation_EM(struct GraphicInfo_EM *g_em, + int tile, int frame_em, int x, int y) +{ + int action = object_mapping[tile].action; +#if 1 + int direction = object_mapping[tile].direction; + int effective_element = get_effective_element_EM(tile, frame_em); + int graphic = (direction == MV_NONE ? + el_act2img(effective_element, action) : + el_act_dir2img(effective_element, action, direction)); + struct GraphicInfo *g = &graphic_info[graphic]; + int sync_frame; +#endif + boolean action_removing = (action == ACTION_DIGGING || + action == ACTION_SNAPPING || + action == ACTION_COLLECTING); + boolean action_moving = (action == ACTION_FALLING || + action == ACTION_MOVING || + action == ACTION_PUSHING || + action == ACTION_EATING || + action == ACTION_FILLING || + action == ACTION_EMPTYING); + boolean action_falling = (action == ACTION_FALLING || + action == ACTION_FILLING || + action == ACTION_EMPTYING); + + /* special case: graphic uses "2nd movement tile" and has defined + 7 frames for movement animation (or less) => use default graphic + for last (8th) frame which ends the movement animation */ + if (g->double_movement && g->anim_frames < 8 && frame_em == 7) + { + action = ACTION_DEFAULT; /* (keep action_* unchanged for now) */ + graphic = (direction == MV_NONE ? + el_act2img(effective_element, action) : + el_act_dir2img(effective_element, action, direction)); + + g = &graphic_info[graphic]; + } + +#if 0 + if (tile == Xsand_stonesand_1 || + tile == Xsand_stonesand_2 || + tile == Xsand_stonesand_3 || + tile == Xsand_stonesand_4) + printf("::: 1: quicksand frame %d [%d]\n", GfxFrame[x][y], tile); +#endif + +#if 1 + if ((action_removing || check_linear_animation_EM(tile)) && frame_em == 0) + { + GfxFrame[x][y] = 0; + + // printf("::: resetting... [%d]\n", tile); + } +#else + if (action_removing || check_linear_animation_EM(tile)) + { + GfxFrame[x][y] = frame_em; + + // printf("::: resetting... [%d]\n", tile); + } +#endif + else if (action_moving) + { + boolean is_backside = object_mapping[tile].is_backside; + + if (is_backside) + { + int direction = object_mapping[tile].direction; + int move_dir = (action_falling ? MV_DOWN : direction); + + GfxFrame[x][y]++; + +#if 1 + /* !!! TEST !!! NEW !!! DOES NOT WORK RIGHT YET !!! */ + if (g->double_movement && frame_em == 0) + { + GfxFrame[x][y] = 0; + + // printf("::: resetting... [%d]\n", tile); + } +#endif + + if (move_dir == MV_LEFT) + GfxFrame[x - 1][y] = GfxFrame[x][y]; + else if (move_dir == MV_RIGHT) + GfxFrame[x + 1][y] = GfxFrame[x][y]; + else if (move_dir == MV_UP) + GfxFrame[x][y - 1] = GfxFrame[x][y]; + else if (move_dir == MV_DOWN) + GfxFrame[x][y + 1] = GfxFrame[x][y]; + } + } + else + { + GfxFrame[x][y]++; + + /* special case: animation for Xsand_stonesand_quickout_1/2 twice as fast */ + if (tile == Xsand_stonesand_quickout_1 || + tile == Xsand_stonesand_quickout_2) + GfxFrame[x][y]++; + } + +#if 0 + if (tile == Xsand_stonesand_1 || + tile == Xsand_stonesand_2 || + tile == Xsand_stonesand_3 || + tile == Xsand_stonesand_4) + printf("::: 2: quicksand frame %d [%d]\n", GfxFrame[x][y], tile); +#endif + +#if 1 + if (graphic_info[graphic].anim_global_sync) + sync_frame = FrameCounter; + else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY)) + sync_frame = GfxFrame[x][y]; + else + sync_frame = 0; /* playfield border (pseudo steel) */ + + SetRandomAnimationValue(x, y); + + int frame = getAnimationFrame(g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame); + + g_em->unique_identifier = + (graphic << 16) | ((frame % 8) << 12) | (g_em->width << 6) | g_em->height; +#endif +} + +void getGraphicSourceObjectExt_EM(struct GraphicInfo_EM *g_em, + int tile, int frame_em, int x, int y) +{ + int action = object_mapping[tile].action; + int direction = object_mapping[tile].direction; + boolean is_backside = object_mapping[tile].is_backside; + int effective_element = get_effective_element_EM(tile, frame_em); +#if 1 + int effective_action = action; +#else + int effective_action = (frame_em < 7 ? action : ACTION_DEFAULT); +#endif + int graphic = (direction == MV_NONE ? + el_act2img(effective_element, effective_action) : + el_act_dir2img(effective_element, effective_action, + direction)); + int crumbled = (direction == MV_NONE ? + el_act2crm(effective_element, effective_action) : + el_act_dir2crm(effective_element, effective_action, + direction)); + int base_graphic = el_act2img(effective_element, ACTION_DEFAULT); + int base_crumbled = el_act2crm(effective_element, ACTION_DEFAULT); + boolean has_crumbled_graphics = (base_crumbled != base_graphic); + struct GraphicInfo *g = &graphic_info[graphic]; +#if 0 + struct GraphicInfo *g_crumbled = &graphic_info[crumbled]; +#endif + int sync_frame; + + /* special case: graphic uses "2nd movement tile" and has defined + 7 frames for movement animation (or less) => use default graphic + for last (8th) frame which ends the movement animation */ + if (g->double_movement && g->anim_frames < 8 && frame_em == 7) + { + effective_action = ACTION_DEFAULT; + graphic = (direction == MV_NONE ? + el_act2img(effective_element, effective_action) : + el_act_dir2img(effective_element, effective_action, + direction)); + crumbled = (direction == MV_NONE ? + el_act2crm(effective_element, effective_action) : + el_act_dir2crm(effective_element, effective_action, + direction)); + + g = &graphic_info[graphic]; + } + +#if 0 + if (frame_em == 7) + return; +#endif + + +#if 0 + if (frame_em == 0) /* reset animation frame for certain elements */ + { + if (check_linear_animation_EM(tile)) + GfxFrame[x][y] = 0; + } +#endif + + if (graphic_info[graphic].anim_global_sync) + sync_frame = FrameCounter; + else if (IN_FIELD(x, y, MAX_LEV_FIELDX, MAX_LEV_FIELDY)) + sync_frame = GfxFrame[x][y]; + else + sync_frame = 0; /* playfield border (pseudo steel) */ + + SetRandomAnimationValue(x, y); + +#if 0 + int i = tile; + int j = frame_em; + int xxx_sync_frame = (i == Xdrip_stretch ? 7 : + i == Xdrip_stretchB ? 7 : + i == Ydrip_s2 ? j + 8 : + i == Ydrip_s2B ? j + 8 : + i == Xacid_1 ? 0 : + i == Xacid_2 ? 10 : + i == Xacid_3 ? 20 : + i == Xacid_4 ? 30 : + i == Xacid_5 ? 40 : + i == Xacid_6 ? 50 : + i == Xacid_7 ? 60 : + i == Xacid_8 ? 70 : + i == Xfake_acid_1 ? 0 : + i == Xfake_acid_2 ? 10 : + i == Xfake_acid_3 ? 20 : + i == Xfake_acid_4 ? 30 : + i == Xfake_acid_5 ? 40 : + i == Xfake_acid_6 ? 50 : + i == Xfake_acid_7 ? 60 : + i == Xfake_acid_8 ? 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 == Xamoeba_1 ? 0 : + i == Xamoeba_2 ? 1 : + i == Xamoeba_3 ? 2 : + i == Xamoeba_4 ? 3 : + i == Xamoeba_5 ? 0 : + i == Xamoeba_6 ? 1 : + i == Xamoeba_7 ? 2 : + i == Xamoeba_8 ? 3 : + i == Xexit_2 ? j + 8 : + i == Xexit_3 ? j + 16 : + i == Xdynamite_1 ? 0 : + i == Xdynamite_2 ? 8 : + i == Xdynamite_3 ? 16 : + i == Xdynamite_4 ? 24 : + i == Xsand_stonein_1 ? j + 1 : + i == Xsand_stonein_2 ? j + 9 : + i == Xsand_stonein_3 ? j + 17 : + i == Xsand_stonein_4 ? j + 25 : + i == Xsand_stoneout_1 && j == 0 ? 0 : + i == Xsand_stoneout_1 && j == 1 ? 0 : + i == Xsand_stoneout_1 && j == 2 ? 1 : + i == Xsand_stoneout_1 && j == 3 ? 2 : + i == Xsand_stoneout_1 && j == 4 ? 2 : + i == Xsand_stoneout_1 && j == 5 ? 3 : + i == Xsand_stoneout_1 && j == 6 ? 4 : + i == Xsand_stoneout_1 && j == 7 ? 4 : + i == Xsand_stoneout_2 && j == 0 ? 5 : + i == Xsand_stoneout_2 && j == 1 ? 6 : + i == Xsand_stoneout_2 && j == 2 ? 7 : + i == Xsand_stoneout_2 && j == 3 ? 8 : + i == Xsand_stoneout_2 && j == 4 ? 9 : + i == Xsand_stoneout_2 && j == 5 ? 11 : + i == Xsand_stoneout_2 && j == 6 ? 13 : + i == Xsand_stoneout_2 && j == 7 ? 15 : + i == Xboom_bug && j == 1 ? 2 : + i == Xboom_bug && j == 2 ? 2 : + i == Xboom_bug && j == 3 ? 4 : + i == Xboom_bug && j == 4 ? 4 : + 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_android && j == 7 ? 6 : + i == Xboom_1 && j == 1 ? 2 : + i == Xboom_1 && j == 2 ? 2 : + i == Xboom_1 && j == 3 ? 4 : + i == Xboom_1 && j == 4 ? 4 : + i == Xboom_1 && j == 5 ? 6 : + i == Xboom_1 && j == 6 ? 6 : + i == Xboom_1 && j == 7 ? 8 : + i == Xboom_2 && j == 0 ? 8 : + i == Xboom_2 && j == 1 ? 8 : + i == Xboom_2 && j == 2 ? 10 : + i == Xboom_2 && j == 3 ? 10 : + i == Xboom_2 && j == 4 ? 10 : + i == Xboom_2 && j == 5 ? 12 : + i == Xboom_2 && j == 6 ? 12 : + i == Xboom_2 && j == 7 ? 12 : +#if 0 + special_animation && j == 4 ? 3 : + effective_action != action ? 0 : +#endif + j); +#endif + +#if 0 + int xxx_effective_action; + int xxx_has_action_graphics; + + { + int element = object_mapping[i].element_rnd; + int action = object_mapping[i].action; + int direction = object_mapping[i].direction; + boolean is_backside = object_mapping[i].is_backside; +#if 0 + boolean action_removing = (action == ACTION_DIGGING || + action == ACTION_SNAPPING || + action == ACTION_COLLECTING); +#endif + boolean action_exploding = ((action == ACTION_EXPLODING || + action == ACTION_SMASHED_BY_ROCK || + action == ACTION_SMASHED_BY_SPRING) && + element != EL_DIAMOND); + boolean action_active = (action == ACTION_ACTIVE); + boolean action_other = (action == ACTION_OTHER); + + { +#if 1 + int effective_element = get_effective_element_EM(i, j); +#else + int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY : + j > 5 && i == Yacid_splash_wB ? EL_EMPTY : + j < 7 ? element : + i == Xdrip_stretch ? element : + i == Xdrip_stretchB ? element : + i == Ydrip_s1 ? element : + i == Ydrip_s1B ? element : + i == Xball_1B ? element : + i == Xball_2 ? element : + i == Xball_2B ? element : + i == Yball_eat ? element : + i == Ykey_1_eat ? element : + i == Ykey_2_eat ? element : + i == Ykey_3_eat ? element : + i == Ykey_4_eat ? element : + i == Ykey_5_eat ? element : + i == Ykey_6_eat ? element : + i == Ykey_7_eat ? element : + i == Ykey_8_eat ? element : + i == Ylenses_eat ? element : + i == Ymagnify_eat ? element : + i == Ygrass_eat ? element : + i == Ydirt_eat ? element : + i == Yemerald_stone ? EL_EMERALD : + i == Ydiamond_stone ? 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); +#endif + 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 == 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 == Xsand_stonein_1 ? action : + i == Xsand_stonein_2 ? action : + i == Xsand_stonein_3 ? action : + i == Xsand_stonein_4 ? action : + i == Xsand_stoneout_1 ? action : + i == Xsand_stoneout_2 ? action : + i == Xboom_android ? ACTION_EXPLODING : + action_exploding ? ACTION_EXPLODING : + action_active ? action : + action_other ? action : + ACTION_DEFAULT); + int graphic = (el_act_dir2img(effective_element, effective_action, + direction)); + int crumbled = (el_act_dir2crm(effective_element, effective_action, + 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]; +#if 0 + struct GraphicInfo *g_crumbled = &graphic_info[crumbled]; +#endif + struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j]; + Bitmap *src_bitmap; + int src_x, src_y; + /* ensure to get symmetric 3-frame, 2-delay animations as used in EM */ + boolean special_animation = (action != ACTION_DEFAULT && + g->anim_frames == 3 && + g->anim_delay == 2 && + g->anim_mode & ANIM_LINEAR); + xxx_sync_frame = (i == Xdrip_stretch ? 7 : + i == Xdrip_stretchB ? 7 : + i == Ydrip_s2 ? j + 8 : + i == Ydrip_s2B ? j + 8 : + i == Xacid_1 ? 0 : + i == Xacid_2 ? 10 : + i == Xacid_3 ? 20 : + i == Xacid_4 ? 30 : + i == Xacid_5 ? 40 : + i == Xacid_6 ? 50 : + i == Xacid_7 ? 60 : + i == Xacid_8 ? 70 : + i == Xfake_acid_1 ? 0 : + i == Xfake_acid_2 ? 10 : + i == Xfake_acid_3 ? 20 : + i == Xfake_acid_4 ? 30 : + i == Xfake_acid_5 ? 40 : + i == Xfake_acid_6 ? 50 : + i == Xfake_acid_7 ? 60 : + i == Xfake_acid_8 ? 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 == Xamoeba_1 ? 0 : + i == Xamoeba_2 ? 1 : + i == Xamoeba_3 ? 2 : + i == Xamoeba_4 ? 3 : + i == Xamoeba_5 ? 0 : + i == Xamoeba_6 ? 1 : + i == Xamoeba_7 ? 2 : + i == Xamoeba_8 ? 3 : + i == Xexit_2 ? j + 8 : + i == Xexit_3 ? j + 16 : + i == Xdynamite_1 ? 0 : + i == Xdynamite_2 ? 8 : + i == Xdynamite_3 ? 16 : + i == Xdynamite_4 ? 24 : + i == Xsand_stonein_1 ? j + 1 : + i == Xsand_stonein_2 ? j + 9 : + i == Xsand_stonein_3 ? j + 17 : + i == Xsand_stonein_4 ? j + 25 : + i == Xsand_stoneout_1 && j == 0 ? 0 : + i == Xsand_stoneout_1 && j == 1 ? 0 : + i == Xsand_stoneout_1 && j == 2 ? 1 : + i == Xsand_stoneout_1 && j == 3 ? 2 : + i == Xsand_stoneout_1 && j == 4 ? 2 : + i == Xsand_stoneout_1 && j == 5 ? 3 : + i == Xsand_stoneout_1 && j == 6 ? 4 : + i == Xsand_stoneout_1 && j == 7 ? 4 : + i == Xsand_stoneout_2 && j == 0 ? 5 : + i == Xsand_stoneout_2 && j == 1 ? 6 : + i == Xsand_stoneout_2 && j == 2 ? 7 : + i == Xsand_stoneout_2 && j == 3 ? 8 : + i == Xsand_stoneout_2 && j == 4 ? 9 : + i == Xsand_stoneout_2 && j == 5 ? 11 : + i == Xsand_stoneout_2 && j == 6 ? 13 : + i == Xsand_stoneout_2 && j == 7 ? 15 : + i == Xboom_bug && j == 1 ? 2 : + i == Xboom_bug && j == 2 ? 2 : + i == Xboom_bug && j == 3 ? 4 : + i == Xboom_bug && j == 4 ? 4 : + 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_android && j == 7 ? 6 : + i == Xboom_1 && j == 1 ? 2 : + i == Xboom_1 && j == 2 ? 2 : + i == Xboom_1 && j == 3 ? 4 : + i == Xboom_1 && j == 4 ? 4 : + i == Xboom_1 && j == 5 ? 6 : + i == Xboom_1 && j == 6 ? 6 : + i == Xboom_1 && j == 7 ? 8 : + i == Xboom_2 && j == 0 ? 8 : + i == Xboom_2 && j == 1 ? 8 : + i == Xboom_2 && j == 2 ? 10 : + i == Xboom_2 && j == 3 ? 10 : + i == Xboom_2 && j == 4 ? 10 : + i == Xboom_2 && j == 5 ? 12 : + i == Xboom_2 && j == 6 ? 12 : + i == Xboom_2 && j == 7 ? 12 : + special_animation && j == 4 ? 3 : + effective_action != action ? 0 : + j); + + xxx_effective_action = effective_action; + xxx_has_action_graphics = has_action_graphics; + } + } +#endif + + int frame = getAnimationFrame(g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame); + + +#if 0 + return; +#endif + +#if 0 + if (frame_em == 7) + return; +#endif + +#if 0 + int old_src_x = g_em->src_x; + int old_src_y = g_em->src_y; +#endif + +#if 1 + getGraphicSourceExt(graphic, frame, &g_em->bitmap, &g_em->src_x, &g_em->src_y, + g->double_movement && is_backside); +#else + getGraphicSourceExt(graphic, frame, &g_em->bitmap, + &g_em->src_x, &g_em->src_y, FALSE); +#endif + + +#if 0 + if (tile == Ydiamond_stone) + printf("::: stone smashing diamond... %d: %d, %d, %d, %d, %d -> %d [%d, %d, %d, %d, %d, %d] [%d]\n", + frame_em, + g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame, + frame, + g_em->src_x, g_em->src_y, + g_em->src_offset_x, g_em->src_offset_y, + g_em->dst_offset_x, g_em->dst_offset_y, + graphic); +#endif + + +#if 0 + return; +#endif + +#if 0 + if (frame_em == 7) + { + if (graphic == IMG_BUG_MOVING_RIGHT) + printf("::: %d, %d, %d: %d, %d [%d, %d -> %d, %d]\n", graphic, x, y, + g->double_movement, is_backside, + old_src_x, old_src_y, g_em->src_x, g_em->src_y); + + return; + } +#endif + + +#if 0 + 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; + + g_em->preserve_background = FALSE; +#endif + + /* (updating the "crumbled" graphic definitions is probably not really needed, + as animations for crumbled graphics can't be longer than one EMC cycle) */ +#if 1 + set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled, + sync_frame); + +#else + + g_em->crumbled_bitmap = NULL; + g_em->crumbled_src_x = 0; + g_em->crumbled_src_y = 0; + + g_em->has_crumbled_graphics = FALSE; + + if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE) + { + int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames, + g_crumbled->anim_delay, + g_crumbled->anim_mode, + g_crumbled->anim_start_frame, + sync_frame); + + getGraphicSource(crumbled, frame_crumbled, &g_em->crumbled_bitmap, + &g_em->crumbled_src_x, &g_em->crumbled_src_y); + + g_em->has_crumbled_graphics = TRUE; + } +#endif + +#if 0 + { + int effective_action = xxx_effective_action; + int has_action_graphics = xxx_has_action_graphics; - if (graphic_info[graphic].anim_global_sync) - sync_frame = FrameCounter; - else - sync_frame = 7 - frame_em; + 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 || + 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 ? 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 ? 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); - SetRandomAnimationValue(x, y); + if (is_backside) /* tile where movement starts */ + { + if (dx < 0 || dy < 0) + { + g_em->src_offset_x = cx * step; + g_em->src_offset_y = cy * step; + } + else + { + g_em->dst_offset_x = cx * step; + g_em->dst_offset_y = cy * step; + } + } + else /* tile where movement ends */ + { + if (dx < 0 || dy < 0) + { + g_em->dst_offset_x = cx * step; + g_em->dst_offset_y = cy * step; + } + else + { + g_em->src_offset_x = cx * step; + g_em->src_offset_y = cy * step; + } + } - int frame = getAnimationFrame(g->anim_frames, - g->anim_delay, - g->anim_mode, - g->anim_start_frame, - sync_frame); + g_em->width = TILEX - cx * step; + g_em->height = TILEY - cy * step; + } + + /* create unique graphic identifier to decide if tile must be redrawn */ + /* bit 31 - 16 (16 bit): EM style graphic + bit 15 - 12 ( 4 bit): EM style frame + bit 11 - 6 ( 6 bit): graphic width + bit 5 - 0 ( 6 bit): graphic height */ + g_em->unique_identifier = + (graphic << 16) | (frame << 12) | (g_em->width << 6) | g_em->height; + } +#endif - getGraphicSourceExt(graphic, frame, src_bitmap, src_x, src_y, FALSE); } -void getGraphicSourcePlayerExt_EM(int player_nr, int anim, int frame_em, - Bitmap **src_bitmap, int *src_x, int *src_y) +void getGraphicSourcePlayerExt_EM(struct GraphicInfo_EM *g_em, + int player_nr, int anim, int frame_em) { int element = player_mapping[player_nr][anim].element_rnd; int action = player_mapping[player_nr][anim].action; @@ -6118,10 +8255,19 @@ void getGraphicSourcePlayerExt_EM(int player_nr, int anim, int frame_em, InitPlayerGfxAnimation(&stored_player[player_nr], action, direction); - stored_player[player_nr].StepFrame = 7 - frame_em; + stored_player[player_nr].StepFrame = frame_em; sync_frame = stored_player[player_nr].Frame; + int frame = getAnimationFrame(g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame); + + getGraphicSourceExt(graphic, frame, &g_em->bitmap, + &g_em->src_x, &g_em->src_y, FALSE); + #if 0 printf("::: %d: %d, %d [%d]\n", player_nr, @@ -6129,14 +8275,6 @@ void getGraphicSourcePlayerExt_EM(int player_nr, int anim, int frame_em, stored_player[player_nr].StepFrame, FrameCounter); #endif - - int frame = getAnimationFrame(g->anim_frames, - g->anim_delay, - g->anim_mode, - g->anim_start_frame, - sync_frame); - - getGraphicSourceExt(graphic, frame, src_bitmap, src_x, src_y, FALSE); } void InitGraphicInfo_EM(void) @@ -6216,9 +8354,11 @@ void InitGraphicInfo_EM(void) int action = object_mapping[i].action; int direction = object_mapping[i].direction; boolean is_backside = object_mapping[i].is_backside; +#if 0 boolean action_removing = (action == ACTION_DIGGING || action == ACTION_SNAPPING || action == ACTION_COLLECTING); +#endif boolean action_exploding = ((action == ACTION_EXPLODING || action == ACTION_SMASHED_BY_ROCK || action == ACTION_SMASHED_BY_SPRING) && @@ -6228,6 +8368,9 @@ void InitGraphicInfo_EM(void) for (j = 0; j < 8; j++) { +#if 1 + int effective_element = get_effective_element_EM(i, j); +#else int effective_element = (j > 5 && i == Yacid_splash_eB ? EL_EMPTY : j > 5 && i == Yacid_splash_wB ? EL_EMPTY : j < 7 ? element : @@ -6260,6 +8403,7 @@ void InitGraphicInfo_EM(void) is_backside ? EL_EMPTY : action_removing ? EL_EMPTY : element); +#endif int effective_action = (j < 7 ? action : i == Xdrip_stretch ? action : i == Xdrip_stretchB ? action : @@ -6301,6 +8445,9 @@ 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]; +#if 0 + struct GraphicInfo *g_crumbled = &graphic_info[crumbled]; +#endif struct GraphicInfo_EM *g_em = &graphic_info_em_object[i][7 - j]; Bitmap *src_bitmap; int src_x, src_y; @@ -6437,13 +8584,20 @@ void InitGraphicInfo_EM(void) g_em->width = TILEX; g_em->height = TILEY; + g_em->preserve_background = FALSE; + +#if 1 + set_crumbled_graphics_EM(g_em, has_crumbled_graphics, crumbled, + sync_frame); + +#else + g_em->crumbled_bitmap = NULL; g_em->crumbled_src_x = 0; g_em->crumbled_src_y = 0; g_em->crumbled_border_size = 0; g_em->has_crumbled_graphics = FALSE; - g_em->preserve_background = FALSE; #if 0 if (has_crumbled_graphics && crumbled == IMG_EMPTY_SPACE) @@ -6453,18 +8607,47 @@ void InitGraphicInfo_EM(void) #endif /* if element can be crumbled, but certain action graphics are just empty - space (like snapping sand with the original R'n'D graphics), do not + space (like instantly snapping sand to empty space in 1 frame), do not treat these empty space graphics as crumbled graphics in EMC engine */ if (has_crumbled_graphics && crumbled != IMG_EMPTY_SPACE) { - getGraphicSource(crumbled, frame, &src_bitmap, &src_x, &src_y); + int frame_crumbled = getAnimationFrame(g_crumbled->anim_frames, + g_crumbled->anim_delay, + g_crumbled->anim_mode, + g_crumbled->anim_start_frame, + sync_frame); + + getGraphicSource(crumbled, frame_crumbled, &src_bitmap, &src_x, &src_y); g_em->has_crumbled_graphics = TRUE; g_em->crumbled_bitmap = src_bitmap; g_em->crumbled_src_x = src_x; g_em->crumbled_src_y = src_y; g_em->crumbled_border_size = graphic_info[crumbled].border_size; + + +#if 0 + if (g_em == &graphic_info_em_object[207][0]) + printf("... %d, %d [%d, %d, %d, %d] [%d, %d, %d, %d, %d, %d => %d]\n", + graphic_info_em_object[207][0].crumbled_src_x, + graphic_info_em_object[207][0].crumbled_src_y, + + crumbled, frame, src_x, src_y, + + g->anim_frames, + g->anim_delay, + g->anim_mode, + g->anim_start_frame, + sync_frame, + gfx.anim_random_frame, + frame); +#endif + +#if 0 + printf("::: EMC tile %d is crumbled\n", i); +#endif } +#endif #if 0 if (element == EL_ROCK && @@ -6762,6 +8945,67 @@ void InitGraphicInfo_EM(void) #endif } +void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame, + boolean any_player_moving, + boolean player_is_dropping) +{ + if (tape.single_step && tape.recording && !tape.pausing) + { +#if 0 + boolean active_players = FALSE; + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + if (action[i] != JOY_NO_ACTION) + active_players = TRUE; +#endif + + // if (frame == 0) + if (frame == 0 && !player_is_dropping) + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + } +} + +void CheckSingleStepMode_SP(boolean murphy_is_waiting, + boolean murphy_is_dropping) +{ +#if 0 + printf("::: waiting: %d, dropping: %d\n", + murphy_is_waiting, murphy_is_dropping); +#endif + + if (tape.single_step && tape.recording && !tape.pausing) + { + // if (murphy_is_waiting || murphy_is_dropping) + if (murphy_is_waiting) + { +#if 0 + printf("::: murphy is waiting -> pause mode\n"); +#endif + + TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); + } + } +} + +void getGraphicSource_SP(struct GraphicInfo_SP *g_sp, + int graphic, int sync_frame, int x, int y) +{ + int frame = getGraphicAnimationFrame(graphic, sync_frame); + + getGraphicSource(graphic, frame, &g_sp->bitmap, &g_sp->src_x, &g_sp->src_y); +} + +boolean isNextAnimationFrame_SP(int graphic, int sync_frame) +{ + return (IS_NEXT_FRAME(sync_frame, graphic)); +} + +int getGraphicInfo_Delay(int graphic) +{ + return graphic_info[graphic].anim_delay; +} + void PlayMenuSoundExt(int sound) { if (sound == SND_UNDEFINED) @@ -6852,40 +9096,59 @@ void ToggleFullscreenIfNeeded() 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); - if (!video.fullscreen_available) + if (change_window_scaling_percent && video.fullscreen_enabled) return; -#if 1 - if (change_fullscreen || change_fullscreen_mode) -#else - if (setup.fullscreen != video.fullscreen_enabled || - setup.fullscreen_mode != video.fullscreen_mode_current) + if (!change_window_scaling_percent && !video.fullscreen_available) + return; + +#if defined(TARGET_SDL2) + if (change_window_scaling_percent) + { + SDLSetWindowScaling(setup.window_scaling_percent); + + return; + } + else if (change_fullscreen) + { + SDLSetWindowFullscreen(setup.fullscreen); + + /* set setup value according to successfully changed fullscreen mode */ + setup.fullscreen = video.fullscreen_enabled; + + return; + } #endif + + if (change_fullscreen || + change_fullscreen_mode || + change_window_scaling_percent) { 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 1 if (change_fullscreen_mode) -#else - if (setup.fullscreen && video.fullscreen_enabled) -#endif { /* keep fullscreen, but change fullscreen mode (screen resolution) */ -#if 1 - /* (this is now set in sdl.c) */ -#else - video.fullscreen_mode_current = setup.fullscreen_mode; -#endif video.fullscreen_enabled = FALSE; /* force new fullscreen mode */ } + if (change_window_scaling_percent) + { + /* keep window mode, but change window scaling */ + video.fullscreen_enabled = TRUE; /* force new window scaling */ + } + /* toggle fullscreen */ ChangeVideoModeIfNeeded(setup.fullscreen); + /* set setup value according to successfully changed fullscreen mode */ setup.fullscreen = video.fullscreen_enabled; /* restore backbuffer content from temporary backbuffer backup bitmap */ @@ -6901,3 +9164,187 @@ void ToggleFullscreenIfNeeded() #endif } } + +void ChangeViewportPropertiesIfNeeded() +{ + int *door_1_x = &DX; + int *door_1_y = &DY; + int *door_2_x = (game_status == GAME_MODE_EDITOR ? &EX : &VX); + int *door_2_y = (game_status == GAME_MODE_EDITOR ? &EY : &VY); + int gfx_game_mode = (game_status == GAME_MODE_PLAYING || + game_status == GAME_MODE_EDITOR ? game_status : + GAME_MODE_MAIN); + struct RectWithBorder *vp_playfield = &viewport.playfield[gfx_game_mode]; + struct RectWithBorder *vp_door_1 = &viewport.door_1[gfx_game_mode]; + struct RectWithBorder *vp_door_2 = &viewport.door_2[gfx_game_mode]; + int border_size = vp_playfield->border_size; + int new_sx = vp_playfield->x + border_size; + int new_sy = vp_playfield->y + border_size; + int new_sxsize = vp_playfield->width - 2 * border_size; + int new_sysize = vp_playfield->height - 2 * border_size; + int new_real_sx = vp_playfield->x; + int new_real_sy = vp_playfield->y; + int new_full_sxsize = vp_playfield->width; + int new_full_sysize = vp_playfield->height; +#if NEW_TILESIZE + int new_tilesize_var = TILESIZE / (setup.small_game_graphics ? 2 : 1); + int tilesize = (gfx_game_mode == GAME_MODE_PLAYING ? new_tilesize_var : + gfx_game_mode == GAME_MODE_EDITOR ? MINI_TILESIZE : TILESIZE); + int new_scr_fieldx = new_sxsize / tilesize; + int new_scr_fieldy = new_sysize / tilesize; + int new_scr_fieldx_buffers = new_sxsize / new_tilesize_var; + int new_scr_fieldy_buffers = new_sysize / new_tilesize_var; +#else + int new_scr_fieldx = (vp_playfield->width - 2 * border_size) / TILESIZE; + int new_scr_fieldy = (vp_playfield->height - 2 * border_size) / TILESIZE; +#endif + boolean init_gfx_buffers = FALSE; + boolean init_video_buffer = FALSE; + boolean init_gadgets_and_toons = FALSE; + +#if 0 + /* !!! TEST ONLY !!! */ + // InitGfxBuffers(); + return; +#endif + + if (viewport.window.width != WIN_XSIZE || + viewport.window.height != WIN_YSIZE) + { + WIN_XSIZE = viewport.window.width; + WIN_YSIZE = viewport.window.height; + +#if 1 + init_video_buffer = TRUE; + init_gfx_buffers = TRUE; +#else + InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); + InitGfxBuffers(); + +#if 1 + SetDrawDeactivationMask(REDRAW_NONE); + SetDrawBackgroundMask(REDRAW_FIELD); + + // RedrawBackground(); +#endif +#endif + + // printf("::: video: init_video_buffer, init_gfx_buffers\n"); + } + + if (new_scr_fieldx != SCR_FIELDX || + new_scr_fieldy != SCR_FIELDY) + { + /* this always toggles between MAIN and GAME when using small tile size */ + + SCR_FIELDX = new_scr_fieldx; + SCR_FIELDY = new_scr_fieldy; + + // printf("::: new_scr_fieldx != SCR_FIELDX ...\n"); + } + +#if 0 + if (new_tilesize_var != TILESIZE_VAR && + gfx_game_mode == GAME_MODE_PLAYING) + { + /* doing this outside GAME_MODE_PLAYING would give wrong playfield size */ + + TILESIZE_VAR = new_tilesize_var; + + init_gfx_buffers = TRUE; + + // printf("::: tilesize: init_gfx_buffers\n"); + } +#endif + + if (new_sx != SX || + new_sy != SY || + new_sxsize != SXSIZE || + new_sysize != SYSIZE || + new_real_sx != REAL_SX || + new_real_sy != REAL_SY || + new_full_sxsize != FULL_SXSIZE || + new_full_sysize != FULL_SYSIZE || + new_tilesize_var != TILESIZE_VAR || + vp_door_1->x != *door_1_x || + vp_door_1->y != *door_1_y || + vp_door_2->x != *door_2_x || + vp_door_2->y != *door_2_y) + { + SX = new_sx; + SY = new_sy; + SXSIZE = new_sxsize; + SYSIZE = new_sysize; + REAL_SX = new_real_sx; + REAL_SY = new_real_sy; + FULL_SXSIZE = new_full_sxsize; + FULL_SYSIZE = new_full_sysize; + TILESIZE_VAR = new_tilesize_var; + +#if 0 + printf("::: %d, %d, %d [%d]\n", + SCR_FIELDX, SCR_FIELDY, TILESIZE_VAR, + setup.small_game_graphics); +#endif + + *door_1_x = vp_door_1->x; + *door_1_y = vp_door_1->y; + *door_2_x = vp_door_2->x; + *door_2_y = vp_door_2->y; + +#if 1 + init_gfx_buffers = TRUE; + + // printf("::: viewports: init_gfx_buffers\n"); +#else + InitGfxBuffers(); +#endif + + if (gfx_game_mode == GAME_MODE_MAIN) + { +#if 1 + init_gadgets_and_toons = TRUE; + + // printf("::: viewports: init_gadgets_and_toons\n"); +#else + InitGadgets(); + InitToons(); +#endif + } + } + + if (init_gfx_buffers) + { + // printf("::: init_gfx_buffers\n"); + + SCR_FIELDX = new_scr_fieldx_buffers; + SCR_FIELDY = new_scr_fieldy_buffers; + + InitGfxBuffers(); + + SCR_FIELDX = new_scr_fieldx; + SCR_FIELDY = new_scr_fieldy; + } + + if (init_video_buffer) + { + // printf("::: init_video_buffer\n"); + + InitVideoBuffer(WIN_XSIZE, WIN_YSIZE, DEFAULT_DEPTH, setup.fullscreen); + + SetDrawDeactivationMask(REDRAW_NONE); + SetDrawBackgroundMask(REDRAW_FIELD); + } + + if (init_gadgets_and_toons) + { + // printf("::: init_gadgets_and_toons\n"); + + InitGadgets(); + InitToons(); + } + +#if 0 + printf("::: %d, %d / %d, %d [%d]\n", VX, VY, EX, EY, game_status); +#endif +}