diff options
author | Jonathan Gray | 2003-07-28 01:47:41 +0000 |
---|---|---|
committer | Jonathan Gray | 2003-07-28 01:47:41 +0000 |
commit | dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57 (patch) | |
tree | 5c6bb0d5236aa9d5102d1cd7d6821fd3848086f8 /sword2/driver/sprite.cpp | |
parent | f020d28b5e9297f93d5bedae62885b380c23f517 (diff) | |
download | scummvm-rg350-dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57.tar.gz scummvm-rg350-dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57.tar.bz2 scummvm-rg350-dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57.zip |
bs2 driver
svn-id: r9212
Diffstat (limited to 'sword2/driver/sprite.cpp')
-rw-r--r-- | sword2/driver/sprite.cpp | 3240 |
1 files changed, 3240 insertions, 0 deletions
diff --git a/sword2/driver/sprite.cpp b/sword2/driver/sprite.cpp new file mode 100644 index 0000000000..33573405e2 --- /dev/null +++ b/sword2/driver/sprite.cpp @@ -0,0 +1,3240 @@ +/* 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 : sprite.c +// Created : 23rd September 1996 +// By : P.R.Porter +// +// Summary : This module holds the sprite drawing functions. +// +// Version Date By Description +// ------- --------- --- ----------------------------------------------- +// 1.0 25-Sep-96 PRP Blits full sprites only. Attempting to draw +// any other type of sprite will return an error +// code. Also, scroll target position is handled +// here +// +// 1.1 26-Sep-96 PRP Added include file render.h for link to scroll +// position. +// +// 1.2 04-Oct-96 PRP Added direct path to ddraw.h +// +// 1.3 09-Oct-96 PRP Made the sprite drawing routines write to either +// the screen buffer or video memory. +// +// 1.4 23-Oct-96 PRP Added the ability to draw a transparent sprite, +// i.e. one with holes in. (with clipping and +// everything) +// +// 1.5 29-Oct-96 PRP Sprite drawing greatly improved. We can now +// combine flags to define whether the sprite is +// compressed, transparent or aligned to the +// top corner of the monitor, as well as adding +// a flag for fx. +// +// 1.6 29-Oct-96 PRP Fixed drawing of sprites with the display align +// bit set in type. +// +// 1.7 29-Oct-96 PRP Made it so that when RDSPR_DISPLAYALIGN is +// combined with RDSPR_TRANS the sprite is drawn +// in the correct place. +// +// 1.8 31-Oct-96 PRP Fixed bug in sprite width calculation. +// +// 1.9 01-Nov-96 PRP Fixed transparent sprite clipping at the bottom +// +// 1.10 01-Nov-96 PRP Added RDSPR_SPRITECOMPRESSION to the attributes +// which may be passed into DrawSprite, and +// implemented a basic decompression piece of code +// which is currently very slooowwww. +// +// 1.11 05-Nov-96 PRP RENDERWIDE and RENDERDEEP now defined in +// render.h +// +// 1.12 06-Nov-96 PRP Fixed clipping for RDSPR_DISPLAYALIGN sprites. +// +// 1.13 08-Nov-96 PRP Added decompression for types RDSPR_RLE256 and +// RDSPR_RLE16. Also changed the format of +// DrawSprite() so that the details required by +// it are passed in a structure. +// +// 1.14 12-Nov-96 PRP Enabled drawing of flipped sprites. This is +// only possible for sprites which are compressed +// and not drawn with DISPLAYALIGN +// +// 1.15 15-Nov-96 PRP Size of menubar moved to menu.h +// +// 1.16 21-Nov-96 PRP Implemented scaling for sprites - only certain +// types mind. +// +// 1.17 25-Nov-96 PRP Removed the second displayed sprite to compare +// the anti-aliasing code. +// +// 1.18 25-Nov-96 PRP Removed the ColourMatch function which only +// worked on a reduced sub-set of the palette, +// and replaced it with QuickMatch in palette.c. +// +// 1.19 26-Nov-96 PRP Implemented scaling of sprites which are +// larger than their original size. +// +// 1.20 27-Nov-96 PRP Fixed the problem with displaying sprites which +// are transparent, uncompressed and display +// aligned. (James will be happy) +// +// 1.21 02-Dec-96 PRP Implemented sprites which blend with the +// background. +// +// 1.22 18-Dec-96 PRP Moved origin of sprites which are not transparent +// and display aligned. +// +// 1.23 09-Jan-97 PRP Display align clipping fixed for sprites which +// are completely off the screen. +// +// 1.24 24-Jan-97 PRP Added an offset to a sprite's x and y position +// depending upon where the latest parallax layer +// was with reference to the background position. +// +// 1.25 28-Jan-97 PRP Updated sprite drawing code to utilise hardware +// blitting where available. +// +// 1.26 06-Feb-97 PRP Fixed drawing of sprites after video memory +// is full up. +// +// 1.27 10-Feb-97 PRP Changed direct draw error reporting function +// calls. +// +// 1.28 11-Feb-97 PRP Implemented blending of sprites - depending +// upon values passed in by spriteInfo. +// +// 1.29 12-Feb-97 PRP Fixed the blended sprite rendering position +// bug. +// +// 1.30 12-Feb-97 PRP Changed the rendering code for blended sprites +// in ALLHARDWARE mode. +// +// 1.31 19-Mar-97 PRP Added CreateSurface, DrawSurface and, you +// guessed it, DeleteSurface functions. +// Added temporary profiling code to optimise +// sprite drawing. +// Implemented sprite compression, and drawing +// whilst decompressing code for sprite +// optimisation +// +// 1.32 24-Mar-97 PRP Fixed DrawSurface so that it returns an error +// code if the surface has been lost. +// +// 1.33 25-Mar-97 PRP Initialised freeSprite in the create surface +// function. +// +// 1.34 27-Mar-97 PRP Further optimisation of different types +// of sprites. New sprite compression type +// RDSPR_RLE256FAST which decompresses and +// draws at the same time. This type should +// be used for static 256 colour transparent +// sprites. +// +// 1.35 01-Apr-97 PRP Got rid of the RDSPR_LAYERCOMPRESSION +// sprite type. +// +// 1.36 01-Apr-97 PRP Made transparent sprites stippled when +// hardware acceleration is used. +// +// 1.37 01-Apr-97 PRP Fixed the bug which was tring to anti-alias +// sprites which were not over the screen area. +// +// 1.38 07-Apr-97 PRP Added code which looks at the light mask +// and renders George accordingly. +// +// 1.38 08-Apr-97 PRP Added code to decompress the light mask! +// +// 1.38 08-Apr-97 JEL Added another instance of light mask check. +// +// 1.39 08-Apr-97 JEL Changed screenWide to locationWide +// +// 1.40 09-Apr-97 PRP Fixed bug with fast draw not clipping +// correctly on the left edge. Now it does :) +// +// 1.41 09-Apr-97 PRP Added shadow layer effects for sprites which +// are not scaled, but have the RDSPR_SHADOW +// flag set. +// +// 1.42 09-Apr-97 JEL No changes. +// +// 1.43 09-Apr-97 PRP Fixed bug. Shadow mask was being referenced +// from the top of the screen, rather than the +// top of the background!!! +// +// 1.44 09-Apr-97 JEL Changed starty to scrolly for driver bug. +// +// 1.45 22-Apr-97 PRP Added return values for decompression code. +// +// 1.46 24-Apr-97 JEL Fixed the decompression choice code. +// +// 1.47 28-May-97 CJR Added more information to the Direct draw +// errors. +// +// 1.48 13-Jun-97 PRP Enabled the shadow mask when the arithmetic +// stretching and anti-aliasing is switched off. +// +// 1.49 13-Jun-97 PRP Made use of shadow mask independently switchable. +// +// 1.50 07-Jul-97 PRP Fixed a bug with the offset of sprites which are +// not compressed. +// +// 1.51 23-Jul-97 PRP Checked src colour key blitting flag before creating +// a surface in video memory +// +// 1.52 31-Jul-97 PRP Only allowed shadow masks to affect the sprite palette. +// +// 1.53 31-Jul-97 PRP Fixed a bug with the above change. Non sprite +// palette sprites were not being drawn, but are now :) +// +// 1.54 31-Jul-97 PRP Fixed the black box from around shadow sprites. +// +// 1.55 31-Jul-97 JEL Fixed the bug of transparent sprites suddenly printing in wrong position! +// +// 1.56 01-Aug-97 PRP Tried to fix the corruption at the end of stippled sprites. +// +// 1.57 01-Aug-97 PRP Replaced algorithm to fix corruption at end of stippled sprites. +// +// 1.58 01-Aug-97 PRP Removed the shitty sprite palette fix (1.52) +// +// 1.60 27-Aug-97 PRP Changed the drawing of transparent sprites so that +// the uncompressed sprites display properly. +// +// 1.61 02-Sep-97 CJR Changed the Decompression code to return an error before causing +// an access violation. +// +// Functions +// --------- +// +// -------------------------------------------------------------------------- +// +// int32 CreateSurface(_spriteInfo *s, uint32 *surface) +// +// Creates a sprite surface in video memory (if possible) and returns it's +// handle in surface. +// +// --------------------------------------------------------------------------- +// +// int32 DrawSurface(_spriteInfo *s, uint32 surface) +// +// Draws the sprite surface created earlier. If the surface has been lost, +// it is recreated. +// +// --------------------------------------------------------------------------- +// +// int32 DeleteSurface(uint32 surface) +// +// Deletes a surface from video memory. +// +// -------------------------------------------------------------------------- +// +// int32 DrawSprite(_spriteInfo *s) +// +// Draws a sprite onto the screen. The _spriteInfo structure holds all of +// the information needed to draw the sprite - see driver96.h for details +// +//============================================================================= + + + + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> +#include <stdio.h> +//#include <mmsystem.h> + +//#include "ddraw.h" + +#include "driver96.h" +#include "d_draw.h" +#include "render.h" +#include "menu.h" +#include "palette.h" + + +#if PROFILING == 1 +extern int32 profileSpriteRender; +extern int32 profileDecompression; +#endif + + +#define DEBUG_TIMING 0 +//LARGE_INTEGER myTimers[10][2]; + + +char shitColourTable[1024]; +static uint8 *lightMask = 0; + + + + + + + + + + + + + + + + + +// -------------------------------------------------------------------------- +// +// int32 MirrorSprite(uint8 *dst, uint8 *src, int16 w, int16 h) +// +// This function takes the sprite pointed to by src and creates a mirror +// image of it in dst. +// +// -------------------------------------------------------------------------- +int32 MirrorSprite(uint8 *dst, uint8 *src, int16 w, int16 h) + +{ + + int16 x, y; + + for (y=0; y<h; y++) + { + for (x=0; x<w; x++) + { + *dst++ = *(src + w-x-1); + } + src += w; + } + + return(RD_OK); + +} + + +// -------------------------------------------------------------------------- +// +// int32 DecompressRLE256(uint8 *dest, uint8 *source, int32 decompSize) +// +// This function takes a compressed frame of a sprite (with up to 256 colours) +// and decompresses it into the area of memory marked by the destination +// pointer. The decompSize is used to measure when the decompression process +// has completed. +// +// -------------------------------------------------------------------------- +int32 DecompressRLE256(uint8 *dest, uint8 *source, int32 decompSize) +{ + // PARAMETERS: + // source points to the start of the sprite data for input + // decompSize gives size of decompressed data in bytes + // dest points to start of destination buffer for decompressed data + + uint8 headerByte; // block header byte + uint8 *endDest=dest+decompSize; // pointer to byte after end of decomp buffer + int32 rv; + +#if PROFILING == 1 + LARGE_INTEGER startTime, endTime; + QueryPerformanceCounter(&startTime); +#endif + + + while(1) + { + //---------------------------- + // FLAT block + headerByte = *source++; // read FLAT block header & increment 'scan' to first pixel of block + + if (headerByte) // if this isn't a zero-length block + { + if (dest+headerByte > endDest) + { + rv = 1; + break; + } + + memset(dest,*source,headerByte); // set the next 'headerByte' pixels to the next colour at 'source' + dest+=headerByte; // increment destination pointer to just after this block + source++; // increment source pointer to just after this colour + + if (dest==endDest) // if we've decompressed all of the data + { + rv = 0; // return "OK" + break; + } + } + //---------------------------- + // RAW block + headerByte = *source++; // read RAW block header & increment 'scan' to first pixel of block + + if (headerByte) // if this isn't a zero-length block + { + if (dest+headerByte > endDest) + { + rv = 1; + break; + } + + memcpy(dest,source,headerByte); // copy the next 'headerByte' pixels from source to destination + dest+=headerByte; // increment destination pointer to just after this block + source+=headerByte; // increment source pointer to just after this block + + if (dest==endDest) // if we've decompressed all of the data + { + rv = 0; // return "OK" + break; + } + } + //---------------------------- + } +#if PROFILING == 1 + QueryPerformanceCounter(&endTime); + profileDecompression += (endTime.LowPart - startTime.LowPart); +#endif + + return(rv); +} + + + +// -------------------------------------------------------------------------- +// +// void UnwindRaw16(uint8 *dest, uint8 *source, uint8 blockSize, uint8 *colTable) +// +// This function unwinds a run of colour 16 data into 256 colour palette +// data. +// -------------------------------------------------------------------------- +void UnwindRaw16(uint8 *dest, uint8 *source, uint8 blockSize, uint8 *colTable) +{ + while(blockSize>1) // for each pair of pixels + { + *dest++ = colTable[(*source) >> 4]; // 1st colour = number in table at position given by upper nibble of source byte + *dest++ = colTable[(*source) & 0x0f]; // 2nd colour = number in table at position given by lower nibble of source byte + source++; // point to next source byte + blockSize-=2; // decrement count of how many pixels left to read + } + + if (blockSize) // if there's a final odd pixel + *dest++ = colTable[(*source)>>4]; // colour = number in table at position given by upper nibble of source byte +} + + + +// -------------------------------------------------------------------------- +// +// int32 DecompressRLE16(uint8 *dest, uint8 *source, int32 decompSize, uint8 *colTable) +// +// This function takes a compressed frame of a sprite (with up to 16 colours) +// and decompresses it into the area of memory marked by the destination +// pointer. The decompSize is used to measure when the decompression process +// has completed. The colour table which maps the 16 encoded colours to the +// current palette is passed in to colTable. +// +// -------------------------------------------------------------------------- +int32 DecompressRLE16(uint8 *dest, uint8 *source, int32 decompSize, uint8 *colTable) +{ + // PARAMETERS: + // source points to the start of the sprite data for input + // decompSize gives size of decompressed data in bytes + // dest points to start of destination buffer for decompressed data + // colTable points to a 16-byte table of colours used to encode the RAW pixels into 4-bits each + + uint8 headerByte; // block header byte + uint8 *endDest=dest+decompSize; // pointer to byte after end of decomp buffer + int32 rv; + +#if PROFILING == 1 + LARGE_INTEGER startTime, endTime; + QueryPerformanceCounter(&startTime); +#endif + + while(1) + { + //---------------------------- + // FLAT block + headerByte = *source++; // read FLAT block header & increment 'scan' to first pixel of block + + if (headerByte) // if this isn't a zero-length block + { + if (dest+headerByte > endDest) + { + rv = 1; + break; + } + + memset(dest,*source,headerByte); // set the next 'headerByte' pixels to the next colour at 'source' + dest+=headerByte; // increment destination pointer to just after this block + source++; // increment source pointer to just after this colour + + if (dest==endDest) // if we've decompressed all of the data + { + rv = 0; // return "OK" + break; + } + } + //---------------------------- + // RAW block + headerByte = *source++; // read RAW block header & increment 'scan' to first pixel of block + + if (headerByte) // if this isn't a zero-length block + { + if (dest+headerByte > endDest) + { + rv = 1; + break; + } + + UnwindRaw16(dest,source,headerByte,colTable); // copy the next 'headerByte' pixels from source to destination (NB. 2 pixels per byte) + dest+=headerByte; // increment destination pointer to just after this block + source+=(headerByte+1)/2; // increment source pointer to just after this block (NB. headerByte gives pixels, so /2 for bytes) + + if (dest>=endDest) // if we've decompressed all of the data + { + rv = 0; // return "OK" + break; + } + } + //---------------------------- + } + +#if PROFILING == 1 + QueryPerformanceCounter(&endTime); + profileDecompression += (endTime.LowPart - startTime.LowPart); +#endif + + return(rv); + +} + + + +int32 PaulCompression(_spriteInfo *s, uint8 *src, uint8 *dst) + +{ + + int j; + int bytesToGo; + uint8 colour; + uint8 runCount; + uint8 *runPointer; + + // Compressed the 256 colour source data into line compressed data. + for (j=0; j<s->h; j++) + { + bytesToGo = s->w; + + while (bytesToGo) + { + // Look for a run of flat colour or zeros first. + if ((bytesToGo == 1) || (*src == 0) || (*src == *(src+1))) + { + colour = *src; + runCount = 0; + while ((*src == colour) && (bytesToGo) && (runCount < 255)) + { + runCount++; + bytesToGo--; + src++; + } + *dst++ = runCount; + *dst++ = colour; + } + else + { + // We do not have a run of flat colour, so set the run length to zero + *dst++ = 0; + } + + if (bytesToGo) + { + // Look for a run of different colours excluding zero + runCount = 0; + colour = 0; + if (((bytesToGo == 1) && (*src)) || ((*src) && (*(src) != *(src+1)))) + { + runPointer = dst++; + while ((bytesToGo) && (runCount < 255) && (*src != colour) && (*src)) + { + runCount++; + bytesToGo--; + colour = *src; + *dst++ = *src++; + } + if (*src == colour) + { + runCount--; + bytesToGo++; + dst--; + src--; + } + *runPointer = runCount; + } + else + { + *dst++ = 0; + } + } + else + { + // We do not have a run of different colours + *dst++ = 0; + } + } + } + return(RD_OK); +} + + + +int32 SoftwareFlipRenderCompressed256(_spriteInfo *s) + +{ + + return(RDERR_NOTIMPLEMENTED); + +} + + + + +int32 SoftwareRenderCompressed256(_spriteInfo *s) + +{ + warning("stub SoftwareRenderCompressed256"); +/* + int32 rv; + int32 i; + int32 clipped = 0; + int32 clippedLeft, clippedRight; + int32 clippedCount; + RECT rSrc; + RECT rDst; + + if (s->type & RDSPR_DISPLAYALIGN) + return(RDERR_NOTIMPLEMENTED); + + if (s->type & RDSPR_FLIP) + { + rv = SoftwareFlipRenderCompressed256(s); + } + else + { + // Check to see whether we are dealing with a scaled sprite or not. + if ((s->scale == 0) || (s->scale == 256)) + { + // The sprite is not scaled + // Work out the clip rectangles - source and destination + rDst.left = s->x - scrollx; + rDst.right = rDst.left + s->w; + rDst.top = s->y - scrolly; + rDst.bottom = rDst.top + s->h; + + // Do major clipping + if ((rDst.left <= 0) && (rDst.right <= 0)) + return(RD_OK); + if ((rDst.left >= RENDERWIDE) && (rDst.right >= RENDERWIDE)) + return(RD_OK); + if ((rDst.top <= 0) && (rDst.bottom <= 0)) + return(RD_OK); + if ((rDst.top >= RENDERDEEP) && (rDst.bottom >= RENDERDEEP)) + return(RD_OK); + + rSrc.top = 0; + rSrc.bottom = s->h; + rSrc.left = 0; + rSrc.right = s->w; + clippedLeft = 0; + clippedRight = 0; + + // Now clip the fuckers + if (rDst.top < 0) + { + rSrc.top -= rDst.top; + rDst.top = 0; + clipped = 1; + } + if (rDst.bottom > RENDERDEEP) + { + rSrc.bottom -= (rDst.bottom - RENDERDEEP); + rDst.bottom = RENDERDEEP; + clipped = 1; + } + if (rDst.left < 0) + { + clippedLeft = -rDst.left; + rSrc.left += clippedLeft; + rDst.left = 0; + clipped = 1; + } + if (rDst.right > RENDERWIDE) + { + clippedRight = rDst.right - RENDERWIDE; + rSrc.right -= clippedRight; + rDst.right = RENDERWIDE; + clipped = 1; + } + + if (s->type & RDSPR_BLEND) + { + // THE SPRITE IS BLENDED + int32 lineBytesToGo = s->w; +// int32 bytesToGo; + uint8 *spr = s->data; + uint8 *dst = myScreenBuffer + rDst.left + rDst.top * RENDERWIDE; + uint8 runLength = 0; + + // The sprite is not blended + + // Decompress the source data until we are at the line where + // the drawing is to start. + + if (clipped) + { + // Clip off any whole lines from the top of the sprite + for (i=0; i<rSrc.top; i++) + { + lineBytesToGo = s->w; + while (lineBytesToGo) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + if (*spr) + { + memset(dst, *spr, runLength); + } +// dst += runLength; + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + memcpy(dst, spr, runLength); + spr += runLength; +// dst += runLength; + lineBytesToGo -= runLength; + } + } +// dst += (RENDERWIDE - s->w); + } + + // Draw until we get to the clipped bottom of the sprite. + while (i < rSrc.bottom) + { + lineBytesToGo = s->w; + // Do the first part of the line + if (clippedLeft) + { + clippedCount = clippedLeft; + while (clippedCount > 0) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + // Check that we aren't going to go over clippedCount + if (runLength > clippedCount) + { + runLength -= clippedCount; + if (*spr) + memset(dst, *spr, runLength); + dst += runLength; +// memset(dst + clippedCount, *spr, runLength); +// dst += (runLength + clippedCount); + spr++; + lineBytesToGo -= (runLength + clippedCount); + clippedCount = -runLength; + } + else + { +// WE DON'T DO THIS BIT BECUASE WE ARE IN THE CLIPPED REGION +// if (*spr) +// { +// memset(dst, *spr, runLength); +// } + +// dst += runLength; + + spr++; + clippedCount -= runLength; + lineBytesToGo -= runLength; + } + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + // See if we are already over the clipped count + if (clippedCount < 0) + { + memcpy(dst, spr, runLength); + dst += runLength; + spr += runLength; + lineBytesToGo -= runLength; + } + // See if we are going to go over the clipped count + else if (runLength > clippedCount) + { + runLength -= clippedCount; +// memcpy(dst + clippedCount , spr + clippedCount, runLength); +// dst += (runLength + clippedCount); + memcpy(dst, spr + clippedCount, runLength); + dst += runLength; + spr += (runLength + clippedCount); + lineBytesToGo -= (runLength + clippedCount); + clippedCount = -runLength; + } + else + { +// WE DON'T DO THIS BIT BECAUSE WE ARE IN THE CLIPPED REGION +// memcpy(dst, spr, runLength); + spr += runLength; +// dst += runLength; + lineBytesToGo -= runLength; + clippedCount -= runLength; + } + } + } + } + +// lineBytesToGo > clippedRight; + while (lineBytesToGo > clippedRight) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + // Ensure we're not going over the clipped region + if (*spr) + { + // Let's check that the run is not longer than the clipped region + if (lineBytesToGo - runLength < clippedRight) + { + if (lineBytesToGo - clippedRight > 0) + { + memset(dst, *spr, lineBytesToGo - clippedRight); + dst += (lineBytesToGo - clippedRight); + } + } + else + { + memset(dst, *spr, runLength); + dst += runLength; + } + } + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + // Let's check that the run is not longer than the clipped region + if (lineBytesToGo - runLength < clippedRight) + { + if (lineBytesToGo - clippedRight > 0) + { + memcpy(dst, spr, lineBytesToGo - clippedRight); + dst += (lineBytesToGo - clippedRight); + } + } + else + { + memcpy(dst, spr, runLength); + dst += runLength; + } + spr += runLength; + lineBytesToGo -= runLength; + } + } + + // Go through the compressed data to the end of the line. + while (lineBytesToGo) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros +// DON'T DO THIS COS WE'RE OUTSIDE CLIP REGION +// if (*spr) +// { +// memset(dst, *spr, runLength); +// } + +// dst += runLength; + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours +// DON'T DO THIS COS WE'RE OUTSIDE CLIP REGION +// memcpy(dst, spr, runLength); + spr += runLength; +// dst += runLength; + lineBytesToGo -= runLength; + } + } + +// dst += (RENDERWIDE - s->w); + dst += (RENDERWIDE - (rDst.right - rDst.left)); + i++; + } + } + else + { + // Fuck the clipping, let's just draw it for now + for (i=0; i<s->h; i++) + { + lineBytesToGo = s->w; + while (lineBytesToGo) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + if (*spr) + { + memset(dst, *spr, runLength); + } + dst += runLength; + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + memcpy(dst, spr, runLength); + spr += runLength; + dst += runLength; + lineBytesToGo -= runLength; + } + } + dst += (RENDERWIDE - s->w); + } + } + } + else + { + int32 lineBytesToGo = s->w; +// int32 bytesToGo; + uint8 *spr = s->data; + uint8 *dst = myScreenBuffer + rDst.left + rDst.top * RENDERWIDE; + uint8 runLength = 0; + + // The sprite is not blended + + // Decompress the source data until we are at the line where + // the drawing is to start. + + if (clipped) + { + // Clip off any whole lines from the top of the sprite + for (i=0; i<rSrc.top; i++) + { + lineBytesToGo = s->w; + while (lineBytesToGo) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + if (*spr) + { + memset(dst, *spr, runLength); + } +// dst += runLength; + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + memcpy(dst, spr, runLength); + spr += runLength; +// dst += runLength; + lineBytesToGo -= runLength; + } + } +// dst += (RENDERWIDE - s->w); + } + + // Draw until we get to the clipped bottom of the sprite. + while (i < rSrc.bottom) + { + lineBytesToGo = s->w; + // Do the first part of the line + if (clippedLeft) + { + clippedCount = clippedLeft; + while (clippedCount > 0) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + // Check that we aren't going to go over clippedCount + if (runLength > clippedCount) + { + runLength -= clippedCount; + if (*spr) + memset(dst, *spr, runLength); + dst += runLength; +// memset(dst + clippedCount, *spr, runLength); +// dst += (runLength + clippedCount); + spr++; + lineBytesToGo -= (runLength + clippedCount); + clippedCount = -runLength; + } + else + { +// WE DON'T DO THIS BIT BECUASE WE ARE IN THE CLIPPED REGION +// if (*spr) +// { +// memset(dst, *spr, runLength); +// } + +// dst += runLength; + + spr++; + clippedCount -= runLength; + lineBytesToGo -= runLength; + } + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + // See if we are already over the clipped count + if (clippedCount < 0) + { + memcpy(dst, spr, runLength); + dst += runLength; + spr += runLength; + lineBytesToGo -= runLength; + } + // See if we are going to go over the clipped count + else if (runLength > clippedCount) + { + runLength -= clippedCount; +// memcpy(dst + clippedCount , spr + clippedCount, runLength); +// dst += (runLength + clippedCount); + memcpy(dst, spr + clippedCount, runLength); + dst += runLength; + spr += (runLength + clippedCount); + lineBytesToGo -= (runLength + clippedCount); + clippedCount = -runLength; + } + else + { +// WE DON'T DO THIS BIT BECAUSE WE ARE IN THE CLIPPED REGION +// memcpy(dst, spr, runLength); + spr += runLength; +// dst += runLength; + lineBytesToGo -= runLength; + clippedCount -= runLength; + } + } + } + } + +// lineBytesToGo > clippedRight; + while (lineBytesToGo > clippedRight) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + // Ensure we're not going over the clipped region + // Let's check that the run is not longer than the clipped region + if (lineBytesToGo - runLength < clippedRight) + { + if (lineBytesToGo - clippedRight > 0) + { + if (*spr) + memset(dst, *spr, lineBytesToGo - clippedRight); + dst += (lineBytesToGo - clippedRight); + } + } + else + { + if (*spr) + memset(dst, *spr, runLength); + dst += runLength; + } + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + // Let's check that the run is not longer than the clipped region + if (lineBytesToGo - runLength < clippedRight) + { + if (lineBytesToGo - clippedRight > 0) + { + memcpy(dst, spr, lineBytesToGo - clippedRight); + dst += (lineBytesToGo - clippedRight); + } + } + else + { + memcpy(dst, spr, runLength); + dst += runLength; + } + spr += runLength; + lineBytesToGo -= runLength; + } + } + + // Go through the compressed data to the end of the line. + while (lineBytesToGo) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros +// DON'T DO THIS COS WE'RE OUTSIDE CLIP REGION +// if (*spr) +// { +// memset(dst, *spr, runLength); +// } + +// dst += runLength; + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours +// DON'T DO THIS COS WE'RE OUTSIDE CLIP REGION +// memcpy(dst, spr, runLength); + spr += runLength; +// dst += runLength; + lineBytesToGo -= runLength; + } + } + +// dst += (RENDERWIDE - s->w); + dst += (RENDERWIDE - (rDst.right - rDst.left)); + i++; + } + } + else + { + // Fuck the clipping, let's just draw it for now + for (i=0; i<s->h; i++) + { + lineBytesToGo = s->w; + while (lineBytesToGo) + { + runLength = *spr++; + if (runLength) + { + // This is a run of the same colour or zeros + if (*spr) + { + memset(dst, *spr, runLength); + } + dst += runLength; + spr++; + lineBytesToGo -= runLength; + } + + runLength = *spr++; + if (runLength) + { + // This is a run of different colours + memcpy(dst, spr, runLength); + spr += runLength; + dst += runLength; + lineBytesToGo -= runLength; + } + } + dst += (RENDERWIDE - s->w); + } + } + } + } + else + { + // The sprite is scaled. + rv = RDERR_NOTIMPLEMENTED; + } + } + return(rv); +*/ + return 0; +} + + +int32 CreateSurface(_spriteInfo *s, uint32 *surface) + +{ + warning("stub CreateSurface"); +/* + + uint8 *sprite, *newSprite; + uint8 *src, *dst; + int32 freeSprite = 0; + int32 i; + HRESULT hr; + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE dds; + + + // Create a surface for the sprite and then draw it. + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(DDSURFACEDESC); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + if (s->scale & 0xff) + { + if (dxHalCaps & RDCAPS_BLTSTRETCH) + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + else + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } + else + { + if (dxHalCaps & RDCAPS_SRCBLTCKEY) + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + else + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } + + ddsd.dwWidth = s->w; + ddsd.dwHeight = s->h; + hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &dds, NULL); + if (hr == DDERR_OUTOFVIDEOMEMORY) + { + ddsd.ddsCaps.dwCaps &= (0xffffffff - DDSCAPS_VIDEOMEMORY); + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &dds, NULL); + } + if (hr != DD_OK) + { + DirectDrawError("Cannot create sprite surface", hr); + return(hr); + } + + if (s->type & RDSPR_TRANS) + hr = IDirectDrawSurface2_SetColorKey(dds, DDCKEY_SRCBLT, &blackColorKey); + + if (s->type &RDSPR_NOCOMPRESSION) + { + sprite = s->data; + } + else + { + sprite = (uint8 *) malloc(s->w * s->h); + freeSprite = 1; + if (sprite == NULL) + { + IDirectDrawSurface2_Release(dds); + return(RDERR_OUTOFMEMORY); + } + + if (s->type >> 8 == RDSPR_RLE16 >> 8) + { + if (DecompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) + return(RDERR_DECOMPRESSION); + } + else + { + if (DecompressRLE256(sprite, s->data, s->w * s->h)) + return(RDERR_DECOMPRESSION); + } + + if (s->type & RDSPR_FLIP) + { + newSprite = (uint8 *) malloc(s->w * s->h); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + MirrorSprite(newSprite, sprite, s->w, s->h); + free(sprite); + sprite = newSprite; + } + } + + hr = IDirectDrawSurface2_Lock(dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + IDirectDrawSurface2_Restore(dds); + hr = IDirectDrawSurface2_Lock(dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + DirectDrawError("Cannot lock sprite surface", hr); + return(hr); + } + } + + src = sprite; + dst = ddsd.lpSurface; + for (i=0; i<s->h; i++) + { + memcpy(dst, src, s->w); + src += s->w; + dst += ddsd.lPitch; + } + + IDirectDrawSurface2_Unlock(dds, ddsd.lpSurface); + + *surface = (uint32) dds; + + if (freeSprite) + free(sprite); +*/ + return(RD_OK); + +} + + +int32 DrawSurface(_spriteInfo *s, uint32 surface) + +{ + warning("stub DrawSurface"); +/* + + HRESULT hr; + RECT rd, rs; + LPDIRECTDRAWSURFACE dds; + char myString[256]; + + + dds = (LPDIRECTDRAWSURFACE) surface; + + // Set startx and starty for the screen buffer ADDED THIS! + if (s->type & RDSPR_DISPLAYALIGN) + rd.top = s->y; + else + rd.top = s->y - scrolly; + + if (s->type & RDSPR_DISPLAYALIGN) + rd.left = s->x; + else + rd.left = s->x - scrollx; + + rs.left = 0; + rs.right = s->w; + rs.top = 0; + rs.bottom = s->h; + if (s->scale & 0xff) + { + rd.right = rd.left + s->scaledWidth; + rd.bottom = rd.top + s->scaledHeight; + // Do clipping + if (rd.top < 40) + { + rs.top = (40 - rd.top) * 256 / s->scale; + rd.top = 40; + } + if (rd.bottom > 440) + { + rs.bottom -= ((rd.bottom - 440) * 256 / s->scale); + rd.bottom = 440; + } + if (rd.left < 0) + { + rs.left = (0 - rd.left) * 256 / s->scale; + rd.left = 0; + } + if (rd.right > 640) + { + rs.right -= ((rd.right - 640) * 256 / s->scale); + rd.right = 640; + } + } + else + { + rd.right = rd.left + s->w; + rd.bottom = rd.top + s->h; + + // Do clipping + if (rd.top < 40) + { + rs.top = 40 - rd.top; + rd.top = 40; + } + if (rd.bottom > 440) + { + rs.bottom -= (rd.bottom - 440); + rd.bottom = 440; + } + if (rd.left < 0) + { + rs.left = 0 - rd.left; + rd.left = 0; + } + if (rd.right > 640) + { + rs.right -= (rd.right - 640); + rd.right = 640; + } + } + + if (s->type & RDSPR_TRANS) + { + hr = IDirectDrawSurface2_Blt(lpBackBuffer, &rd, dds, &rs, DDBLT_WAIT | DDBLT_KEYSRC, NULL); + if (hr) + { + if (hr == DDERR_SURFACELOST) + hr = RDERR_SURFACELOST; + else if (dxHalCaps & RDCAPS_BLTSTRETCH) + dxHalCaps -= RDCAPS_BLTSTRETCH; + else + { + sprintf(myString, "DrawSurface failed, sprite: x%d y%d w%d h%d s%d t%d sx%d sy%d", s->x, s->y, s->w, s->h, s->scale, s->type, scrollx, scrolly); + DirectDrawError(myString, hr); + } + } + } + else + { + hr = IDirectDrawSurface2_Blt(lpBackBuffer, &rd, dds, &rs, DDBLT_WAIT, NULL); + if (hr) + { + if (hr == DDERR_SURFACELOST) + hr = RDERR_SURFACELOST; + else + { + sprintf(myString, "DrawSurface failed, sprite: x%d y%d w%d h%d s%d t%d sx%d sy%d", s->x, s->y, s->w, s->h, s->scale, s->type, scrollx, scrolly); + DirectDrawError(myString, hr); + } + } + } + + return(hr); +*/ + return 0; +} + + +int32 DeleteSurface(uint32 surface) + +{ + warning("stub DeleteSurface( %d )", surface); +/* + + LPDIRECTDRAWSURFACE dds; + + dds = (LPDIRECTDRAWSURFACE) surface; + return(IDirectDrawSurface2_Release(dds)); +*/ + return 0; + +} + + + + + + + + + + + + + + + + + + + + + +#define SCALE_MAXWIDTH 512 +#define SCALE_MAXHEIGHT 512 + +uint16 xScale[SCALE_MAXWIDTH]; +uint16 yScale[SCALE_MAXHEIGHT]; + + +int32 DrawSprite(_spriteInfo *s) + +{ + warning("stub DrawSprite"); +/* + +#if PROFILING == 1 + LARGE_INTEGER startTime, endTime; + + QueryPerformanceCounter(&startTime); +#endif + + if (!(s->type & RDSPR_DISPLAYALIGN)) + { + s->x += parallaxScrollx; + s->y += parallaxScrolly; + } + + if (renderCaps & RDBLTFX_ALLHARDWARE) + { + uint8 *src, *dst; + uint8 *sprite, *newSprite; + uint8 pixel, red, green, blue; + int16 i, j; + int16 flag = 0; + int16 freeSprite = 0; + // int32 start, total; // For timing! + RECT rd, rs; + HRESULT hr; + DDSURFACEDESC ddsd; + LPDIRECTDRAWSURFACE dds; + + s->y += 40; + + // For now, we draw blended sprites with our own code, as they + // are not supported by DX3. + if ((s->type & RDSPR_BLEND) && (renderCaps & RDBLTFX_FLATALPHA)) + { + if (s->type & RDSPR_NOCOMPRESSION) + sprite = s->data; + else + { + sprite = malloc(s->w * s->h); + if (sprite == NULL) + return(RDERR_OUTOFMEMORY); + freeSprite = 1; + if (s->type >> 8 == RDSPR_RLE16 >> 8) + { + if (DecompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) + return(RDERR_DECOMPRESSION); + } + else + { + if (DecompressRLE256(sprite, s->data, s->w * s->h)) + return(RDERR_DECOMPRESSION); + } + } + + // We want to blend the sprite FROM the RECT rs. + // We want to blend the sprite TO the RECT rd. + rd.left = s->x - scrollx; + rd.right = rd.left + s->w; + rd.top = s->y - scrolly; + rd.bottom = rd.top + s->h; + + rs.top = 0; + rs.bottom = s->h; + rs.left = 0; + rs.right = s->w; + + //Now do the clipping - top + if (rd.top < 40) + { + rs.top = (40 - rd.top); + rd.top = 40; + } + //Clip the bottom + if (rd.bottom > RENDERDEEP) + { + rs.bottom -= (rd.bottom - RENDERDEEP); + rd.bottom = RENDERDEEP; + } + //Clip the left + if (rd.left < 0) + { + rs.left -= rd.left; + rd.left = 0; + } + //Clip the right + if (rd.right > RENDERWIDE) + { + rs.right -= (rd.right - RENDERWIDE); + rd.right = RENDERWIDE; + } + + // start = timeGetTime(); + memset(&ddsd, 0, sizeof(ddsd)); + ddsd.dwSize = sizeof(ddsd); + 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) + { + if (s->blend & 0x01) + { + red = s->blend >> 8; + for (i=0; i<rs.bottom - rs.top; i++) + { + src = sprite + (rs.top + i) * s->w + rs.left; + dst = (uint8 *) ddsd.lpSurface + ddsd.lPitch * (rd.top + i) + rd.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j<rs.right - rs.left; j++) + { + if (*src) + { + pixel = *dst; + // pixel = *newSprite; + *dst = paletteMatch[(((palCopy[*src][0] * red + palCopy[pixel][0] * (8 - red)) >> 5) << 12) + + (((palCopy[*src][1] * red + palCopy[pixel][1] * (8 - red)) >> 5) << 6) + + (((palCopy[*src][2] * red + palCopy[pixel][2] * (8 - red)) >> 5) )]; + } + src++; + dst++; + // newSprite++; + } + } + } + else if (s->blend & 0x02) + { + red = palCopy[s->blend >> 8][0]; + green = palCopy[s->blend >> 8][0]; + blue = palCopy[s->blend >> 8][0]; + for (i=0; i<rs.bottom - rs.top; i++) + { + src = sprite + (rs.top + i) * s->w + rs.left; + dst = (uint8 *) ddsd.lpSurface + ddsd.lPitch * (rd.top + i) + rd.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j<rs.right - rs.left; j++) + { + if (*src) + { + pixel = *dst; + // pixel = *newSprite; + *dst = paletteMatch[((((*src * red + (16 - *src) * palCopy[pixel][0]) >> 4) >> 2) << 12) + + ((((*src * green + (16 - *src) * palCopy[pixel][1]) >> 4) >> 2) << 6) + + (((*src * blue + (16 - *src) * palCopy[pixel][2]) >> 4) >> 2)]; + } + src++; + dst++; + // newSprite++; + } + } + } + else + { + IDirectDrawSurface2_Unlock(lpBackBuffer, ddsd.lpSurface); + if (freeSprite) + free(sprite); + DirectDrawError("Invalid blended sprite", 0); + return(RDERR_UNKNOWNTYPE); + } + IDirectDrawSurface2_Unlock(lpBackBuffer, ddsd.lpSurface); + } + + // IDirectDrawSurface2_Unlock(ddsSystem, ddsdSystem.lpSurface); + // IDirectDrawSurface2_Release(ddsSystem); + + // total = timeGetTime() - start; + // PlotDots(10, 14, total); + + if (freeSprite) + free(sprite); + + } + else + { + + // Create a surface for the sprite and then draw it. + memset(&ddsd, 0, sizeof(DDSURFACEDESC)); + ddsd.dwSize = sizeof(DDSURFACEDESC); + ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT; + ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; + if (s->scale & 0xff) + { + if (dxHalCaps & RDCAPS_BLTSTRETCH) + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + else + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } + else + { + if (dxHalCaps & RDCAPS_SRCBLTCKEY) + ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; + else + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + } + + ddsd.dwWidth = s->w; + ddsd.dwHeight = s->h; + hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &dds, NULL); + if (hr == DDERR_OUTOFVIDEOMEMORY) + { + ddsd.ddsCaps.dwCaps &= (0xffffffff - DDSCAPS_VIDEOMEMORY); + ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &dds, NULL); + } + if (hr != DD_OK) + { + DirectDrawError("Cannot create sprite surface", hr); + return(hr); + } + + if (s->type & RDSPR_TRANS) + hr = IDirectDrawSurface2_SetColorKey(dds, DDCKEY_SRCBLT, &blackColorKey); + + if (s->type &RDSPR_NOCOMPRESSION) + { + sprite = s->data; + } + else + { + sprite = (uint8 *) malloc(s->w * s->h); + freeSprite = 1; + if (sprite == NULL) + { + IDirectDrawSurface2_Release(dds); + return(RDERR_OUTOFMEMORY); + } + if (s->type >> 8 == RDSPR_RLE16 >> 8) + { + if (DecompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) + return(RDERR_DECOMPRESSION); + } + else + { + if (DecompressRLE256(sprite, s->data, s->w * s->h)) + return(RDERR_DECOMPRESSION); + } + + if (s->type & RDSPR_FLIP) + { + newSprite = (uint8 *) malloc(s->w * s->h); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + MirrorSprite(newSprite, sprite, s->w, s->h); + free(sprite); + sprite = newSprite; + } + } + + hr = IDirectDrawSurface2_Lock(dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + IDirectDrawSurface2_Restore(dds); + hr = IDirectDrawSurface2_Lock(dds, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); + if (hr != DD_OK) + { + DirectDrawError("Cannot lock sprite surface", hr); + return(hr); + } + } + + flag = 0; + if (s->type & RDSPR_BLEND) + { + for (i=0; i<s->h; i++) + { + src = sprite + i * s->w; + dst = (uint8 *) ddsd.lpSurface + ddsd.lPitch * i; + flag ^= 1; + if (flag) + { + j=0; + while (j < s->w) + { + *dst = *src; + if (++j == s->w) + break; + *(dst+1) = 0; + j++; + dst += 2; + src += 2; + } + +// for (j=0; j<(s->w-1)/2; j++) +// { +// *dst = *src; +// *(dst+1) = 0; +// dst += 2; +// src += 2; +// } + } + else + { +// dst += 1; +// src += 1; + j = 0; + while (j < s->w) + { + *dst = 0; + if (++j == s->w) + break; + *(dst + 1) = *(src + 1); + j++; + dst += 2; + src += 2; + } +// for (j=0; j<s->w/2; j++) +// { +// *dst = 0; +// *(dst+1) = *(src+1); +// dst += 2; +// src += 2; +// } + } + } + } + else + { + src = sprite; + dst = (uint8 *) ddsd.lpSurface; + for (i=0; i<s->h; i++) + { + memcpy(dst, src, s->w); + src += s->w; + dst += ddsd.lPitch; + } + } + + IDirectDrawSurface2_Unlock(dds, ddsd.lpSurface); + + // Set startx and starty for the screen buffer ADDED THIS! + if (s->type & RDSPR_DISPLAYALIGN) + rd.top = s->y; + else + rd.top = s->y - scrolly; + + if (s->type & RDSPR_DISPLAYALIGN) + rd.left = s->x; + else + rd.left = s->x - scrollx; + + rs.left = 0; + rs.right = s->w; + rs.top = 0; + rs.bottom = s->h; + if (s->scale & 0xff) + { + rd.right = rd.left + s->scaledWidth; + rd.bottom = rd.top + s->scaledHeight; + // Do clipping + if (rd.top < 40) + { + rs.top = (40 - rd.top) * 256 / s->scale; + rd.top = 40; + } + if (rd.bottom > 440) + { + rs.bottom -= ((rd.bottom - 440) * 256 / s->scale); + rd.bottom = 440; + } + if (rd.left < 0) + { + rs.left = (0 - rd.left) * 256 / s->scale; + rd.left = 0; + } + if (rd.right > 640) + { + rs.right -= ((rd.right - 640) * 256 / s->scale); + rd.right = 640; + } + } + else + { + rd.right = rd.left + s->w; + rd.bottom = rd.top + s->h; + + // Do clipping + if (rd.top < 40) + { + rs.top = 40 - rd.top; + rd.top = 40; + } + if (rd.bottom > 440) + { + rs.bottom -= (rd.bottom - 440); + rd.bottom = 440; + } + if (rd.left < 0) + { + rs.left = 0 - rd.left; + rd.left = 0; + } + if (rd.right > 640) + { + rs.right -= (rd.right - 640); + rd.right = 640; + } + } + + if (s->type & RDSPR_TRANS) + { + hr = IDirectDrawSurface2_Blt(lpBackBuffer, &rd, dds, &rs, DDBLT_WAIT | DDBLT_KEYSRC, NULL); + if (hr) + if (dxHalCaps & RDCAPS_BLTSTRETCH) + dxHalCaps -= RDCAPS_BLTSTRETCH; + } + else + hr = IDirectDrawSurface2_Blt(lpBackBuffer, &rd, dds, &rs, DDBLT_WAIT, NULL); + + IDirectDrawSurface2_Release(dds); + if (freeSprite) + free(sprite); + } + + } + else + { + uint16 i, j, k; + int16 starty, endy; + int16 startx, endx; + uint8 *src, *dst; + uint8 *lightMap; + uint8 *srcExtra[4]; + uint8 *sprite, *newSprite, *newerSprite, *spr, *p; + uint8 pixel; + int32 dx, dy, ince, incne, d; + int16 x, y; + static int16 randCount = 0; + int16 count, spriteCount; + int16 red, green, blue; + uint8 pt[5]; + RECT clippedTarget, clippedSprite; + int32 diff; + +// if (!(s->type & RDSPR_DISPLAYALIGN)) +// { +// s->x += parallaxScrollx; +// s->y += parallaxScrolly; +// } + + if (s->type & RDSPR_TRANS) + { + + if (s->type & RDSPR_NOCOMPRESSION) + { + + // We want to blend the sprite FROM the RECT clippedSprite. + // We want to blend the sprite TO the RECT clippedTarget. + clippedSprite.top = 0; + clippedSprite.bottom = s->h; + clippedSprite.left = 0; + clippedSprite.right = s->w; + if (s->type & RDSPR_DISPLAYALIGN) + clippedTarget.top = s->y; + else + clippedTarget.top = s->y - scrolly; + + if (s->type & RDSPR_DISPLAYALIGN) + clippedTarget.left = s->x; + else + clippedTarget.left = s->x - scrollx; + + clippedTarget.right = clippedTarget.left + s->w; + clippedTarget.bottom = clippedTarget.top + s->h; + + //Now do the clipping - top + if (clippedTarget.top < 0) + { + clippedSprite.top -= clippedTarget.top; + clippedTarget.top = 0; + } + //Clip the bottom + if (clippedTarget.bottom > RENDERDEEP) + { + clippedSprite.bottom -= (clippedTarget.bottom - RENDERDEEP); + clippedTarget.bottom = RENDERDEEP; + } + //Clip the left + if (clippedTarget.left < 0) + { + clippedSprite.left -= clippedTarget.left; + clippedTarget.left = 0; + } + //Clip the right + if (clippedTarget.right > RENDERWIDE) + { + clippedSprite.right -= (clippedTarget.right - RENDERWIDE); + clippedTarget.right = RENDERWIDE; + } + + if (s->type & RDSPR_BLEND) + { + if (renderCaps & RDBLTFX_FLATALPHA) + { + red = s->blend >> 8; + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + src = s->data + (clippedSprite.top + i) * s->w + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j<clippedSprite.right - clippedSprite.left; j++) + { + if (*src) + { + pixel = *dst; + // pixel = *newSprite; + *dst = paletteMatch[(((palCopy[*src][0] * red + palCopy[pixel][0] * (8 - red)) >> 5) << 12) + + (((palCopy[*src][1] * red + palCopy[pixel][1] * (8 - red)) >> 5) << 6) + + (((palCopy[*src][2] * red + palCopy[pixel][2] * (8 - red)) >> 5) )]; + } + src++; + dst++; + // newSprite++; + } + } + } + } + else + { + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + src = s->data + (clippedSprite.top + i) * s->w + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + for (j=0; j<clippedSprite.right - clippedSprite.left; j++) + { + if (*src) + *dst = *src; + dst++; + src++; + } + } + } + } + else + { + + // Ok, the sprite is compressed, so lets find out what type + switch (s->type >> 8) + { + + case (RDSPR_RLE256FAST >> 8): + SoftwareRenderCompressed256(s); + break; + + case (RDSPR_RLE256 >> 8): + case (RDSPR_RLE16>>8): + + if (s->type & RDSPR_DISPLAYALIGN) + return(RDERR_NOTIMPLEMENTED); + + sprite = malloc(s->w * s->h); + if (sprite == NULL) + return(RDERR_OUTOFMEMORY); + + if (s->type >> 8 == RDSPR_RLE16 >> 8) + { + if (DecompressRLE16(sprite, s->data, s->w * s->h, s->colourTable)) + return(RDERR_DECOMPRESSION); + } + else + { + if (DecompressRLE256(sprite, s->data, s->w * s->h)) + return(RDERR_DECOMPRESSION); + } + + if (s->type & RDSPR_FLIP) + { + newSprite = (uint8 *) malloc(s->w * s->h); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + MirrorSprite(newSprite, sprite, s->w, s->h); + free(sprite); + sprite = newSprite; + } + + if ((s->scale == 0) || (s->scale == 256)) + { + if ((s->type & RDSPR_EDGEBLEND) && (renderCaps & RDBLTFX_EDGEBLEND)) + { + // The sprite is to be edge blended. Let's get a copy of the background + // into a new sprite buffer, and write the sprite over it with edge blending + newSprite = malloc(s->w * s->h); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + + // RIGHT, SORT THIS FUCKING MESS OUT. + // We want to draw the sprite FROM the RECT clippedSprite. + // We want to draw the sprite TO the RECT clippedTarget. + clippedTarget.left = s->x - scrollx; + clippedTarget.right = clippedTarget.left + s->w; + clippedTarget.top = s->y - scrolly; + clippedTarget.bottom = clippedTarget.top + s->h; + + clippedSprite.top = 0; + clippedSprite.bottom = s->h; + clippedSprite.left = 0; + clippedSprite.right = s->w; + + //Now do the clipping - top + if (clippedTarget.top < 0) + { + clippedSprite.top -= clippedTarget.top; + clippedTarget.top = 0; + } + //Clip the bottom + if (clippedTarget.bottom > RENDERDEEP) + { + clippedSprite.bottom -= (clippedTarget.bottom - RENDERDEEP); + clippedTarget.bottom = RENDERDEEP; + } + //Clip the left + if (clippedTarget.left < 0) + { + clippedSprite.left -= clippedTarget.left; + clippedTarget.left = 0; + } + //Clip the right + if (clippedTarget.right > RENDERWIDE) + { + clippedSprite.right -= (clippedTarget.right - RENDERWIDE); + clippedTarget.right = RENDERWIDE; + } + + // We now have our clipped regions, so let's copy the background to the sprite. + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + memcpy(newSprite + s->w * i + clippedSprite.left, myScreenBuffer + RENDERWIDE * (clippedTarget.top+i) + clippedTarget.left, clippedSprite.right - clippedSprite.left); + } + + + // Now put the sprite onto the background sprite!?! + src = sprite + (clippedSprite.top + 1) * s->w + clippedSprite.left + 1; + srcExtra[0] = src - s->w; + srcExtra[1] = src - 1; + srcExtra[2] = src + 1; + srcExtra[3] = src + s->w; + dst = newSprite + (clippedSprite.top + 1) * s->w + clippedSprite.left + 1; + for (j=1; j<clippedSprite.bottom - clippedSprite.top - 1; j++) + { + for (i=1; i<clippedSprite.right - clippedSprite.left - 1; i++) + { + if (*src) + { + uint8 newp = *src; + count = 1; + + red = palCopy[newp][0]; + green = palCopy[newp][1]; + blue = palCopy[newp][2]; + for (k=0; k<4; k++) + { + if (newp = *srcExtra[k]) + { + red += palCopy[newp][0]; + green += palCopy[newp][1]; + blue += palCopy[newp][2]; + count += 1; + } + else + { + newp = *(dst - (src - srcExtra[k])); + red += palCopy[newp][0]; + green += palCopy[newp][1]; + blue += palCopy[newp][2]; + } + } + + if (count != 5) + *dst = QuickMatch((uint8) (red / 5), (uint8) (green / 5), (uint8) (blue / 5)); + else + *dst = *src; + } + src++; + dst++; + for (k=0; k<4; k++) + srcExtra[k]++; + } + diff = (s->w - (clippedSprite.right - clippedSprite.left)) + 2; + for (k=0; k<4; k++) + srcExtra[k] += diff; + src += diff; + dst += diff; + } + + // And copy the sprite back to the screen + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + memcpy(myScreenBuffer + RENDERWIDE * (clippedTarget.top+i) + clippedTarget.left, newSprite + s->w * i + clippedSprite.left, clippedSprite.right - clippedSprite.left); + } + + free(newSprite); + } + else if (s->type & RDSPR_BLEND) + { + + // We want to blend the sprite FROM the RECT clippedSprite. + // We want to blend the sprite TO the RECT clippedTarget. + clippedTarget.left = s->x - scrollx; + clippedTarget.right = clippedTarget.left + s->w; + clippedTarget.top = s->y - scrolly; + clippedTarget.bottom = clippedTarget.top + s->h; + + clippedSprite.top = 0; + clippedSprite.bottom = s->h; + clippedSprite.left = 0; + clippedSprite.right = s->w; + + //Now do the clipping - top + if (clippedTarget.top < 0) + { + clippedSprite.top -= clippedTarget.top; + clippedTarget.top = 0; + } + //Clip the bottom + if (clippedTarget.bottom > RENDERDEEP) + { + clippedSprite.bottom -= (clippedTarget.bottom - RENDERDEEP); + clippedTarget.bottom = RENDERDEEP; + } + //Clip the left + if (clippedTarget.left < 0) + { + clippedSprite.left -= clippedTarget.left; + clippedTarget.left = 0; + } + //Clip the right + if (clippedTarget.right > RENDERWIDE) + { + clippedSprite.right -= (clippedTarget.right - RENDERWIDE); + clippedTarget.right = RENDERWIDE; + } + + if (s->blend & 0x01) + { + if (renderCaps & RDBLTFX_FLATALPHA) + { + red = s->blend >> 8; + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + src = sprite + (clippedSprite.top + i) * s->w + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j<clippedSprite.right - clippedSprite.left; j++) + { + if (*src) + { + pixel = *dst; + // pixel = *newSprite; + *dst = paletteMatch[(((palCopy[*src][0] * red + palCopy[pixel][0] * (8 - red)) >> 5) << 12) + + (((palCopy[*src][1] * red + palCopy[pixel][1] * (8 - red)) >> 5) << 6) + + (((palCopy[*src][2] * red + palCopy[pixel][2] * (8 - red)) >> 5) )]; + } + src++; + dst++; + // newSprite++; + } + } + } + else + { + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + src = sprite + (clippedSprite.top + i) * s->w + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j<clippedSprite.right - clippedSprite.left; j++) + { + if (*src) + { + *dst = *src; + } + src++; + dst++; + } + } + } + } + else if (s->blend & 0x02) + { + red = palCopy[s->blend >> 8][0]; + green = palCopy[s->blend >> 8][0]; + blue = palCopy[s->blend >> 8][0]; + + + if (renderCaps & RDBLTFX_GRADEDALPHA) + { + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + src = sprite + (clippedSprite.top + i) * s->w + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + for (j=0; j<clippedSprite.right - clippedSprite.left; j++) + { + if (*src) + { + *dst = paletteMatch[((((*src * red + (16 - *src) * palCopy[*(dst)][0]) >> 4) >> 2) << 12) + + ((((*src * green + (16 - *src) * palCopy[*(dst)][1]) >> 4) >> 2) << 6) + + (((*src * blue + (16 - *src) * palCopy[*(dst)][2]) >> 4) >> 2)]; + + } + src++; + dst++; + } + } + } + else + { + char col = paletteMatch[((36 >> 2) << 12) + ((35 >> 2) << 6) + (34 >> 2)]; + for (i=0; i<clippedSprite.bottom - clippedSprite.top; i++) + { + src = sprite + (clippedSprite.top + i) * s->w + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + for (j=0; j<clippedSprite.right - clippedSprite.left; j++) + { + if (*src) + { + *dst = col; + } + src++; + dst++; + } + } + } + } + else + { + free(sprite); + DirectDrawError("Invalid blended sprite params", RDERR_UNKNOWNTYPE); + return(RDERR_UNKNOWNTYPE); + } + + + + } + else + { + + starty = s->y - scrolly; + endy = starty + s->h; + if (starty < 0) + starty = 0; + if (endy > RENDERDEEP) + endy = RENDERDEEP; + + startx = s->x - scrollx; + endx = startx + s->w; + if (startx < 0) + startx = 0; + if (endx > RENDERWIDE) + endx = RENDERWIDE; + + for (i=starty; i<endy; i++) + { + dst = myScreenBuffer + i * RENDERWIDE+ startx; + src = sprite + (i - (s->y - scrolly)) * s->w + (startx - (s->x - scrollx)); + if ((s->type & RDSPR_SHADOW) && (lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i+scrolly) * locationWide + s->x; + for (j=startx; j<endx; j++) + { + if (*src) + { + if (*lightMap) + *dst = QuickMatch((uint8) (((int32) (32 - *lightMap) * palCopy[*src][0]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][1]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][2]) >> 5)); + else + *dst = *src; + } + dst++; + src++; + lightMap++; + } + } + else + { + for (j=startx; j<endx; j++) + { + if (*src) + *dst = *src; + dst++; + src++; + } + } + } + } + } + else if (s->scale < 256) // Draw the sprite with scaling and arithmetic stretching + { + if (renderCaps & RDBLTFX_ARITHMETICSTRETCH) + { + + if ((s->scaledWidth > SCALE_MAXWIDTH) || (s->scaledHeight > SCALE_MAXHEIGHT)) + { + free(sprite); + return(RDERR_NOTIMPLEMENTED); + } + + // Create the buffer to copy the small sprite into + newSprite = malloc(s->scaledWidth * s->scaledHeight); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + + // Work out the x-scale + dx = s->w; + dy = s->scaledWidth; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + xScale[y] = x; + while (x < s->w) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + xScale[y] = x; + } + + // Work out the y-scale + dx = s->h; + dy = s->scaledHeight; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + yScale[y] = x; + while (x < s->h) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + yScale[y] = x; + } + + // If the sprite is clipped, then don't try to anti-alias it and arithmetic stretch. + // Just go for the quick and dirty squash! + if ((s->x - scrollx < 0) || (s->x - scrollx + s->scaledWidth > RENDERWIDE) || + (s->y - scrolly < 0) || (s->y - scrolly + s->scaledHeight > RENDERDEEP)) + { + spr = newSprite; + for (y=0; y<s->scaledHeight; y++) + { + for (x=0; x<s->scaledWidth; x++) + { + *spr++ = *(sprite + yScale[y] * s->w + xScale[x]); + } + } + } + else + { + spr = newSprite; + for (y=0; y<s->scaledHeight; y++) + { + for (x=0; x<s->scaledWidth; x++) + { + count = 0; + spriteCount = 0; + red = 0; + green = 0; + blue = 0; + for (j=yScale[y]; j<yScale[y+1]; j++) + { + for (i=xScale[x]; i<xScale[x+1]; i++) + { + p = sprite + j * s->w + i; + if (*p == 0) + { + uint8 newp; + + newp = myScreenBuffer[(s->y - scrolly + y) * RENDERWIDE + s->x - scrollx + x]; + red += palCopy[newp][0]; + green += palCopy[newp][1]; + blue += palCopy[newp][2]; + } + else + { + red += palCopy[*p][0]; + green += palCopy[*p][1]; + blue += palCopy[*p][2]; + spriteCount += 1; + } + count += 1; + } + } + if (spriteCount == 0) + { + *spr++ = 0; + } + else if (count == 1) + { + *spr++ = *p; + } + else + { + *spr++ = QuickMatch((uint8) (red / count), (uint8) (green / count), (uint8) (blue / count)); + } + } + } + } + + // Draw the sprite + starty = s->y - scrolly; + endy = starty + s->scaledHeight; + if (starty < 0) + starty = 0; + if (endy > RENDERDEEP) + endy = RENDERDEEP; + + startx = s->x - scrollx; + endx = startx + s->scaledWidth; + if (startx < 0) + startx = 0; + if (endx > RENDERWIDE) + endx = RENDERWIDE; + + for (i=starty; i<endy; i++) + { + dst = myScreenBuffer + i * RENDERWIDE+ startx; + src = newSprite + (i - (s->y - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i+scrolly) * locationWide + s->x; + for (j=startx; j<endx; j++) + { + if (*src) + { + if (*lightMap) + *dst = QuickMatch((uint8) (((int32) (32 - *lightMap) * palCopy[*src][0]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][1]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][2]) >> 5)); + else + *dst = *src; + } + dst++; + src++; + lightMap++; + } + } + else + { + + + for (j=startx; j<endx; j++) + { + if (*src) + *dst = *src; + dst++; + src++; + } + } + } + + free(newSprite); + + } + else // Draw scaled, value less than 256, line doubling + { + if ((s->scaledWidth > SCALE_MAXWIDTH) || (s->scaledHeight > SCALE_MAXHEIGHT)) + { + free(sprite); + return(RDERR_NOTIMPLEMENTED); + } + + // Create the buffer to copy the small sprite into + newSprite = malloc(s->scaledWidth * s->scaledHeight); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + + // Work out the x-scale + dx = s->w; + dy = s->scaledWidth; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + xScale[y] = x; + while (x < s->w) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + xScale[y] = x; + } + + // Work out the y-scale + dx = s->h; + dy = s->scaledHeight; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + yScale[y] = x; + while (x < s->h) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + } + yScale[y] = x; + } + + // Copy the sprite + // InitialiseColourMatch(s->colourTable); + spr = newSprite; + for (y=0; y<s->scaledHeight; y++) + { + for (x=0; x<s->scaledWidth; x++) + { + *spr++ = *(sprite + yScale[y] * s->w + xScale[x]); + } + } + + // Draw the sprite + starty = s->y - scrolly; + endy = starty + s->scaledHeight; + if (starty < 0) + starty = 0; + if (endy > RENDERDEEP) + endy = RENDERDEEP; + + startx = s->x - scrollx; + endx = startx + s->scaledWidth; + if (startx < 0) + startx = 0; + if (endx > RENDERWIDE) + endx = RENDERWIDE; + + for (i=starty; i<endy; i++) + { + dst = myScreenBuffer + i * RENDERWIDE+ startx; + src = newSprite + (i - (s->y - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i + scrolly) * locationWide + s->x; + for (j=startx; j<endx; j++) + { + if (*src) + { + if (*lightMap) + *dst = QuickMatch((uint8) (((int32) (32 - *lightMap) * palCopy[*src][0]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][1]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][2]) >> 5)); + else + *dst = *src; + } + dst++; + src++; + lightMap++; + } + } + else + { + for (j=startx; j<endx; j++) + { + if (*src) + *dst = *src; + dst++; + src++; + } + } + } + + free(newSprite); + } + + } + else //if (s->scale > 256) + { + if (s->scale > 512) + { + free(sprite); + return(RDERR_INVALIDSCALING); + } + + if (renderCaps & RDBLTFX_ARITHMETICSTRETCH) // Draw the sprite with scaling and anti-aliasing + { + + // Create the buffer to copy the bigger sprite into + newSprite = malloc(s->scaledWidth * s->scaledHeight); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + + // Work out the x-scale + dy = s->w; + dx = s->scaledWidth; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + xScale[y] = x; + while (x < s->scaledWidth) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + xScale[y] = x; + } + } + + // Work out the y-scale + dy = s->h; + dx = s->scaledHeight; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + yScale[y] = x; + while (x < s->scaledHeight) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + yScale[y] = x; + } + } + + // Copy the sprite + // InitialiseColourMatch(s->colourTable); + spr = newSprite; + for (y=0; y<s->h; y++) + { + for (j=yScale[y]; j<yScale[y+1]; j++) + { + for (x=0; x<s->w; x++) + { + for (i=xScale[x]; i<xScale[x+1]; i++) + { + *spr++ = *(sprite + y * s->w + x); + } + } + } + } + + // Piece of code to anti-alias the sprite. + newerSprite = malloc(s->scaledWidth * s->scaledHeight); + if (newerSprite == NULL) + { + free(newSprite); + free(sprite); + return(RDERR_OUTOFMEMORY); + } + + // THIS IS THE ANTI-ALIAS LOOP - IF THE SPRITE IS CLIPPED, DON'T ANTI-ALIAS + + if (!((s->x - scrollx < 0) || (s->x - scrollx + s->scaledWidth > RENDERWIDE) || + (s->y - scrolly < 0) || (s->y - scrolly + s->scaledHeight > RENDERDEEP))) + { + memcpy(newerSprite, newSprite, s->scaledWidth); + for (y = 1; y < s->scaledHeight-1; y++) + { + src = newSprite + y * s->scaledWidth; + dst = newerSprite + y * s->scaledWidth; + *dst++ = *src++; + for (x=1; x<s->scaledWidth-1; x++) + { + p = &myScreenBuffer[(s->y - scrolly + y) * RENDERWIDE + s->x - scrollx + x]; + count = 0; + if (*src) + { + count ++; + pt[0] = *src; + } + else + pt[0] = *p; + + pt[1] = *(src - s->scaledWidth); + if (pt[1] == 0) + pt[1] = *(p - RENDERWIDE); + else + count++; + + pt[2] = *(src - 1); + if (pt[2] == 0) + pt[2] = *(p - 1); + else + count++; + + pt[3] = *(src + 1); + if (pt[3] == 0) + pt[3] = *(p + 1); + else + count++; + + pt[4] = *(src + s->scaledWidth); + if (pt[4] == 0) + pt[4] = *(p + RENDERWIDE); + else + count++; + + if (count) + { + red = palCopy[pt[0]][0] << 2; + green = palCopy[pt[0]][1] << 2; + blue = palCopy[pt[0]][2] << 2; + for (i=1; i<5; i++) + { + red += palCopy[pt[i]][0]; + green += palCopy[pt[i]][1]; + blue += palCopy[pt[i]][2]; + } + + *dst++ = QuickMatch((uint8) (red >> 3), (uint8) (green >> 3), (uint8) (blue >> 3)); + } + else + { + *dst++ = 0; + } + src++; + } + *dst++ = *src++; + + } + memcpy(dst, src, s->scaledWidth); + free(newSprite); + newSprite = newerSprite; + } + + + + + + // Draw the sprite + starty = s->y - scrolly; + endy = starty + s->scaledHeight; + if (starty < 0) + starty = 0; + if (endy > RENDERDEEP) + endy = RENDERDEEP; + + startx = s->x - scrollx; + endx = startx + s->scaledWidth; + if (startx < 0) + startx = 0; + if (endx > RENDERWIDE) + endx = RENDERWIDE; + + for (i=starty; i<endy; i++) + { + dst = myScreenBuffer + i * RENDERWIDE+ startx; + src = newSprite + (i - (s->y - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i + scrolly) * locationWide + s->x; + for (j=startx; j<endx; j++) + { + if (*src) + { + if (*lightMap) + *dst = QuickMatch((uint8) (((int32) (32 - *lightMap) * palCopy[*src][0]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][1]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][2]) >> 5)); + else + *dst = *src; + } + dst++; + src++; + lightMap++; + } + } + else + { + for (j=startx; j<endx; j++) + { + if (*src) + *dst = *src; + dst++; + src++; + } + } + } + + free(newSprite); + } + else // Draw the stretched sprite with line doubling. + { + // Create the buffer to copy the bigger sprite into + newSprite = malloc(s->scaledWidth * s->scaledHeight); + if (newSprite == NULL) + { + free(sprite); + return(RDERR_OUTOFMEMORY); + } + + // Work out the x-scale + dy = s->w; + dx = s->scaledWidth; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + xScale[y] = x; + while (x < s->scaledWidth) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + xScale[y] = x; + } + } + + // Work out the y-scale + dy = s->h; + dx = s->scaledHeight; + ince = 2 * dy; + incne = 2 * (dy - dx); + d = 2 * dy - dx; + + x = 0; + y = 0; + yScale[y] = x; + while (x < s->scaledHeight) + { + if (d <= 0) + { + d += ince; + x += 1; + } + else + { + d += incne; + x += 1; + y += 1; + yScale[y] = x; + } + } + + // Copy the sprite + // InitialiseColourMatch(s->colourTable); + spr = newSprite; + for (y=0; y<s->h; y++) + { + for (j=yScale[y]; j<yScale[y+1]; j++) + { + for (x=0; x<s->w; x++) + { + for (i=xScale[x]; i<xScale[x+1]; i++) + { + *spr++ = *(sprite + y * s->w + x); + } + } + } + } + + // Piece of code to anti-alias the sprite. + + // Draw the sprite + starty = s->y - scrolly; + endy = starty + s->scaledHeight; + if (starty < 0) + starty = 0; + if (endy > RENDERDEEP) + endy = RENDERDEEP; + + startx = s->x - scrollx; + endx = startx + s->scaledWidth; + if (startx < 0) + startx = 0; + if (endx > RENDERWIDE) + endx = RENDERWIDE; + + for (i=starty; i<endy; i++) + { + dst = myScreenBuffer + i * RENDERWIDE+ startx; + src = newSprite + (i - (s->y - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + + + + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i + scrolly) * locationWide + s->x; + for (j=startx; j<endx; j++) + { + if (*src) + { + if (*lightMap) + *dst = QuickMatch((uint8) (((int32) (32 - *lightMap) * palCopy[*src][0]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][1]) >> 5), + (uint8) (((int32) (32 - *lightMap) * palCopy[*src][2]) >> 5)); + else + *dst = *src; + } + dst++; + src++; + lightMap++; + } + } + else + { + for (j=startx; j<endx; j++) + { + if (*src) + *dst = *src; + dst++; + src++; + } + } + } + + free(newSprite); + } + + } + + free(sprite); + break; +// case (RDSPR_LAYERCOMPRESSION>>8): +// return(RDERR_NOTIMPLEMENTED); +// break; + default: + return(RDERR_UNKNOWNTYPE); + } + } + } + else //(type & RDSPR_FULL): + { + + // Set startx and starty for the screen buffer + if (s->type & RDSPR_DISPLAYALIGN) + { + starty = s->y; + startx = s->x; + } + else + { + starty = s->y - scrolly; + startx = s->x - scrollx; + } + + + // Set end position of x and y. + endy = s->h + starty; + endx = s->w + startx; + + + // Do clipping + if ((starty < RENDERDEEP) && (endy > 0) && (startx < RENDERWIDE) && (endx > 0)) + { + if (starty < 0) + starty = 0; + + if (endy > RENDERDEEP) + endy = RENDERDEEP; + + if (startx < 0) + startx = 0; + + if (endx > RENDERWIDE) + endx = RENDERWIDE; + + + dst = (uint8 *) myScreenBuffer + starty * RENDERWIDE + s->x; + if (s->type & RDSPR_DISPLAYALIGN) + src = (uint8 *) s->data + s->w * (starty - (s->y)) + (startx - s->x); + else + src = (uint8 *) s->data + s->w * (starty - (s->y - scrolly)) + (startx - (s->x - scrollx)); + + for (i=starty; i<endy; i++) + { + memcpy(dst, src, endx - startx); + src += s->w; + dst += RENDERWIDE; + } + } + } + } + +#if PROFILING == 1 + QueryPerformanceCounter(&endTime); + profileSpriteRender += (endTime.LowPart - startTime.LowPart); +#endif +*/ + return(RD_OK); +} + + + +int32 OpenLightMask(_spriteInfo *s) + +{ + + if (lightMask) + return(RDERR_NOTCLOSED); + + lightMask = (uint8 *) malloc(s->w * s->h); + + if (lightMask == NULL) + return(RDERR_OUTOFMEMORY); + + if (DecompressRLE256(lightMask, s->data, s->w * s->h)) + return(RDERR_DECOMPRESSION); + + return(RD_OK); + +} + +int32 CloseLightMask(void) +{ + + if (!lightMask) + return(RDERR_NOTOPEN); + + free(lightMask); + + lightMask = 0; + + return(RD_OK); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + |