mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-05 17:57:14 +00:00
patch #790060 SWORD2: Initial graphics work from erik very nice indeed :)
svn-id: r9737
This commit is contained in:
parent
d343ef10b3
commit
48ceff0545
@ -45,6 +45,8 @@
|
||||
#define MILLISECSPERCYCLE 83
|
||||
|
||||
|
||||
// Surface *lpPrimarySurface;
|
||||
Surface *lpBackBuffer;
|
||||
|
||||
/*
|
||||
LPDIRECTDRAW7 m_pDD;
|
||||
@ -234,6 +236,12 @@ int32 RestoreDisplay(void)
|
||||
|
||||
int32 InitialiseDisplay(int16 width, int16 height, int16 colourDepth, int32 windowType)
|
||||
{
|
||||
screenWide = width;
|
||||
screenDeep = height;
|
||||
|
||||
// lpPrimarySurface = new Surface(width, height);
|
||||
lpBackBuffer = new Surface(width, height);
|
||||
|
||||
/*
|
||||
DDSURFACEDESC ddsd;
|
||||
DDSCAPS ddscaps;
|
||||
@ -715,7 +723,11 @@ int32 GetRenderType(void)
|
||||
int32 FlipScreens(void)
|
||||
|
||||
{
|
||||
warning("stub FlipScreens");
|
||||
// I think this function can be removed. We render to lpBackBuffer,
|
||||
// and the backend acts as the primary buffer.
|
||||
|
||||
debug(0, "FlipScreens");
|
||||
|
||||
/*
|
||||
HRESULT hr;
|
||||
BOOL vbl;
|
||||
@ -825,7 +837,9 @@ int32 WaitForVbl(void)
|
||||
|
||||
int32 EraseBackBuffer( void )
|
||||
{
|
||||
warning("stub EraseBackBuffer");
|
||||
debug(0, "EraseBackBuffer");
|
||||
lpBackBuffer->clear();
|
||||
|
||||
/*
|
||||
DDBLTFX ddbltfx;
|
||||
HRESULT hr;
|
||||
@ -1224,7 +1238,7 @@ void GetDrawStatus(_drvDrawStatus *s)
|
||||
// s->lpDraw = lpDraw;
|
||||
// s->lpDD2 = lpDD2;
|
||||
// s->lpPrimarySurface = lpPrimarySurface;
|
||||
// s->lpBackBuffer = lpBackBuffer;
|
||||
s->lpBackBuffer = lpBackBuffer;
|
||||
// s->lpPalette = lpPalette;
|
||||
s->screenDeep = screenDeep;
|
||||
s->screenWide = screenWide;
|
||||
|
@ -78,8 +78,8 @@ extern "C" {
|
||||
|
||||
|
||||
extern uint8 *lpPalette; // palette
|
||||
extern uint8 *lpBackBuffer; // back surface
|
||||
extern uint8 *lpPrimarySurface; // DirectDraw front buffer.
|
||||
extern Surface *lpBackBuffer; // back surface
|
||||
// extern Surface *lpPrimarySurface; // DirectDraw front buffer.
|
||||
extern uint8 *lpDD2; // DirectDraw2 object
|
||||
extern BOOL bFullScreen; // Defines whether the app is running in full screen mode or not.
|
||||
//extern DDCOLORKEY blackColorKey; // transparent pixel for color key blitting.
|
||||
|
@ -1053,6 +1053,7 @@
|
||||
#include "common/scummsys.h"
|
||||
#include "common/engine.h" // for warning()
|
||||
#include "common/system.h"
|
||||
#include "common/rect.h"
|
||||
//#include "ddraw.h"
|
||||
//#include "dsound.h"
|
||||
|
||||
@ -1254,6 +1255,29 @@ typedef int BOOL;
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
// FIXME: Temporary (?) surface class to replace LPDIRECTDRAWSURFACE for now.
|
||||
|
||||
class Surface {
|
||||
public:
|
||||
uint16 _width, _height;
|
||||
uint16 _pitch;
|
||||
byte *_pixels;
|
||||
|
||||
Surface(uint width, uint height) {
|
||||
_width = width;
|
||||
_height = height;
|
||||
_pixels = (byte *) calloc(_width, _height);
|
||||
};
|
||||
|
||||
~Surface() {
|
||||
free(_pixels);
|
||||
};
|
||||
|
||||
void clear();
|
||||
void blit(Surface *s, ScummVM::Rect *r);
|
||||
void blit(Surface *s, ScummVM::Rect *r, ScummVM::Rect *clip_rect);
|
||||
};
|
||||
|
||||
//
|
||||
// Structure definitions
|
||||
// ---------------------
|
||||
@ -1351,8 +1375,8 @@ typedef struct
|
||||
// HWND hwnd;
|
||||
// LPDIRECTDRAW lpDraw;
|
||||
// LPDIRECTDRAW2 lpDD2;
|
||||
// LPDIRECTDRAWSURFACE lpPrimarySurface;
|
||||
// LPDIRECTDRAWSURFACE lpBackBuffer;
|
||||
// Surface *lpPrimarySurface;
|
||||
Surface *lpBackBuffer;
|
||||
// LPDIRECTDRAWPALETTE lpPalette;
|
||||
int16 screenDeep;
|
||||
int16 screenWide;
|
||||
|
@ -318,7 +318,20 @@ __inline uint8 QuickMatch(uint8 r, uint8 g, uint8 b)
|
||||
int32 SetPalette(int16 startEntry, int16 noEntries, uint8 *colourTable, uint8 fadeNow)
|
||||
|
||||
{
|
||||
warning("stub SetPalette( %d, %d, %d )", startEntry, noEntries, fadeNow);
|
||||
debug(0, "SetPalette(%d, %d, %d)", startEntry, noEntries, fadeNow);
|
||||
|
||||
StackLock lock(g_sword2->_paletteMutex);
|
||||
|
||||
if (noEntries == 0) {
|
||||
RestorePalette();
|
||||
return RD_OK;
|
||||
}
|
||||
|
||||
// FIXME: Handle the fadeNow parameter
|
||||
|
||||
memcpy(&palCopy[startEntry][0], colourTable, noEntries * 4);
|
||||
g_sword2->_system->set_palette((byte *) palCopy, startEntry, noEntries);
|
||||
|
||||
/*
|
||||
|
||||
int32 hr;
|
||||
|
@ -208,6 +208,7 @@
|
||||
#include "_mouse.h"
|
||||
#include "render.h"
|
||||
#include "menu.h"
|
||||
#include "../sword2.h"
|
||||
|
||||
|
||||
|
||||
@ -248,7 +249,7 @@ static int16 scrollxTarget;
|
||||
static int16 scrollyTarget;
|
||||
static int16 scrollxOld;
|
||||
static int16 scrollyOld;
|
||||
//static uint16 layer = 0;
|
||||
static uint16 layer = 0;
|
||||
|
||||
|
||||
|
||||
@ -275,14 +276,90 @@ int32 renderTooSlow;
|
||||
uint8 xblocks[MAXLAYERS];
|
||||
uint8 yblocks[MAXLAYERS];
|
||||
uint8 restoreLayer[MAXLAYERS];
|
||||
//LPDIRECTDRAWSURFACE *blockSurfaces[MAXLAYERS] = {0,0,0,0,0};
|
||||
|
||||
// Each layer is composed by several sub-blocks
|
||||
|
||||
Surface **blockSurfaces[MAXLAYERS] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
|
||||
|
||||
void Surface::clear() {
|
||||
memset(_pixels, 0, _width * _height);
|
||||
g_sword2->_system->copy_rect(_pixels, _width, 0, 0, _width, _height);
|
||||
}
|
||||
|
||||
void Surface::blit(Surface *s, ScummVM::Rect *r) {
|
||||
ScummVM::Rect clip_rect;
|
||||
|
||||
clip_rect.left = 0;
|
||||
clip_rect.top = 0;
|
||||
clip_rect.right = 640;
|
||||
clip_rect.bottom = 480;
|
||||
|
||||
blit(s, r, &clip_rect);
|
||||
}
|
||||
|
||||
void Surface::blit(Surface *s, ScummVM::Rect *r, ScummVM::Rect *clip_rect) {
|
||||
if (r->top > clip_rect->bottom || r->left > clip_rect->right || r->bottom <= clip_rect->top || r->right <= clip_rect->left)
|
||||
return;
|
||||
|
||||
byte *src = s->_pixels;
|
||||
|
||||
if (r->top < clip_rect->top) {
|
||||
src -= s->_width * (r->top - clip_rect->top);
|
||||
r->top = clip_rect->top;
|
||||
}
|
||||
if (r->left < clip_rect->left) {
|
||||
src -= (r->left - clip_rect->left);
|
||||
r->left = clip_rect->left;
|
||||
}
|
||||
if (r->bottom > clip_rect->bottom)
|
||||
r->bottom = clip_rect->bottom;
|
||||
if (r->right > clip_rect->right)
|
||||
r->right = clip_rect->right;
|
||||
|
||||
byte *dst = _pixels + r->top * _width + r->left;
|
||||
int i, j;
|
||||
|
||||
// FIXME: We first render the data to the back buffer, and then copy
|
||||
// it to the backend. Since the same area will probably be copied
|
||||
// several times, as each new parallax layer is rendered, this may be
|
||||
// a bit inefficient.
|
||||
|
||||
for (i = 0; i < r->bottom - r->top; i++) {
|
||||
for (j = 0; j < r->right - r->left; j++) {
|
||||
if (src[j])
|
||||
dst[j] = src[j];
|
||||
}
|
||||
src += s->_width;
|
||||
dst += _width;
|
||||
}
|
||||
|
||||
g_sword2->_system->copy_rect(_pixels + r->top * _width + r->left, _width, r->left, r->top, r->right - r->left, r->bottom - r->top);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int32 RestoreBackgroundLayer(_parallax *p, int16 l)
|
||||
{
|
||||
warning("stub RestoreBackgroundLayer %d", l);
|
||||
int16 oldLayer = layer;
|
||||
int16 i;
|
||||
|
||||
debug(0, "RestoreBackgroundLayer %d", l);
|
||||
|
||||
layer = l;
|
||||
if (blockSurfaces[l]) {
|
||||
for (i = 0; i < xblocks[l] * yblocks[l]; i++)
|
||||
if (blockSurfaces[l][i])
|
||||
delete blockSurfaces[l][i];
|
||||
|
||||
free(blockSurfaces[l]);
|
||||
blockSurfaces[l] = NULL;
|
||||
}
|
||||
RestoreSurfaces();
|
||||
InitialiseBackgroundLayer(p);
|
||||
layer = oldLayer;
|
||||
|
||||
/*
|
||||
int16 oldLayer = layer;
|
||||
int16 i;
|
||||
@ -605,10 +682,47 @@ int32 SetLocationMetrics(uint16 w, uint16 h)
|
||||
|
||||
|
||||
|
||||
int32 RenderParallax(_parallax *p, int16 layer)
|
||||
int32 RenderParallax(_parallax *p, int16 l) {
|
||||
int16 x, y;
|
||||
int16 i, j;
|
||||
ScummVM::Rect r;
|
||||
|
||||
debug(0, "RenderParallax %d", l);
|
||||
|
||||
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)));
|
||||
|
||||
ScummVM::Rect clip_rect;
|
||||
|
||||
// Leave enough space for the top and bottom menues
|
||||
|
||||
clip_rect.left = 0;
|
||||
clip_rect.right = 640;
|
||||
clip_rect.top = 40;
|
||||
clip_rect.bottom = 440;
|
||||
|
||||
for (j = 0; j < yblocks[l]; j++) {
|
||||
for (i = 0; i < xblocks[l]; i++) {
|
||||
if (blockSurfaces[l][i + j * xblocks[l]]) {
|
||||
r.left = i * BLOCKWIDTH - x;
|
||||
r.right = r.left + BLOCKWIDTH;
|
||||
r.top = j * BLOCKHEIGHT - y + 40;
|
||||
r.bottom = r.top + BLOCKHEIGHT;
|
||||
lpBackBuffer->blit(blockSurfaces[l][i + j * xblocks[l]], &r, &clip_rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parallaxScrollx = scrollx - x;
|
||||
parallaxScrolly = scrolly - y;
|
||||
|
||||
{
|
||||
warning("stub RenderParallax %d", layer);
|
||||
/*
|
||||
|
||||
#if PROFILING == 1
|
||||
@ -619,7 +733,7 @@ int32 RenderParallax(_parallax *p, int16 layer)
|
||||
|
||||
#endif
|
||||
|
||||
if ((renderCaps & RDBLTFX_ALLHARDWARE) || ((renderCaps & RDBLTFX_FGPARALLAX) && (layer > 2)))
|
||||
if ((renderCaps & RDBLTFX_ALLHARDWARE) || ((renderCaps & RDBLTFX_FGPARALLAX) && (l > 2)))
|
||||
{
|
||||
|
||||
int16 x, y;
|
||||
@ -628,10 +742,10 @@ int32 RenderParallax(_parallax *p, int16 layer)
|
||||
HRESULT hr = 0;
|
||||
RECT r, rd;
|
||||
|
||||
if (restoreLayer[layer])
|
||||
if (restoreLayer[l])
|
||||
{
|
||||
RestoreBackgroundLayer(p, layer);
|
||||
restoreLayer[layer] = 0;
|
||||
RestoreBackgroundLayer(p, l);
|
||||
restoreLayer[l] = 0;
|
||||
}
|
||||
|
||||
if (locationWide == screenWide)
|
||||
@ -648,12 +762,12 @@ int32 RenderParallax(_parallax *p, int16 layer)
|
||||
while (TRUE)
|
||||
{
|
||||
j = 0;
|
||||
while (j < yblocks[layer])
|
||||
while (j < yblocks[l])
|
||||
{
|
||||
i = 0;
|
||||
while (i < xblocks[layer])
|
||||
while (i < xblocks[l])
|
||||
{
|
||||
if (*(blockSurfaces[layer] + i + j * xblocks[layer]))
|
||||
if (*(blockSurfaces[l] + i + j * xblocks[l]))
|
||||
{
|
||||
r.left = i * BLOCKWIDTH - x;
|
||||
r.right = r.left + BLOCKWIDTH;
|
||||
@ -684,7 +798,7 @@ int32 RenderParallax(_parallax *p, int16 layer)
|
||||
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);
|
||||
hr = IDirectDrawSurface2_Blt(lpBackBuffer, &r, *(blockSurfaces[l] + i + j * xblocks[l]), &rd, DDBLT_WAIT | DDBLT_KEYSRC, NULL);
|
||||
if (hr == DDERR_INVALIDRECT)
|
||||
hr = 0;
|
||||
if (hr)
|
||||
@ -707,7 +821,7 @@ int32 RenderParallax(_parallax *p, int16 layer)
|
||||
if (++restoreSurfaces == 4)
|
||||
return(RDERR_RESTORELAYERS);
|
||||
else
|
||||
RestoreBackgroundLayer(p, layer);
|
||||
RestoreBackgroundLayer(p, l);
|
||||
}
|
||||
else
|
||||
return(RD_OK);
|
||||
@ -996,7 +1110,14 @@ int32 SetScrollTarget(int16 sx, int16 sy)
|
||||
int32 CopyScreenBuffer(void)
|
||||
|
||||
{
|
||||
warning("stub CopyScreenBuffer");
|
||||
debug(0, "CopyScreenBuffer");
|
||||
|
||||
// FIXME: The backend should keep track of dirty rects, but I have a
|
||||
// feeling each one may be drawn several times, so we may have do add
|
||||
// our own handling of them instead.
|
||||
|
||||
g_sword2->_system->update_screen();
|
||||
|
||||
/*
|
||||
|
||||
uint8 *dst, *src;
|
||||
@ -1065,10 +1186,126 @@ int32 CopyScreenBuffer(void)
|
||||
|
||||
|
||||
|
||||
int32 InitialiseBackgroundLayer(_parallax *p)
|
||||
int32 InitialiseBackgroundLayer(_parallax *p) {
|
||||
uint8 *memchunk;
|
||||
uint32 *quaddata;
|
||||
uint8 zeros;
|
||||
uint16 count;
|
||||
uint16 i, j, k;
|
||||
uint16 x;
|
||||
uint8 *data;
|
||||
uint8 *dst;
|
||||
_parallaxLine *line;
|
||||
|
||||
debug(0, "InitialiseBackgroundLayer");
|
||||
|
||||
// This function is called to re-initialise the layers if they have
|
||||
// been lost. We know this if the layers have already been assigned.
|
||||
|
||||
// TODO: Can layers still be lost, or is that a DirectDraw-ism?
|
||||
|
||||
if (layer == MAXLAYERS)
|
||||
CloseBackgroundLayer();
|
||||
|
||||
if (!p) {
|
||||
layer++;
|
||||
return RD_OK;
|
||||
}
|
||||
|
||||
xblocks[layer] = (p->w + BLOCKWIDTH - 1) >> BLOCKWBITS;
|
||||
yblocks[layer] = (p->h + BLOCKHEIGHT - 1) >> BLOCKHBITS;
|
||||
|
||||
blockSurfaces[layer] = (Surface **) calloc(xblocks[layer] * yblocks[layer], sizeof(Surface *));
|
||||
if (!blockSurfaces[layer])
|
||||
return RDERR_OUTOFMEMORY;
|
||||
|
||||
// Decode the parallax layer into a large chunk of memory
|
||||
|
||||
memchunk = (uint8 *) malloc(xblocks[layer] * BLOCKWIDTH * yblocks[layer] * BLOCKHEIGHT);
|
||||
if (!memchunk)
|
||||
return RDERR_OUTOFMEMORY;
|
||||
|
||||
// We clear not the entire memory chunk, but enough of it to store
|
||||
// the entire parallax layer.
|
||||
|
||||
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++;
|
||||
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!
|
||||
|
||||
for (i = 0; i < xblocks[layer] * yblocks[layer]; i++) {
|
||||
bool block_has_data = false;
|
||||
|
||||
data = memchunk + (p->w * BLOCKHEIGHT * (i / xblocks[layer])) + BLOCKWIDTH * (i % xblocks[layer]);
|
||||
|
||||
quaddata = (uint32 *) data;
|
||||
|
||||
for (j = 0; j < BLOCKHEIGHT; j++) {
|
||||
for (k = 0; k < BLOCKWIDTH / 4; k++) {
|
||||
if (*quaddata) {
|
||||
block_has_data = true;
|
||||
goto bailout;
|
||||
}
|
||||
quaddata++;
|
||||
}
|
||||
quaddata += ((p->w - BLOCKWIDTH) / 4);
|
||||
}
|
||||
|
||||
bailout:
|
||||
|
||||
// Only assign a surface to the block if it contains data.
|
||||
|
||||
if (block_has_data) {
|
||||
blockSurfaces[layer][i] = new Surface(BLOCKWIDTH, BLOCKHEIGHT);
|
||||
|
||||
// Copy the data into the surfaces.
|
||||
dst = blockSurfaces[layer][i]->_pixels;
|
||||
for (j = 0; j < BLOCKHEIGHT; j++) {
|
||||
memcpy(dst, data, BLOCKWIDTH);
|
||||
data += p->w;
|
||||
dst += BLOCKWIDTH;
|
||||
}
|
||||
} else
|
||||
blockSurfaces[layer][i] = NULL;
|
||||
}
|
||||
free(memchunk);
|
||||
layer++;
|
||||
|
||||
{
|
||||
warning("stub InitialiseBackgroundLayer");
|
||||
/*
|
||||
uint8 *memchunk;
|
||||
uint32 *quaddata;
|
||||
@ -1252,7 +1489,20 @@ int32 InitialiseBackgroundLayer(_parallax *p)
|
||||
int32 CloseBackgroundLayer(void)
|
||||
|
||||
{
|
||||
warning("stub CloseBackgroundLayer");
|
||||
debug(0, "CloseBackgroundLayer");
|
||||
|
||||
int16 i, j;
|
||||
|
||||
for (j = 0; j < MAXLAYERS; j++) {
|
||||
if (blockSurfaces[j]) {
|
||||
for (i = 0; i < xblocks[j] * yblocks[j]; i++)
|
||||
if (blockSurfaces[j][i])
|
||||
delete blockSurfaces[j][i];
|
||||
free(blockSurfaces[j]);
|
||||
}
|
||||
}
|
||||
|
||||
layer = 0;
|
||||
/*
|
||||
int16 i, j;
|
||||
|
||||
|
@ -281,9 +281,8 @@ void Sword2State::go()
|
||||
|
||||
|
||||
Zdebug("CALLING: InitialiseDisplay");
|
||||
// rv = InitialiseDisplay(640, 480, 8, RD_FULLSCREEN);
|
||||
_system->init_size(640, 480);
|
||||
rv = RD_OK;
|
||||
rv = InitialiseDisplay(640, 480, 8, RD_FULLSCREEN);
|
||||
|
||||
Zdebug("RETURNED with rv = %.8x", rv);
|
||||
if (rv != RD_OK)
|
||||
|
Loading…
x
Reference in New Issue
Block a user