diff options
Diffstat (limited to 'sword2/driver/render.cpp')
-rw-r--r-- | sword2/driver/render.cpp | 1283 |
1 files changed, 1283 insertions, 0 deletions
diff --git a/sword2/driver/render.cpp b/sword2/driver/render.cpp new file mode 100644 index 0000000000..589a86e2ab --- /dev/null +++ b/sword2/driver/render.cpp @@ -0,0 +1,1283 @@ +/* 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$ + */ + +//============================================================================= +// +// Filename : render.c +// Created : 26th September 1996 +// By : P.R.Porter +// +// Summary : This module holds the functions which deal with rendering +// the background and parallax layers, and controlling the +// speed of the scroll (number of frames) +// +// Version Date By Description +// ------- --------- --- ----------------------------------------------- +// 1.0 26-Sep-96 PRP The functions have been moved here from d_draw +// because this is a more sensible place for them. +// +// 1.1 04-Oct-96 PRP Added direct path to ddraw.h +// +// 1.2 09-Oct-96 PRP Moved SOFTWARE_SCREEN_BUFFER into driver96.h, +// and renamed to RD_SOFTWARESCREENBUFFER. +// +// 1.3 23-Oct-96 PRP Moved definition of _parallaxLine structure to +// render.h. Got rid of the divide by zero error. +// +// 1.4 05-Nov-96 PRP Moved defines of RENDERWIDE, RENDERDEEP, etc., +// to render.h +// +// 1.5 15-Nov-96 PRP Definition of menu size is now obtained from +// menu.h +// +// 1.6 18-Nov-96 PRP Changed the direct draw interface to +// IDirectDraw2. Added the PlotPoint and +// DrawLine functions. +// +// 1,7 21-Nov-96 PRP Implemented the DrawLine function. +// +// 1.8 24-Jan-97 PRP Added parallaxScrollx and parallaxScrolly to +// define the offset for linking sprites to +// parallax layers. +// +// 1.9 06-Feb-97 PRP Added rendering functions to draw from display +// memory. Made the code switchable so that if +// the hardware is not available, the old software +// rendering functions are used. +// +// 1.10 06-Feb-97 PRP Fixed a bug with releasing the surfaces for a +// room. +// +// 1.11 06-Feb-97 PRP Implemented PlotPoint and DrawLine for hardware +// version. +// +// 1.12 07-Feb-97 PRP Implemented function to restore the background +// layers. Changed the layer rendering code to +// restore the layers when they've gone. +// +// 1.13 07-Feb-97 PRP Fixed a bug in the layer renderer, which +// dropped out when the first block in a layer was +// blank. +// +// 1.14 10-Feb-97 PRP Changed the calls to the direct draw error +// reporting code, and made the rendering dependant +// upon the hardware functions availability. +// +// 1.15 12-Feb-97 PRP Fixed rendering position bug. +// +// 1.16 18-Mar-97 PRP Fixed the smooth scroll, and render timing. +// Added a function to initialise the render timer +// +// 1.17 18-Mar-97 PRP Added code to profile the rendering functions. +// +// 1.18 04-Apr-97 PRP Restored the primary surface and back buffer +// before the parallax layers. +// +// 1.19 07-Apr-97 PRP No changes. +// +// 1.20 08-Apr-97 JEL Made location wide and location deep global. +// +// 1.21 10-Apr-97 PRP Added the return value RDERR_LOCKFAILED to +// the CopyScreenBuffer function. +// +// 1.22 11-Apr-97 PRP Added function to clear the software render +// buffer. +// +// 1.23 11-Apr-97 PRP Fixed benign redefinition of type bug +// +// 1.24 13-Jun-97 PRP Fixed switching between hardware and software +// rendering during gameplay. +// +// 1.25 30-Jun-97 JEL Tried to fix sc23 sprite position bug, but no changes made in the end +// +// 1.26 08-July-97 JEL Fixed bug in RenderParallax for when not gotTheFocus, to prevent crash when switching task in NT +// +// Functions +// --------- +// +// --------------------------------------------------------------------------- +// +// int32 RenderParallax(_parallax *p, int16 layer) +// +// Draws a parallax layer at the current position determined by the scroll. +// A parallax can be either foreground, background or the main screen. +// +// --------------------------------------------------------------------------- +// +// int32 CopyScreenBuffer(void) +// +// Copies the screen buffer to screen memory. This function should be called +// when the drawing should be done to the back buffer. It only does this +// when we are using a software screen buffer. +// +// --------------------------------------------------------------------------- +// +// int32 SetScrollTarget(int16 sx, int16 sy) +// +// Sets the scroll target position for the end of the game cycle. The drivers +// will then automatically scroll as many times as it can to reach this +// position in the allotted time. +// +// -------------------------------------------------------------------------- +// +// int32 StartRenderCycle(void) +// +// This function should be called when the game engine is ready to start +// the render cycle. +// +// -------------------------------------------------------------------------- +// +// int32 EndRenderCycle(BOOL *end) +// +// This function should be called at the end of the render cycle. If the +// render cycle is to be terminated, the function sets *end to 1. Otherwise, +// the render cycle should continue. +// +// -------------------------------------------------------------------------- +// +// int32 SetLocationMetrics(uint16 w, uint16 h) +// +// This function tells the drivers the size of the background screen for the +// current location. +// +// -------------------------------------------------------------------------- +// +// int32 PlotPoint(uint16 x, uint16 y, uint8 colour) +// +// Plots the point x,y in relation to the top left corner of the background. +// +// -------------------------------------------------------------------------- +// +// int32 DrawLine(int16 x1, int16 y1, int16 x2, int16 y2, uint8 colour) +// +// Draws a line from the point x1,y1 to x2,y2 of the specified colour. +// +// -------------------------------------------------------------------------- +// +// int32 InitialiseBackgroundLayer(_parallax *p) +// +// This function should be called five times with either the parallax layer +// or a NULL pointer in order of background parallax to foreground parallax. +// +// -------------------------------------------------------------------------- +// +// int32 CloseBackgroundLayer(void) +// +// Should be called once after leaving a room to free up video memory. +// +// -------------------------------------------------------------------------- +// +// int32 PlotDots(int16 x, int16 y, int16 count) +// +// Plots 'count' dots at the position x,y. +// +//============================================================================= + + + + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> +//#include <mmsystem.h> +#include <stdio.h> + +//#include "ddraw.h" + +#include "driver96.h" +#include "d_draw.h" +#include "rdwin.h" +#include "_mouse.h" +#include "render.h" +#include "menu.h" + + + +#define MILLISECSPERCYCLE 83 + + + +#if PROFILING == 1 +int32 profileCopyScreenBuffer = 0; +int32 profileRenderLayers = 0; +int32 profileSpriteRender = 0; +int32 profileDecompression = 0; +#endif + + + + +uint8 myScreenBuffer[RENDERWIDE * RENDERDEEP]; + + + + + +// Scroll variables. scrollx and scrolly hold the current scroll position, +// and scrollxTarget and scrollyTarget are the target position for the end +// of the game cycle. + +//int16 scrollx; +//int16 scrolly; +extern int16 scrollx; +extern int16 scrolly; +int16 parallaxScrollx; +int16 parallaxScrolly; +int16 locationWide; +int16 locationDeep; + +static int16 scrollxTarget; +static int16 scrollyTarget; +static int16 scrollxOld; +static int16 scrollyOld; +static uint16 layer = 0; + + + +#define RENDERAVERAGETOTAL 4 +int32 renderCountIndex = 0; +int32 renderTimeLog[RENDERAVERAGETOTAL] = {60, 60, 60, 60}; +int32 initialTime; +int32 startTime; +int32 originTime; +int32 totalTime; +int32 renderAverageTime = 60; +int32 framesPerGameCycle; +int32 renderTooSlow; + + + + +#define BLOCKWIDTH 64 +#define BLOCKHEIGHT 64 +#define BLOCKWBITS 6 +#define BLOCKHBITS 6 +#define MAXLAYERS 5 + +uint8 xblocks[MAXLAYERS]; +uint8 yblocks[MAXLAYERS]; +uint8 restoreLayer[MAXLAYERS]; +//LPDIRECTDRAWSURFACE *blockSurfaces[MAXLAYERS] = {0,0,0,0,0}; + + + + +int32 RestoreBackgroundLayer(_parallax *p, int16 l) +{ + warning("stub RestoreBackgroundLayer %d", l); +/* + int16 oldLayer = layer; + int16 i; + + layer = l; + if (blockSurfaces[l]) + { + for (i=0; i<xblocks[l] * yblocks[l]; i++) + if (*(blockSurfaces[l]+i)) + IDirectDrawSurface2_Release(*(blockSurfaces[l] + i)); + free(blockSurfaces[l]); + blockSurfaces[l] = NULL; + } + RestoreSurfaces(); + InitialiseBackgroundLayer(p); + layer = oldLayer; +*/ + return(RD_OK); + +} + + + + + + +int32 PlotPoint(uint16 x, uint16 y, uint8 colour) + +{ + warning("stub PlotPoint( %d, %d, %d )", x, y, colour); +/* + int16 newx, newy; + + newx = x - scrollx; + newy = y - scrolly; + + if ((newx < 0) || (newx > RENDERWIDE) || (newy < 0) || (newy > RENDERDEEP)) + { + return(RD_OK); + } + if (renderCaps & RDBLTFX_ALLHARDWARE) + { + DDSURFACEDESC ddsd; + HRESULT hr; + + ddsd.dwSize = sizeof(DDSURFACEDESC); + hr = IDirectDrawSurface2_Lock(lpBackBuffer, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + RestoreSurfaces(); + hr = IDirectDrawSurface2_Lock(lpBackBuffer, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + } + + if (hr == DD_OK) + { + + *((uint8 *) ddsd.lpSurface + (newy + 40) * ddsd.lPitch + newx) = colour; + IDirectDrawSurface2_Unlock(lpBackBuffer, ddsd.lpSurface); + } + } + else + myScreenBuffer[newy * RENDERWIDE + newx] = colour; +*/ + return(RD_OK); + +} + + +// Uses Bressnham's incremental algorithm! +int32 DrawLine(int16 x0, int16 y0, int16 x1, int16 y1, uint8 colour) + +{ + warning("stub DrawLine( %d, %d, %d, %d, %d )", x0, y0, x1, y1, colour); +/* + int dx, dy; + int dxmod, dymod; + int ince, incne; + int d; + int x, y; + int addTo; + DDSURFACEDESC ddsd; + HRESULT hr; + + x1 -= scrollx; + y1 -= scrolly; + x0 -= scrollx; + y0 -= scrolly; + + + // Lock the surface if we're rendering to the back buffer. + + if (renderCaps & RDBLTFX_ALLHARDWARE) + { + ddsd.dwSize = sizeof(DDSURFACEDESC); + hr = IDirectDrawSurface2_Lock(lpBackBuffer, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + RestoreSurfaces(); + hr = IDirectDrawSurface2_Lock(lpBackBuffer, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + } + if (hr != DD_OK) + return(RD_OK); + + (uint8 *) ddsd.lpSurface += (40 * ddsd.lPitch); + + } + + + + + //Make sure we're going from left to right + if (x1 < x0) + { + x = x1; + x1 = x0; + x0 = x; + y = y1; + y1 = y0; + y0 = y; + } + dx = x1 - x0; + dy = y1 - y0; + + if (dx < 0) + dxmod = -dx; + else + dxmod = dx; + + if (dy < 0) + dymod = -dy; + else + dymod = dy; + + if (dxmod >= dymod) + { + if (dy > 0) + { + d = 2 * dy - dx; + ince = 2 * dy; + incne = 2 * (dy - dx); + x = x0; + y = y0; + if ((x >= 0) && (x < RENDERWIDE) && (y >= 0) && (y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + y * ddsd.lPitch + x) = colour; + else + myScreenBuffer[y * RENDERWIDE + x] = colour; + while (x < x1) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + if ((x >= 0) && (x < RENDERWIDE) && (y >= 0) && (y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + y * ddsd.lPitch + x) = colour; + else + myScreenBuffer[y * RENDERWIDE + x] = colour; + } + } + else + { + addTo = y0; + y0 = 0; + y1 -= addTo; + y1 = -y1; + dy = y1 - y0; + + d = 2 * dy - dx; + ince = 2 * dy; + incne = 2 * (dy - dx); + x = x0; + y = y0; + if ((x >= 0) && (x < RENDERWIDE) && (addTo - y >= 0) && (addTo - y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + (addTo - y) * ddsd.lPitch + x) = colour; + else + myScreenBuffer[(addTo - y) * RENDERWIDE + x] = colour; + while (x < x1) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + if ((x >= 0) && (x < RENDERWIDE) && (addTo - y >= 0) && (addTo - y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + (addTo - y) * ddsd.lPitch + x) = colour; + else + myScreenBuffer[(addTo - y) * RENDERWIDE + x] = colour; + } + + } + } + else + { + //OK, y is now going to be the single increment. + // Ensure the line is going top to bottom + if (y1 < y0) + { + x = x1; + x1 = x0; + x0 = x; + y = y1; + y1 = y0; + y0 = y; + } + dx = x1 - x0; + dy = y1 - y0; + + if (dx > 0) + { + d = 2 * dx - dy; + ince = 2 * dx; + incne = 2 * (dx - dy); + x = x0; + y = y0; + if ((x >= 0) && (x < RENDERWIDE) && (y >= 0) && (y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + y * ddsd.lPitch + x) = colour; + else + myScreenBuffer[y * RENDERWIDE + x] = colour; + while (y < y1) + { + if (d <= 0) + { + d += ince; + y += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + if ((x >= 0) && (x < RENDERWIDE) && (y >= 0) && (y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + y * ddsd.lPitch + x) = colour; + else + myScreenBuffer[y * RENDERWIDE + x] = colour; + } + } + else + { + addTo = x0; + x0 = 0; + x1 -= addTo; + x1 = -x1; + dx = x1 - x0; + + d = 2 * dx - dy; + ince = 2 * dx; + incne = 2 * (dx - dy); + x = x0; + y = y0; + if ((addTo - x >= 0) && (addTo - x < RENDERWIDE) && (y >= 0) && (y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + y * ddsd.lPitch + addTo - x) = colour; + else + myScreenBuffer[y * RENDERWIDE + addTo - x] = colour; + while (y < y1) + { + if (d <= 0) + { + d += ince; + y += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + if ((addTo - x >= 0) && (addTo - x < RENDERWIDE) && (y >= 0) && (y < RENDERDEEP)) + if (renderCaps & RDBLTFX_ALLHARDWARE) + *((uint8 *) ddsd.lpSurface + y * ddsd.lPitch + addTo - x) = colour; + else + myScreenBuffer[y * RENDERWIDE + addTo - x] = colour; + } + + } + + } + + if (renderCaps & RDBLTFX_ALLHARDWARE) + { + (uint8 *) ddsd.lpSurface -= (40 * ddsd.lPitch); + IDirectDrawSurface2_Unlock(lpBackBuffer, ddsd.lpSurface); + } +*/ + return(RD_OK); + +} + + + +int32 SetLocationMetrics(uint16 w, uint16 h) + +{ + + locationWide = w; + locationDeep = h; + + return(RD_OK); + +} + + + +int32 RenderParallax(_parallax *p, int16 layer) + +{ + warning("stub RenderParallax %d", layer); +/* + +#if PROFILING == 1 + + LARGE_INTEGER startTime, endTime; + + QueryPerformanceCounter(&startTime); + +#endif + + if ((renderCaps & RDBLTFX_ALLHARDWARE) || ((renderCaps & RDBLTFX_FGPARALLAX) && (layer > 2))) + { + + int16 x, y; + int16 i, j; + int16 restoreSurfaces = 0; + HRESULT hr = 0; + RECT r, rd; + + if (restoreLayer[layer]) + { + RestoreBackgroundLayer(p, layer); + restoreLayer[layer] = 0; + } + + if (locationWide == screenWide) + x = 0; + else + x = ((int32) ((p->w - screenWide) * scrollx) / (int32) (locationWide - screenWide)); + + if (locationDeep == (screenDeep - MENUDEEP*2)) + y = 0; + else + y = ((int32) ((p->h - (screenDeep - MENUDEEP*2)) * scrolly) / (int32) (locationDeep - (screenDeep - MENUDEEP*2))); + + + while (TRUE) + { + j = 0; + while (j < yblocks[layer]) + { + i = 0; + while (i < xblocks[layer]) + { + if (*(blockSurfaces[layer] + i + j * xblocks[layer])) + { + r.left = i * BLOCKWIDTH - x; + r.right = r.left + BLOCKWIDTH; + r.top = j * BLOCKHEIGHT - y + 40; + r.bottom = r.top + BLOCKHEIGHT; + rd.left = 0; + rd.right = BLOCKWIDTH; + rd.top = 0; + rd.bottom = BLOCKHEIGHT; + + if ((r.left < 0) && (r.left > 0 - BLOCKWIDTH)) + { + rd.left = 0 - r.left; + r.left = 0; + } + if ((r.top < 40) && (r.top > 40 - BLOCKHEIGHT)) + { + rd.top = 40 - r.top; + r.top = 40; + } + if ((r.right > 640) && (r.right < 640 + BLOCKWIDTH)) + { + rd.right = BLOCKWIDTH - (r.right - 640); + r.right = 640; + } + if ((r.bottom > 440) && (r.bottom < 440 + BLOCKHEIGHT)) + { + rd.bottom = BLOCKHEIGHT - (r.bottom - 440); + r.bottom = 440; + } + hr = IDirectDrawSurface2_Blt(lpBackBuffer, &r, *(blockSurfaces[layer] + i + j * xblocks[layer]), &rd, DDBLT_WAIT | DDBLT_KEYSRC, NULL); + if (hr == DDERR_INVALIDRECT) + hr = 0; + if (hr) + break; + } + i++; + if (hr) + break; + } + j++; + if (hr) + break; + } + if (hr) + { + if (hr == DDERR_SURFACELOST) + { + if (gotTheFocus) + { + if (++restoreSurfaces == 4) + return(RDERR_RESTORELAYERS); + else + RestoreBackgroundLayer(p, layer); + } + else + return(RD_OK); + } + else + return(hr); + + } + else + break; + } + + parallaxScrollx = scrollx - x; + parallaxScrolly = scrolly - y; + } + else + { + uint8 zeros; + uint16 count; + uint16 skip; + uint16 i, j; + uint16 x; + int32 px, py; + uint8 *data; + uint8 *dst; + _parallaxLine *line; + + if (locationWide == screenWide) + px = 0; + else + px = ( (int32) ((p->w - screenWide) * scrollx) / (int32) (locationWide - screenWide)); + + if (locationDeep == (screenDeep - MENUDEEP*2)) + py = 0; + else + py = ( (int32) ((p->h - (screenDeep - MENUDEEP*2)) * scrolly) / (int32) (locationDeep - (screenDeep - MENUDEEP*2))); + + + for (i = py; i < py + (screenDeep - MENUDEEP * 2); i++) + { + if (p->offset[i] == 0) + continue; + + line = (_parallaxLine *) ((uint8 *) p + p->offset[i]); + data = (uint8 *) line + sizeof(_parallaxLine); + x = line->offset; + if (x > px) + skip = x - px; + else + skip = 0; + + dst = myScreenBuffer + (i - py) * RENDERWIDE + skip; + + + zeros = 0; + if (line->packets == 0) + { + data += px; + memcpy(dst, data, screenWide); + continue; + } + + for (j=0; j<line->packets; j++) + { + if (zeros) + { + if (x >= px) + { + dst += *data; + x += *data; + } + else + { + x += *data; + if (x > px) + { + dst += (x - px); + } + } + data += 1; + zeros = 0; + } + else + { + if (*data == 0) + { + data ++; + } + else if (x >= px) + { + if (x + *data <= px + screenWide) + { + count = *data++; + memcpy(dst, data, count); + data += count; + dst += count; + x += count; + } + else if (x < px + screenWide) + { + data++; + count = screenWide - (x - px); + memcpy(dst, data, count); + j = line->packets; + } + } + else + { + count = *data++; + + if (x + count > px) + { + skip = px - x; + data += skip; + count -= skip; + memcpy(dst, data, count); + data += count; + dst += count; + x += count + skip; + } + else + { + data += count; + x += count; + if (x > px) + { + dst += (x - px); + } + } + } + zeros = 1; + } + } + } + + parallaxScrollx = scrollx - px; + parallaxScrolly = scrolly - py; + } + +#if PROFILING == 1 + QueryPerformanceCounter(&endTime); + profileRenderLayers += (endTime.LowPart - startTime.LowPart); +#endif +*/ + return(RD_OK); + +} + + + + + + +/* +#define LOGSIZE 10 +int32 previousTimeLog[LOGSIZE]; +int32 renderCycleStartLog[LOGSIZE]; +int32 lastRenderTimeLog[LOGSIZE]; +int32 renderCycleEndLog[LOGSIZE]; +int32 timeLeftLog[LOGSIZE]; +int32 scrollxOldLog[LOGSIZE]; +int32 scrollxLog[LOGSIZE]; +int32 scrollxTargetLog[LOGSIZE]; + + +void LogMe(int32 in) +{ + static int32 i; + + if (in == 0) + i = 0; + + previousTimeLog[i] = previousTime; + aveRenderCycleLog[i] = aveRenderCycle; + renderCycleStartLog[i] = renderCycleStart; + lastRenderTimeLog[i] = lastRenderTime; + renderCycleEndLog[i] = renderCycleEnd; + timeLeftLog[i] = timeLeft; + scrollxOldLog[i] = scrollxOld; + scrollxLog[i] = scrollx; + scrollxTargetLog[i] = scrollxTarget; + + if (++i == LOGSIZE) + i = 0; + +} +*/ + + +int32 InitialiseRenderCycle(void) + +{ + + initialTime = timeGetTime(); + originTime = initialTime; + totalTime = initialTime + MILLISECSPERCYCLE; + + return(RD_OK); + +} + + + +int32 StartRenderCycle(void) + +{ + + + scrollxOld = scrollx; + scrollyOld = scrolly; + + startTime = timeGetTime(); + + if (startTime + renderAverageTime >= totalTime) + { + scrollx = scrollxTarget; + scrolly = scrollyTarget; + renderTooSlow = 1; + } + else + { + scrollx = scrollxOld + ((scrollxTarget - scrollxOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime); + scrolly = scrollyOld + ((scrollyTarget - scrollyOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime); + renderTooSlow = 0; + } + + framesPerGameCycle = 0; + + return(RD_OK); + +} + + + +int32 EndRenderCycle(BOOL *end) + +{ + + int32 time; + + time = timeGetTime(); + renderTimeLog[renderCountIndex] = time - startTime; + startTime += renderTimeLog[renderCountIndex]; + renderAverageTime = (renderTimeLog[0] + renderTimeLog[1] + renderTimeLog[2] + renderTimeLog[3]) >> 2; + + framesPerGameCycle += 1; + + if (++renderCountIndex == RENDERAVERAGETOTAL) + renderCountIndex = 0; + + if (renderTooSlow) + { + *end = TRUE; + InitialiseRenderCycle(); + } + else if (startTime + renderAverageTime >= totalTime) + { + *end = TRUE; + originTime = totalTime; + totalTime += MILLISECSPERCYCLE; + initialTime = time; + } + else + { + *end = FALSE; + scrollx = scrollxOld + ((scrollxTarget - scrollxOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime); + scrolly = scrollyOld + ((scrollyTarget - scrollyOld) * (startTime - initialTime + renderAverageTime)) / (totalTime - initialTime); + } + + return(RD_OK); + +} + + +int32 SetScrollTarget(int16 sx, int16 sy) + +{ + + scrollxTarget = sx; + scrollyTarget = sy; + + return(RD_OK); + +} + +int32 CopyScreenBuffer(void) + +{ + warning("stub CopyScreenBuffer"); +/* + + uint8 *dst, *src; + int16 i; + DDSURFACEDESC ddDescription; + HRESULT hr; + +#if PROFILING == 1 + static LARGE_INTEGER endTime; + LARGE_INTEGER startTime; + int32 lastEndTime, profileTotalTime; +#endif + + +#if PROFILING == 1 + QueryPerformanceCounter(&startTime); +// time = timeGetTime(); +#endif + + + if (!(renderCaps & RDBLTFX_ALLHARDWARE)) + { + ddDescription.dwSize = sizeof(ddDescription); + hr = IDirectDrawSurface2_Lock(lpBackBuffer, NULL, &ddDescription, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + RestoreSurfaces(); + hr = IDirectDrawSurface2_Lock(lpBackBuffer, NULL, &ddDescription, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + } + if (hr == DD_OK) + { + dst = (uint8 *) ddDescription.lpSurface + MENUDEEP * ddDescription.lPitch; + src = myScreenBuffer; + for (i=0; i<RENDERDEEP; i++) + { + memcpy(dst, src, screenWide); + src += RENDERWIDE; + dst += ddDescription.lPitch; + } + IDirectDrawSurface2_Unlock(lpBackBuffer, ddDescription.lpSurface); + } + else + { + return(RDERR_LOCKFAILED); + } + } + +#if PROFILING == 1 + lastEndTime = endTime.LowPart; + QueryPerformanceCounter(&endTime); + profileCopyScreenBuffer = (int32) (endTime.LowPart - startTime.LowPart) / 1000; + profileTotalTime = (endTime.LowPart - lastEndTime) / 1000; + if ((profileTotalTime > 0) && (profileTotalTime < 5000)) + PlotDots(0, 5, (int16) profileTotalTime); + PlotDots(0, 10, (int16) profileCopyScreenBuffer); + PlotDots(0, 15, (int16) (profileRenderLayers / 1000)); + PlotDots(0, 20, (int16) (profileSpriteRender / 1000)); + PlotDots(0, 25, (int16) (profileDecompression / 1000)); + profileRenderLayers = 0; + profileSpriteRender = 0; + profileDecompression = 0; +#endif +*/ + return(RD_OK); +} + + + +int32 InitialiseBackgroundLayer(_parallax *p) + +{ + warning("stub InitialiseBackgroundLayer"); +/* + uint8 *memchunk; + uint32 *quaddata; + uint8 zeros; + uint16 count; +// uint16 skip; + uint16 i, j, k; + uint16 x; + uint8 *data; + uint8 *dst; + _parallaxLine *line; + HRESULT hr; + DDSURFACEDESC ddsd; + + + if ((renderCaps & RDBLTFX_ALLHARDWARE) || ((renderCaps & RDBLTFX_FGPARALLAX) && (layer > 2))) + { + + // This function is called to re-initialise the layers if they have been lost. + // We know this if the layers have already been assigned. + if (layer == MAXLAYERS) + { + CloseBackgroundLayer(); + // RestoreSurfaces(); // for the primary and back buffer. + } + + + if (p == NULL) + { + layer += 1; + return(RD_OK); + } + + xblocks[layer] = (p->w + BLOCKWIDTH - 1) >> BLOCKWBITS; + yblocks[layer] = (p->h + BLOCKHEIGHT - 1) >> BLOCKHBITS; + blockSurfaces[layer] = (LPDIRECTDRAWSURFACE *) malloc(xblocks[layer] * yblocks[layer] * sizeof(LPDIRECTDRAWSURFACE)); + if (blockSurfaces[layer] == NULL) + return(RDERR_OUTOFMEMORY); + + // Decode the parallax layer into a large chunk of memory + memchunk = (uint8 *) malloc(xblocks[layer] * BLOCKWIDTH * yblocks[layer] * BLOCKHEIGHT); + if (memchunk == NULL) + return(RDERR_OUTOFMEMORY); + + memset(memchunk, 0, p->w * p->h); + + for (i = 0; i < p->h; i++) + { + if (p->offset[i] == 0) + continue; + + line = (_parallaxLine *) ((uint8 *) p + p->offset[i]); + data = (uint8 *) line + sizeof(_parallaxLine); + x = line->offset; + + dst = memchunk + i * p->w + x; + + zeros = 0; + if (line->packets == 0) + { + memcpy(dst, data, p->w); + continue; + } + + for (j=0; j<line->packets; j++) + { + if (zeros) + { + dst += *data; + x += *data; + data += 1; + zeros = 0; + } + else + { + if (*data == 0) + { + data ++; + zeros = 1; + } + else + { + count = *data++; + memcpy(dst, data, count); + data += count; + dst += count; + x += count; + zeros = 1; + } + } + } + } + + // Now create the surfaces! + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(DDSURFACEDESC); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + if (dxHalCaps & RDCAPS_SRCBLTCKEY) + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + else + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + + ddsd.dwWidth = BLOCKWIDTH; + ddsd.dwHeight = BLOCKHEIGHT; + for (i=0; i<xblocks[layer] * yblocks[layer]; i++) + { + // Only assign a surface to the block if it contains data. + quaddata = (int32 *) (memchunk + (p->w * BLOCKHEIGHT * (i / xblocks[layer])) + BLOCKWIDTH * (i % xblocks[layer])); + for (j=0; j<BLOCKHEIGHT; j++) + { + for (k=0; k<BLOCKWIDTH / 4; k++) + { + if (*quaddata) + break; + quaddata++; + } + quaddata += ((p->w - BLOCKWIDTH) / 4); + if (k < BLOCKWIDTH / 4) + break; + } + + if (k < BLOCKWIDTH / 4) + { + hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, blockSurfaces[layer] + i, NULL); + if (hr != DD_OK) + { + if (hr == DDERR_OUTOFVIDEOMEMORY) + { + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; + hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, blockSurfaces[layer] + i, NULL); + } + if (hr != DD_OK) + { + DirectDrawError("Cannot create parallax surface", hr); + return(hr); + } + } + // Set the surface blt source colour key + hr = IDirectDrawSurface2_SetColorKey(*(blockSurfaces[layer] + i), DDCKEY_SRCBLT, &blackColorKey); + + // Copy the data into the surfaces. + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(DDSURFACEDESC); + hr = IDirectDrawSurface2_Lock(*(blockSurfaces[layer] + i), NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + IDirectDrawSurface2_Restore(*(blockSurfaces[layer] + i)); + hr = IDirectDrawSurface2_Lock(*(blockSurfaces[layer] + i), NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + DirectDrawError("Cannot lock parallax surface", hr); + return(hr); + } + } + + data = memchunk + (p->w * BLOCKHEIGHT * (i / xblocks[layer])) + BLOCKWIDTH * (i % xblocks[layer]); + dst = ddsd.lpSurface; + for (j=0; j<BLOCKHEIGHT; j++) + { + memcpy(dst, data, BLOCKWIDTH); + data += p->w; + dst += ddsd.lPitch; + } + IDirectDrawSurface2_Unlock(*(blockSurfaces[layer] + i), ddsd.lpSurface); + } + else + { + *(blockSurfaces[layer] + i) = NULL; + } + } + free(memchunk); + } + layer += 1; +*/ + return(RD_OK); + +} + + +int32 CloseBackgroundLayer(void) + +{ + warning("stub CloseBackgroundLayer"); +/* + int16 i, j; + +// if (renderCaps & RDBLTFX_ALLHARDWARE) +// { + for (j=0; j<MAXLAYERS; j++) + { + if (blockSurfaces[j]) + { + for (i=0; i<xblocks[j] * yblocks[j]; i++) + if (*(blockSurfaces[j]+i)) + IDirectDrawSurface2_Release(*(blockSurfaces[j] + i)); + free(blockSurfaces[j]); + blockSurfaces[j] = NULL; + } + } + layer = 0; +// } +*/ + return(RD_OK); + +} + + +int32 EraseSoftwareScreenBuffer(void) +{ + memset(myScreenBuffer, 0, RENDERWIDE * RENDERDEEP); + return(RD_OK); +} |