From 572a4bab20b6f36ef1a4782094b27ac5a703a476 Mon Sep 17 00:00:00 2001 From: Holger Schemel Date: Thu, 12 Nov 2009 23:55:15 +0100 Subject: [PATCH] rnd-20091112-1-src * fixed bug with single step mode (there were some cases where the game did not automatically return to pause mode, e.g. when trying to push things that don't move or when trying to run against a wall) --- ChangeLog | 5 + src/conftime.h | 2 +- src/game.c | 9 ++ src/game_sp/DDScrollBuffer.c | 196 +++++++++++++++++++++++++++++++++++ src/game_sp/DDScrollBuffer.h | 6 ++ src/game_sp/DDSpriteBuffer.c | 108 ++++++++++++++++++- src/game_sp/Globals.c | 2 - src/game_sp/MainForm.c | 5 +- src/game_sp/MainGameLoop.c | 7 ++ src/game_sp/export.h | 2 + src/game_sp/init.c | 2 +- src/game_sp/main.c | 16 ++- src/game_sp/main_sp.h | 4 +- 13 files changed, 351 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index e42c6d05..c1bb34c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2009-11-12 + * fixed bug with single step mode (there were some cases where the game + did not automatically return to pause mode, e.g. when trying to push + things that don't move or when trying to run against a wall) + 2009-11-01 * added support for loading Supaplex levels in MPX level file format diff --git a/src/conftime.h b/src/conftime.h index 524cdb82..70b165cd 100644 --- a/src/conftime.h +++ b/src/conftime.h @@ -1 +1 @@ -#define COMPILE_DATE_STRING "2009-11-01 21:31" +#define COMPILE_DATE_STRING "2009-11-12 23:54" diff --git a/src/game.c b/src/game.c index 80f15701..e2b67c24 100644 --- a/src/game.c +++ b/src/game.c @@ -11983,7 +11983,16 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) if (tape.single_step && tape.recording && !tape.pausing) { +#if 1 + /* as it is called "single step mode", just return to pause mode when the + player stopped moving after one tile (or never starts moving at all) */ + if (!player->is_moving) +#else + /* this is buggy: there are quite some cases where the single step mode + does not return to pause mode (like pushing things that don't move + or simply by trying to run against a wall) */ if (button1 || (dropped && !moved)) +#endif { TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); SnapField(player, 0, 0); /* stop snapping */ diff --git a/src/game_sp/DDScrollBuffer.c b/src/game_sp/DDScrollBuffer.c index 23ce4ce9..e9b94f96 100644 --- a/src/game_sp/DDScrollBuffer.c +++ b/src/game_sp/DDScrollBuffer.c @@ -33,6 +33,83 @@ long mhWnd; long mScrollX, mScrollY; long mDestXOff, mDestYOff; +long ScreenBuffer[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; +boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; + + +void UpdatePlayfield() +{ + int x, y; + int sx1 = mScrollX - TILEX; + int sy1 = mScrollY - TILEY; + int sx2 = mScrollX + SXSIZE + TILEX; + int sy2 = mScrollY + SYSIZE + TILEY; + int x1 = sx1 / TILEX; + int y1 = sy1 / TILEY; + int x2 = sx2 / TILEX; + int y2 = sy2 / TILEY; + + for (y = DisplayMinY; y <= DisplayMaxY; y++) + { + for (x = DisplayMinX; x <= DisplayMaxX; x++) + { + if (x >= x1 && x < x2 && y >= y1 && y < y2) + { + int sx = x - x1; + int sy = y - y1; + int tsi = GetSI(x, y); + long id = ((PlayField16[tsi]) | + (PlayField8[tsi] << 16) | + (DisPlayField[tsi] << 24)); + boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id); + + if (redraw_screen_tile) + { + DrawFieldNoAnimated(x, y); + DrawFieldAnimated(x, y); + + ScreenBuffer[sx][sy] = id; + + redraw[sx][sy] = TRUE; + redraw_tiles++; + } + } + } + } +} + +void OLD_UpdatePlayfield() +{ + int x, y; + int left = mScrollX / TILEX; + int top = mScrollY / TILEY; + + for (y = top; y < top + MAX_BUF_YSIZE; y++) + { + for (x = left; x < left + MAX_BUF_XSIZE; x++) + { + int sx = x % MAX_BUF_XSIZE; + int sy = y % MAX_BUF_YSIZE; + int tsi = GetSI(x, y); + long id = ((PlayField16[tsi]) | + (PlayField8[tsi] << 16) | + (DisPlayField[tsi] << 24)); + boolean redraw_screen_tile = (ScreenBuffer[sx][sy] != id); + + if (redraw_screen_tile) + { + DrawFieldNoAnimated(x, y); + DrawFieldAnimated(x, y); + + ScreenBuffer[sx][sy] = id; + + redraw[sx][sy] = TRUE; + redraw_tiles++; + } + } + } +} + void DDScrollBuffer_Let_DestXOff(long NewVal) { mDestXOff = NewVal; @@ -131,6 +208,110 @@ void DDScrollBuffer_Cls(int BackColor) Buffer.BltColorFill(EmptyRect, BackColor); } + +/* copy the entire screen to the window at the scroll position */ + +void BlitScreenToBitmap_SP(Bitmap *target_bitmap) +{ + int sx = TILEX + mScrollX % TILEX; + int sy = TILEY + mScrollY % TILEY; + + BlitBitmap(screenBitmap, target_bitmap, sx, sy, + SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY); +} + +void OLD_BlitScreenToBitmap_SP(Bitmap *target_bitmap) +{ + int x = mScrollX % (MAX_BUF_XSIZE * TILEX); + int y = mScrollY % (MAX_BUF_YSIZE * TILEY); + + if (x < 2 * TILEX && y < 2 * TILEY) + { + BlitBitmap(screenBitmap, target_bitmap, x, y, + SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY); + } + else if (x < 2 * TILEX && y >= 2 * TILEY) + { + BlitBitmap(screenBitmap, target_bitmap, x, y, + SCR_FIELDX * TILEX, MAX_BUF_YSIZE * TILEY - y, + SX, SY); + BlitBitmap(screenBitmap, target_bitmap, x, 0, + SCR_FIELDX * TILEX, y - 2 * TILEY, + SX, SY + MAX_BUF_YSIZE * TILEY - y); + } + else if (x >= 2 * TILEX && y < 2 * TILEY) + { + BlitBitmap(screenBitmap, target_bitmap, x, y, + MAX_BUF_XSIZE * TILEX - x, SCR_FIELDY * TILEY, + SX, SY); + BlitBitmap(screenBitmap, target_bitmap, 0, y, + x - 2 * TILEX, SCR_FIELDY * TILEY, + SX + MAX_BUF_XSIZE * TILEX - x, SY); + } + else + { + BlitBitmap(screenBitmap, target_bitmap, x, y, + MAX_BUF_XSIZE * TILEX - x, MAX_BUF_YSIZE * TILEY - y, + SX, SY); + BlitBitmap(screenBitmap, target_bitmap, 0, y, + x - 2 * TILEX, MAX_BUF_YSIZE * TILEY - y, + SX + MAX_BUF_XSIZE * TILEX - x, SY); + BlitBitmap(screenBitmap, target_bitmap, x, 0, + MAX_BUF_XSIZE * TILEX - x, y - 2 * TILEY, + SX, SY + MAX_BUF_YSIZE * TILEY - y); + BlitBitmap(screenBitmap, target_bitmap, 0, 0, + x - 2 * TILEX, y - 2 * TILEY, + SX + MAX_BUF_XSIZE * TILEX - x, SY + MAX_BUF_YSIZE * TILEY - y); + } +} + +void BackToFront_SP(void) +{ + static boolean scrolling_last = FALSE; + int left = mScrollX / TILEX; + int top = mScrollY / TILEY; + boolean scrolling = (mScrollX % TILEX != 0 || mScrollY % TILEY != 0); + int x, y; + + SyncDisplay(); + + if (1 || + redraw_tiles > REDRAWTILES_THRESHOLD || scrolling || scrolling_last) + { + /* blit all (up to four) parts of the scroll buffer to the backbuffer */ + BlitScreenToBitmap_SP(backbuffer); + + /* blit the completely updated backbuffer to the window (in one blit) */ + BlitBitmap(backbuffer, window, SX, SY, SXSIZE, SYSIZE, SX, SY); + } + else + { + for (x = 0; x < SCR_FIELDX; x++) + { + for (y = 0; y < SCR_FIELDY; y++) + { + int xx = (left + x) % MAX_BUF_XSIZE; + int yy = (top + y) % MAX_BUF_YSIZE; + + if (redraw[xx][yy]) + BlitBitmap(screenBitmap, window, + xx * TILEX, yy * TILEY, TILEX, TILEY, + SX + x * TILEX, SY + y * TILEY); + } + } + } + + FlushDisplay(); + + for (x = 0; x < MAX_BUF_XSIZE; x++) + for (y = 0; y < MAX_BUF_YSIZE; y++) + redraw[x][y] = FALSE; + redraw_tiles = 0; + + scrolling_last = scrolling; +} + + void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap) { RECT DR, SR; @@ -157,11 +338,14 @@ void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap) tX = (DR.right - DR.left) / Stretch; tY = (DR.bottom - DR.top) / Stretch; } + { SR.left = mScrollX + mDestXOff; SR.top = mScrollY + mDestYOff; + SR.right = SR.left + tX; SR.bottom = SR.top + tY; + // If mWidth < SR.right Then // SR.right = mWidth // DR.right = DR.left + Stretch * (SR.right - SR.left) @@ -356,7 +540,19 @@ void DDScrollBuffer_Blt_Ext(Bitmap *target_bitmap) void DDScrollBuffer_Blt() { +#if 1 + +#if 1 + BackToFront_SP(); +#else + /* !!! TEST ONLY !!! */ + BlitBitmap(screenBitmap, window, + 0, 0, SCR_FIELDX * TILEX, SCR_FIELDY * TILEY, SX, SY); +#endif + +#else DDScrollBuffer_Blt_Ext(window); +#endif } void DDScrollBuffer_ScrollTo(int X, int Y) diff --git a/src/game_sp/DDScrollBuffer.h b/src/game_sp/DDScrollBuffer.h index 9f30e307..dbcb1db5 100644 --- a/src/game_sp/DDScrollBuffer.h +++ b/src/game_sp/DDScrollBuffer.h @@ -12,6 +12,12 @@ #include "global.h" +extern long mScrollX, mScrollY; + +extern boolean redraw[MAX_BUF_XSIZE][MAX_BUF_YSIZE]; + +extern void UpdatePlayfield(); + extern void DDScrollBuffer_Blt_Ext(Bitmap *); extern void DDScrollBuffer_Blt(); extern void DDScrollBuffer_Cls(int BackColor); diff --git a/src/game_sp/DDSpriteBuffer.c b/src/game_sp/DDSpriteBuffer.c index e7412265..7572c919 100644 --- a/src/game_sp/DDSpriteBuffer.c +++ b/src/game_sp/DDSpriteBuffer.c @@ -177,13 +177,109 @@ static void Blt(int pX, int pY, int SpriteX, int SpriteY) long Tmp; #endif + int sx1 = mScrollX - TILEX; + int sy1 = mScrollY - TILEY; + int sx2 = mScrollX + SXSIZE + TILEX; + int sy2 = mScrollY + SYSIZE + TILEY; + int x1 = sx1 / TILEX; + int y1 = sy1 / TILEY; + int x2 = sx2 / TILEX; + int y2 = sy2 / TILEY; + + int sx = pX - x1 * TILEX; + int sy = pY - y1 * TILEY; + +#if 0 + printf(":1: DDSpriteBuffer.c: Blt(): %d, %d [%ld, %ld]\n", + pX, pY, mScrollX, mScrollY); +#endif + + if (NoDisplayFlag) + return; + + /* do not draw fields that are outside the visible screen area */ + if (pX < sx1 || pX >= sx2 || pY < sy1 || pY >= sy2) + return; + +#if 0 + printf(":2: DDSpriteBuffer.c: Blt(): %d, %d [%ld, %ld]\n", + pX, pY, mScrollX, mScrollY); +#endif + + { + DR.left = pX + mDestXOff; + DR.top = pY + mDestYOff; + DR.right = pX + mSpriteWidth + mDestXOff; + DR.bottom = pY + mSpriteHeight + mDestYOff; + } + { + SR.left = mSpriteWidth * (SpriteX - 1); + SR.top = mSpriteHeight * (SpriteY - 1); + SR.right = SR.left + mSpriteWidth; + SR.bottom = SR.top + mSpriteHeight; + } + +#if 0 + printf("::: DDSpriteBuffer.c: Blt(): %d, %d\n", DR.left, DR.top); +#endif + +#if 0 + if (pX == 0 * StretchWidth && pY == 0 * StretchWidth) + printf("::: TEST: drawing topleft corner ...\n"); + if (pX == 59 * StretchWidth && pY == 23 * StretchWidth) + printf("::: TEST: drawing bottomright corner ...\n"); +#endif + +#if 1 + +#if 1 + BlitBitmap(sp_objects, screenBitmap, + SR.left, SR.top, + mSpriteWidth, mSpriteHeight, + sx, sy); +#else + BlitBitmap(sp_objects, screenBitmap, + SR.left, SR.top, + mSpriteWidth, mSpriteHeight, + DR.left, DR.top); +#endif + +#else + Tmp = mDest.Blt(DR, &Buffer, SR, DDBLT_WAIT); +#endif +} + +static void OLD_Blt(int pX, int pY, int SpriteX, int SpriteY) +{ + RECT DR, SR; +#if 0 + long Tmp; +#endif + +#if 1 + int left = mScrollX; + int top = mScrollY; +#else + int left = mScrollX / TILEX; + int top = mScrollY / TILEY; +#endif + + int sx = pX % (MAX_BUF_XSIZE * TILEX); + int sy = pY % (MAX_BUF_YSIZE * TILEY); + #if 0 - printf("::: DDSpriteBuffer.c: Blt(): %d, %d\n", pX, pY); + printf("::: DDSpriteBuffer.c: Blt(): %d, %d [%ld, %ld] [%d, %d]\n", + pX, pY, mScrollX, mScrollY, left, top); #endif if (NoDisplayFlag) return; + /* do not draw fields that are outside the visible screen area */ + if (pX < left || pX >= left + MAX_BUF_XSIZE * TILEX || + pY < top || pY >= top + MAX_BUF_YSIZE * TILEY) + return; + { DR.left = pX + mDestXOff; DR.top = pY + mDestYOff; @@ -208,11 +304,20 @@ static void Blt(int pX, int pY, int SpriteX, int SpriteY) printf("::: TEST: drawing bottomright corner ...\n"); #endif +#if 1 + #if 1 + BlitBitmap(sp_objects, screenBitmap, + SR.left, SR.top, + mSpriteWidth, mSpriteHeight, + sx, sy); +#else BlitBitmap(sp_objects, screenBitmap, SR.left, SR.top, mSpriteWidth, mSpriteHeight, DR.left, DR.top); +#endif + #else Tmp = mDest.Blt(DR, &Buffer, SR, DDBLT_WAIT); #endif @@ -227,6 +332,7 @@ void DDSpriteBuffer_BltEx(int pX, int pY, int SpritePos) XPos = (SpritePos % mXSpriteCount) + 1; YPos = (SpritePos / mXSpriteCount) + 1; + Blt(pX, pY, XPos, YPos); } diff --git a/src/game_sp/Globals.c b/src/game_sp/Globals.c index a54380ef..4c4f7afe 100644 --- a/src/game_sp/Globals.c +++ b/src/game_sp/Globals.c @@ -64,8 +64,6 @@ int *PlayField16; byte *PlayField8; byte *DisPlayField; -long ScreenBuffer[SP_SCREEN_BUFFER_XSIZE][SP_SCREEN_BUFFER_YSIZE]; - // Public DisplayMin%, DisplayMax%, DisplayWidth%, DisplayHeight% int TimerVar; diff --git a/src/game_sp/MainForm.c b/src/game_sp/MainForm.c index 7936fee2..2f845154 100644 --- a/src/game_sp/MainForm.c +++ b/src/game_sp/MainForm.c @@ -1370,8 +1370,9 @@ void Form_Load() PauseMode = 0; // BaseWidth = 16 -#if 0 - menBorder_Click(); +#if 1 + if (0) + menBorder_Click(); #endif Loaded = True; diff --git a/src/game_sp/MainGameLoop.c b/src/game_sp/MainGameLoop.c index bae1d6d9..42bafa50 100644 --- a/src/game_sp/MainGameLoop.c +++ b/src/game_sp/MainGameLoop.c @@ -117,8 +117,15 @@ locRepeatMainGameLoop: // start repeating game loop LastFrame = Clock.TickNow(); // store the frame time #endif // never any additional code between here! + + + +#if 0 if (! NoDisplayFlag) // copy the BackBuffer(=Stage) to visible screen Stage.Blt(); +#endif + + // FS end of synchronization // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/game_sp/export.h b/src/game_sp/export.h index aecfcc85..f54bb28a 100644 --- a/src/game_sp/export.h +++ b/src/game_sp/export.h @@ -24,8 +24,10 @@ SP_PLAYFIELD_HEIGHT) #define SP_LEVEL_SIZE (SP_HEADER_SIZE + SP_PLAYFIELD_SIZE) +#if 0 #define SP_SCREEN_BUFFER_XSIZE (SCR_FIELDX + 2) #define SP_SCREEN_BUFFER_YSIZE (SCR_FIELDY + 2) +#endif #define SP_FRAMES_PER_SECOND 35 #define SP_MAX_TAPE_LEN 64010 /* (see "spfix63.doc") */ diff --git a/src/game_sp/init.c b/src/game_sp/init.c index 0e217a9d..ee703424 100644 --- a/src/game_sp/init.c +++ b/src/game_sp/init.c @@ -36,7 +36,7 @@ void sp_open_all() SetBitmaps_SP(&sp_objects); -#if 1 +#if 0 /* too small for oversized levels, but too big for graphics performance */ /* (the whole playfield is drawn/updated, not only visible/scrolled area) */ /* !!! FIX THIS !!! */ diff --git a/src/game_sp/main.c b/src/game_sp/main.c index be2cb29f..467c82d2 100644 --- a/src/game_sp/main.c +++ b/src/game_sp/main.c @@ -18,19 +18,27 @@ void InitGameEngine_SP() #endif } +#if 0 void BlitScreenToBitmap_SP(Bitmap *target_bitmap) { DDScrollBuffer_Blt_Ext(target_bitmap); } +#endif + +void RedrawPlayfield_SP(boolean force_redraw) +{ + // subDisplayLevel(); + + UpdatePlayfield(); + + BackToFront_SP(); +} void GameActions_SP(byte action[MAX_PLAYERS], boolean warp_mode) { byte single_player_action = action[0]; subMainGameLoop_Main(single_player_action, warp_mode); -} -void RedrawPlayfield_SP(boolean force_redraw) -{ - subDisplayLevel(); + RedrawPlayfield_SP(FALSE); } diff --git a/src/game_sp/main_sp.h b/src/game_sp/main_sp.h index d9294194..7e0480e2 100644 --- a/src/game_sp/main_sp.h +++ b/src/game_sp/main_sp.h @@ -40,8 +40,8 @@ #define SCR_MENUY 12 #define SCR_FIELDX 17 #define SCR_FIELDY 17 -#define MAX_BUF_XSIZE (SCR_FIELDX + 2) -#define MAX_BUF_YSIZE (SCR_FIELDY + 2) +#define MAX_BUF_XSIZE (2 + SCR_FIELDX + 2) +#define MAX_BUF_YSIZE (2 + SCR_FIELDY + 2) /* often used screen positions */ #define SX 8 -- 2.34.1