aboutsummaryrefslogtreecommitdiff
path: root/sword2
diff options
context:
space:
mode:
authorTorbjörn Andersson2003-08-29 06:42:34 +0000
committerTorbjörn Andersson2003-08-29 06:42:34 +0000
commited698cb63591963d0eb73c8dee69b95951bd476b (patch)
tree6ac37b00bd91f63ace2bfd20c39d3a91844b516c /sword2
parentd900ea66bdac3f6e4cbda41e085a4665f26a79b1 (diff)
downloadscummvm-rg350-ed698cb63591963d0eb73c8dee69b95951bd476b.tar.gz
scummvm-rg350-ed698cb63591963d0eb73c8dee69b95951bd476b.tar.bz2
scummvm-rg350-ed698cb63591963d0eb73c8dee69b95951bd476b.zip
Added some code to stop producing interpolation frames if the scene has
already reached its scroll target. This keeps BS2 from using all available CPU time all of the time. It may still be that we need a mechanism for throttling the frame rate when the scene is moving towards a scroll target, but my computer isn't really fast enough to test that. Two other bugs fixed in the process: * I think the last frame of the render cycle was rendered, but not displayed. If so, that should be fixed now. * I discovered that there are cases where we do need to clear the screen (e.g. at the "Meanwhile..." message when George has found out about the Glease Gallery), so I've re-enabled the function and disabled it in the render cycle. svn-id: r9904
Diffstat (limited to 'sword2')
-rw-r--r--sword2/build_display.cpp17
-rw-r--r--sword2/driver/d_draw.cpp10
-rw-r--r--sword2/driver/rdwin.cpp12
-rw-r--r--sword2/driver/rdwin.h1
-rw-r--r--sword2/driver/render.cpp52
-rw-r--r--sword2/driver/sprite.cpp4
6 files changed, 67 insertions, 29 deletions
diff --git a/sword2/build_display.cpp b/sword2/build_display.cpp
index d4f9bc54c2..08783c5874 100644
--- a/sword2/build_display.cpp
+++ b/sword2/build_display.cpp
@@ -157,8 +157,10 @@ void Build_display(void) //Tony21Sept96
//----------------------------------------------------
// clear the back buffer, before building up the new screen
// from the back forwards
-
- EraseBackBuffer();
+
+ // FIXME: I'm not convinced that this is needed. Isn't
+ // the whole screen redrawn each time?
+ // EraseBackBuffer();
//----------------------------------------------------
// first background parallax + related anims
@@ -253,7 +255,8 @@ void Build_display(void) //Tony21Sept96
//----------------------------------------------------
// ready - blit to screen
- CopyScreenBuffer();
+ if (ServiceWindows() == RDERR_APPCLOSED) // if the game is being shut down, drop out
+ break;
//----------------------------------------------------
// update our fps reading
@@ -262,7 +265,7 @@ void Build_display(void) //Tony21Sept96
if (SVM_timeGetTime() > cycleTime)
{
fps = frameCount;
- debug(2, "FPS: %d", fps);
+ debug(0, "FPS: %d", fps);
frameCount = 0;
cycleTime = SVM_timeGetTime()+1000;
}
@@ -270,17 +273,11 @@ void Build_display(void) //Tony21Sept96
// check if we've got time to render the screen again this cycle
// (so drivers can smooth out the scrolling in between normal game cycles)
- // FIXME: If we have already reached the scroll target,
- // we should sleep for the rest of the render cycle.
-
EndRenderCycle(&end);
if (end) // if we haven't got time to render again this cycle, drop out of 'render cycle' while-loop
break;
- if (ServiceWindows() == RDERR_APPCLOSED) // if the game is being shut down, drop out
- break;
-
//----------------------------------------------------
} // END OF RENDER CYCLE
diff --git a/sword2/driver/d_draw.cpp b/sword2/driver/d_draw.cpp
index 573278ae27..d91eacb503 100644
--- a/sword2/driver/d_draw.cpp
+++ b/sword2/driver/d_draw.cpp
@@ -24,6 +24,7 @@
#include "_mouse.h"
#include "d_draw.h"
#include "palette.h"
+#include "render.h"
#define SCREENYOFFSET 40
#define MILLISECSPERCYCLE 83
@@ -205,14 +206,7 @@ int32 WaitForVbl(void)
}
int32 EraseBackBuffer( void ) {
- // Since the entire screen is redrawn each time, there probably isn't
- // any need to actually clear the back buffer.
- //
- // At the very least, since the menu code now is solely responsible
- // for its own parts of the screen, we'd only need to clear the
- // picture area.
-
- // memset(lpBackBuffer + MENUDEEP * screnWide, 0, screenWide * (screenDeep - 2 * MENUDEEP));
+ memset(lpBackBuffer + MENUDEEP * screenWide, 0, screenWide * RENDERDEEP);
return RD_OK;
}
diff --git a/sword2/driver/rdwin.cpp b/sword2/driver/rdwin.cpp
index 83ff62f970..299721c9ce 100644
--- a/sword2/driver/rdwin.cpp
+++ b/sword2/driver/rdwin.cpp
@@ -537,7 +537,11 @@ int32 CloseAppWindow(void)
}
+static bool _needRedraw = false;
+void SetNeedRedraw() {
+ _needRedraw = true;
+}
int32 ServiceWindows(void)
@@ -548,8 +552,14 @@ int32 ServiceWindows(void)
// FIXME: We re-render the entire picture area of the screen for each
// frame, which is pretty horrible.
- g_system->copy_rect(lpBackBuffer + MENUDEEP * screenWide, screenWide, 0, MENUDEEP, screenWide, screenDeep - 2 * MENUDEEP);
+ if (_needRedraw) {
+ g_system->copy_rect(lpBackBuffer + MENUDEEP * screenWide, screenWide, 0, MENUDEEP, screenWide, screenDeep - 2 * MENUDEEP);
+ _needRedraw = false;
+ }
+
+ // We still need to update because of fades, menu animations, etc.
g_system->update_screen();
+
// warning("stub ServiceWindows"); // too noisy
/*
MSG msg;
diff --git a/sword2/driver/rdwin.h b/sword2/driver/rdwin.h
index e176f9a40b..271b313ad7 100644
--- a/sword2/driver/rdwin.h
+++ b/sword2/driver/rdwin.h
@@ -52,5 +52,6 @@ extern RECT rcWindow; // size of the current window.
extern void Message(LPSTR fmt, ...);
*/
+extern void SetNeedRedraw(void);
#endif
diff --git a/sword2/driver/render.cpp b/sword2/driver/render.cpp
index 5b05d4958f..7997d8e3dd 100644
--- a/sword2/driver/render.cpp
+++ b/sword2/driver/render.cpp
@@ -258,7 +258,6 @@ int32 renderCountIndex = 0;
int32 renderTimeLog[RENDERAVERAGETOTAL] = {60, 60, 60, 60};
int32 initialTime;
int32 startTime;
-int32 originTime;
int32 totalTime;
int32 renderAverageTime = 60;
int32 framesPerGameCycle;
@@ -331,6 +330,7 @@ void BlitBlockSurface(BlockSurface *s, ScummVM::Rect *r, ScummVM::Rect *clip_rec
}
// UploadRect(r);
+ SetNeedRedraw();
}
#define SCALE_MAXWIDTH 512
@@ -987,10 +987,11 @@ void LogMe(int32 in)
}
*/
+// Uncomment this when benchmarking the drawing routines.
+#define LIMIT_FRAME_RATE
int32 InitialiseRenderCycle(void) {
initialTime = SVM_timeGetTime();
- originTime = initialTime;
totalTime = initialTime + MILLISECSPERCYCLE;
return RD_OK;
}
@@ -1018,13 +1019,27 @@ int32 StartRenderCycle(void) {
}
+// FIXME: Move this to some better place?
+
+void sleepUntil(int32 time) {
+ while ((int32) SVM_timeGetTime() < time) {
+ g_sword2->parseEvents();
+
+ // Make sure menu animations and fades don't suffer
+ ProcessMenu();
+ if (ServiceWindows() == RDERR_APPCLOSED)
+ break;
+
+ g_system->delay_msecs(10);
+ }
+}
int32 EndRenderCycle(BOOL *end) {
int32 time;
time = SVM_timeGetTime();
renderTimeLog[renderCountIndex] = time - startTime;
- startTime += renderTimeLog[renderCountIndex];
+ startTime = time;
renderAverageTime = (renderTimeLog[0] + renderTimeLog[1] + renderTimeLog[2] + renderTimeLog[3]) >> 2;
framesPerGameCycle += 1;
@@ -1037,13 +1052,31 @@ int32 EndRenderCycle(BOOL *end) {
InitialiseRenderCycle();
} else if (startTime + renderAverageTime >= totalTime) {
*end = TRUE;
- originTime = totalTime;
totalTime += MILLISECSPERCYCLE;
initialTime = time;
+#ifdef LIMIT_FRAME_RATE
+ } else if (scrollxTarget == scrollx && scrollyTarget == scrolly) {
+ // If we have already reached the scroll target sleep for the
+ // rest of the render cycle.
+ *end = TRUE;
+ sleepUntil(totalTime);
+ initialTime = SVM_timeGetTime();
+ totalTime += MILLISECSPERCYCLE;
+#endif
} else {
*end = FALSE;
- scrollx = (int16) (scrollxOld + ((scrollxTarget - scrollxOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime));
- scrolly = (int16) (scrollyOld + ((scrollyTarget - scrollyOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime));
+
+ // This is an attempt to ensure that we always reach the scroll
+ // target. Otherwise the game frequently tries to pump out new
+ // interpolation frames without ever getting anywhere.
+
+ if (ABS(scrollx - scrollxTarget) <= 1 && ABS(scrolly - scrollyTarget) <= 1) {
+ scrollx = scrollxTarget;
+ scrolly = scrollyTarget;
+ } else {
+ scrollx = (int16) (scrollxOld + ((scrollxTarget - scrollxOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime));
+ scrolly = (int16) (scrollyOld + ((scrollyTarget - scrollyOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime));
+ }
}
return RD_OK;
@@ -1057,9 +1090,8 @@ int32 SetScrollTarget(int16 sx, int16 sy) {
}
int32 CopyScreenBuffer(void) {
- // FIXME: This function no longer seems needed. Calling copy_rect()
- // for the whole screen is slower than the current approach. Not by
- // much, but still...
+ // FIXME: This function no longer seems to be needed. We copy the
+ // back buffer to the screen in ServiceWindows() instead.
return RD_OK;
}
@@ -1207,6 +1239,6 @@ int32 CloseBackgroundLayer(void) {
int32 EraseSoftwareScreenBuffer(void)
{
- memset(myScreenBuffer, 0, RENDERWIDE * RENDERDEEP);
+ // memset(myScreenBuffer, 0, RENDERWIDE * RENDERDEEP);
return(RD_OK);
}
diff --git a/sword2/driver/sprite.cpp b/sword2/driver/sprite.cpp
index 5054a6c782..9542956f92 100644
--- a/sword2/driver/sprite.cpp
+++ b/sword2/driver/sprite.cpp
@@ -265,6 +265,7 @@
#include "render.h"
#include "menu.h"
#include "palette.h"
+#include "rdwin.h"
#if PROFILING == 1
@@ -1330,6 +1331,8 @@ int32 DrawSurface(_spriteInfo *s, uint8 *surface) {
free(sprite);
// UploadRect(&rd);
+ SetNeedRedraw();
+
return 0;
}
@@ -1621,6 +1624,7 @@ int32 DrawSprite(_spriteInfo *s) {
free(sprite);
// UploadRect(&rd);
+ SetNeedRedraw();
/*