scummvm/sword2/driver/rdwin.cpp
Torbjörn Andersson ed698cb635 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
2003-08-29 06:42:34 +00:00

639 lines
13 KiB
C++

/* Copyright (C) 1994-2003 Revolution Software Ltd
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header$
*/
#define WIN32_LEAN_AND_MEAN
//#include <windows.h>
//#include <windowsx.h>
#include <stdio.h>
#include "common/stdafx.h"
#include "common/engine.h"
#include "driver96.h"
#include "_mouse.h"
#include "keyboard.h"
#include "rdwin.h"
#include "d_draw.h"
#include "palette.h"
#include "render.h"
#include "menu.h"
#include "d_sound.h"
#include "../sword2.h"
#define MENUDEEP 40 // Temporary, until menu.h is written!
//static BOOL bMouseVisible = FALSE;
//static BOOL controlKey = FALSE;
//static BOOL altKey = FALSE;
//static BOOL wasScreenSaverActive = FALSE;
//static BOOL myAppClosed = FALSE;
static BOOL controlQDisabled = FALSE;
//static uint8 gameName[80];
//BOOL gotTheFocus = FALSE;
//assume we always have focus for the time being - khalek
BOOL gotTheFocus = TRUE;
//HWND hwnd;
//RECT rcWindow;
//-----------------------------------------------------------------------------
void Zdebug(const char *format,...) {
#ifdef __PALM_OS__
char buf[256]; // 1024 is too big overflow the stack
#else
char buf[1024];
#endif
va_list va;
va_start(va, format);
vsprintf(buf, format, va);
va_end(va);
#ifdef __GP32__ //ph0x FIXME: implement fprint?
printf("ZDEBUG: %s\n", buf);
#else
fprintf(stderr, "ZDEBUG: %s!\n", buf);
#endif
#if defined( USE_WINDBG )
strcat(buf, "\n");
#if defined( _WIN32_WCE )
TCHAR buf_unicode[1024];
MultiByteToWideChar(CP_ACP, 0, buf, strlen(buf) + 1, buf_unicode, sizeof(buf_unicode));
OutputDebugString(buf_unicode);
#else
OutputDebugString(buf);
#endif
#endif
}
/*
void Zdebug(char *format,...) //Tony's special debug logging file March96
{
warning("stub Zdebug");
// Write a printf type string to a debug file
va_list arg_ptr; // Variable argument pointer
FILE * debug_filep=0; // Debug file pointer
static int first_debug = 1; // Flag for first time this is used
va_start(arg_ptr,format);
if (first_debug) //First time round delete any previous debug file
{
unlink("debug.txt");
first_debug = 0;
}
debug_filep = fopen("debug.txt","a+t");
if (debug_filep != NULL) // if it could be opened
{
vfprintf(debug_filep, format, arg_ptr);
fprintf(debug_filep,"\n");
fclose(debug_filep);
}
}
*/
//-----------------------------------------------------------------------------
/*
void Message(LPSTR fmt, ...)
{
char buff[256];
va_list va;
va_start(va, fmt);
//
// format message with header
//
lstrcpy( buff, "DRIVER96:" );
wvsprintf( &buff[lstrlen(buff)], fmt, va );
lstrcat( buff, "\r\n" );
//
// To the debugger
//
OutputDebugString( buff );
}
*/
//-----------------------------------------------------------------------------
// OSystem Event Handler. Full of cross platform goodness and 99% fat free!
//-----------------------------------------------------------------------------
void Sword2State::parseEvents() {
OSystem::Event event;
while (_system->poll_event(&event)) {
switch(event.event_code) {
case OSystem::EVENT_KEYDOWN:
if (event.kbd.flags==OSystem::KBD_CTRL) {
if (event.kbd.keycode == 'w')
GrabScreenShot();
}
WriteKey(event.kbd.ascii);
break;
case OSystem::EVENT_MOUSEMOVE:
mousex = event.mouse.x;
mousey = event.mouse.y - MENUDEEP;
break;
case OSystem::EVENT_LBUTTONDOWN:
LogMouseEvent(RD_LEFTBUTTONDOWN);
break;
case OSystem::EVENT_RBUTTONDOWN:
LogMouseEvent(RD_RIGHTBUTTONDOWN);
break;
case OSystem::EVENT_LBUTTONUP:
LogMouseEvent(RD_LEFTBUTTONUP);
break;
case OSystem::EVENT_RBUTTONUP:
LogMouseEvent(RD_RIGHTBUTTONUP);
break;
case OSystem::EVENT_QUIT:
Close_game();
CloseAppWindow();
break;
default:
break;
}
}
}
//-----------------------------------------------------------------------------
// Windows Message Handler. All keyboard and mouse input is handled here.
//-----------------------------------------------------------------------------
/*
long FAR PASCAL WindowsMessageHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
switch( message )
{
case WM_TIMER:
switch (wParam)
{
case 25:
FadeServer();
return(0);
case 1:
FxServer();
return(0);
}
break;
case WM_CLOSE:
Zdebug("WM_CLOSE");
break;
case WM_SIZE:
case WM_MOVE:
if (IsIconic(hwnd))
{
Message("minimising");
// PauseGame();
}
if (bFullScreen)
{
SetRect(&rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
}
else
{
GetClientRect(hwnd, &rcWindow);
ClientToScreen(hwnd, (LPPOINT)&rcWindow);
ClientToScreen(hwnd, (LPPOINT)&rcWindow+1);
}
Message("WINDOW RECT: [%d,%d,%d,%d]", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom);
if (bFullScreen)
{
SetCapture(hwnd);
}
else
{
ReleaseCapture();
}
// SetCursor(NULL);
// ShowCursor(FALSE);
break;
case WM_ACTIVATEAPP:
gotTheFocus = wParam;
if (gotTheFocus)
{
Message("Got the focus");
bMouseVisible = FALSE;
Message("Mouse invisible");
ShowCursor(FALSE);
}
else
{
if (bMouseVisible == FALSE)
ShowCursor(TRUE);
Message("Lost the focus");
bMouseVisible = TRUE;
Message("Mouse visible");
}
break;
case WM_SYSKEYUP:
switch( wParam )
{
// int32 rv;
// handle ALT+ENTER (fullscreen)
case VK_RETURN:
break;
}
break;
case WM_DISPLAYCHANGE:
break;
case WM_CREATE:
SystemParametersInfo(SPI_GETSCREENSAVEACTIVE , 0 , &wasScreenSaverActive , 0);
if (wasScreenSaverActive)
{
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE , FALSE , 0 , 0 );
}
break;
case WM_QUERYNEWPALETTE:
//
// we are getting the palette focus, select our palette
//
if (!bFullScreen && lpPalette && lpPrimarySurface)
{
int32 hr;
hr = IDirectDrawSurface_BS2_SetPalette(lpPrimarySurface, lpPalette);
if (hr == DDERR_SURFACELOST)
{
IDirectDrawSurface_Restore(lpPrimarySurface);
hr= IDirectDrawSurface_BS2_SetPalette(lpPrimarySurface, lpPalette);
if(hr == DDERR_SURFACELOST)
{
Message("Failed to restore palette after second try");
}
}
//
// Restore normal title if palette is ours
//
if(hr == DD_OK)
{
SetWindowText(hwnd, gameName);
}
}
break;
case WM_PALETTECHANGED:
//
// if another app changed the palette we dont have full control
// of the palette. NOTE this only applies for FoxBear in a window
// when we are fullscreen we get all the palette all of the time.
//
if ((HWND)wParam != hwnd)
{
if( !bFullScreen )
{
Message("Lost palette but continuing");
}
}
break;
// case WM_SETCURSOR:
// if (bMouseVisible)
// SetCursor(LoadCursor(NULL, IDC_ARROW));
// else
// SetCursor(NULL);
// return TRUE;
// break;
case WM_CHAR:
if (lParam & (1 << 30))
return(0);
WriteKey((char) (wParam & 0xff));
return(0);
case WM_KEYDOWN:
Zdebug("key %d", wParam);
switch( wParam )
{
case VK_CONTROL:
controlKey = TRUE;
break;
// case VK_ALT:
// altKey = TRUE;
// break;
case 'W':
if (controlKey)
GrabScreenShot();
return 0;
case 'Q':
if (controlKey && !controlQDisabled)
DestroyWindow( hWnd );
return 0;
case 'F4':
DestroyWindow( hWnd );
return 0;
}
break;
case WM_KEYUP:
switch(wParam)
{
case VK_CONTROL:
controlKey = FALSE;
break;
// case VK_ALT:
// altKey = FALSE;
// break;
}
break;
case WM_DESTROY:
Zdebug("*destroy*");
if (wasScreenSaverActive)
SystemParametersInfo(SPI_SETSCREENSAVEACTIVE , TRUE , 0 , 0 );
PostQuitMessage( 0 );
break;
case WM_MOUSEMOVE:
mousex = lParam & 0xffff;
if (bFullScreen)
{
mousey = (uint16) (lParam >> 16) - MENUDEEP;
}
else
{
mousey = (uint16) (lParam >> 16) - MENUDEEP;
if (mousex < 0)
mousex = 0;
if (mousex >= RENDERWIDE)
mousex = RENDERWIDE-1;
}
if (mousey < -MENUDEEP)
mousey = -MENUDEEP;
if (mousey >= RENDERDEEP + MENUDEEP)
mousey = RENDERDEEP + MENUDEEP - 1;
return(0);
case WM_LBUTTONDOWN:
LogMouseEvent(RD_LEFTBUTTONDOWN);
return(0);
case WM_LBUTTONUP:
LogMouseEvent(RD_LEFTBUTTONUP);
return(0);
case WM_RBUTTONDOWN:
LogMouseEvent(RD_RIGHTBUTTONDOWN);
return(0);
case WM_RBUTTONUP:
LogMouseEvent(RD_RIGHTBUTTONUP);
return(0);
case WM_LBUTTONDBLCLK:
LogMouseEvent(RD_LEFTBUTTONDOWN);
return(0);
case WM_RBUTTONDBLCLK:
LogMouseEvent(RD_RIGHTBUTTONDOWN);
case WM_SYSCOMMAND:
if (gotTheFocus)
return(0);
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
*/
/*
int32 InitialiseWindow(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow, char *gameName)
{
WNDCLASS wc;
// uint32 err;
// hPrevInstance = hPrevInstance;
wc.style = CS_DBLCLKS;
wc.lpfnWndProc = WindowsMessageHandler;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( hInstance, "resourc1"); //IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = gameName;
wc.lpszClassName = gameName;
RegisterClass( &wc );
// Create a window
hwnd = CreateWindowEx(WS_EX_APPWINDOW, gameName, gameName, WS_VISIBLE | WS_SYSMENU | WS_POPUP, 0, 0,
GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ),
NULL, NULL, hInstance, NULL );
if(!hwnd)
{
MessageBox(hwnd, "Failed to create window", gameName, MB_OK );
DestroyWindow(hwnd);
return(RDERR_CREATEWINDOW);
}
// ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
SetFocus(hwnd);
SetTimer(hwnd, 25, 1000 / 25, NULL);
SetTimer(hwnd, 1, 100, NULL);
return(RD_OK);
}
*/
int32 CloseAppWindow(void)
{
warning("stub CloseAppWindow");
/*
DestroyWindow(hwnd);
*/
// just quit for now
g_system->quit();
return(RD_OK);
}
static bool _needRedraw = false;
void SetNeedRedraw() {
_needRedraw = true;
}
int32 ServiceWindows(void)
{
g_sword2->parseEvents();
FadeServer();
// FIXME: We re-render the entire picture area of the screen for each
// frame, which is pretty horrible.
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;
if (myAppClosed)
return(RDERR_APPCLOSED);
while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE))
{
if (!GetMessage(&msg, NULL, 0, 0))
{
myAppClosed = TRUE;
return(RDERR_APPCLOSED);
}
TranslateMessage(&msg);
DispatchMessage(&msg);
}
*/
return(RD_OK);
}
int32 _ReportDriverError(int32 error, const uint8 *filename, uint32 line)
{
warning("stub _ReportDriverError 0x%.8x file: %s, line: %d ", error, (const char *) filename, line);
/*
char errorText[128];
char name[80];
GetGameName(name);
sprintf(errorText, "Fatal error in %s, line %u! Code 0x%.8x", filename, line, error);
MessageBox(hwnd, errorText, name, MB_SYSTEMMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE);
*/
return(RD_OK);
}
int32 _ReportFatalError(const uint8 *error, const uint8 *filename, uint32 line)
{
warning("stub _ReportFatalError");
char errorText[500];
char name[80];
GetGameName((uint8 *)name);
sprintf(errorText, "FATAL ERROR - GAME TERMINATED\n%s", error);
//MessageBox(hwnd, errorText, name, MB_SYSTEMMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE);
warning("%s", errorText);
return(RD_OK);
}
int32 DisableQuitKey(void)
{
controlQDisabled = TRUE;
return(RD_OK);
}
void SetWindowName(const char *windowName)
{
warning("stub SetWindowName( %s )", windowName);
// SetWindowText(hwnd,windowName);
// strcpy(gameName,windowName);
}