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 | |
| parent | f020d28b5e9297f93d5bedae62885b380c23f517 (diff) | |
| download | scummvm-rg350-dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57.tar.gz scummvm-rg350-dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57.tar.bz2 scummvm-rg350-dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57.zip | |
bs2 driver
svn-id: r9212
| -rw-r--r-- | sword2/driver/.cvsignore | 1 | ||||
| -rw-r--r-- | sword2/driver/_console.cpp | 165 | ||||
| -rw-r--r-- | sword2/driver/_console.h | 47 | ||||
| -rw-r--r-- | sword2/driver/_mouse.cpp | 618 | ||||
| -rw-r--r-- | sword2/driver/_mouse.h | 54 | ||||
| -rw-r--r-- | sword2/driver/d_draw.cpp | 1274 | ||||
| -rw-r--r-- | sword2/driver/d_draw.h | 96 | ||||
| -rw-r--r-- | sword2/driver/d_sound.cpp | 3095 | ||||
| -rw-r--r-- | sword2/driver/d_sound.h | 43 | ||||
| -rw-r--r-- | sword2/driver/ddutil.h | 159 | ||||
| -rw-r--r-- | sword2/driver/driver96.h | 1665 | ||||
| -rw-r--r-- | sword2/driver/keyboard.cpp | 129 | ||||
| -rw-r--r-- | sword2/driver/keyboard.h | 46 | ||||
| -rw-r--r-- | sword2/driver/language.cpp | 134 | ||||
| -rw-r--r-- | sword2/driver/menu.cpp | 570 | ||||
| -rw-r--r-- | sword2/driver/menu.h | 47 | ||||
| -rw-r--r-- | sword2/driver/misc.cpp | 62 | ||||
| -rw-r--r-- | sword2/driver/palette.cpp | 482 | ||||
| -rw-r--r-- | sword2/driver/palette.h | 66 | ||||
| -rw-r--r-- | sword2/driver/rdwin.cpp | 627 | ||||
| -rw-r--r-- | sword2/driver/rdwin.h | 56 | ||||
| -rw-r--r-- | sword2/driver/render.cpp | 1283 | ||||
| -rw-r--r-- | sword2/driver/render.h | 93 | ||||
| -rw-r--r-- | sword2/driver/sprite.cpp | 3240 | 
24 files changed, 14052 insertions, 0 deletions
| diff --git a/sword2/driver/.cvsignore b/sword2/driver/.cvsignore new file mode 100644 index 0000000000..39a06683b7 --- /dev/null +++ b/sword2/driver/.cvsignore @@ -0,0 +1 @@ +.deps diff --git a/sword2/driver/_console.cpp b/sword2/driver/_console.cpp new file mode 100644 index 0000000000..fe9bb69cd1 --- /dev/null +++ b/sword2/driver/_console.cpp @@ -0,0 +1,165 @@ +/* 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	:	console.c +//	Created		:	19th September 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This module holds the code which controls and displays +//					the console/debugging window. +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		20-Sep-96	PRP		Inital console code.  Currently draws the  +//								background of the console window.  Tex +// +// +//	Functions +//	--------- +// +//	-------------------------------------------------------------------------- +// +//	int32 OpenConsole(void) +// +//	Displays the console window and directs keyboard input to it. +// +//	-------------------------------------------------------------------------- +// +//	int32 CloseConsole(void) +// +//	Removes the console from the display. +// +//============================================================================= + + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> + +//#include "ddraw.h" + +#include "driver96.h" + +#include "d_draw.h" + + + +uint8			consoleStatus = 0;			// 1 - console display +static uint16	consoley = 0; +static uint32	consoleSize; +static uint8	*consoleSprite = NULL; + + + +//	-------------------------------------------------------------------------- +//	Called before the screens are flipped, so that the console can be drawn +//	over the screen if necessary. +//	-------------------------------------------------------------------------- +void DisplayConsole(void) + +{ +	warning("stub DisplayConsole"); +/* +	uint8			*src, *dst; +	uint8			i; +//	DDSURFACEDESC	ddDescription; +//	HRESULT			hr; + + +	if (consoleStatus) +	{ + +		ddDescription.dwSize = sizeof(ddDescription); +	 +		hr = IDirectDrawSurface_Lock(lpBackBuffer, NULL, &ddDescription, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +		if (hr != DD_OK) +		{ +			RestoreSurfaces(); +			hr = IDirectDrawSurface_Lock(lpBackBuffer, NULL, &ddDescription, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +		} + +		if (hr == DD_OK) +		{ + +			dst = (uint8 *) ddDescription.lpSurface + (screenDeep - consoley) * ddDescription.lPitch; +			src = (uint8 *) consoleSprite; + +			for (i=0; i<consoley; i++) +			{ +				memcpy(dst, src, screenWide); +				src += screenWide; +				dst += ddDescription.lPitch; +			} +			IDirectDrawSurface_Unlock(lpBackBuffer, ddDescription.lpSurface); +		} +	} +	*/ +} + + + + +int32 OpenConsole(void) + +{ +	warning("stub OpenConsole"); +/* +	if (consoleStatus) +		return(RDERR_ALREADYOPEN); + +	if (consoleSprite == NULL) +	{ +		consoley = screenDeep >> 2; +		consoleSize = screenWide * consoley; +		consoleSprite = (uint8 *) malloc(consoleSize); +	} + +	if (consoleSprite == NULL) +		return(RDERR_OUTOFMEMORY); + +	memset(consoleSprite, 0, consoleSize); +*/ +	consoleStatus = 1; +	 +	return(RD_OK); + +} + + + + +int32 CloseConsole(void) + +{ + +	if (!consoleStatus) +		return(RDERR_ALREADYCLOSED); + +	free(consoleSprite); +	consoleSprite = NULL; + +	consoleStatus = 0; + +	return(RD_OK); + +} + diff --git a/sword2/driver/_console.h b/sword2/driver/_console.h new file mode 100644 index 0000000000..8907a00164 --- /dev/null +++ b/sword2/driver/_console.h @@ -0,0 +1,47 @@ +/* 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	:	console.h +//	Created		:	19th September 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		20-Sep-96	PRP		Internal driver interface to the console +//								functions and data. +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the console.c module, but can be accessed by +//					other parts of the driver96 library. +// +//============================================================================= + + +#ifndef CONSOLE_H +#define CONSOLE_H + + + +extern void DisplayConsole(void); + + +#endif diff --git a/sword2/driver/_mouse.cpp b/sword2/driver/_mouse.cpp new file mode 100644 index 0000000000..da2627a3f1 --- /dev/null +++ b/sword2/driver/_mouse.cpp @@ -0,0 +1,618 @@ +/* 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	:	mouse.c +//	Created		:	17th September 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This module holds the interface to the mouse.. +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		18-Sep-96	PRP		Initial mouse functions.  Simple logging of +//								previous 16 mouse events implemented.  Mouse +//								drawing is currently hard coded, but animations +//								will be definable at a later date. +// +//	1.1		03-Oct-96	PRP		Changed the mouse position so that mouse y of +//								zero is the top left corner of the screen, and +//								not the top left corner of the top menubar. +//								Also, removed the x and y position from the +//								mouse log.  And changed the MouseEvent function +//								so that it returns a pointer to _mouseEvent +// +//	1.2		04-Oct-96	PRP		Put direct path in for ddraw.h +// +//	1.3		31-Oct-96	PRP		Added code to draw the proper type of mouse +//								sprite, which comprises of the internal +//								function DrawMouse and globally available +//								AnimateMouse and SetMouseAnim. +// +//	1.4		15-Nov-96	PRP		Definition of menubar size is now obtained +//								from menu.h +// +//	1.5		18-Nov-96	PRP		Changed the direct draw interface to +//								IDirectDraw2. +// +//	1.6		25-Nov-96	PRP		Added functionality to set the luggage +//								sprite. +// +//	1.7		06-Jan-97	PRP		Changed the width and height of sprites +//								to be signed. +// +//	1.8		14-Jan-97	JEL		Reset mouse frame when new animation starts. +// +//	1.9		27-Jan-97	PRP		Changed the mouse drawing routines to utilize +//								directDraw surfaces and transparency blitting. +// +//	1.10	10-Feb-97	PRP		Changed the directDraw error reporting so that +//								it works properly.  Also, created the mouse +//								sprite depending upon whether the hardware can +//								blt or not. +// +//	1.11	19-Mar-97	PRP		Fixed a bug which was causing the mouse sprite +//								to be freed up each frame and therefore  +//								decompressed and re-loaded each frame. +// +//	1.12	20-Mar-97	PRP		Added a function to reset the render code when +//								the control panel is entered. +// +//	1.13	09-Apr-97	PRP		Made the mouse animation wrap back to the +//								seventh frame. +// +//	1.14	10-Apr-97	PRP		Added parameter to define whether mouse flashes +//								or not. +// +//	1.15	23-Jul-97	JEL		Added CheckForMouseEvents() to return no. of events outstanding +// +// +//	Functions +//	--------- +// +//	-------------------------------------------------------------------------- +// +//  _mouseEvent *MouseEvent(void) +// +//	The address of a _mouseEvent pointer is passed in.  If there is a mouse  +//	event in the queue, a the value of the mouse event pointer is set to the +//	address of the event, otherwise, the mouse event pointer is set to NULL. +// +//	-------------------------------------------------------------------------- +// +//	int32 SetMouseAnim(uint8 *ma, int32 size) +// +//	A pointer to a valid mouse animation is passed in, along with the size of +//	the header plus sprite data.  Remember to check that the function has  +//	successfully completed, as memory allocation is required. +//	Pass NULL in to clear the mouse sprite. +// +//	-------------------------------------------------------------------------- +// +//	int32 SetLuggageAnim(uint8 *ma, int32 size) +// +//	A pointer to a valid luggage animation is passed in, along with the size of +//	the header plus sprite data.  Remember to check that the function has  +//	successfully completed, as memory allocation is required. +//	Pass NULL in to clear the luggage sprite.  Luggage sprites are of the same +//	format as mouse sprites. +// +//	-------------------------------------------------------------------------- +// +//	int32 AnimateMouse(void) +// +//	This function animates the current mouse pointer.  If no pointer is  +//	currently defined, an error code is returned. +// +//============================================================================= + + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> + +//#include "ddraw.h" + +#include "driver96.h" + +#include "d_draw.h" +#include "render.h" +#include "menu.h" + + + +#define MAX_MOUSE_EVENTS 16 +#define MOUSEFLASHFRAME 6 + + +typedef struct +{ +	uint8	runTimeComp;	// type of runtime compression used for the frame data +	uint8	noAnimFrames;	// number of frames in the anim +	int8	xHotSpot;		 +	int8	yHotSpot; +	uint8	mousew; +	uint8	mouseh; +} _mouseAnim; + + +int16				mousex; +int16				mousey; + +static	uint8		mouseBacklog = 0; +static	uint8		mouseLogPos = 0; +static	uint8		mouseFrame; +static	uint8		luggageFrame = 0; +static	uint8		*mouseSprite = NULL; +static	_mouseAnim	*mouseAnim = NULL; +static	_mouseAnim	*luggageAnim = NULL; +static	_mouseEvent	mouseLog[MAX_MOUSE_EVENTS]; +static  int32		*mouseOffsets; +static	int32		*luggageOffset; +//static	LPDIRECTDRAWSURFACE	*mouseSurfaces; +//static	LPDIRECTDRAWSURFACE luggageSurface = NULL; + + + + + + + +void ResetRenderEngine(void) + +{ +	 +	memset(myScreenBuffer, 0, RENDERWIDE * RENDERDEEP); +	parallaxScrollx = 0; +	parallaxScrolly = 0; +	scrollx = 0; +	scrolly = 0; + +} + + + + +//	-------------------------------------------------------------------------- +//	Logs the mouse button event passed in buttons.  The button events are  +//	defined as RD_LEFTBUTTONDOWN, RD_LEFTBUTTONUP, RD_RIGHTBUTTONDOWN and +//	RD_RIGHTBUTTONUP. +//	-------------------------------------------------------------------------- +void LogMouseEvent(uint16 buttons) + +{ + +	_mouseEvent *me; + + +	if (mouseBacklog == MAX_MOUSE_EVENTS-1)			// We need to leave the one which is +	{												// the current event alone! +		return; +	} +	 +	me = &mouseLog[(mouseBacklog + mouseLogPos) % MAX_MOUSE_EVENTS]; +	me->buttons = buttons; +	mouseBacklog += 1; + +} + + + + + + +int32 DecompressMouse(uint8 *decomp, uint8 *comp, int32 size) + +{ + +	int32 i = 0; + +	while (i < size) +	{ +		if (*comp > 183) +		{ +			*decomp++ = *comp++; +			i += 1; +		} +		else +		{ +			memset(decomp, 0, *comp); +			decomp += *comp; +			i += *comp++; +		} +	} +	return(RD_OK); +} + + + +//	-------------------------------------------------------------------------- +//	Draws the mouse sprite to the back buffer. +//	-------------------------------------------------------------------------- +int32 DrawMouse(void) + +{ +	warning("stub DrawMouse"); +/* +	uint8			*src, *dst; +	int16			i; +	int16			xoff=0, yoff=0; +	uint8			*decompSprite; +	DDSURFACEDESC	ddsd; +	HRESULT			hr; +	RECT			rs, rd; + + + +	if (luggageAnim) +	{ + +		if (luggageSurface == NULL) +		{ +			// Create the luggage surface. +			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 = luggageAnim->mousew; +			ddsd.dwHeight = luggageAnim->mouseh; +			hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &luggageSurface, NULL); +			if (hr != DD_OK) +			{ +				if (hr == DDERR_OUTOFVIDEOMEMORY) +				{ +					ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; +					hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &luggageSurface, NULL); +				} +				if (hr != DD_OK) +				{ +					DirectDrawError("Cannot create mouse surface", hr); +					return(hr); +				} +			} +			//	Set the surface blt source colour key +			hr = IDirectDrawSurface2_SetColorKey(luggageSurface, DDCKEY_SRCBLT, &blackColorKey); + +			//  Copy the data into the surfaces. +			decompSprite = (uint8 *) malloc(luggageAnim->mousew * luggageAnim->mouseh); +			if (decompSprite == NULL) +				return(RDERR_OUTOFMEMORY); +//			DecompressMouse(decompSprite, (uint8 *) luggageAnim + *mouseOffsets, luggageAnim->mousew * luggageAnim->mouseh); +			DecompressMouse(decompSprite, (uint8 *) luggageAnim + *luggageOffset, luggageAnim->mousew * luggageAnim->mouseh); +			memset(&ddsd, 0, sizeof(DDSURFACEDESC)); +			ddsd.dwSize = sizeof(DDSURFACEDESC); +			hr = IDirectDrawSurface2_Lock(luggageSurface, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +			if (hr != DD_OK) +			{ +				IDirectDrawSurface2_Restore(luggageSurface); +				hr = IDirectDrawSurface2_Lock(luggageSurface, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +				if (hr != DD_OK) +				{ +					DirectDrawError("Unable to lock luggage surface", hr); +					return(hr); +				} +			} +			dst = ddsd.lpSurface; +			src = decompSprite; +			for (i=0; i<luggageAnim->mouseh; i++) +			{ +				memcpy(dst, src, luggageAnim->mousew); +				dst += ddsd.lPitch; +				src += luggageAnim->mousew; +			} +			IDirectDrawSurface2_Unlock(luggageSurface, ddsd.lpSurface); +			free(decompSprite); +		} + + +		rd.top = mousey + MENUDEEP - luggageAnim->yHotSpot; +		rd.bottom = rd.top + luggageAnim->mouseh; +		rd.left = mousex - luggageAnim->xHotSpot; +		rd.right = rd.left + luggageAnim->mousew; + +		rs.left = 0; +		rs.right = luggageAnim->mousew; +		rs.top = 0; +		rs.bottom = luggageAnim->mouseh; + +		if (rd.left < 0) +		{ +			rs.left = 0 - rd.left; +			rd.left = 0; +		} +		if (rd.top < 0) +		{ +			rs.top = 0 - rd.top; +			rd.top = 0; +		} +		if (rd.right > RENDERWIDE) +		{ +			rs.right -= (rd.right - RENDERWIDE); +			rd.right = RENDERWIDE; +		} +		if (rd.bottom > ALIGNRENDERDEEP) +		{ +			rs.bottom -= (rd.bottom - ALIGNRENDERDEEP); +			rd.bottom = ALIGNRENDERDEEP; +		} + +		hr = IDirectDrawSurface2_Blt(lpBackBuffer, &rd, luggageSurface, &rs, DDBLT_WAIT | DDBLT_KEYSRC, NULL); +		if (hr = DDERR_SURFACELOST) +		{ +			IDirectDrawSurface2_Release(luggageSurface); +			luggageSurface = NULL; +		} + +	} + +	if (mouseAnim == NULL) +	{ +		return(RD_OK); +	} + + +	//  Decompress the mouse sprite onto the directDraw surface, if it is not +	//	there already. +	if (*(mouseSurfaces + mouseFrame) == NULL) +	{ + +		// Create the mouse surface. +		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 = mouseAnim->mousew; +		ddsd.dwHeight = mouseAnim->mouseh; +		hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, mouseSurfaces + mouseFrame, NULL); +		if (hr != DD_OK) +		{ +			if (hr == DDERR_OUTOFVIDEOMEMORY) +			{ +				ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY; +				hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, mouseSurfaces + mouseFrame, NULL); +			} +			if (hr != DD_OK) +			{ +				DirectDrawError("Cannot create mouse surface", hr); +				return(hr); +			} +		} +		//	Set the surface blt source colour key +		hr = IDirectDrawSurface2_SetColorKey(*(mouseSurfaces + mouseFrame), DDCKEY_SRCBLT, &blackColorKey); + +		//  Copy the data into the surfaces. +		decompSprite = (uint8 *) malloc(mouseAnim->mousew * mouseAnim->mouseh); +		if (decompSprite == NULL) +			return(RDERR_OUTOFMEMORY); +		DecompressMouse(decompSprite, mouseSprite, mouseAnim->mousew * mouseAnim->mouseh); +		memset(&ddsd, 0, sizeof(DDSURFACEDESC)); +		ddsd.dwSize = sizeof(DDSURFACEDESC); +		hr = IDirectDrawSurface2_Lock(*(mouseSurfaces + mouseFrame), NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +		if (hr != DD_OK) +		{ +			IDirectDrawSurface2_Restore(*(mouseSurfaces + mouseFrame)); +			hr = IDirectDrawSurface2_Lock(*(mouseSurfaces + mouseFrame), NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +			if (hr != DD_OK) +			{ +				DirectDrawError("Cannot lock mouse surface", hr); +				return(hr); +			} +		} +		dst = ddsd.lpSurface; +		src = decompSprite; +		for (i=0; i<mouseAnim->mouseh; i++) +		{ +			memcpy(dst, src, mouseAnim->mousew); +			dst += ddsd.lPitch; +			src += mouseAnim->mousew; +		} +		IDirectDrawSurface2_Unlock(*(mouseSurfaces + mouseFrame), ddsd.lpSurface); +		free(decompSprite); +	} + + +	rd.top = mousey + MENUDEEP - mouseAnim->yHotSpot; +	rd.bottom = rd.top + mouseAnim->mouseh; +	rd.left = mousex - mouseAnim->xHotSpot; +	rd.right = rd.left + mouseAnim->mousew; + +	rs.left = 0; +	rs.right = mouseAnim->mousew; +	rs.top = 0; +	rs.bottom = mouseAnim->mouseh; + +	if (rd.left < 0) +	{ +		rs.left = 0 - rd.left; +		rd.left = 0; +	} +	if (rd.top < 0) +	{ +		rs.top = 0 - rd.top; +		rd.top = 0; +	} +	if (rd.right > RENDERWIDE) +	{ +		rs.right -= (rd.right - RENDERWIDE); +		rd.right = RENDERWIDE; +	} +	if (rd.bottom > ALIGNRENDERDEEP) +	{ +		rs.bottom -= (rd.bottom - ALIGNRENDERDEEP); +		rd.bottom = ALIGNRENDERDEEP; +	} + +	hr = IDirectDrawSurface2_Blt(lpBackBuffer, &rd, *(mouseSurfaces + mouseFrame), &rs, DDBLT_WAIT | DDBLT_KEYSRC, NULL); +	if (hr == DDERR_SURFACELOST) +	{ +		IDirectDrawSurface2_Release(*(mouseSurfaces + mouseFrame)); +		*(mouseSurfaces + mouseFrame) = NULL; +	} +*/ +	return(RD_OK); + +} + + + +_mouseEvent *MouseEvent(void) + +{ +	_mouseEvent *me; + +	if (mouseBacklog) +	{ +		me = &mouseLog[mouseLogPos]; +		if (++mouseLogPos == MAX_MOUSE_EVENTS) +		{ +			mouseLogPos = 0; +		} +		mouseBacklog -= 1; +		return(me); +	} + +	return(NULL); + +} + + +uint8 CheckForMouseEvents(void)		// (James23july97) +{ +	return (mouseBacklog);	// return the number of mouse events waiting	 +} + + +int32 AnimateMouse(void) + +{ +	if (mouseAnim) +	{ +		if (++mouseFrame == mouseAnim->noAnimFrames) +		{ +			mouseFrame = MOUSEFLASHFRAME; +		} +		mouseSprite = (uint8 *) mouseAnim + *(mouseOffsets+mouseFrame); +	} +	else +	{ +		return(RDERR_UNKNOWN); +	} +	 +	return(RD_OK); + +} + + + +int32 SetMouseAnim(uint8 *ma, int32 size, int32 mouseFlash) + +{ +	warning("stub SetMouseAnim( %d, %d )", size, mouseFlash); +/* +	int32 i; + +	if (mouseAnim) +	{ +		for (i=0; i<mouseAnim->noAnimFrames; i++) +		{ +			if (*(mouseSurfaces + i)) +			{ +				IDirectDrawSurface2_Release(*(mouseSurfaces + i)); +				*(mouseSurfaces + i) = NULL; +			} +		} + +		free(mouseAnim); +		mouseAnim = NULL; +		free(mouseSurfaces); +		mouseSurfaces = NULL; +	} + +	if (ma) +	{ +		if (mouseFlash == RDMOUSE_FLASH) +			mouseFrame = 0; +		else +			mouseFrame = MOUSEFLASHFRAME; +		mouseAnim = malloc(size); +		if (mouseAnim == NULL) +		{ +			return(RDERR_OUTOFMEMORY); +		} +		else +		{ +			memcpy((uint8 *) mouseAnim, ma, size); +			mouseOffsets = (int32 *) ((uint8 *) mouseAnim + sizeof(_mouseAnim)); +			AnimateMouse(); +			mouseSurfaces = (LPDIRECTDRAWSURFACE *) malloc(mouseAnim->noAnimFrames * sizeof(LPDIRECTDRAWSURFACE)); +			if (mouseSurfaces == NULL) +				return(RDERR_OUTOFMEMORY); +			memset(mouseSurfaces, 0, sizeof(LPDIRECTDRAWSURFACE) * mouseAnim->noAnimFrames); +		} +	} +*/ +	return(RD_OK); + +} + + +int32 SetLuggageAnim(uint8 *ma, int32 size) + +{ +	warning("stub SetLugggeAnim"); +/* +	 +	if (luggageAnim) +	{ +		free(luggageAnim); +		luggageAnim = NULL; +	} + +	if (ma) +	{ +		luggageAnim = malloc(size); +		if (luggageAnim == NULL) +		{ +			return(RDERR_OUTOFMEMORY); +		} +		else +		{ +			memcpy((uint8 *) luggageAnim, ma, size); +			luggageOffset = (int32 *) ((uint8 *) luggageAnim + sizeof(_mouseAnim)); +			AnimateMouse(); +		} +	} +*/ +	return(RD_OK); + +} + + diff --git a/sword2/driver/_mouse.h b/sword2/driver/_mouse.h new file mode 100644 index 0000000000..290f5caf34 --- /dev/null +++ b/sword2/driver/_mouse.h @@ -0,0 +1,54 @@ +/* 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	:	mouse.h +//	Created		:	18th September 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		18-Sep-96	PRP		Internal driver interface to the mouse driver +//								functions and data. +// +//	1.1		03-Oct-96	PRP		Changed the definition of mousex and y so that +//								negative values are allowed. +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the mouse.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef MOUSE_H +#define MOUSE_H + + +extern	int16	mousex;						// Mouse x coordinate +extern	int16	mousey;						// Mouse y coordinate + +extern	void LogMouseEvent(uint16 buttons);	// Adds a mouse event to the log +extern	int32 DrawMouse(void);				// Renders the mouse onto the back buffer. + + +#endif diff --git a/sword2/driver/d_draw.cpp b/sword2/driver/d_draw.cpp new file mode 100644 index 0000000000..30baabeb2d --- /dev/null +++ b/sword2/driver/d_draw.cpp @@ -0,0 +1,1274 @@ +/* Copyright (C) 1994-2003 Revolution Software Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * + * $Header$ + */ + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> +//#include <mmsystem.h> +#include <stdio.h> + +//#include "ddraw.h" + +#include "driver96.h" +#include "rdwin.h" +#include "_mouse.h" +#include "d_draw.h" +#include "palette.h" + +//#include "ddutil.h" +//CDisplay	*g_pDisplay        = NULL; + + + + + +#define SCREENYOFFSET	40 + +#define MILLISECSPERCYCLE 83 + + + +/* +LPDIRECTDRAW7        m_pDD; + + +static LPDIRECTDRAW		lpDraw;				// DirectDraw object +LPDIRECTDRAW2			lpDD2;				// DirectDraw2 object +LPDIRECTDRAWSURFACE		lpPrimarySurface;	// DirectDraw primary surface +LPDIRECTDRAWSURFACE		lpBackBuffer;		// DirectDraw back surface +LPDIRECTDRAWPALETTE		lpPalette = NULL;	// DirectDraw palette + +static PALETTEENTRY AppPalette[256];		// Application wide logical palette +*/ + + +// Game screen metrics +int16			screenDeep; +int16			screenWide; + + +// Set to 1 if vertical blank status cannot be checked. +static BOOL		noVbl = 0; +BOOL			bFullScreen = 0; + + + +// 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; +static	int16	scrollxTarget; +static	int16	scrollyTarget; +static	int16	scrollxOld; +static	int16	scrollyOld; +static	int16	failCount = 0; +//static	DDCAPS	driverCaps; + +int32			renderCaps = 0; +int32			dxHalCaps = 0; +int32			dxHelCaps = 0; +//DDCOLORKEY		blackColorKey; + + +static int32 platformIsNT = 0; + + +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- + + +void FatalDirectDrawError(char *str, int32 code, char *filename, int32 line) +{ + +	char string[256]; + +	RestoreDisplay(); + +	sprintf(string, "FATAL: %s - code 0x%.8x - file %s - line %d", str, code, filename, line); +	//MessageBox(hwnd, string, "DDraw error", MB_OK); +	warning("%s", string); + +} + + + + +//---------------------------------------------------------------------------------------------------------------- + + + +int32 PlotDots(int16 x, int16 y, int16 count) + +{ + +	int16			i; +	uint8			*dst; + +	warning("stub PlotDots( %d, %d, %d )", x, y, count); +/* +	DDSURFACEDESC	ddDescription; +	HRESULT			hr; + +	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 + y * ddDescription.lPitch + x; + +		for (i=0; i<=count; i++) +		{ +			*dst = 184; +			dst += 2; +		} +		dst = (uint8 *) ddDescription.lpSurface + (y+1) * ddDescription.lPitch + x; +		for (i=0; i<=count/10; i++) +		{ +			*dst = 184; +			dst += 20; +		} +		IDirectDrawSurface2_Unlock(lpBackBuffer, ddDescription.lpSurface); +	} +*/ +	return(RD_OK); + +} +//---------------------------------------------------------------------------------------------------------------- + + + +void RestoreSurfaces(void) + +{ +	warning("stub RestoreSurfaces"); +/* +	IDirectDrawSurface2_Restore(lpPrimarySurface); +	IDirectDrawSurface2_Restore(lpBackBuffer); +*/ +} + +//---------------------------------------------------------------------------------------------------------------- + +/* +static PALETTEENTRY *CreateAppPalette(PALETTEENTRY *pe) +{ + +	HDC	screen_dc; + +//  Fill the palette with system colours +	screen_dc = GetDC(NULL); +	GetSystemPaletteEntries(screen_dc, 0, 256, pe); +	ReleaseDC(NULL, screen_dc); + +	return pe; + +} +*/ + + +//---------------------------------------------------------------------------------------------------------------- + +int32 RestoreDisplay(void) + +{ +	warning("stub RestoreDisplay"); +/* +    if( lpDraw != NULL ) +    { +        if( lpPrimarySurface != NULL ) +        { +            IDirectDrawSurface2_Release(lpPrimarySurface); +            lpPrimarySurface = NULL; +        } +        if( lpPalette != NULL ) +        { +            IDirectDrawPalette_Release(lpPalette); +            lpPalette = NULL; +        } +		if (lpDD2 != NULL) +		{ +			IDirectDraw2_Release(lpDD2); +			lpDD2 = NULL; +		} + +		IDirectDraw_Release(lpDraw); +		lpDraw = NULL; +    } +*/ +	return(RD_OK); + +} + + +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- + +int32 InitialiseDisplay(int16 width, int16 height, int16 colourDepth, int32 windowType) +{ +/* +	DDSURFACEDESC       ddsd; +    DDSCAPS             ddscaps; +    HRESULT             hr; +	DDCAPS				helCaps; +	LARGE_INTEGER timerFrequency; +	int32 capsError = 0; + + +   OSVERSIONINFO VersionInfo; +   VersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); +    +   if (GetVersionEx(&VersionInfo)) +   { + +	   switch (VersionInfo.dwPlatformId) +	   { +	   case VER_PLATFORM_WIN32s : +	   case VER_PLATFORM_WIN32_WINDOWS : +		  break; +	   case VER_PLATFORM_WIN32_NT	: +		   platformIsNT = 1; +		   break; +	   } +   } + + +	if (windowType == RD_FULLSCREEN) +		bFullScreen = TRUE; +	else +		bFullScreen = FALSE; + +	// Colour depths of 8 bits only are currently supported +	if (colourDepth != 8) +	{ +		return(RDERR_COLOURDEPTH); +	} + +	screenWide = width; +	screenDeep = height; + +	// Create the directDraw object +    hr = DirectDrawCreate(NULL, &lpDraw, NULL); +//	hr=DirectDrawCreateEx( NULL, (VOID**)&m_pDD, IID_IDirectDraw7, NULL ); + + +    if ( hr != DD_OK ) +	{ +//		Zdebug(" DirectDrawCreate failed!"); + +        DirectDrawError("DirectDraw unavailable", hr); +		return(hr); +	} + + +    // Get exclusive mode +	if (bFullScreen) +	{ + +//		hr = m_pDD->SetCooperativeLevel( hWnd, DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ); +	    hr = IDirectDraw2_SetCooperativeLevel(lpDraw, hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN); +		if (hr != DD_OK) +		{ +			DirectDrawError("Exclusive mode unavailable", hr); +			return(hr); +		} + +		// TONY TEMP	 + + +		hr = IDirectDraw2_QueryInterface(lpDraw, &IID_IDirectDraw2, (LPVOID *) &lpDD2); +		if (hr != DD_OK) +		{ +			DirectDrawError("DirectDraw2 unavailable", hr); +			return(hr); +		} + +		// Set up the display mode which has been requested +//		hr = lpDD2->lpVtbl->SetDisplayMode(lpDD2, width, height, colourDepth, 0, 0); +		hr = IDirectDraw2_SetDisplayMode(lpDD2, width, height, colourDepth, 0, 0); +		if (hr != DD_OK) +		{ +			DirectDrawError("Unable to set display mode", hr); +			return(hr); +		} + +	    // Set up the primary surface descriptor +		ddsd.dwSize = sizeof(ddsd); +	    ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT; +		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX; +	    ddsd.dwBackBufferCount = 1; + +		// Create the primary surface +	    hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &lpPrimarySurface, NULL); +		if (hr != DD_OK) +		{ +		    DirectDrawError("Cannot create primary surface", hr); +			return(hr); +		} + +		// Create the back buffer as a page flipping surface +		ddscaps.dwCaps = DDSCAPS_BACKBUFFER; +	    hr = IDirectDrawSurface2_GetAttachedSurface(lpPrimarySurface, &ddscaps, &lpBackBuffer); +		if (hr != DD_OK) +		{ +		    DirectDrawError("Unable to attach back buffer", hr); +			return(hr); +		} + +		EraseBackBuffer(); +		FlipScreens(); +		EraseBackBuffer(); +		FlipScreens(); + +		// Create a palette object +		hr = IDirectDraw2_CreatePalette(lpDD2, DDPCAPS_8BIT | DDPCAPS_ALLOW256 | DDPCAPS_INITIALIZE, +				CreateAppPalette(AppPalette), &lpPalette, NULL); +	    if (hr != DD_OK ) +		{ +			DirectDrawError("Cannot create 8-bit palette", hr); +			return(hr); +		} + +		// Set our palette object active +		hr = IDirectDrawSurface2_SetPalette(lpPrimarySurface, lpPalette); +	    if (hr != DD_OK ) +		{ +			DirectDrawError("Unable to set palette", hr); +			return(hr); +		} + +	} +	else +	{ +        RECT rcWork; +        RECT rc; +        HDC hdc; +        DWORD dwStyle; +		uint32 GameBPP; + + + +		hr = IDirectDraw_SetCooperativeLevel(lpDraw, hwnd, DDSCL_NORMAL); +		if (hr != DD_OK) +		{ +			DirectDrawError("Cannot set normal cooperative level", hr); +			return(hr); +		} + + + +		hr = IDirectDraw_QueryInterface(lpDraw, &IID_IDirectDraw2, (LPVOID *) &lpDD2); +		if (hr != DD_OK) +		{ +			DirectDrawError("DirectDraw2 unavailable", hr); +			return(hr); +		} + +        // +        //  when in windows we should use the current mode +        // +        hdc = GetDC(NULL); +        GameBPP = GetDeviceCaps(hdc, PLANES) * GetDeviceCaps(hdc, BITSPIXEL); +        ReleaseDC(NULL, hdc); + +		if ((GameBPP != 8) && (GameBPP != 16)) +		{ +			MessageBox(hwnd, "Cannot execute in high colour mode - going to full screen", "Broken Sword II", MB_OK); +			return(RDERR_GOFULLSCREEN); +		} +		else if (GameBPP != 8) +		{ +			if (MessageBox(hwnd, "Your display is not in 256 colour mode.  Would you like to go to full screen mode (better performance)", "Broken Sword II", MB_YESNO) == IDYES) +			{ +				return(RDERR_GOFULLSCREEN); +			} +		} + +        // +        // if we are still a WS_POPUP window we should convert to a +        // normal app window so we look like a windows app. +        // +        dwStyle = GetWindowStyle(hwnd); +        dwStyle &= ~WS_POPUP; +        dwStyle |= WS_OVERLAPPED | WS_CAPTION | WS_THICKFRAME | WS_MINIMIZEBOX; +        SetWindowLong(hwnd, GWL_STYLE, dwStyle); + +//        if (bStretch) +//            SetRect(&rc, 0, 0, GameMode.cx*2, GameMode.cy*2); +//        else +//            SetRect(&rc, 0, 0, GameMode.cx, GameMode.cy); +		SetRect(&rc, 0, 0, 640, 480); + +        AdjustWindowRectEx(&rc, +            GetWindowStyle(hwnd), +            GetMenu(hwnd) != NULL, +            GetWindowExStyle(hwnd)); + +        SetWindowPos(hwnd, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, +            SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); + +        SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0, +            SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE); + +        // +        //  make sure our window does not hang outside of the work area +        //  this will make people who have the tray on the top or left +        //  happy. +        // +        SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0); +        GetWindowRect(hwnd, &rc); +        if (rc.left < rcWork.left) rc.left = rcWork.left; +        if (rc.top  < rcWork.top)  rc.top  = rcWork.top; +        SetWindowPos(hwnd, NULL, rc.left, rc.top, 0, 0, +            SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); + + + + +	    // Set up the primary surface descriptor +		ddsd.dwSize = sizeof(ddsd); +	    ddsd.dwFlags = DDSD_CAPS; +	    ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE; + +		// Create the primary surface +		hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &lpPrimarySurface, NULL); +	    if (hr != DD_OK) +		{ +			DirectDrawError("Cannot create primary surface", hr); +			return(hr); +		} + +		// Create the back buffer as a page flipping surface +	    memset( &ddsd, 0, sizeof( ddsd ) ); +		ddsd.dwSize = sizeof( ddsd ); +		ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT |DDSD_WIDTH; + +		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN; +	    ddsd.dwHeight = 480; +	    ddsd.dwWidth = 640; + +	    hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &lpBackBuffer, NULL ); +	    if (hr != DD_OK) +		{ +	        DirectDrawError("Cannot attach back buffer", hr); +			return(hr); +		} + +	//    DDClear(); + +		if (IDirectDrawSurface2_GetDC(lpPrimarySurface, &hdc) == DD_OK) +	    { +		    char *szMsg = "Broken Sword II is loading.......please wait."; +			SetTextColor(hdc, RGB(255,255,255)); +	        SetBkMode(hdc, TRANSPARENT); +		    TextOut(hdc, rcWindow.left, rcWindow.top, szMsg, lstrlen(szMsg)); +			IDirectDrawSurface2_ReleaseDC(lpPrimarySurface, hdc); +	    } + +		// Create a palette object - only if we have a palette! +		if (GameBPP == 8) +		{ +			hr = IDirectDraw2_CreatePalette(lpDD2, DDPCAPS_8BIT, CreateAppPalette(AppPalette), &lpPalette, NULL); +			if (hr != DD_OK ) +			{ +				DirectDrawError("Cannot create 8-bit palette", hr); +				return(hr); +			} + +			hr = IDirectDrawSurface2_SetPalette(lpPrimarySurface, lpPalette); +			if (hr != DD_OK ) +			{ +				DirectDrawError("Cannot set palette", hr); +				return(hr); +			} +		} +	} + +	// Set my capability bits. +	memset(&driverCaps, 0, sizeof(DDCAPS)); +	memset(&helCaps, 0, sizeof(DDCAPS)); +	driverCaps.dwSize = sizeof(DDCAPS); +	helCaps.dwSize = sizeof(DDCAPS); +	hr = IDirectDraw2_GetCaps(lpDD2, &driverCaps, &helCaps); +	if (hr != DD_OK) +	{ +		driverCaps.dwSize = sizeof(DDCAPS_DX3); +		helCaps.dwSize = sizeof(DDCAPS_DX3); +		hr = IDirectDraw2_GetCaps(lpDD2, &driverCaps, &helCaps); +		if (hr != DD_OK) +		{ +			MessageBox(hwnd, "Cannot get hardware capabilities.  Software emulation only.  Re-install DirectX!", "DDraw error", MB_OK); +			capsError = 1; +		} +	} + +	blackColorKey.dwColorSpaceLowValue = 0; +	blackColorKey.dwColorSpaceHighValue = 0; + +	if (capsError) +	{ +		helCaps.dwCaps = DDCAPS_BLT + DDCAPS_BLTSTRETCH + DDCAPS_COLORKEY; +		helCaps.dwCKeyCaps = DDCKEYCAPS_SRCBLT; +		dxHelCaps += RDCAPS_BLTSTRETCH; +		dxHelCaps += RDCAPS_SRCBLTCKEY; +		renderCaps = RDBLTFX_MOUSEBLT | RDBLTFX_ARITHMETICSTRETCH | RDBLTFX_EDGEBLEND | +						 RDBLTFX_SHADOWBLEND | RDBLTFX_FLATALPHA | RDBLTFX_GRADEDALPHA; +	} +	else +	{ +		if ((helCaps.dwCaps & DDCAPS_BLT == 0) ||  +			(helCaps.dwCaps & DDCAPS_BLTSTRETCH == 0) || +			(helCaps.dwCaps & DDCAPS_COLORKEY == 0) || +			(helCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT == 0)) +		{ +			RestoreDisplay(); +			return(RDERR_NOEMULATION); +		} + +//		if (driverCaps.dwCaps & DDCAPS_BLTSTRETCH) +//		{ +//			if (driverCaps.dwFXCaps & (DDFXCAPS_BLTSHRINKX + DDFXCAPS_BLTSHRINKY + DDFXCAPS_BLTSTRETCHX + DDFXCAPS_BLTSTRETCHY) ==  +//				DDFXCAPS_BLTSHRINKX + DDFXCAPS_BLTSHRINKY + DDFXCAPS_BLTSTRETCHX + DDFXCAPS_BLTSTRETCHY) +//				dxHalCaps += RDCAPS_BLTSTRETCH; +//			else if (helCaps.dwCaps & DDCAPS_BLTSTRETCH) +//				dxHelCaps += RDCAPS_BLTSTRETCH; +//			else  +//				return RDERR_DDRAWNOEMULATION; +//		} +//		else if (helCaps.dwCaps & DDCAPS_BLTSTRETCH) +//			dxHelCaps += RDCAPS_BLTSTRETCH; +//		else +//			return(RDERR_DDRAWNOEMULATION); + +		if (helCaps.dwCaps & DDCAPS_BLTSTRETCH) +			dxHelCaps += RDCAPS_BLTSTRETCH; +		else +			return(RDERR_DDRAWNOEMULATION); + +		if ((driverCaps.dwCaps & DDCAPS_BLT) && (driverCaps.dwCaps & DDCAPS_COLORKEY) && (driverCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) +			dxHalCaps += RDCAPS_SRCBLTCKEY; +		else if ((helCaps.dwCaps & DDCAPS_BLT) && (helCaps.dwCaps & DDCAPS_COLORKEY) && (helCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) +			dxHelCaps += RDCAPS_SRCBLTCKEY; +		else +			return(RDERR_DDRAWNOEMULATION); + + +		 +		// Do computer speed testing here to set bits. - this is the path we go through: +		// +		//	if (Can everything be done in hardware?) +		//		renderCaps = RDBLTFX_ALLHARDWARE; +		//	else +		//		if (Everything fast enough in software) +		//			turn everything on in software +		//		else +		//			Turn blending off +		//			if (can everything but blending be done in hardware?) +		//				renderCaps = RDBLTFX_ALLHARDWARE +		//			else +		//				if (everything but blending fast enough in software) +		//					Do everything but blending in software +		//				else +		//					Turn off sprite effects +		//				endif +		//			endif +		//		endif +		//	endif + + + + +		if ((driverCaps.dwCaps & DDCAPS_BLT) && (driverCaps.dwCaps & DDCAPS_COLORKEY) && (driverCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT) +			&& (driverCaps.dwCaps & DDSCAPS_ALPHA) && (driverCaps.dwAlphaBltConstBitDepths)) +			renderCaps = RDBLTFX_ALLHARDWARE | RDBLTFX_GRADEDALPHA | RDBLTFX_FLATALPHA; +		else if	((driverCaps.dwCaps & DDCAPS_BLT) && (driverCaps.dwCaps & DDCAPS_COLORKEY) && (driverCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) +			renderCaps = RDBLTFX_ALLHARDWARE; +		else +			renderCaps = RDBLTFX_MOUSEBLT | RDBLTFX_ARITHMETICSTRETCH | RDBLTFX_EDGEBLEND | +						 RDBLTFX_SHADOWBLEND | RDBLTFX_FLATALPHA | RDBLTFX_GRADEDALPHA; + +		if (QueryPerformanceFrequency(&timerFrequency) == TRUE) +			if (timerFrequency.QuadPart > 700000) +				renderCaps = RDBLTFX_MOUSEBLT | RDBLTFX_ARITHMETICSTRETCH | RDBLTFX_EDGEBLEND | +						 RDBLTFX_SHADOWBLEND | RDBLTFX_FLATALPHA | RDBLTFX_GRADEDALPHA; + +	//	if ((driverCaps.dwCaps & DDCAPS_BLT) && (driverCaps.dwCaps & DDCAPS_COLORKEY) && (driverCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) +	//		renderCaps = RDBLTFX_MOUSEBLT | RDBLTFX_ARITHMETICSTRETCH | RDBLTFX_EDGEBLEND | +	//					 RDBLTFX_SHADOWBLEND | RDBLTFX_FLATALPHA | RDBLTFX_GRADEDALPHA | RDBLTFX_FGPARALLAX; +	//	else +	//		renderCaps = RDBLTFX_MOUSEBLT | RDBLTFX_ARITHMETICSTRETCH | RDBLTFX_EDGEBLEND | +	//					 RDBLTFX_SHADOWBLEND | RDBLTFX_FLATALPHA | RDBLTFX_GRADEDALPHA; + +		//	renderCaps = RDBLTFX_MOUSEBLT | RDBLTFX_SHADOWBLEND | RDBLTFX_FLATALPHA | RDBLTFX_ALLHARDWARE; +	} +*/ +	return(RD_OK); + +} +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- +//---------------------------------------------------------------------------------------------------------------- + + + +int32 RenderHard(void) +{ +	warning("stub RenderHard"); +/* +	if (renderCaps & RDBLTFX_ALLHARDWARE) +		return(RDERR_ALREADYON); +	if	((driverCaps.dwCaps & DDCAPS_BLT) && (driverCaps.dwCaps & DDCAPS_COLORKEY) && (driverCaps.dwCKeyCaps & DDCKEYCAPS_SRCBLT)) +		renderCaps = RDBLTFX_ALLHARDWARE; +	else +		return(RDERR_NOHARDWARE); + +*/ +	return(RD_OK); +} + +int32 RenderSoft(void) +{ +	warning("stub RenderSoft"); +/* +	if (!(renderCaps & RDBLTFX_ALLHARDWARE)) +		return(RDERR_ALREADYON); +	renderCaps = RDBLTFX_MOUSEBLT | RDBLTFX_ARITHMETICSTRETCH | RDBLTFX_EDGEBLEND | +			 RDBLTFX_SHADOWBLEND | RDBLTFX_FLATALPHA | RDBLTFX_GRADEDALPHA; +*/ +	return(RD_OK); +} + +int32 SetBltFx(void) +{ +	renderCaps |= RDBLTFX_EDGEBLEND + RDBLTFX_ARITHMETICSTRETCH; +	return(RD_OK); +} + +int32 ClearBltFx(void) +{ +	renderCaps &= (0xffffffff - RDBLTFX_EDGEBLEND - RDBLTFX_ARITHMETICSTRETCH); +	return(RD_OK); +} + +int32 ClearShadowFx(void) +{ +	renderCaps &= (0xffffffff - RDBLTFX_SHADOWBLEND); +	return(RD_OK); +} + +int32 SetShadowFx(void) +{ +	renderCaps |= RDBLTFX_SHADOWBLEND; +	return RD_OK; +} + +int32 GetRenderType(void) +{ +	if (renderCaps & RDBLTFX_ALLHARDWARE) +	{ +		return (0); +	} +	else +	{ +		if (renderCaps & (RDBLTFX_EDGEBLEND + RDBLTFX_ARITHMETICSTRETCH)) +			return (3); +		else +		{ +			if (renderCaps & RDBLTFX_SHADOWBLEND) +				return(2); +			else +				return (1); +		} +	} +} + +int32 FlipScreens(void) + +{ +	warning("stub FlipScreens"); +/* +    HRESULT		hr; +	BOOL		vbl; +	int32		startTime; + +	DrawMouse(); + +	if (bFullScreen) +	{ +		startTime = timeGetTime(); + +		while(TRUE) +	    { +			if (!noVbl) +			{ +				hr = IDirectDraw2_GetVerticalBlankStatus(lpDD2, &vbl); +				if (hr != DD_OK) +				{ +					DirectDrawError("Vertical blank status unavailable", hr); +				} +			} + +			if (vbl || noVbl) +			{ +				hr = IDirectDrawSurface2_Flip(lpPrimarySurface, NULL, 0); +				if (hr == DD_OK) +    			{ +					break; +				} + +				if (hr == DDERR_SURFACELOST) +				{ +					if (gotTheFocus) +					{ +    					hr = IDirectDrawSurface2_Restore(lpPrimarySurface); +					 +        				if(hr != DD_OK) +	          			{ +							if (++failCount == 32) +								return(RDERR_CANNOTFLIP); +						} +					} + +				} +				else +					failCount = 0; + +				if(hr != DDERR_WASSTILLDRAWING) +		  		{ +				    break; +				} +			} +			if (timeGetTime() - startTime > 20) +			{ +				noVbl = 1; +			} +		} +    } +	else +	{ + +		hr = IDirectDrawSurface2_Blt(lpPrimarySurface, &rcWindow, lpBackBuffer, NULL, DDBLT_WAIT, NULL); +		if (hr != DD_OK) +		{ +			return(RDERR_UNKNOWN); +		} +	} +*/ +	return(RD_OK); + +} + + + +int32 WaitForVbl(void) +{ +	warning("stub WaitForVbl"); +/* +	BOOL		vbl; +	HRESULT		hr; +	uint32		counter = 0; + + +	while(1) +	{ +		hr = IDirectDraw2_GetVerticalBlankStatus(lpDD2, &vbl); +		 +		if (hr != DD_OK) +		{ +			DirectDrawError("Cannot get vertical blank status", hr); +			return(hr); +		} + +		if (vbl || noVbl) +			break; +		 +		if (++counter == 250000) +			noVbl = 1; +	} +*/	 +	return(RD_OK); + +} + + + + +int32 EraseBackBuffer( void ) +{ +	warning("stub EraseBackBuffer"); +/* +    DDBLTFX     ddbltfx; +    HRESULT     hr; +	RECT		r = {0, 0, screenWide, screenDeep}; + + +    //	Erase the background +    ddbltfx.dwSize = sizeof(ddbltfx); +    ddbltfx.dwFillColor = 0; + +    while( 1 ) +    { + +        hr = IDirectDrawSurface2_Blt(lpBackBuffer, &r, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); + +		if (hr == DDERR_SURFACELOST) +        { + +			RestoreSurfaces(); + +	        hr = IDirectDrawSurface2_Blt(lpBackBuffer, &r, NULL, NULL, DDBLT_COLORFILL, &ddbltfx ); + +            if (hr != DD_OK) +            { +				if (++failCount == 32) +				{ +	                DirectDrawError("Cannot render back buffer", hr); +					return(hr); +				} +				else +				{ +					failCount = 0; +					return(RD_OK); +				} +            } + +        } + +		if (hr == DD_OK) +        { +            break; +        } +     +		if (hr != DDERR_WASSTILLDRAWING) +        { +            DirectDrawError("Cannot render back buffer", hr); +			return(hr); +        } +    } +*/	 +	return(RD_OK); + +} + + + + +int32 SaveScreenShot(uint8 *buffer, uint8 *palette) +{ + +	static uint16 pcxCount = 0; +  int virtualWidth; +  int pix; +  int keyPix; +  int line; +  int i; +  int runLength; +  char filename[80]; +  unsigned char ch; +  unsigned char *pcxData; +  unsigned char pal[256*3]; +  FILE *fp; +  _pcxHeader pcxHead; + +  sprintf(filename, "snap%.4d.pcx", pcxCount); + +  fp = fopen(filename, "wb"); +  if (fp == NULL) +  { +    sprintf(filename, "c:\\snap%.4d.pcx", pcxCount); +    fp = fopen(filename, "wb"); +    if (fp == NULL) +    { +      return(0); +    } +  } +  pcxCount += 1; + +  // Set up and write the header +  pcxHead.manufacturer = 0x0a; +  pcxHead.version = 5; +  pcxHead.encoding = 1; +  pcxHead.bitsPerPixel = 8; +  pcxHead.xmin = 0; +  pcxHead.ymin = 0; +  pcxHead.xmax = 639; +  pcxHead.ymax = 479; +  pcxHead.hres = 72; +  pcxHead.vres = 72; +  pcxHead.reserved = 0; +  pcxHead.colourPlanes = 1; +  pcxHead.bytesPerLine = 640; +  pcxHead.paletteType = 1; +  fwrite(&pcxHead , sizeof(pcxHead), 1, fp); + +  // The simplest job is to write out the entire file as a series of single units + +  virtualWidth = 640; +//  char *pcxDataBase = buffer;           //GetBitMap() + (GetHeight()-1)* virtualWidth ; +  for (line = 0 ; line < 480; line++) +  {        +          pcxData = (unsigned char *)buffer;   //pcxDataBase; + +          // Look to compress this line of 'width' pixels +          pix = 0; +          while (pix < 640) +          {       // Look for some run length coding +                  keyPix = pcxData[pix++]; +                  runLength = 1; +                  while ( (pix < 640) && (keyPix == pcxData[pix]) ) +                  {       runLength++; +                          pix++; +                  } +                  while (runLength > 1) +                  {       // We have a run length bit. Runs are a maximum of 0x3f +                          int lRun = runLength > 0x3f ? 0x3f : runLength; +                          runLength -= lRun; +                          lRun |= 0xc0; +                          ch = (unsigned char) lRun; +                          fwrite(&ch, 1, 1, fp); +                          ch = (unsigned char) keyPix; +                          fwrite(&ch, 1, 1, fp); +//                          fFile.WriteChar(lRun); +//                          fFile.WriteChar(keyPix); +                  } +                  if (runLength) +                  {       // Single pixel. If its <= 0x3f it goes straight in, otherwise it is a single run length +                          if (keyPix < 0xc0) +                          { +                                  ch = (unsigned char) keyPix; +                                  fwrite(&ch, 1, 1, fp); +//                                  fFile.WriteChar(keyPix); +                          } +                          else +                          { +                             ch = 0xc1; +                             fwrite(&ch, 1, 1, fp); +                             ch = (unsigned char) keyPix; +                             fwrite(&ch, 1, 1, fp); +//                                  fFile.WriteChar(0xc1); +//                                  fFile.WriteChar(keyPix); +                          } +                  } +          } +//          pcxDataBase -= virtualWidth; +          buffer += virtualWidth; +  } + +  // Convert and write out the palette +//  StringClass sPal(768); +//  unsigned char *pal = palette; +//  for (int count = 0 ; count < 256 ; count++) +//  {       *(pal++) = bmi.bmiColors[count].rgbRed; +//          *(pal++) = bmi.bmiColors[count].rgbGreen; +//          *(pal++) = bmi.bmiColors[count].rgbBlue; +//  } +  ch = 0x0c; +  fwrite(&ch, 1, 1, fp); + +  for (i=0; i<256*3; i++) +  { +    pal[i] = *((unsigned char *) palette + i); +  } + +//  fFile.WriteChar(0x0c); +  fwrite(pal, 256*3, 1, fp); +//  if (fFile.Write(sPal , 768)!=768) +//          return(-1); +  fclose(fp); + +  return(1); + +} + + + + + + +int32 GrabScreenShot(void) + +{ +	warning("stub GrabScreenShot"); +/* +	uint8			*screenGrabBuffer; +	uint8			*palette; +	DDSURFACEDESC	ddsd; +	HRESULT			hr; +	int32			i; + + +	screenGrabBuffer = (uint8 *) malloc(screenWide * screenDeep); +	if (screenGrabBuffer == NULL) +		return(RDERR_OUTOFMEMORY); + +	ddsd.dwSize = sizeof(DDSURFACEDESC); +	hr = IDirectDrawSurface2_Lock(lpPrimarySurface, NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +	if (hr != DD_OK) +	{ +		free(screenGrabBuffer); +		return(RDERR_LOCKFAILED); +	} +	 +	for (i=0; i<screenDeep; i++) +	{ +		memcpy(screenGrabBuffer + i * screenWide, (uint8 *) ddsd.lpSurface + ddsd.lPitch * i, screenWide); +	} +	IDirectDrawSurface2_Unlock(lpPrimarySurface, ddsd.lpSurface); + + +	palette = (uint8 *) malloc(256 * 3); +	if (palette == NULL) +	{ +		free(screenGrabBuffer); +		return(RDERR_OUTOFMEMORY); +	} + +	for (i=0; i<256; i++) +	{ +		palette[i*3] = palCopy[i][0]; +		palette[i*3+1] = palCopy[i][1]; +		palette[i*3+2] = palCopy[i][2]; +	} + +	hr = SaveScreenShot(screenGrabBuffer,palette); + + +	free(palette); +	free(screenGrabBuffer); +*/ +	return(RD_OK); +} + + + +int32 NextSmackerFrame(void) +{ +	warning("stub NextSmackerFrame"); +	return(RD_OK); +} + + +uint32 textSurface = 0; + +void OpenTextObject(_movieTextObject *obj) +{ +	CreateSurface(obj->textSprite, &textSurface); +} + +void CloseTextObject(_movieTextObject *obj) +{ +	DeleteSurface(textSurface); +	textSurface = 0; +} + +void DrawTextObject(_movieTextObject *obj) +{ +	warning("stub DrawTextObject"); +/* +	HRESULT				hr; +	RECT				rd, rs; +	LPDIRECTDRAWSURFACE	dds; +	_spriteInfo *s = obj->textSprite; +	char myString[256]; + + +	dds = (LPDIRECTDRAWSURFACE) textSurface; + +	// 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(lpPrimarySurface, &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, "Cannot print smacker text x%d y%d w%d h%d s%d t%d\n", s->x, s->y, s->w, s->h, s->scale, s->type); +				DirectDrawError(myString, hr); +			} +		} +	} +	else +	{ +		hr = IDirectDrawSurface2_Blt(lpPrimarySurface, &rd, dds, &rs, DDBLT_WAIT, NULL); +		if (hr) +		{ +			if (hr == DDERR_SURFACELOST) +				hr = RDERR_SURFACELOST; +			else +			{ +				sprintf(myString, "Cannot print smacker text x%d y%d w%d h%d s%d t%d\n", s->x, s->y, s->w, s->h, s->scale, s->type); +				DirectDrawError(myString, hr); +			} +		} +	} +*/ +} + + +extern uint8 musicMuted; + +int32 PlaySmacker(char *filename, _movieTextObject *text[], uint8 *musicOut) +{ +	warning("stub PlaySmacker %s", filename); +	return(RD_OK); + +} + + + +void GetDrawStatus(_drvDrawStatus *s) +{ +//	s->hwnd				= hwnd; +//	s->lpDraw			= lpDraw; +//	s->lpDD2			= lpDD2; +//	s->lpPrimarySurface = lpPrimarySurface; +//	s->lpBackBuffer		= lpBackBuffer; +//	s->lpPalette		= lpPalette; +	s->screenDeep		= screenDeep; +	s->screenWide		= screenWide; +	s->scrollx			= scrollx; +	s->scrolly			= scrolly; +	s->scrollxTarget	= scrollxTarget; +	s->scrollyTarget	= scrollyTarget; +	s->scrollxOld		= scrollxOld; +	s->scrollyOld		= scrollyOld; +	s->failCount		= failCount; +	s->renderCaps		= renderCaps; +	s->dxHalCaps		= dxHalCaps; +	s->dxHelCaps		= dxHelCaps; +	s->noVbl			= noVbl; +	s->bFullScreen		= bFullScreen; +	 +//	memcpy(&s->driverCaps,	 &driverCaps,	sizeof(DDCAPS)); +//	memset(&blackColorKey, 0, sizeof(DDCOLORKEY)); +} + + + +void SetDrawStatus(_drvDrawStatus *s) +{ +//	hwnd			= s->hwnd; +//	lpDraw			= s->lpDraw; +//	lpDD2			= s->lpDD2; +//	lpPrimarySurface= s->lpPrimarySurface; +//	lpBackBuffer	= s->lpBackBuffer; +//	lpPalette		= s->lpPalette; +	screenDeep		= s->screenDeep; +	screenWide		= s->screenWide; +	scrollx			= s->scrollx; +	scrolly			= s->scrolly; +	scrollxTarget	= s->scrollxTarget; +	scrollyTarget	= s->scrollyTarget; +	scrollxOld		= s->scrollxOld; +	scrollyOld		= s->scrollyOld; +	failCount		= s->failCount; +//	renderCaps		= s->renderCaps; +	dxHalCaps		= s->dxHalCaps; +	dxHelCaps		= s->dxHelCaps; +	noVbl			= s->noVbl; +	bFullScreen		= s->bFullScreen; +	 +//	memcpy(&driverCaps,	 &s->driverCaps,	sizeof(DDCAPS)); +//	memset(&blackColorKey, 0, sizeof(DDCOLORKEY)); +} diff --git a/sword2/driver/d_draw.h b/sword2/driver/d_draw.h new file mode 100644 index 0000000000..0c4302bfaa --- /dev/null +++ b/sword2/driver/d_draw.h @@ -0,0 +1,96 @@ +/* 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	:	d_draw.h +//	Created		:	22nd August 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		16-Sep-96	PRP		Interface to the DirectDraw driver functions +//								and data. +// +//	1.1		19-Sep-96	PRP		Increased scope of directDraw data, such as +//								the back buffer object, so that mouse.c can +//								have access to the screen. +// +//	1.2		25-Sep-96	PRP		Made scrollx and scrolly available to all +//								driver code. +// +//	1.3		26-Sep-96	PRP		Moved scroll stuff to render.h for clarity. +// +//	1.4		07-Nov-96	PRP		Made bFullScreen available to all driver code. +// +//	1.5		18-Nov-96	PRP		Added reference to lpDD2 object. +// +//	1.6		24-Jan-97	PRP		Added hardware capability bits and defines. +// +//	1.7		06-Mar-97	PRP		Changed capability bits, and changed the  +//								direct draw error reporting call.  Added  +//								function to grab screen shot. +// +//	1.8		16-Jun-97	PSJ		Made globall externable to c++. +// +//	1.9		27-Jun-97	PRP		Moving the definition of GrabScreenShot to  +//								driver96.h for external access. +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the d_draw.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef D_DRAW_H +#define D_DRAW_H + +#ifdef __cplusplus +extern "C" { +#endif + +//#include "ddraw.h" + +//  Bits defining hardware and emulation capabilities. +#define RDCAPS_BLTSTRETCH	1 +#define RDCAPS_SRCBLTCKEY	2 +#define DirectDrawError(f, g) FatalDirectDrawError(f, g, __FILE__, __LINE__) + + +extern uint8 *lpPalette;			// palette +extern uint8 *lpBackBuffer;		// back surface +extern uint8 *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. +extern uint8 blackColorKey;		// transparent pixel for color key blitting. +extern int32					dxHalCaps;			// Hardware capabilities. +extern int32					dxHelCaps;			// Emulation capabilities. + +extern void FatalDirectDrawError(char *str, int32 dderr, char *file, int32 line); +extern void RestoreSurfaces(void);					// Restores direct draw surfaces. + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/sword2/driver/d_sound.cpp b/sword2/driver/d_sound.cpp new file mode 100644 index 0000000000..d3ec3200ae --- /dev/null +++ b/sword2/driver/d_sound.cpp @@ -0,0 +1,3095 @@ +/* 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	:	d_sound.c +//	Created		:	3rd December 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This module holds the driver interface to direct sound. +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		03-Dec-96	PRP		The sound buffer can be created, with the +//								format defined by the game engine, and speech +//								can be played. +// +//	1.1		05-Dec-96	PRP		Sound effects now done. +// +//	1.2		19-Dec-96	PRP		Added volume and pan to speech and sound +//								effects.  Also, added type to sound effects +//								so that they can be looped.  Implemented +//								a CloseAllFx function which will clear out +//								all sound effects. +// +//	1.3		20-Dec-96	PRP		Fixed a bug in the function which clears +//								spot effects when they have finished playing. +// +//	1.4		02-Jan-97	PRP		Fixed a bug in ClearAllFx which was trying +//								to close the speech. +// +//	1.5		08-Apr-97	PRP		Added ... to the +//								InitialiseSound function. +// +//	1.6		09-Apr-97	PRP		Added functions to steam music from CD. +// +//	1.7		29-May-97	PSJ		Added functions to save and restore the state +//								of the sound drivers. +// +//	1.8		04-Jun-97	PRP		Added bodge to PlayFx routine which registers +//								a sound effect to remove itself from the list +//								if it is the tune to leave a sequence. +// +//	1.9		06-Jun-97	PSJ		Expanded volTable from 17 to 241 entries. +//								Added an fx and a speech master volume level. +//								Added SetFxVolume and GetFxVolume for fx master +//								volume. Added SetSpeechVolume and GetSpeechVolume +//								for speech master volume. +// +//	1.10	09-Jun-97	PSJ		Added SetMusicVolume and GetMusicVolume. +// +//	1.11	09-Jun-97	PSJ		Fixed bug in SetSpeechVolume. +// +//	1.12	10-Jun-97	PSJ		Added MuteMusic, MuteSpeech, MuteFx, IsMusicMute, +//								IsFxMute and IsSpeechMute. +// +//	1.13	12-Jun-97	PSJ		Added PlayCompSpeech to play compressed speech +//								from a speech cluster. +// +//	1.14	19-Jun-97	PSJ		Added StreamCompMusic and UpdateCompSampleStreaming +//								to play compressed music from a music cluster. +//								Added StopMusic to fade out any music playing. +// +//	1.15	24-Jun-97	PSJ		Changed PlayCompSpeech to physically check for +//								playing samples rather than using the assuming the +//								speechStatus flag is correct. +// +//	1.16	24-Jun-97	PSJ		Fixed bug it SetSpeechVolume. +// +//	1.17	26-Jun-97	PSJ		Added AmISpeaking() for lip syncing. +// +//	1.18	26-Jun-97	PSJ		Tweaked the nose of the dread, killer AmISpeaking +//								function. +// +//	1.19	26-Jun-97	PSJ		Added PauseSpeech and UnpauseSpeech. +// +//	1.20	26-Jun-97	PSJ		Fixed a bug in the muteSpeech routine. +// +//	1.21	26-Jun-97	PSJ		Fixed a bug in the AmISpeaking routine. +// +//	1.22	26-Jun-97	PSJ		PlayCompSpeech loads and pauses the speech +//								ready to be played by UnpauseSpeech. +// +//	1.23	01-Jul-97	PSJ		Fixed GetSpeechStatus to work when speech is paused +// +//	1.24	03-Jul-97	PSJ		Stopped PlayCompSpeech clicking at the end of samples. +// +//	1.25	10-Jul-97	PSJ		Reduced music volume by 1/4 when playing speech +// +//	1.26	10-Jul-97	PSJ		GetMusicVolume return safeMusicVol if it is set. +// +//	1.27	15-Jul-97	PRP		Added functions to pause and unpause the sound effects. +// +//	1.28	15-Jul-97	PRP		Fixed PauseFx +// +//	1.29	16-Jul-97	PSJ		Added GetCompSpeechSize and PreFetchCompSpeech +// +//	1.30	16-Jul-97	PRP		Fixed setting of sound fx volume. +// +//	1.31	18-Jul-97	PRP		Added speech expansion to get samples to sound the same. +// +//	1.32	18-Jul-97	PRP		Hopefully fixed expansion algorithm. +// +//	1.33	18-Jul-97	JEL		Fixed UnpauseFx() +// +//	1.34	18-Jul-97	JEL		Fixed PlayCompSpeech() +// +//	1.35	18-Jul-97	JEL		Removed speech volume enhancing (now to be done in speech compressor) +// +//	1.36	21-Jul-97	PRP		Added new type of sound effect which is the music lead in. +//								Also, added function to pause the sound effects +//								just for sequences. +// +//	1.37	21-Jul-97	PRP		Modified ClearAllFx so that it doesn't kick out +//								lead in and lead out music for smacker sequences. +// +//	1.38	21-Jul-97	PRP		Tried to fix the bug where the second lead in +//								music will not play due to a duplicate id. +// +//	1.39	21-Jul-97	PRP		Finally fixed the bug to kick out lead in music +//								fx when they have finished. +// +//	1.40	25-Jul-97	JEL		Fixed crashing when music paused & unpaused repeatedly +// +//	1.41	28-Jul-97	PRP		Checked to see if fx are looping as well as playing! +// +//	1.42	30-Jul-97	PSJ		Added Music dipping. +// +//	1.43	30-Jul-97	PSJ		Added MusicTimeRemaining. +// +//	1.44	31-Jul-97	PSJ		Adjusted MusicTimeRemaining to include music left in buffer. +// +//	1.45	06-Aug-97	PSJ		Updated Get and Set scroll SoundStatus. +// +//	1.46	12-Aug-97	PSJ		Added ReverseStereo(void) +// +//	1.47	13-Aug-97	PSJ		Updated DipMusic so it fades up after speech has finished. +// +//	1.48	13-Aug-97	PRP		Added IsFxOpen(). +// +//	1.49	15-Aug-97	PRP		Added SetFxVolumePan(). +// +//	1.50	15-Aug-97	PRP		Added SetFxIdVolume() +// +//	1.51	15-Aug-97	PSJ		Fixed bug in PlayCompMusic(); +// +//	1.52	19-Aug-97	JEL		Fixed bug in MusicTimeRemaining() +// +//	WE'VE SCREWED UP THE NUMBERING! +// +//	1.59	19-Aug-97	JEL		Fixed bug in MusicTimeRemaining(),  ;) +// +//	1.60	19-Aug-97	PSJ		Updated DipMusic so it fades music a bit more. +// +//	1.61	21-Aug-97	PSJ		Updated StreamCompMusic so if both streams are in use, +//								the fading stream is stopped and the new tune started. +// +//	1.62	21-Aug-97	PSJ		Updated StreamCompMusic so if the music is unmuted, +//								the last tune is restarted if it was looping. +// +//	1.63	22-Aug-97	PSJ		Update PlayFx to handle smacker leadouts. +// +//	1.64	27-Aug-97	PSJ		Update PlayFx to record an fx's local volume, +//								So SetFxVolume can update playing fx's with the +//								correct volume. +// +//	1.65	27-Aug-97	PSJ		Stopped CloseFX from closing invalid fx's. +// +//	1.66	01-Sep-97	PRP		Cleared the fxPaused flag when closing fx. +// +//	1.67	01-Sep-97	PRP		Fixed the fact that SetFxVolume was still +//								being done even if the fx were muted. +// +//	1.68	01-Sep-97	PRP		Set zero sound to -10000 +// +//	Functions +//	--------- +// +//	-------------------------------------------------------------------------- +// +//	int32 InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth) +// +//	This function initialises DirectSound by specifying the parameters of the +//	primary buffer. +// +//	Freq is the sample rate - 44100, 22050 or 11025 +//	Channels should be 1 for mono, 2 for stereo +//	BitDepth should be either 8 or 16 bits per sample.	 +// +//	-------------------------------------------------------------------------- +// +//	int32 PlaySpeech(uint8 *data, uint8 vol, int8 pan) +// +//	This function plays the wav file passed into it as speech.  An error occurs +//	if speech is already playing, or directSound comes accross problems.  The +//	volume is 0 for zero volume and 16 for maximum volume.  The pan position +//	is -16 for full left, 0 for central and 16 for full right. +// +//	-------------------------------------------------------------------------- +// +//	int32 PlayCompSpeech(const char *filename, uint32 id, uint8 vol, int8 pan) +// +//	This function loads, decompresses and plays the wav 'id' from the cluster +// 'filename'.  An error occurs if speech is already playing, or directSound +//  comes accross problems. 'volume' can be from 0 to 16. 'pan' can be from +//  -16 (full left) to 16 (full right). +//  id is the text line id used to reference the speech within the speech +//  cluster. +// +//	-------------------------------------------------------------------------- +// +//	int32 StopSpeech(void) +// +//	Stops the speech from playing. +// +//	-------------------------------------------------------------------------- +// +//	int32 GetSpeechStatus(void) +// +//	Returns either RDSE_SAMPLEPLAYING or RDSE_SAMPLEFINISHED +// +//	-------------------------------------------------------------------------- +// +//	int32 AmISpeaking(void) +// +//	Returns either RDSE_QUIET or RDSE_SPEAKING +// +//	-------------------------------------------------------------------------- +// +//	int32 PauseSpeech(void) +// +//	Stops the speech dead in it's tracks. +// +//	-------------------------------------------------------------------------- +// +//	int32 UnpauseSpeech(void) +// +//	Re-starts the speech from where it was stopped. +// +//	-------------------------------------------------------------------------- +// +//	int32 OpenFx(int32 id, uint8 *data) +// +//	This function opens a sound effect ready for playing.  A unique id should +//	be passed in so that each effect can be referenced individually. +// +//	WARNING: Zero is not a valid ID. +// +//	-------------------------------------------------------------------------- +// +//	int32 PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type) +// +//	This function plays a sound effect.  If the effect has already been opened +//	then *data should be NULL, and the sound effect will simply be obtained  +//	from the id passed in.  If the effect has not been opened, then the wav +//	data should be passed in data.  The sound effect will be closed when it +//	has finished playing. +// +//	The volume can be between 0 (minimum) and 16 (maximum).  The pan defines +//	the left/right balance of the sample.  -16 is full left, and 16 is full +//	right with 0 in the middle.  The sample type can be either RDSE_FXSPOT, or +//	RDSE_FXLOOP. +// +//	WARNING: Zero is not a valid ID +// +//	-------------------------------------------------------------------------- +// +//	int32 CloseFx(int32 id) +// +//	This function closes a sound effect which has been previously opened for +//	playing.  Sound effects must be closed when they are finished with, +//	otherwise you will run out of sound effect buffers. +// +//	-------------------------------------------------------------------------- +// +//	int32 ClearAllFx(void) +// +//	This function clears all of the sound effects which are currently open or +//	playing, irrespective of type. +// +//	-------------------------------------------------------------------------- +// +//	int32 StreamMusic(uint8 *filename, int32 loopFlag) +// +//	Streams music from the file defined by filename.  The loopFlag should +//	be set to RDSE_FXLOOP if the music is to loop back to the start. +//	Otherwise, it should be RDSE_FXSPOT. +//	The return value must be checked for any problems. +// +//	-------------------------------------------------------------------------- +// +//	int32 StreamCompMusic(uint8 *filename, uint32 id, int32 loopFlag) +// +//	Streams music 'id' from the cluster file 'filename'.  The loopFlag should +//	be set to RDSE_FXLOOP if the music is to loop back to the start. +//	Otherwise, it should be RDSE_FXSPOT. +//	The return value must be checked for any problems. +// +//  StreamCompMusic should not be used inconjunction with StreamMusic. +// +//	-------------------------------------------------------------------------- +// +//	void StopMusic(void) +// +//	Fades out and stops the music. +// +//	-------------------------------------------------------------------------- +// +//	int32 PauseMusic(void) +// +//	Stops the music dead in it's tracks. +// +//	-------------------------------------------------------------------------- +// +//	int32 UnpauseMusic(void) +// +//	Re-starts the music from where it was stopped. +// +//	--------------------------------------------------------------------------- +// +//	int32 MusicTimeRemaining(void) +// +//  Returns the time left for the current tune. +// +//	---------------------------------------------------------------------------- +// +//	int32 ReverseStereo(void) +// +//	This function reverse the pan table, thus reversing the stereo. +// +//============================================================================= + + + + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> +#include <stdio.h> + +#include "driver96.h" +#include "rdwin.h"			// for hwnd. + +// Decompression macros +#define MakeCompressedByte(shift,sign,amplitude) (((shift)<<4) + ((sign)<<3) + (amplitude)) +#define GetCompressedShift(byte)                 ((byte)>>4) +#define GetCompressedSign(byte)                  (((byte)>>3) & 1) +#define GetCompressedAmplitude(byte)             ((byte) & 7) +#define GetdAPower(dA,power)                     for (power = 15;power>0 && !((dA) & (1<<power)); power--) + +int32 panTable[33] = { +	-10000, +	-1500, -1400, -1300, -1200, +	-1100, -1000, -900, -800, +	-700, -600, -500, -400, +	-300, -200, -100, 0, +	100, 200, 300, 400, +	500, 600, 700, 800, +	900, 1000, 1100, 1200, +	1300, 1400, 1500, 10000 +}; + +int32 volTable[241] = { + +-10000,	-3925,	-3852,	-3781,	-3710,	-3642,	-3574,	-3508,	-3443,	-3379,	-3316,	-3255,	-3194,	-3135,	-3077,	-3020,	-2964,	-2909,	-2855,	-2802,	-2750,	-2699,	-2649,	-2600,	-2551,	-2504,	-2458,	-2412,	-2367,	-2323,	-2280,	-2238,	-2197,	-2156,	-2116,	-2077,	-2038,	-2000,	-1963,	-1927,	-1891,	-1856,	-1821,	-1788,	-1755,	-1722,	-1690,	-1659,	-1628,	-1598,	-1568,	-1539,	-1510,	-1482,	-1455,	-1428,	-1401,	-1375,	-1350,	-1325,	 +-1300,	-1290,	-1279,	-1269,	-1259,	-1249,	-1239,	-1229,	-1219,	-1209,	-1199,	-1190,	-1180,	-1171,	-1161,	-1152,	-1142,	-1133,	-1124,	-1115,	-1106,	-1097,	-1088,	-1080,	-1071,	-1062,	-1054,	-1045,	-1037,	-1028,	-1020,	-1012,	-1004,	-996,	-988,	-980,	-972,	-964,	-956,	-949,	-941,	-933,	-926,	-918,	-911,	-904,	-896,	-889,	-882,	-875,	-868,	-861,	-854,	-847,	-840,	-833,	-827,	-820,	-813,	-807,	 +-800,	-791,	-782,	-773,	-764,	-755,	-747,	-738,	-730,	-721,	-713,	-705,	-697,	-689,	-681,	-673,	-665,	-658,	-650,	-643,	-635,	-628,	-621,	-613,	-606,	-599,	-593,	-586,	-579,	-572,	-566,	-559,	-553,	-546,	-540,	-534,	-528,	-522,	-516,	-510,	-504,	-498,	-492,	-487,	-481,	-476,	-470,	-465,	-459,	-454,	-449,	-444,	-439,	-434,	-429,	-424,	-419,	-414,	-409,	-404,	 +-400,	-362,	-328,	-297,	-269,	-244,	-221,	-200,	-181,	-164,	-148,	-134,	-122,	-110,	-100,	-90,	-82,	-74,	-67,	-61,	-55,	-50,	-45,	-41,	-37,	-33,	-30,	-27,	-25,	-22,	-20,	-18,	-16,	-15,	-13,	-12,	-11,	-10,	-9,	-8,	-7,	-6,	-6,	-5,	-5,	-4,	-4,	-3,	-3,	-3,	-2,	-2,	-2,	-2,	-1,	-1,	-1,	-1,	-1,	0	 + +};	 + +/* +LPDIRECTSOUND				lpDS; +LPDIRECTSOUNDBUFFER			dsbPrimary; +LPDIRECTSOUNDBUFFER			dsbSpeech; +LPDIRECTSOUNDBUFFER			dsbFx[MAXFX]; +*/ + +int32						fxId[MAXFX]; +uint8						fxCached[MAXFX]; +uint8						fxiPaused[MAXFX]; +uint8						fxLooped[MAXFX]; +uint8						fxVolume[MAXFX]; + +uint8						soundOn			= 0; +uint8						speechStatus	= 0; +uint8						fxPaused		= 0; +uint8						speechPaused	= 0; +uint8						speechVol		= 14; +uint8						fxVol			= 14; +uint8                       speechMuted     = 0; +uint8                       fxMuted			= 0; +uint8						compressedMusic = 0; + +int16 									musStreaming[MAXMUS]; +int16									musicPaused[MAXMUS]; +int16 									musCounter[MAXMUS]; +int16									musFading[MAXMUS]; +int16									musLooping[MAXMUS]; +//DSBUFFERDESC 							dsbdMus[MAXMUS]; +//LPDIRECTSOUNDBUFFER 					lpDsbMus[MAXMUS]; +FILE									*fpMus[MAXMUS]; +//PCMWAVEFORMAT       					wfMus[MAXMUS]; +int32									streamCursor[MAXMUS]; +char									musFilename[MAXMUS][256]; +int32									musFilePos[MAXMUS]; +int32									musEnd[MAXMUS]; +int16									musLastSample[MAXMUS]; +uint32									musId[MAXMUS]; +uint32									volMusic[2] = {16, 16}; +uint8									musicMuted = 0; +int32 musicVolTable[17] = { +  -10000,  +  -5000, -3000, -2500, -2250,  +  -2000, -1750, -1500, -1250,  +  -1000, -750, -500, -350,  +  -200, -100, -50, 0 +}; + + + +void  UpdateSampleStreaming(void); +void  UpdateCompSampleStreaming(void); +int32 DipMusic(void); + + +#define SPEECH_EXPANSION + +#ifdef SPEECH_EXPANSION + +int16 ExpandSpeech(int16 sample) +//	This code is executed to expand the speech samples to make them sound +//	louder, without losing the quality of the sample +{ +	double x, xsquared, result; +	double expansionFactor = 2.5; + +	x = (double) sample; +	xsquared = sample * sample; + +	if (x < 0.0) +	{ +		result = expansionFactor * x + (expansionFactor - 1.0) * xsquared / 32768.0; +		if (result < -32767.0) +			result = -32767.0; +	} +	else +	{ +		result = expansionFactor * x + (1.0 - expansionFactor) * xsquared / 32768.0; +		if (result > 32767.0) +			result = 32767.0; +	} +	 +	return (int16) result; + +} +#endif + + +//	-------------------------------------------------------------------------- +//	This function reverse the pan table, thus reversing the stereo. +//	-------------------------------------------------------------------------- +int32 ReverseStereo(void) +{ +	int32 i,j; + +	for (i = 0; i<16; i++) +	{ +		j = panTable[i]; +		panTable[i] = panTable[32-i]; +		panTable[32-i] = j; +	} + +	return (RD_OK); +} + + + +//	-------------------------------------------------------------------------- +//	This function returns the index of the sound effect with the ID passed in. +//	-------------------------------------------------------------------------- +int32 GetFxIndex(int32 id) + +{ + +	int32 i = 0; + +	while (i < MAXFX) +	{ +		if (fxId[i] == id) +			break; +		i++; +	} + +	return(i); + +} + + +int32 IsFxOpen(int32 id) +{ + +	int32 i = 0; + +	while (i < MAXFX) +	{ +		if (fxId[i] == id) +			break; +		i++; +	} + +	if (i == MAXFX) +		return 1; +	else +		return 0; + +} + + +//	-------------------------------------------------------------------------- +//	This function checks the status of all current sound effects, and clears +//	out the ones which are no longer required in a buffer.  It is called on +//	a slow timer from rdwin.c +//	-------------------------------------------------------------------------- +void FxServer(void) + +{ +	warning("stub FxServer"); +/* +	int32 i; +	int32 status; + + +	if (!soundOn) +		return; + +	if (musicPaused[0] + musicPaused[1] == 0) +	{ +		if (compressedMusic == 1) +			UpdateCompSampleStreaming(); +		else if (compressedMusic == 2) +			UpdateSampleStreaming(); +	} + +	 if (fxPaused) +	 { +		for (i=0; i<MAXFX; i++) +		{ +			if ((fxId[i] == 0xfffffffe) || (fxId[i] == 0xffffffff)) +			{ +				IDirectSoundBuffer_GetStatus(dsbFx[i], &status); +				if (!(status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING))) +				{ +					if (fxCached[i] == RDSE_FXTOCLEAR) +					{ +						IDirectSoundBuffer_Release(dsbFx[i]); +						fxId[i] = 0; +					} +				} +			} +		} +		return; +	 } + + +	for (i=0; i<MAXFX; i++) +	{ +		if (fxId[i]) +		{ +			IDirectSoundBuffer_GetStatus(dsbFx[i], &status); +			if (!(status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING))) +			{ +				if (fxCached[i] == RDSE_FXTOCLEAR) +				{ +					IDirectSoundBuffer_Release(dsbFx[i]); +					fxId[i] = 0; +				} +			} +		} +	} +*/ +} + + + + + +int32 InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth) + +{ +	warning("stub InitaliseSound( %d, %d, %d )", freq, channels, bitDepth); +/* +	int32			i; +	HRESULT			hrz; +	DSBUFFERDESC	dsbd; +	WAVEFORMATEX	pf; + + +	hrz = DirectSoundCreate(NULL, &lpDS, NULL); +	if (hrz != DS_OK) +		return(RDERR_DSOUNDCREATE); + +	hrz = IDirectSound_SetCooperativeLevel(lpDS, hwnd, DSSCL_EXCLUSIVE); +	if (hrz != DS_OK) +	{ +		IDirectSound_Release(lpDS); +		return(RDERR_DSOUNDCOOPERATE); +	} + + +	memset(&dsbd, 0, sizeof(DSBUFFERDESC)); +	dsbd.dwSize = sizeof(DSBUFFERDESC); +	dsbd.dwFlags = DSBCAPS_PRIMARYBUFFER; +	dsbd.lpwfxFormat = NULL; +	hrz = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &dsbPrimary, NULL); +	if (hrz != DS_OK) +	{ +		IDirectSound_Release(lpDS); +		return(RDERR_DSOUNDPBUFFER); +	} + +	memset(&pf, 0, sizeof(WAVEFORMATEX)); +	 +	pf.wFormatTag = WAVE_FORMAT_PCM; + +	pf.nSamplesPerSec = freq; +	 +	pf.nChannels = channels; +	 +	pf.wBitsPerSample = bitDepth; +	pf.nBlockAlign = pf.wBitsPerSample * pf.nChannels >> 3; +	pf.nAvgBytesPerSec = pf.nBlockAlign * pf.nSamplesPerSec; +	pf.cbSize = 0; +	hrz = IDirectSoundBuffer_SetFormat(dsbPrimary, (LPWAVEFORMATEX) &pf); +	if (hrz != DS_OK) +	{ +		// We have not been able to set the primary format to the format requested!!! +		//	But carry on anyway, the mixer will just have to work harder :) +	} + +	// Clear the fx id's +	for (i=0; i<MAXFX; i++) +		fxId[i] = 0; + +	soundOn = 1; + +	//---------------------------------- +	// New initialisers (James19aug97) + +	memset (fxId,			0, MAXFX*sizeof(int32)); +	memset (fxCached,		0, MAXFX*sizeof(uint8)); +	memset (fxiPaused,		0, MAXFX*sizeof(uint8)); +	memset (fxLooped, 		0, MAXFX*sizeof(uint8)); + + 	memset (musStreaming,	0, MAXFX*sizeof(int16)); +	memset (musicPaused,	0, MAXFX*sizeof(int16)); +	memset (musCounter, 	0, MAXFX*sizeof(int16)); +	memset (musFading, 		0, MAXFX*sizeof(int16)); + +	memset (musLooping,		0, MAXFX*sizeof(int16)); +	memset (fpMus,			0, MAXFX*sizeof(FILE*)); + +	memset (streamCursor,	0, MAXFX*sizeof(int32)); +	memset (musFilePos,		0, MAXFX*sizeof(int32)); +	memset (musEnd,			0, MAXFX*sizeof(int32)); +	memset (musLastSample,	0, MAXFX*sizeof(int16)); +	memset (musId,			0, MAXFX*sizeof(uint32)); +*/ +	return(RD_OK); + +} + + +int32 PlaySpeech(uint8 *data, uint8 vol, int8 pan) + +{ +	warning("stub PlaySpeech"); +/* +	uint32			dwBytes1, dwBytes2; +  	int32 			i; +	uint32			*data32; +	void 			*lpv1, *lpv2; +	_wavHeader		*wav; +	HRESULT 		hr; +	DSBUFFERDESC	dsbd; +	PCMWAVEFORMAT	wf; + + +	wav = (_wavHeader *) data; + +	if (soundOn) +	{ +		if (speechStatus) +			return(RDERR_SPEECHPLAYING); + +		memset(&wf, 0, sizeof(PCMWAVEFORMAT)); +		wf.wf.wFormatTag = WAVE_FORMAT_PCM; +		wf.wf.nChannels = wav->channels; +		wf.wf.nSamplesPerSec = wav->samplesPerSec; +		wf.wBitsPerSample = 8 * wav->blockAlign / (wav->samplesPerSec * wav->channels); +		wf.wf.nBlockAlign = wf.wf.nChannels * wf.wBitsPerSample / 8; +		wf.wf.nAvgBytesPerSec = wf.wf.nSamplesPerSec * wf.wf.nBlockAlign; +    +		memset(&dsbd, 0, sizeof(DSBUFFERDESC)); +		dsbd.dwSize = sizeof(DSBUFFERDESC); +	//	dsbd.dwFlags = DSBCAPS_CTRLDEFAULT; +		dsbd.lpwfxFormat = (LPWAVEFORMATEX) &wf; +	 +	    //  Set the sample size - search for the size of the data. +		i = 0; +		while (i<100) +		{ +			if (*data == 'd') +			{ +				data32 = (int32 *) data; +				if (*data32 == 'atad') +					break; +			} +			i += 1; +			data++; +		} +		if (i == 100) +			return(RDERR_INVALIDWAV); + +		dsbd.dwBufferBytes = *(data32 + 1); + +		//	Create the speech sample buffer +		hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &dsbSpeech, NULL); +		if (hr != DS_OK) +			return(RDERR_CREATESOUNDBUFFER); + +		//	Lock the speech buffer, ready to fill it with data +		hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +		if (hr == DSERR_BUFFERLOST) +		{ +			IDirectSoundBuffer_Restore(dsbSpeech); +			hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +		} + +		if (hr == DS_OK) +		{ +			//	Fill the speech buffer with data +			memcpy((uint8 *) lpv1, (uint8 *) (data32 + 2), dwBytes1); + +			if (dwBytes1 != dsbd.dwBufferBytes) +			{ +				memcpy((uint8 *) lpv1 + dwBytes1, (uint8 *) (data32 + 2) + dwBytes1, dwBytes2); +			} + +			//	Unlock the buffer now that we've filled it +			IDirectSoundBuffer_Unlock(dsbSpeech, lpv1, dwBytes1, lpv2, dwBytes2); + +			//  Modify the volume according to the master volume +			if (speechMuted) +				IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); +			else +				IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[vol*speechVol]); + +			IDirectSoundBuffer_SetPan(dsbSpeech, panTable[pan+16]); + +			//	Start the speech playing +			IDirectSoundBuffer_Play(dsbSpeech, 0, 0, 0); +			speechStatus = 1; + +		} +		else +		{ +			IDirectSoundBuffer_Release(dsbSpeech); +			return(RDERR_LOCKSPEECHBUFFER); +		} +	} +*/ +	return(RD_OK); + +} + + +int32 AmISpeaking() +{ +	warning("stub AmISpeaking"); +/* +	int32	len; +//	int32 status; +	int32 	readCursor, writeCursor; +	int32	dwBytes1, dwBytes2; +	int16  *sample; +	int32   count = 0; +	LPVOID 	lpv1, lpv2; +	HRESULT	hr; + +#define POSITIVE_THRESHOLD 350 +#define NEGATIVE_THRESHOLD -350 +	if ((!speechMuted) && (!speechPaused) && (dsbSpeech)) +	{ +		if (IDirectSoundBuffer_GetCurrentPosition(dsbSpeech, &readCursor, &writeCursor) != DS_OK) +		{ +			return (RDSE_SPEAKING); +		} + +		len = 44100 / 12; + +		hr = IDirectSoundBuffer_Lock(dsbSpeech, readCursor, len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +		if (hr == DS_OK) +		{ +			for (sample = (int16*)lpv1; sample<(int16*)((int8*)lpv1+dwBytes1); sample+= 90)  // 20 samples +				if (*sample>POSITIVE_THRESHOLD || *sample<NEGATIVE_THRESHOLD) +					count++; + +			IDirectSoundBuffer_Unlock(dsbSpeech,lpv1,dwBytes1,lpv2,dwBytes2); + +			if (count>5)		// 25% of the samples +				return (RDSE_SPEAKING); +		} +		return (RDSE_QUIET); +	} +	return (RDSE_SPEAKING); +*/ +	return RDSE_QUIET; +} + + +int32 GetCompSpeechSize(const char *filename, uint32 speechid) +{ +  	int32 			i; +	uint32			speechIndex[2]; +	FILE		   *fp; +	 +    //  Open the speech cluster and find the data offset & size +	fp = fopen(filename, "rb"); +	if (fp == NULL) +		return(0); + +	if (fseek(fp, (++speechid)*8, SEEK_SET)) +	{ +		fclose(fp); +		return (0); +	} + +	if (fread(speechIndex, sizeof(uint32), 2, fp) != 2) +	{ +		fclose(fp); +		return (0); +	} + +	if (!speechIndex[0] || !speechIndex[1]) +	{ +		fclose(fp); +		return (0); +	} + +	fclose(fp); + +	i = (speechIndex[1]-1)*2 + sizeof(_wavHeader) + 8; +	 +	return(i); +} + + +int32 PreFetchCompSpeech(const char *filename, uint32 speechid, uint8 *waveMem) +{ +  	uint32 			i; +	uint16			*data16; +	uint8			*data8; +	uint32			speechIndex[2]; +	_wavHeader		*pwf = (_wavHeader *) waveMem; +	FILE		   *fp; + +	//  Open the speech cluster and find the data offset & size +	fp = fopen(filename, "rb"); +	if (fp == NULL) +		return(RDERR_INVALIDFILENAME); + +	if (fseek(fp, (++speechid)*8, SEEK_SET)) +	{ +		fclose(fp); +		return (RDERR_READERROR); +	} + +	if (fread(speechIndex, sizeof(uint32), 2, fp) != 2) +	{ +		fclose(fp); +		return (RDERR_READERROR); +	} + +	if (!speechIndex[0] || !speechIndex[1]) +	{ +		fclose(fp); +		return (RDERR_INVALIDID); +	} + +	data16 = (uint16*)(waveMem + sizeof(_wavHeader)); + +	memset(pwf, 0, sizeof(_wavHeader)); + +	*((uint32*)pwf->riff) = 'FFIR'; +	*((uint32*)pwf->wavID) = 'EVAW'; +	*((uint32*)pwf->format) = ' tmf'; + +	pwf->formatLen		= 0x00000010; +	pwf->formatTag		= 0x0001; +	pwf->channels		= 0x0001; +	pwf->samplesPerSec	= 0x5622; +	pwf->avgBytesPerSec = 0x0000; +	pwf->blockAlign		= 0xAC44; +	pwf->unknown1		= 0x0000; +	pwf->unknown2		= 0x0002; +	pwf->bitsPerSample	= 0x0010; + +	*((uint32*)data16) = 'atad'; + +	data16 += 2; + +	*((uint32*)data16) = (speechIndex[1]-1)*2; + +	data16 += 2; + +	pwf->fileLength = (speechIndex[1]-1)*2 + sizeof(_wavHeader) + 8; + + +	// Calculate position in buffer to load compressed sound into +	data8 = (uint8*)data16 + (speechIndex[1]-1); +	 +	if (fseek(fp, speechIndex[0], SEEK_SET)) +	{ +		fclose(fp); +		return (RDERR_INVALIDID); +	} + +	if (fread(data8, sizeof(uint8), speechIndex[1], fp) != speechIndex[1]) +	{ +		fclose(fp); +		return (RDERR_INVALIDID); +	} + +	fclose(fp); + +	data16[0] = *((int16*)data8);	// Starting Value +	i=1; + +	while (i<(speechIndex[1]-1)) +	{ +		if (GetCompressedSign(data8[i+1])) +			data16[i] = data16[i-1] - (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); +		else +			data16[i] = data16[i-1] + (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); +		i++; +	} + +	return(RD_OK); +} + + +int32 PlayCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan) +{ +	warning("stub PlayCompSpeech( %s, %d, %d, %d )", filename, speechid, vol, pan); +/* +	uint32			dwBytes1, dwBytes2; +  	uint32 			i; +	uint16			*data16; +	uint8			*data8; +	uint32			speechIndex[2]; +	void 			*lpv1, *lpv2; +	HRESULT 		hr; +	DSBUFFERDESC	dsbd; +	PCMWAVEFORMAT	wf; +	FILE		   *fp; + +	if (!speechMuted) +	{ +		if (GetSpeechStatus() == RDERR_SPEECHPLAYING) +			return RDERR_SPEECHPLAYING; + +		memset(&wf, 0, sizeof(PCMWAVEFORMAT)); +		wf.wf.wFormatTag = WAVE_FORMAT_PCM; +		wf.wf.nChannels = 1; +		wf.wf.nSamplesPerSec = 22050; +		wf.wBitsPerSample = 16; +		wf.wf.nBlockAlign = 2; +		wf.wf.nAvgBytesPerSec = 44100; +    +		memset(&dsbd, 0, sizeof(DSBUFFERDESC)); +		dsbd.dwSize = sizeof(DSBUFFERDESC); +//		dsbd.dwFlags = DSBCAPS_CTRLDEFAULT; +		dsbd.lpwfxFormat = (LPWAVEFORMATEX) &wf; +	 +	    //  Open the speech cluster and find the data offset & size +		fp = fopen(filename, "rb"); +		if (fp == NULL) +			return(RDERR_INVALIDFILENAME); + +		if (fseek(fp, (++speechid)*8, SEEK_SET)) +		{ +			fclose(fp); +			return (RDERR_READERROR); +		} + +		if (fread(speechIndex, sizeof(uint32), 2, fp) != 2) +		{ +			fclose(fp); +			return (RDERR_READERROR); +		} + +		if (speechIndex[0]==0 || speechIndex[1]==0) +		{ +			fclose(fp); +			return (RDERR_INVALIDID); +		} + + +		dsbd.dwBufferBytes = (speechIndex[1]-1)*2; + +		// Create tempory buffer for compressed speech +		if ((data8 = malloc(speechIndex[1])) == NULL) +		{ +			fclose(fp); +			return(RDERR_OUTOFMEMORY); +		} + +		if (fseek(fp, speechIndex[0], SEEK_SET)) +		{ +			fclose(fp); +			free(data8); +			return (RDERR_INVALIDID); +		} + +		if (fread(data8, sizeof(uint8), speechIndex[1], fp) != speechIndex[1]) +		{ +			fclose(fp); +			free(data8); +			return (RDERR_INVALIDID); +		} + +		fclose(fp); + +		//	Create the speech sample buffer +		hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &dsbSpeech, NULL); +		if (hr != DS_OK) +		{ +			free(data8); +			return(RDERR_CREATESOUNDBUFFER); +		} + +		//	Lock the speech buffer, ready to fill it with data +		hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +		if (hr == DSERR_BUFFERLOST) +		{ +			IDirectSoundBuffer_Restore(dsbSpeech); +			hr = IDirectSoundBuffer_Lock(dsbSpeech, 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +		} + +		if (hr == DS_OK) +		{ +			// decompress data into speech buffer. +			data16 = (uint16*)lpv1; +			 +			data16[0] = *((int16*)data8);	// Starting Value +			i=1; + +			while (i<dwBytes1/2) +			{ +				if (GetCompressedSign(data8[i+1])) +					data16[i] = data16[i-1] - (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); +				else +					data16[i] = data16[i-1] + (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); + + +				i++; +			} + +			if (dwBytes1 != dsbd.dwBufferBytes) +			{ +				while (i<(dwBytes1+dwBytes2)/2) +				{ +					if (GetCompressedSign(data8[i+1])) +						data16[i] = data16[i-1] - (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); +					else +						data16[i] = data16[i-1] + (GetCompressedAmplitude(data8[i+1])<<GetCompressedShift(data8[i+1])); + + +					i++; +				} +			} + +			free(data8); + +			//	Unlock the buffer now that we've filled it +			IDirectSoundBuffer_Unlock(dsbSpeech, lpv1, dwBytes1, lpv2, dwBytes2); + +			//  Modify the volume according to the master volume +			if (speechMuted) +				IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); +			else +				IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[vol*speechVol]); + +			IDirectSoundBuffer_SetPan(dsbSpeech, panTable[pan+16]); + +			//	Start the speech playing +			speechPaused = 1; +//			IDirectSoundBuffer_Play(dsbSpeech, 0, 0, 0); +			speechStatus = 1; +		} +		else +		{ +			IDirectSoundBuffer_Release(dsbSpeech); +			free(data8); +			return(RDERR_LOCKSPEECHBUFFER); +		} +	} + +	DipMusic(); +*/ +	return(RD_OK); +} + + +int32 StopSpeech(void) + +{ +	warning("stub StopSpeech"); +/* +	int32 status; + + +	if (!soundOn) +		return(RD_OK); +   +	if (speechStatus) +	{ +		IDirectSoundBuffer_GetStatus(dsbSpeech, &status); +		if (status & DSBSTATUS_PLAYING) +		{ +			IDirectSoundBuffer_Stop(dsbSpeech); +//			SetMusicVolume(GetMusicVolume()); +		} +		 +		IDirectSoundBuffer_Release(dsbSpeech); +		dsbSpeech = 0; +		speechStatus = 0; +		return(RD_OK); +	} +*/	 +	return(RDERR_SPEECHNOTPLAYING); + +} + + + +int32 GetSpeechStatus(void) +{ +	warning("stub GetSpeechStatus"); +/* +	int32 status; + + +	if ((!soundOn) || (!speechStatus)) +		return(RDSE_SAMPLEFINISHED); + +	if (speechPaused) +		return(RDSE_SAMPLEPLAYING); + +	IDirectSoundBuffer_GetStatus(dsbSpeech, &status); +	if (!(status & DSBSTATUS_PLAYING)) +	{ +		speechStatus = 0; +		IDirectSoundBuffer_Release(dsbSpeech); +		dsbSpeech = 0; +//		SetMusicVolume(GetMusicVolume()); +		return(RDSE_SAMPLEFINISHED); +	} +	return(RDSE_SAMPLEPLAYING); +*/ +	return RDSE_SAMPLEFINISHED; + +} + + +void SetSpeechVolume(uint8 volume) +{ +	warning("stub SetSpeechVolume"); +/* +	speechVol = volume; +	if (dsbSpeech && !speechMuted && GetSpeechStatus() == RDSE_SAMPLEPLAYING) +		IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[16*speechVol]); +*/ +} + + +uint8 GetSpeechVolume() +{ +	return speechVol; +} + + +void MuteSpeech(uint8 mute) +{ +	warning("stub MuteSpeech( %d )", mute); +/* +	speechMuted = mute; + +	if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) +	{ +		if (mute) +			IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[0]); +		else +			IDirectSoundBuffer_SetVolume(dsbSpeech, volTable[16*speechVol]); +	} +*/ +} + + +uint8 IsSpeechMute(void) +{ +	return (speechMuted); +} + + +int32 PauseSpeech(void) +{ +	warning("PauseSpeech"); +/* +	if (GetSpeechStatus() == RDSE_SAMPLEPLAYING) +	{ +		speechPaused = 1; +		return (IDirectSoundBuffer_Stop(dsbSpeech)); +	} +*/ +	return(RD_OK); +} + +int32 UnpauseSpeech(void) +{ +	warning("UnpauseSpeech"); +/* +	if (speechPaused) +	{ +		speechPaused = 0; +		return (IDirectSoundBuffer_Play(dsbSpeech, 0, 0, 0)); +	} +*/ +	return(RD_OK); +} + + +int32 OpenFx(int32 id, uint8 *data) + +{ +	warning("stub OpenFx( %d )", id); +/* +	uint32			dwBytes1, dwBytes2; +  	int32 			i, fxi; +	uint32			*data32; +	void 			*lpv1, *lpv2; +	_wavHeader		*wav; +	HRESULT 		hr; +	DSBUFFERDESC	dsbd; +	PCMWAVEFORMAT	wf; + + +	wav = (_wavHeader *) data; + +	if (soundOn) +	{ + +		// Check for a valid id. +		if (id == 0) +			return(RDERR_INVALIDID); + +		// Check that the fx is not already open +		for (i=0; i<MAXFX; i++) +			if (fxId[i] == id) +				return(RDERR_FXALREADYOPEN); + +		// Now choose a free slot for the fx +		fxi = 0; +		while (fxi<MAXFX) +		{ +			if (fxId[fxi] == 0) +				break; +			fxi++; +		} + +		if (fxi == MAXFX) +			return(RDERR_NOFREEBUFFERS); + +		memset(&wf, 0, sizeof(PCMWAVEFORMAT)); +		wf.wf.wFormatTag = WAVE_FORMAT_PCM; +		wf.wf.nChannels = wav->channels; +		wf.wf.nSamplesPerSec = wav->samplesPerSec; +		wf.wBitsPerSample = 8 * wav->blockAlign / (wav->samplesPerSec * wav->channels); +		wf.wf.nBlockAlign = wf.wf.nChannels * wf.wBitsPerSample / 8; +		wf.wf.nAvgBytesPerSec = wf.wf.nSamplesPerSec * wf.wf.nBlockAlign; +    +		memset(&dsbd, 0, sizeof(DSBUFFERDESC)); +		dsbd.dwSize = sizeof(DSBUFFERDESC); +//		dsbd.dwFlags = DSBCAPS_CTRLDEFAULT; +		dsbd.lpwfxFormat = (LPWAVEFORMATEX) &wf; +	 +	    //  Set the sample size - search for the size of the data. +		i = 0; +		while (i<100) +		{ +			if (*data == 'd') +			{ +				data32 = (int32 *) data; +				if (*data32 == 'atad') +					break; +			} +			i += 1; +			data++; +		} +		if (i == 100) +			return(RDERR_INVALIDWAV); + +		dsbd.dwBufferBytes = *(data32 + 1); + +		//	Create the speech sample buffer +		hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbd, &dsbFx[fxi], NULL); +		if (hr != DS_OK) +			return(RDERR_CREATESOUNDBUFFER); + +		//	Lock the speech buffer, ready to fill it with data +		hr = IDirectSoundBuffer_Lock(dsbFx[fxi], 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +		if (hr == DSERR_BUFFERLOST) +		{ +			IDirectSoundBuffer_Restore(dsbFx[fxi]); +			hr = IDirectSoundBuffer_Lock(dsbFx[fxi], 0, dsbd.dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +		} + +		if (hr == DS_OK) +		{ +			//	Fill the speech buffer with data +			memcpy((uint8 *) lpv1, (uint8 *) (data32 + 2), dwBytes1); + +			if (dwBytes1 != dsbd.dwBufferBytes) +			{ +				memcpy((uint8 *) lpv1 + dwBytes1, (uint8 *) (data32 + 2) + dwBytes1, dwBytes2); +			} + +			//	Unlock the buffer now that we've filled it +			IDirectSoundBuffer_Unlock(dsbFx[fxi], lpv1, dwBytes1, lpv2, dwBytes2); + +		} +		else +		{ +			IDirectSoundBuffer_Release(dsbFx[fxi]); +			return(RDERR_LOCKSPEECHBUFFER); +		} +		 +		fxId[fxi] = id; +		fxCached[fxi] = RDSE_FXCACHED; + +	} +*/ +	return(RD_OK); + +} + + +int32 PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type) + +{ +	warning("stub PlayFx( %d, %d, %d, %d )", id, vol, pan, type); +/* +	int32 i, loop; +	HRESULT hr; + +	if (type == RDSE_FXLOOP) +		loop = DSBPLAY_LOOPING; +	else +		loop = 0; + +	if (soundOn) +	{ +		if (data == NULL) +		{ +			if (type == RDSE_FXLEADOUT) +			{ +				id = 0xffffffff; +				i = GetFxIndex(id); +				if (i == MAXFX) +					return(RDERR_FXNOTOPEN); + +				fxLooped[i] = 0; + +				//	Start the sound effect playing +				if (musicMuted) +					IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); +				else +					IDirectSoundBuffer_SetVolume(dsbFx[i], musicVolTable[volMusic[0]]); +				IDirectSoundBuffer_SetPan(dsbFx[i], 0); +				IDirectSoundBuffer_Play(dsbFx[i], 0, 0, 0); + +				fxCached[i] = RDSE_FXTOCLEAR; +			} +			else +			{ +				i = GetFxIndex(id); +				if (i == MAXFX) +					return(RDERR_FXNOTOPEN); + +				fxLooped[i] = loop; +				fxVolume[i] = vol; + +				//	Start the sound effect playing +				if (fxMuted) +					IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); +				else +					IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); +				IDirectSoundBuffer_SetPan(dsbFx[i], panTable[pan+16]); + +				IDirectSoundBuffer_Play(dsbFx[i], 0, 0, loop); +				if (id == 0xffffffff) +					fxCached[i] = RDSE_FXTOCLEAR; +			} +		} +		else +		{ +			if (type == RDSE_FXLEADIN) +			{ +				id = 0xfffffffe; +				hr = OpenFx(id, data); +				if (hr != RD_OK) +					return hr; +				i = GetFxIndex(id); +				if (i == MAXFX) +					return RDERR_FXFUCKED; +				fxCached[i] = RDSE_FXTOCLEAR; +				if (musicMuted) +					IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); +				else +					IDirectSoundBuffer_SetVolume(dsbFx[i], musicVolTable[volMusic[0]]); +				IDirectSoundBuffer_SetPan(dsbFx[i], 0); +				IDirectSoundBuffer_Play(dsbFx[i], 0, 0, 0); +			} +			else +			{ +				hr = OpenFx(id, data); +				if (hr != RD_OK) +					return(hr); + +				i = GetFxIndex(id); +				if (i == MAXFX) +					return(RDERR_FXFUCKED); + +				fxCached[i] = RDSE_FXTOCLEAR; +				fxLooped[i] = loop; +				fxVolume[i] = vol; + +				//	Start the sound effect playing +				if (fxMuted) +					IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[0]); +				else +					IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); +				IDirectSoundBuffer_SetPan(dsbFx[i], panTable[pan+16]); +				IDirectSoundBuffer_Play(dsbFx[i], 0, 0, loop); +			} +		} +	} +*/ +	return(RD_OK); + +} + + +int32 SetFxVolumePan(int32 id, uint8 vol, int8 pan) +{ +	warning("stub SetFxVolumePan( %d, %d, %d )", id, vol, pan); +/* +	int32 i = GetFxIndex(id); +	if (i == MAXFX) +		return RDERR_FXNOTOPEN; + +	fxVolume[i] = vol; +	if (!fxMuted) +		IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); +	IDirectSoundBuffer_SetPan(dsbFx[i], panTable[pan+16]); +*/ +	return RD_OK; +} + +int32 SetFxIdVolume(int32 id, uint8 vol) +{ +	warning("stub SetFxIdVolume( %d, %d )", id, vol); +/* +	int32 i = GetFxIndex(id); +	if (i == MAXFX) +		return RDERR_FXNOTOPEN; + +	fxVolume[i] = vol; +	if (!fxMuted) +		IDirectSoundBuffer_SetVolume(dsbFx[i], volTable[vol*fxVol]); +*/ +	return RD_OK; +} + + + +int32 ClearAllFx(void) + +{ +	warning("stub ClearAllFx"); +/* +	int32 status; +	int32 i; + + +	if (!soundOn) +		return(RD_OK); + +	i = 0; +	while (i < MAXFX) +	{ +		if ((fxId[i]) && (fxId[i] != 0xfffffffe) && (fxId[i] != 0xffffffff)) +		{ +			IDirectSoundBuffer_GetStatus(dsbFx[i], &status); +			if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) +			{ +				IDirectSoundBuffer_Stop(dsbFx[i]); +			} +			IDirectSoundBuffer_Release(dsbFx[i]); +			fxId[i] = 0; +			fxiPaused[i] = 0; +		} +		i++; +	} + +*/	 +	return(RD_OK); + +} + + +int32 CloseFx(int32 id) + +{ +	warning("stub CloseFx( %d )", id); +/* +	int32 i; +	int32 status; + + +	if (!soundOn) +		return(RD_OK); + +	i = GetFxIndex(id); +	if (i<MAXFX) +	{ +		IDirectSoundBuffer_GetStatus(dsbFx[i], &status); +		if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) +		{ +			IDirectSoundBuffer_Stop(dsbFx[i]); +		} + +		IDirectSoundBuffer_Release(dsbFx[i]); +		fxId[i] = 0; +		fxiPaused[i] = 0; +	} +*/ +	return(RD_OK); + +} + + +int32 PauseFx(void) + +{ +	warning("stub PauseFx"); +/* +	int32 i; +	int32 status; + +	if (!fxPaused) +	{ +		for (i=0; i<MAXFX; i++) +		{ +			if (fxId[i]) +			{ +				IDirectSoundBuffer_GetStatus(dsbFx[i], &status); +				if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) +				{ +					fxiPaused[i] = 1; +					if (IDirectSoundBuffer_Stop(dsbFx[i]) != RD_OK) +						return(RDERR_FXFUCKED); +				} +			} +			else +			{ +				fxiPaused[i] = 0; +			} +		} +		fxPaused = 1; +	} +*/	 +	return (RD_OK); + +} + + +int32 PauseFxForSequence(void) + +{ +	warning("stub PauseFxForSequence"); +/* +	int32 i; +	int32 status; + +	if (!fxPaused) +	{ +		for (i=0; i<MAXFX; i++) +		{ +			if ((fxId[i]) && (fxId[i] != 0xfffffffe)) +			{ +				IDirectSoundBuffer_GetStatus(dsbFx[i], &status); +				if (status & (DSBSTATUS_PLAYING + DSBSTATUS_LOOPING)) +				{ +					fxiPaused[i] = 1; +					IDirectSoundBuffer_Stop(dsbFx[i]); +				} +			} +			else +			{ +				fxiPaused[i] = 0; +			} +		} +		fxPaused = 1; +	} +*/	 +	return (RD_OK); + +} + + + +int32 UnpauseFx(void) + +{ +	warning("stub UnpauseFx"); +/* +	int32 i; + +	if (fxPaused) +	{ +		for (i=0; i<MAXFX; i++) +		{ +			if (fxiPaused[i] && fxId[i]) +			{ +				if (IDirectSoundBuffer_Play(dsbFx[i], 0, 0, fxLooped[i]) != RD_OK) +					return(RDERR_FXFUCKED); +			} +		} +		fxPaused = 0; +	} +*/ +	return (RD_OK); +} + + + +uint8 GetFxVolume() +{ +	return fxVol; +} + + +void SetFxVolume(uint8 volume) +{ +	warning("stub SetFxVolume( %d )", volume); +/* +	int32 fxi; +	fxVol = volume; + +	// Now update the volume of any fxs playing +	for (fxi = 0; fxi<MAXFX; fxi++) +	{ +		if (fxId[fxi] && !fxMuted) +			IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[fxVolume[fxi]*fxVol]); +	} +*/ +} + + +void MuteFx(uint8 mute) +{ +	warning("stub MuteFx( %d )"); +/* +	int32 fxi; + +	fxMuted = mute; + +	// Now update the volume of any fxs playing +	for (fxi = 0; fxi<MAXFX; fxi++) +	{ +		if (fxId[fxi]) +		{ +			if (mute) +				IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[0]); +			else +				IDirectSoundBuffer_SetVolume(dsbFx[fxi], volTable[fxVolume[fxi]*fxVol]); +		} +	} +*/ +} + +uint8 IsFxMute(void) +{ +	return (fxMuted); +} + + + + +static void StartMusicFadeDown(int i) + +{ + +//	IDirectSoundBuffer_Stop(lpDsbMus[i]); +//	IDirectSoundBuffer_Release(lpDsbMus[i]); +	musFading[i] = -16; +//	musStreaming[i] = 0; +	fclose(fpMus[i]); + +} + + +int32 StreamMusic(uint8 *filename, int32 looping) + +{ +	warning("stub StreamMusic( %s, %d )", filename, looping); +/* + +	HRESULT		hr; +	LPVOID		lpv1, lpv2; +	DWORD			dwBytes1, dwBytes2; +	int32			i; +	int32 		v0, v1; +	int32			bytes; +	_wavHeader	head; + +	// Do not allow compressed and uncompressed music to be streamed at the same time. +	if (compressedMusic == 1) +		return (RDERR_FXFUCKED); + +	compressedMusic = 2; + + +	if (musStreaming[0] + musStreaming[1] == 0) +	{ + +		i = 0; + +		fpMus[i] = fopen(filename, "rb"); +		if (fpMus[i] == NULL) +			return(RDERR_INVALIDFILENAME); + +		fread(&head, sizeof(_wavHeader), 1, fpMus[i]); +		streamCursor[i] = 0; +		musLooping[i] = looping; +		 + +  	memset(&wfMus[i], 0, sizeof(PCMWAVEFORMAT)); +    wfMus[i].wf.wFormatTag = WAVE_FORMAT_PCM; +    wfMus[i].wf.nChannels = head.channels; +    wfMus[i].wf.nSamplesPerSec = head.samplesPerSec; +	wfMus[i].wBitsPerSample = 8 * head.blockAlign / (head.samplesPerSec * head.channels); +	wfMus[i].wf.nBlockAlign = wfMus[i].wf.nChannels * wfMus[i].wBitsPerSample / 8; +    wfMus[i].wf.nAvgBytesPerSec = wfMus[i].wf.nSamplesPerSec * wfMus[i].wf.nBlockAlign; + + +    //  Reset the sample format and size +    memset(&dsbdMus[i], 0, sizeof(DSBUFFERDESC)); +    dsbdMus[i].dwSize = sizeof(DSBUFFERDESC); +//    dsbdMus[i].dwFlags = DSBCAPS_CTRLDEFAULT; +	dsbdMus[i].dwBufferBytes = 3 * wfMus[i].wf.nAvgBytesPerSec; 		// 3 seconds +    dsbdMus[i].lpwfxFormat = (LPWAVEFORMATEX) &wfMus[i]; + +		//	Create the sound effect sample buffer +    hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbdMus[i], &lpDsbMus[i], NULL); +    if (hr == DS_OK) +		{ +			hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); + +			if (hr == DSERR_BUFFERLOST) +			{ +				IDirectSoundBuffer_Restore(lpDsbMus[i]); +				hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +			} + +			if (hr == DS_OK) +			{ + +				//	Fill the speech buffer with data +				bytes = fread(lpv1, 1, dwBytes1, fpMus[i]); +//				memcpy((uint8 *) lpv1, (uint8 *) wavData + sizeof(wavHeader), dwBytes1); + +				//	Unlock the buffer now that we've filled it +				IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); + +    			//  Modify the volume according to the master volume and music mute state +				if (musicMuted) +					v0 = v1 = 0; +				else +				{ +    				v0 = volMusic[0]; +    				v1 = volMusic[1]; +				} + +				if (v0 > v1) +				{ +					IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +					IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); +				} +				else +				{ +					if (v1 > v0) +					{ +				  	    IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +						IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); +					} +					else +					{ +				        IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +						IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); +					} +				} + + +				//	Start the sound effect playing +				IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING); + +				musStreaming[i] = 1; +				musCounter[i] = 250; +				strcpy(musFilename[i], filename); + +    	  //  and exit the function. +			} +			else +			{ +//				Pdebug("Failed to lock sound buffer upon creation - (%d)", hr & 0x0000ffff); +//				DirectSoundDebug("Error - ", hr); +				fclose(fpMus[i]); +				return(RDERR_LOCKFAILED); +			} +    } +		else +		{ +//			Pdebug("Failed to create sound buffer - (%d)", hr & 0x0000ffff); +//			Pdebug("Error - ", hr); +			fclose(fpMus[i]); +			return(RDERR_CREATESOUNDBUFFER); +		} +	} +	else if (musStreaming[0] + musStreaming[1] == 1) +	{ + +		i = musStreaming[0]; +		musLooping[i] = looping; + +		if (!musFading[1-i]) +			StartMusicFadeDown(1 - i); + +		fpMus[i] = fopen(filename, "rb"); +		if (fpMus[i] == NULL) +			return(RDERR_INVALIDFILENAME); + +		fread(&head, sizeof(_wavHeader), 1, fpMus[i]); +		streamCursor[i] = 0; +		 + +  	memset(&wfMus[i], 0, sizeof(PCMWAVEFORMAT)); +    wfMus[i].wf.wFormatTag = WAVE_FORMAT_PCM; +    wfMus[i].wf.nChannels = head.channels; +    wfMus[i].wf.nSamplesPerSec = head.samplesPerSec; +	wfMus[i].wBitsPerSample = 8 * head.blockAlign / (head.samplesPerSec * head.channels); +	wfMus[i].wf.nBlockAlign = wfMus[i].wf.nChannels * wfMus[i].wBitsPerSample / 8; +    wfMus[i].wf.nAvgBytesPerSec = wfMus[i].wf.nSamplesPerSec * wfMus[i].wf.nBlockAlign; + + +    //  Reset the sample format and size +    memset(&dsbdMus[i], 0, sizeof(DSBUFFERDESC)); +    dsbdMus[i].dwSize = sizeof(DSBUFFERDESC); +//    dsbdMus[i].dwFlags = DSBCAPS_CTRLDEFAULT; +	dsbdMus[i].dwBufferBytes = 6 * wfMus[i].wf.nAvgBytesPerSec; 		// 3 seconds +    dsbdMus[i].lpwfxFormat = (LPWAVEFORMATEX) &wfMus[i]; + +		//	Create the sound effect sample buffer +    hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbdMus[i], &lpDsbMus[i], NULL); +    if (hr == DS_OK) +		{ +			hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); + +			if (hr == DSERR_BUFFERLOST) +			{ +				IDirectSoundBuffer_Restore(lpDsbMus[i]); +				hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +			} + +			if (hr == DS_OK) +			{ + +				//	Fill the speech buffer with data +				bytes = fread(lpv1, 1, dwBytes1, fpMus[i]); +//				Pdebug("Read %d bytes\n", bytes); +//				memcpy((uint8 *) lpv1, (uint8 *) wavData + sizeof(_wavHeader), dwBytes1); + +				//	Unlock the buffer now that we've filled it +				IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); + +    			//  Modify the volume according to the master volume and music mute state +				if (musicMuted) +					v0 = v1 = 0; +				else +				{ +    				v0 = volMusic[0]; +    				v1 = volMusic[1]; +				} + + +				if (v0 > v1) +				{ +					IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +					IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); +				} +				else +				{ +					if (v1 > v0) +					{ +		  				IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +						IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); +					} +					else +					{ +						IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +						IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); +					} +				} + + +				//	Start the sound effect playing +				IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING); + +				musStreaming[i] = 1; +				musCounter[i] = 250; +				strcpy(musFilename[i], filename); + +			} +			else +			{ +//				Pdebug("Failed to lock sound buffer upon creation - (%d)", hr & 0x0000ffff); +//				DirectSoundDebug("Error - ", hr); +				fclose(fpMus[i]); +				return(RDERR_LOCKFAILED); +			} +    } +		else +		{ +//			Pdebug("Failed to create sound buffer - (%d)", hr & 0x0000ffff); +//			Pdebug("Error - ", hr); +			fclose(fpMus[i]); +			return(RDERR_CREATESOUNDBUFFER); +		} + +	} +*/ +	return(RD_OK); +} + + +void UpdateSampleStreaming(void) + +{ +	warning("stub UpdateSampleStreaming"); +/* + +	int32 	i; +	int32 	v0, v1; +	int32		readLen; +	int32		len; +	int32 	readCursor, writeCursor; +	int32		dwBytes1, dwBytes2; +	LPVOID 	lpv1, lpv2; +	HRESULT	hr; + + +	for (i=0; i<MAXMUS; i++) +	{ +		if (musStreaming[i]) +		{ +			if (musFading[i]) +			{ +				if (musFading[i] < 0) +				{ +					if (++musFading[i] == 0) +					{ +						IDirectSoundBuffer_Stop(lpDsbMus[i]); +						IDirectSoundBuffer_Release(lpDsbMus[i]); +						musStreaming[i] = 0; +					} +					else +					{ +		    			//  Modify the volume according to the master volume and music mute state +						if (musicMuted) +							v0 = v1 = 0; +						else +						{ +							v0 = (volMusic[0] * (0 - musFading[i]) / 16); +					    	v1 = (volMusic[1] * (0 - musFading[i]) / 16); +						} + +						if (v0 > v1) +						{ +							IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +							IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); +						} +						else +						{ +							if (v1 > v0) +							{ +				  				IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +								IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); +							} +							else +							{ +								IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +								IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); +							} +						} +					} +				} +			} +			else +			{ + +					if (IDirectSoundBuffer_GetCurrentPosition(lpDsbMus[i], &readCursor, &writeCursor) != DS_OK) +					{ +//						Pdebug ("Stopping sample %d cos cant get position", i); +						IDirectSoundBuffer_Stop(lpDsbMus[i]); +					} + + +					len = readCursor - streamCursor[i]; +					if (len < 0) +					{ +						len += dsbdMus[i].dwBufferBytes; +					} +					if (len > 0) +					{ +						hr = IDirectSoundBuffer_Lock(lpDsbMus[i], streamCursor[i], len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +						if (hr == DSERR_BUFFERLOST) +						{ +							IDirectSoundBuffer_Restore(lpDsbMus[i]); +							hr = IDirectSoundBuffer_Lock(lpDsbMus[i], streamCursor[i], len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +						} + +						if (hr == DS_OK) +						{ +							streamCursor[i] += len; +							if (streamCursor[i] >= (int32) dsbdMus[i].dwBufferBytes) +								streamCursor[i] -= dsbdMus[i].dwBufferBytes; + +							if (len > dwBytes1) +							{ +								readLen = fread(lpv1, 1, dwBytes1, fpMus[i]); +								if (readLen == dwBytes1) +								{ +									readLen = fread(lpv2, 1, dwBytes2, fpMus[i]); +									if (readLen != dwBytes2) +									{ +										IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); +										StartMusicFadeDown(i); +										if (musLooping[i]) +										{ +											StreamMusic(musFilename[i], musLooping[i]); +										} +									} +									else +									{ +										IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); +									} +								} +								else +								{ +									IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); +									StartMusicFadeDown(i); +									if (musLooping[i]) +									{ +										StreamMusic(musFilename[i], musLooping[i]); +									} +								} +							} +							else +							{ +								readLen = fread(lpv1, 1, len, fpMus[i]); +								if (readLen != len) +								{ +									IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); +									StartMusicFadeDown(i); +									if (musLooping[i]) +									{ +										StreamMusic(musFilename[i], musLooping[i]); +									} +								} +								else +								{ +									IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); +								} +							} +						} +//						else +//						{ +//							DirectSoundDebug("Failed to lock sound buffer to write bytes", hr); +//							Pdebug("Stream cursor %d", streamCursor[i]); +//							Pdebug("len %d", len); +//						} +					} +				//} +			} +		} +	} +*/ +} + + + +int32 StreamCompMusic(const char *filename, uint32 musicId, int32 looping) +{ +	warning("stub StreamCompMusic( %s, %d, %d )", filename, musicId, looping); +/* +	HRESULT		hr; +	LPVOID		lpv1, lpv2; +	DWORD		dwBytes1, dwBytes2; +	uint32		i,j; +	int32 		v0, v1; +	uint16	   *data16; +	uint8	   *data8; + +	// Do not allow compressed and uncompressed music to be streamed at the same time. +	if (compressedMusic == 2) +		return (RDERR_FXFUCKED); + +	compressedMusic = 1; + +	if (musStreaming[0] + musStreaming[1] == 0) // No music streaming at present. +	{ +		i = 0; + +		musLooping[i] = looping;			// Save looping info +		strcpy(musFilename[i], filename);	// And tune id's +		musId[i] = musicId; + +		if (IsMusicMute())		// Don't start streaming if the volume is off. +			return (RD_OK); + +		if (!fpMus[0]) +			fpMus[0] = fopen(filename, "rb");	// Always use fpMus[0] (all music in one cluster)  musFilePos[i] for different pieces of music. +		if (fpMus[0] == NULL) +			return(RDERR_INVALIDFILENAME); + +		if (fseek(fpMus[0], (musicId+1)*8, SEEK_SET))	// Seek to music index +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +			return (RDERR_READERROR); +		} + +		if (fread(&musFilePos[i], sizeof(uint32), 1, fpMus[0]) != 1)  // Read music index +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +			return (RDERR_READERROR); +		} + +		if (fread(&musEnd[i], sizeof(uint32), 1, fpMus[0]) != 1)  // Read music length +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +			return (RDERR_READERROR); +		} + +		if (!musEnd[i] || !musFilePos[i])	// Check that music is valid (has length & offset) +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +			return (RDERR_INVALIDID); +		} + +		musEnd[i] += musFilePos[i];		// Calculate the file position of the end of the music + +		streamCursor[i] = 0;			// Reset streaming cursor and store looping flag +	 +  		memset(&wfMus[i], 0, sizeof(PCMWAVEFORMAT));	// Set up wave format (no headers in cluster) +		wfMus[i].wf.wFormatTag = WAVE_FORMAT_PCM; +		wfMus[i].wf.nChannels = 1; +		wfMus[i].wf.nSamplesPerSec = 22050; +		wfMus[i].wBitsPerSample = 16; +		wfMus[i].wf.nBlockAlign = 2; +		wfMus[i].wf.nAvgBytesPerSec = 44100; + +		//  Reset the sample format and size +   		memset(&dsbdMus[i], 0, sizeof(DSBUFFERDESC)); +		dsbdMus[i].dwSize = sizeof(DSBUFFERDESC); +//		dsbdMus[i].dwFlags = DSBCAPS_CTRLDEFAULT; +		dsbdMus[i].dwBufferBytes = 3 * wfMus[i].wf.nAvgBytesPerSec; 		// 3 seconds +		dsbdMus[i].lpwfxFormat = (LPWAVEFORMATEX) &wfMus[i]; + +		// Create a temporary buffer +		if ((data8 = malloc(dsbdMus[i].dwBufferBytes/2)) == NULL)	// Allocate a compressed data buffer +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +			return(RDERR_OUTOFMEMORY); +		} + +		// Seek to start of the compressed music +		if (fseek(fpMus[0], musFilePos[i], SEEK_SET)) +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +			free(data8); +			return (RDERR_INVALIDID); +		} + +		// Read the compressed data in to the buffer +		if (fread(data8, sizeof(uint8), dsbdMus[i].dwBufferBytes/2, fpMus[0]) != dsbdMus[i].dwBufferBytes/2) +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +			free(data8); +			return (RDERR_INVALIDID); +		} + +		// Store the current position in the file for future streaming +		musFilePos[i] = ftell(fpMus[0]); + +		//	Create the music buffer +		hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbdMus[i], &lpDsbMus[i], NULL); +		if (hr == DS_OK) +		{ +			hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); + +			if (hr == DSERR_BUFFERLOST) +			{ +				IDirectSoundBuffer_Restore(lpDsbMus[i]); +				hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +			} + +			if (hr == DS_OK) +			{ +				// decompress the music into the music buffer. +				data16 = (uint16*)lpv1; +				 +				data16[0] = *((int16*)data8);	// First sample value +				j=1; + +				while (j<(dwBytes1/2)-1) +				{ +					if (GetCompressedSign(data8[j+1])) +						data16[j] = data16[j-1] - (GetCompressedAmplitude(data8[j+1])<<GetCompressedShift(data8[j+1])); +					else +						data16[j] = data16[j-1] + (GetCompressedAmplitude(data8[j+1])<<GetCompressedShift(data8[j+1])); +					j++; +				} + +				// Never need to fill lpv2 because we started at the begining of the sound buffer + +				// Store the value of the last sample ready for next batch of decompression +				musLastSample[i] = data16[j-1]; + +				//	Free the decompression buffer and unlock the buffer now that we've filled it +				free(data8); +				IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); + +    			//  Modify the volume according to the master volume and music mute state +				if (musicMuted) +					v0 = v1 = 0; +				else +				{ +    				v0 = volMusic[0]; +    				v1 = volMusic[1]; +				} + +				if (v0 > v1) +				{ +					IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +					IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); +				} +				else +				{ +					if (v1 > v0) +					{ +				  	    IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +						IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); +					} +					else +					{ +				        IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +						IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); +					} +				} + + +				//	Start the sound effect playing +				IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING); + +				// Recorder some last variables +				musStreaming[i] = 1; +				musCounter[i] = 250; + +    		//  and exit the function. +			} +			else +			{ +				// Opps Failed to lock the sound buffer +				fclose(fpMus[0]); +				fpMus[0] = 0; +				return(RDERR_LOCKFAILED); +			} +		} +		else +		{ +			// Opps Failed to create the sound buffer +			fclose(fpMus[0]); +			fpMus[0] = 0; +			return(RDERR_CREATESOUNDBUFFER); +		} +	} +	else +	{ +		if (musStreaming[0] + musStreaming[1] == 2)	// Both streams in use, try to find a fading stream +		{ +			if (musFading[0]) +				i = 0; +			else +				i = 1; +			 +			musFading[i] = 0; +			IDirectSoundBuffer_Stop(lpDsbMus[i]); +			IDirectSoundBuffer_Release(lpDsbMus[i]); +			musStreaming[i] = 0; +		} + +		if (musStreaming[0] + musStreaming[1] == 1)	// Some music is already streaming +		{ +			i = musStreaming[0];			// Set i to the free channel + +			musLooping[i] = looping;			// Save looping info +			strcpy(musFilename[i], filename);	// And tune id's +			musId[i] = musicId; + +			if (IsMusicMute())		// Don't start streaming if the volume is off. +				return (RD_OK); + +			if (!fpMus[0]) +				fpMus[0] = fopen(filename, "rb");			// Always use fpMus[0] (all music in one cluster)  musFilePos[i] for different pieces of music. +			if (fpMus[0] == NULL) +				return(RDERR_INVALIDFILENAME); + + +			if (!musFading[1-i])			// Start other music stream fading out +				musFading[1 - i] = -16; + +			streamCursor[i] = 0;			// Reset the streaming cursor for this sample + +			if (fseek(fpMus[0], (musicId+1)*8, SEEK_SET))	// Seek to music index +			{ +				fclose(fpMus[0]); +				fpMus[0] = 0; +				return (RDERR_READERROR); +			} + +			if (fread(&musFilePos[i], sizeof(uint32), 1, fpMus[0]) != 1)  // Read music index +			{ +				fclose(fpMus[0]); +				fpMus[0] = 0; +				return (RDERR_READERROR); +			} + +			if (fread(&musEnd[i], sizeof(uint32), 1, fpMus[0]) != 1)  // Read music length +			{ +				fclose(fpMus[0]); +				fpMus[0] = 0; +				return (RDERR_READERROR); +			} + +			if (!musEnd[i] || !musFilePos[i])	// Check that music is valid (has length & offset) +			{ +				fclose(fpMus[0]); +				fpMus[0] = 0; +				return (RDERR_INVALIDID); +			} + +			musEnd[i] += musFilePos[i];		// Calculate the file position of the end of the music + +	  		memset(&wfMus[i], 0, sizeof(PCMWAVEFORMAT));	// Set up the music format info +			wfMus[i].wf.wFormatTag = WAVE_FORMAT_PCM; +			wfMus[i].wf.nChannels = 1; +			wfMus[i].wf.nSamplesPerSec = 22050; +			wfMus[i].wBitsPerSample = 16; +			wfMus[i].wf.nBlockAlign = 2; +			wfMus[i].wf.nAvgBytesPerSec = 44100; + +			//  Reset the sample format and size +			memset(&dsbdMus[i], 0, sizeof(DSBUFFERDESC)); +			dsbdMus[i].dwSize = sizeof(DSBUFFERDESC); +//			dsbdMus[i].dwFlags = DSBCAPS_CTRLDEFAULT; +			dsbdMus[i].dwBufferBytes = 3 * wfMus[i].wf.nAvgBytesPerSec; 		// 3 seconds +			dsbdMus[i].lpwfxFormat = (LPWAVEFORMATEX) &wfMus[i]; + +			// Allocate a compressed data buffer +			if ((data8 = malloc(dsbdMus[i].dwBufferBytes/2)) == NULL) +			{ +				fclose(fpMus[0]); +				fpMus[0] = 0; +				return(RDERR_OUTOFMEMORY); +			} + +			// Seek to start of the compressed music +			if (fseek(fpMus[0], musFilePos[i], SEEK_SET)) +			{ +				fclose(fpMus[0]); +				fpMus[0] = 0; +				free(data8); +				return (RDERR_INVALIDID); +			} + +			// Read the compressed data in to the buffer +			if (fread(data8, sizeof(uint8), dsbdMus[i].dwBufferBytes/2, fpMus[0]) != dsbdMus[i].dwBufferBytes/2) +			{ +				fclose(fpMus[0]); +				fpMus[0] = 0; +				free(data8); +				return (RDERR_INVALIDID); +			} +			 +			// Store the current position in the file for future streaming +			musFilePos[i] = ftell(fpMus[0]); + +			//	Create the sound effect sample buffer +			hr = IDirectSound_CreateSoundBuffer(lpDS, &dsbdMus[i], &lpDsbMus[i], NULL); +			if (hr == DS_OK) +			{ +				hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); + +				if (hr == DSERR_BUFFERLOST) +				{ +					IDirectSoundBuffer_Restore(lpDsbMus[i]); +					hr = IDirectSoundBuffer_Lock(lpDsbMus[i], 0, dsbdMus[i].dwBufferBytes, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +				} + +				if (hr == DS_OK) +				{ + +					// decompress the music into the music buffer. +					data16 = (uint16*)lpv1; +					 +					data16[0] = *((int16*)data8);	// First sample value +					j=1; + +					while (j<(dwBytes1/2)-1) +					{ +						if (GetCompressedSign(data8[j+1])) +							data16[j] = data16[j-1] - (GetCompressedAmplitude(data8[j+1])<<GetCompressedShift(data8[j+1])); +						else +							data16[j] = data16[j-1] + (GetCompressedAmplitude(data8[j+1])<<GetCompressedShift(data8[j+1])); +						j++; +					} + +					// Never need to fill lpv2 because we started at the begining of the sound buffer + +					// Store the value of the last sample ready for next batch of decompression +					musLastSample[i] = data16[j-1]; + +					// Free the compressiong buffer and unlock the buffer now that we've filled it +					free(data8); +					IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); + +    				//  Modify the volume according to the master volume and music mute state +					if (musicMuted) +						v0 = v1 = 0; +					else +					{ +    					v0 = volMusic[0]; +    					v1 = volMusic[1]; +					} + + +					if (v0 > v1) +					{ +						IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +						IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); +					} +					else +					{ +						if (v1 > v0) +						{ +		  					IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +							IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); +						} +						else +						{ +							IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +							IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); +						} +					} + + +					//	Start the sound effect playing +					IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING); + +					// Record the last variables for streaming and looping +					musStreaming[i] = 1; +					musCounter[i] = 250; +				} +				else +				{ +					// Opps failed to lock the sound buffer +					fclose(fpMus[0]); +					fpMus[0] = 0; +					return(RDERR_LOCKFAILED); +				} +			} +			else +			{ +				// Opps failed to create the sound buffer +				fclose(fpMus[0]); +				fpMus[0] = 0; +				return(RDERR_CREATESOUNDBUFFER); +			} +		} +	} +*/ +	return(RD_OK); +} + + +void UpdateCompSampleStreaming(void) +{ +	warning("stub UpdateCompSampleStreaming"); +/* + +	uint32 	i,j,k; +	int32 	v0, v1; +	int32	len; +	int32 	readCursor, writeCursor; +	int32	dwBytes1, dwBytes2; +	LPVOID 	lpv1, lpv2; +	HRESULT	hr; +	uint16 *data16; +	uint8  *data8; +	int     fade; + + +	for (i=0; i<MAXMUS; i++) +	{ +		if (musStreaming[i]) +		{ +			if (musFading[i]) +			{ +				if (musFading[i] < 0) +				{ +					if (++musFading[i] == 0) +					{ +						IDirectSoundBuffer_Stop(lpDsbMus[i]); +						IDirectSoundBuffer_Release(lpDsbMus[i]); +						musStreaming[i] = 0; +						musLooping[i] = 0; +					} +					else +					{ +		    			//  Modify the volume according to the master volume and music mute state +						if (musicMuted) +							v0 = v1 = 0; +						else +						{ +							v0 = (volMusic[0] * (0 - musFading[i]) / 16); +					    	v1 = (volMusic[1] * (0 - musFading[i]) / 16); +						} + +						if (v0 > v1) +						{ +							IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v0]); +							IDirectSoundBuffer_SetPan(lpDsbMus[i], musicVolTable[v1*16/v0]); +						} +						else +						{ +							if (v1 > v0) +							{ +				  				IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +								IDirectSoundBuffer_SetPan(lpDsbMus[i], -musicVolTable[v0*16/v1]); +							} +							else +							{ +								IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[v1]); +								IDirectSoundBuffer_SetPan(lpDsbMus[i], 0); +							} +						} +					} +				} +			} +			else +			{ +				if (IDirectSoundBuffer_GetCurrentPosition(lpDsbMus[i], &readCursor, &writeCursor) != DS_OK) +				{ +					// Failed to get read and write positions +					IDirectSoundBuffer_Stop(lpDsbMus[i]); +				} + + +				// Caluculate the amount of data to load into the sound buffer +				len = readCursor - streamCursor[i]; +				if (len < 0) +				{ +					len += dsbdMus[i].dwBufferBytes;	// Wrap around ! +				} + +				// Reduce length if it requires reading past the end of the music +				if (musFilePos[i]+len >= musEnd[i]) +				{ +					len = musEnd[i] - musFilePos[i]; +					fade = 1;		// End of music reaced so we'll need to fade and repeat +				} +				else +					fade = 0; + +				if (len > 0) +				{ +					hr = IDirectSoundBuffer_Lock(lpDsbMus[i], streamCursor[i], len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +					if (hr == DSERR_BUFFERLOST) +					{ +						IDirectSoundBuffer_Restore(lpDsbMus[i]); +						hr = IDirectSoundBuffer_Lock(lpDsbMus[i], streamCursor[i], len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0); +					} + +					if (hr == DS_OK) +					{ +						streamCursor[i] += len; +						if (streamCursor[i] >= (int32) dsbdMus[i].dwBufferBytes) +							streamCursor[i] -= dsbdMus[i].dwBufferBytes; + +						// Allocate a compressed data buffer +						if ((data8 = malloc(len/2)) == NULL) +						{ +							fclose(fpMus[0]); +							fpMus[0] = 0; +							musFading[i] = -16; +						} + +						// Seek to update position of compressed music when neccassary (probably never occurs) +						if (ftell(fpMus[0]) != musFilePos[i]) +							fseek(fpMus[0], musFilePos[i], SEEK_SET); + +						// Read the compressed data in to the buffer +						if (fread(data8, sizeof(uint8), len/2, fpMus[0]) != (size_t)len/2) +						{ +							fclose(fpMus[0]); +							fpMus[0] = 0; +							free(data8); +							musFading[i] = -16; +							return; +						} + +						// Update the current position in the file for future streaming +						musFilePos[i] = ftell(fpMus[0]); + +						// decompress the music into the music buffer. +						data16 = (uint16*)lpv1; + +						// Decompress the first byte using the last decompressed sample +						if (GetCompressedSign(data8[0])) +							data16[0] = musLastSample[i] - (GetCompressedAmplitude(data8[0])<<GetCompressedShift(data8[0])); +						else +							data16[0] = musLastSample[i] + (GetCompressedAmplitude(data8[0])<<GetCompressedShift(data8[0])); + +						j = 1; + +						// Decompress the rest of lpv1 +						while (j<(uint32)dwBytes1/2) +						{ +							if (GetCompressedSign(data8[j])) +								data16[j] = data16[j-1] - (GetCompressedAmplitude(data8[j])<<GetCompressedShift(data8[j])); +							else +								data16[j] = data16[j-1] + (GetCompressedAmplitude(data8[j])<<GetCompressedShift(data8[j])); +							j++; +						} + +						// Store the value of the last sample ready for next batch of decompression +						musLastSample[i] = data16[j-1]; + +						if (dwBytes1 < len) // The buffer has wrapped so we need to decompress to lpv2 as well +						{ +							data16 = (uint16*)lpv2; + +							// Decompress first sample int lpv2 from lastsample in lpv1 +							if (GetCompressedSign(data8[j])) +								data16[0] = musLastSample[i] - (GetCompressedAmplitude(data8[j])<<GetCompressedShift(data8[j])); +							else +								data16[0] = musLastSample[i] + (GetCompressedAmplitude(data8[j])<<GetCompressedShift(data8[j])); + +							j++; +							k = 1; + +							// Decompress the rest of lpv2 +							while (k<(uint32)dwBytes2/2) +							{ +								if (GetCompressedSign(data8[j])) +									data16[k] = data16[k-1] - (GetCompressedAmplitude(data8[j])<<GetCompressedShift(data8[j])); +								else +									data16[k] = data16[k-1] + (GetCompressedAmplitude(data8[j])<<GetCompressedShift(data8[j])); +								j++; +								k++; +							} +							 +							// Store the value of the last sample ready for next batch of decompression +							musLastSample[i] = data16[k-1]; +						} + +						// Free the compressed data buffer and unlock the sound buffer. +						free(data8); +						IDirectSoundBuffer_Unlock(lpDsbMus[i], lpv1, dwBytes1, lpv2, dwBytes2); + +						// End of the music so we need to start fading and start the music again +						if (fade) +						{ +							musFading[i] = -16;		// Fade the old music + +							// Close the music cluster if it's open +							if (fpMus[0]) +							{ +								fclose(fpMus[0]); +								fpMus[0] = 0; +							} + +							// Loop if neccassary +							if (musLooping[i]) +								StreamCompMusic(musFilename[i], musId[i], musLooping[i]); +						} +					} +				} +			} +		} +	} +	DipMusic(); +*/ +} + +int32 DipMusic() +{ +	warning("stub DipMusic"); +/* +	int32				 len; +	int32 				 readCursor, writeCursor; +	int32				 dwBytes1, dwBytes2; +	int16				*sample; +	int32				 total = 0; +	int32				 i; +	int32				 status; +	LPVOID 				 lpv1, lpv2; +	HRESULT				 hr = DS_OK; +	LPDIRECTSOUNDBUFFER  dsbMusic = NULL; + +	int32				 currentMusicVol = musicVolTable[volMusic[0]]; +	int32				 minMusicVol; + +	// Find which music buffer is currently playing +	for (i = 0; i<MAXMUS && !dsbMusic; i++) +	{ +		if (musStreaming[i] && musFading[i] == 0) +			dsbMusic = lpDsbMus[i]; +	} + +	if ((!musicMuted) && dsbMusic && (!speechMuted) && (volMusic[0]>2)) +	{ +		minMusicVol = musicVolTable[volMusic[0] - 3]; + +		if (speechStatus) +		{ +			IDirectSoundBuffer_GetStatus(dsbSpeech, &status); +			if ((hr = IDirectSoundBuffer_GetCurrentPosition(dsbMusic, &readCursor, &writeCursor)) != DS_OK) +				return hr; + +			len = 44100 / 12 ;//  12th of a second + +			if ((hr = IDirectSoundBuffer_Lock(dsbMusic, readCursor, len, &lpv1, &dwBytes1, &lpv2, &dwBytes2, 0)) != DS_OK) +				return hr; + +			for (i = 0, sample = (int16*)lpv1; sample<(int16*)((int8*)lpv1+dwBytes1); sample+= 30, i++)  // 60 samples +			{ +				if (*sample>0) +					total += *sample; +				else +					total -= *sample; +			} + +			total /= i; + +			total = minMusicVol + ( ( (currentMusicVol - minMusicVol) * total ) / 8000); + +			if (total > currentMusicVol) +				total = currentMusicVol; + +			IDirectSoundBuffer_SetVolume(dsbMusic, total); + +			IDirectSoundBuffer_Unlock(dsbMusic,lpv1,dwBytes1,lpv2,dwBytes2); +		} +		else +		{ +			IDirectSoundBuffer_GetVolume(dsbMusic, &total); +			total += 50; +			if (total > currentMusicVol) +				total = currentMusicVol; + +			IDirectSoundBuffer_SetVolume(dsbMusic, total); +		} +	} +	 +	return (hr); +*/ +	return RD_OK; +} + +int32 MusicTimeRemaining() +{ +	warning("stub MusicTimeRemaaining"); +/* +	int32 writeCursor; +	int32 i; +	int32 readCursor; + +	for (i=0; i<MAXMUS && !musStreaming[i]; i++) +	{ +		// this is meant to be empty! (James19aug97) +	} + +	if (i == MAXMUS) +		return 0; + + +	if ((IDirectSoundBuffer_GetCurrentPosition(lpDsbMus[i], &readCursor, &writeCursor)) != DS_OK) +		return 0; +	 +	return (((132300-readCursor)/2 + (musEnd[i] - musFilePos[i])) / 22050); +*/ +	return 0; +} + + + +void StopMusic(void) +{ +	int32 i; + +	switch (compressedMusic) +	{ +	case 1:	// compressed music streaming +		for (i = 0; i<MAXMUS; i++) +		{ +			if (musStreaming[i]) +				musFading[i] = -16; +			else +				// If the music is muted, make sure the tune doesn't restart. +				musLooping[i] = 0; +		} + +		if (fpMus[0]) +		{ +			fclose(fpMus[0]); +			fpMus[0] = 0; +		} +		break; +	case 2: +		for (i = 0; i<MAXMUS; i++) +		{ +			if (musStreaming[i]) +				StartMusicFadeDown(i); +		} +		break; +	default: +		break; +	} +} + + +int32 PauseMusic(void) +{ +	warning("stub PauseMusic"); +/*	 +	int32 i; + +	if (soundOn) +	{ +		for (i=0; i<2; i++) +		{ +			if (musStreaming[i]) +			{ +				musicPaused[i] = TRUE; + +				if (IDirectSoundBuffer_Stop(lpDsbMus[i]) != RD_OK) +					return(RDERR_FXFUCKED); +			} +			else +			{ +				musicPaused[i] = FALSE; +			} +		} +	} +*/ +	return(RD_OK); +} + +int32 UnpauseMusic(void) +{ +	warning("stub UnpauseMusic"); +/* +	 +	int32 i; + +	if (soundOn) +	{ +		for (i=0; i<2; i++) +		{ +			if (musicPaused[i]) +			{ +				if (IDirectSoundBuffer_Play(lpDsbMus[i], 0, 0, DSBPLAY_LOOPING) != RD_OK) +					return(RDERR_FXFUCKED); + +				musicPaused[i] = FALSE; +			} +		} +	} +*/ +	return(RD_OK); +} + + +void SetMusicVolume(uint8 volume) +{ +	warning("stub SetMusicVolume( %d )", volume); +/* +	int32 i; +	for (i = 0; i<MAXMUS; i++) +	{ +		volMusic[i] = volume; +		if (musStreaming[i] && !musFading[i] && !musicMuted) +			IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[volume]); +	} +*/ +} + + +uint8 GetMusicVolume() +{ +		return volMusic[0]; +} + + +void MuteMusic(uint8 mute) +{ +	warning("stub MuteMusic( %d )", mute); +/* +	int32 i; + +	musicMuted = mute; + +	for (i = 0; i<MAXMUS; i++) +	{ +		if (!mute) +		{ +			if (!musStreaming[i] && musLooping[i]) +				StreamCompMusic(musFilename[i], musId[i], musLooping[i]); +		} + +		if (musStreaming[i] && !musFading[i]) +		{ +			if (mute) +				IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[0]); +			else +				IDirectSoundBuffer_SetVolume(lpDsbMus[i], musicVolTable[volMusic[i]]); +		} +	} +*/ +} + + +uint8 IsMusicMute(void) +{ +	return (musicMuted); +} + + + +void GetSoundStatus(_drvSoundStatus *s) +{ +	int i; + +//	s->hwnd				= hwnd; +//	s->lpDS				= lpDS; +//	s->dsbPrimary		= dsbPrimary; +//	s->dsbSpeech		= dsbSpeech; +	s->soundOn			= soundOn; +	s->speechStatus		= speechStatus; +	s->fxPaused			= fxPaused; +	s->speechPaused		= speechPaused; +	s->speechVol		= speechVol; +	s->fxVol			= fxVol; +	s->speechMuted		= speechMuted; +	s->fxMuted			= fxMuted; +	s->compressedMusic	= compressedMusic; +	s->musicMuted		= musicMuted; + +	memcpy(s->fxId,			fxId,			sizeof(int32) * MAXFX); +	memcpy(s->fxCached,		fxCached,		sizeof(uint8) * MAXFX); +//	memcpy(s->dsbFx,		dsbFx,			sizeof(LPDIRECTSOUNDBUFFER) * MAXFX); +	memcpy(s->fxiPaused,	fxiPaused,		sizeof(uint8) * MAXFX); +	memcpy(s->fxLooped,		fxLooped,		sizeof(uint8) * MAXFX); +	memcpy(s->musStreaming, musStreaming,	sizeof(int16) * MAXMUS); +	memcpy(s->musicPaused,	musicPaused,	sizeof(int16) * MAXMUS); +	memcpy(s->musCounter,	musCounter,		sizeof(int16) * MAXMUS); +	memcpy(s->musFading,	musFading,		sizeof(int16) * MAXMUS); +	memcpy(s->musLooping,	musLooping,		sizeof(int16) * MAXMUS); +	memcpy(s->musLastSample,musLastSample,	sizeof(int16) * MAXMUS); +	memcpy(s->streamCursor, streamCursor,	sizeof(int32) * MAXMUS); +	memcpy(s->musFilePos,	musFilePos,		sizeof(int32) * MAXMUS); +	memcpy(s->musEnd,		musEnd,			sizeof(int32) * MAXMUS); +	memcpy(s->musId,		musId,			sizeof(uint32) * MAXMUS); +	memcpy(s->volMusic,		volMusic,		sizeof(uint32) * 2); +//	memcpy(s->dsbdMus,		dsbdMus,		sizeof(DSBUFFERDESC) * MAXMUS); +//	memcpy(s->lpDsbMus,		lpDsbMus,		sizeof(LPDIRECTSOUNDBUFFER) * MAXMUS); +	memcpy(s->fpMus,		fpMus,			sizeof(FILE*) * MAXMUS); +//	memcpy(s->wfMus,		wfMus,			sizeof(PCMWAVEFORMAT) * MAXMUS); + +	for (i = 0; i<MAXMUS; i++) +		memcpy(s->musFilename[i], musFilename[i], sizeof(char) * 256); +} + + +void SetSoundStatus(_drvSoundStatus *s) +{ +	int i; + +//	hwnd			= s->hwnd; +//	lpDS			= s->lpDS; +//	dsbPrimary		= s->dsbPrimary; +//	dsbSpeech		= s->dsbSpeech; +	soundOn			= s->soundOn; +	speechStatus	= s->speechStatus; +	fxPaused		= s->fxPaused; +	speechPaused	= s->speechPaused; +	speechVol		= s->speechVol; +	fxVol			= s->fxVol; +	speechMuted		= s->speechMuted; +	fxMuted			= s->fxMuted; +	compressedMusic	= s->compressedMusic; +	musicMuted		= s->musicMuted; + +	memcpy(fxId,		 s->fxId,			sizeof(int32) * MAXFX); +	memcpy(fxCached,	 s->fxCached,		sizeof(uint8) * MAXFX); +//	memcpy(dsbFx,		 s->dsbFx,			sizeof(LPDIRECTSOUNDBUFFER) * MAXFX); +	memcpy(fxiPaused,	 s->fxiPaused,		sizeof(uint8) * MAXFX); +	memcpy(fxLooped,	 s->fxLooped,		sizeof(uint8) * MAXFX); +	memcpy(musStreaming, s->musStreaming,	sizeof(int16) * MAXMUS); +	memcpy(musicPaused,	 s->musicPaused,	sizeof(int16) * MAXMUS); +	memcpy(musCounter,	 s->musCounter,		sizeof(int16) * MAXMUS); +	memcpy(musFading,	 s->musFading,		sizeof(int16) * MAXMUS); +	memcpy(musLooping,	 s->musLooping,		sizeof(int16) * MAXMUS); +	memcpy(musLastSample,s->musLastSample,	sizeof(int16) * MAXMUS); +	memcpy(streamCursor, s->streamCursor,	sizeof(int32) * MAXMUS); +	memcpy(musFilePos,	 s->musFilePos,		sizeof(int32) * MAXMUS); +	memcpy(musEnd,		 s->musEnd,			sizeof(int32) * MAXMUS); +	memcpy(musId,		 s->musId,			sizeof(uint32) * MAXMUS); +	memcpy(volMusic,	 s->volMusic,		sizeof(uint32) * 2); +//	memcpy(dsbdMus,		 s->dsbdMus,		sizeof(DSBUFFERDESC) * MAXMUS); +//	memcpy(lpDsbMus,	 s->lpDsbMus,		sizeof(LPDIRECTSOUNDBUFFER) * MAXMUS); +//	memcpy(fpMus,		 s->fpMus,			sizeof(FILE*) * MAXMUS); +//	memcpy(wfMus,		 s->wfMus,			sizeof(PCMWAVEFORMAT) * MAXMUS); + +	for (i = 0; i<MAXMUS; i++) +		memcpy(musFilename[i], s->musFilename[i], sizeof(char) * 256); +} + diff --git a/sword2/driver/d_sound.h b/sword2/driver/d_sound.h new file mode 100644 index 0000000000..5281cf01c9 --- /dev/null +++ b/sword2/driver/d_sound.h @@ -0,0 +1,43 @@ +/* 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	:	d_sound.h +//	Created		:	5th December 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		05-Dec-96	PRP		Interface to the DirectSound driver functions +// +//	Summary		:	This include file defines links to all data which is +//					defined in the d_sound.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef D_SOUND_H +#define D_SOUND_H + +extern void FxServer(void); + +#endif diff --git a/sword2/driver/ddutil.h b/sword2/driver/ddutil.h new file mode 100644 index 0000000000..f6976eca15 --- /dev/null +++ b/sword2/driver/ddutil.h @@ -0,0 +1,159 @@ +/* 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$ + */ + +//----------------------------------------------------------------------------- +// File: ddutil.cpp +// +// Desc: Routines for loading bitmap and palettes from resources +// +// Copyright (C) 1998-2001 Microsoft Corporation. All Rights Reserved. +//----------------------------------------------------------------------------- +#ifndef DDUTIL_H +#define DDUTIL_H + +#include <ddraw.h> +#include <d3d.h> + + + + +//----------------------------------------------------------------------------- +// Classes defined in this header file  +//----------------------------------------------------------------------------- +class CDisplay; +class CSurface; + + + + +//----------------------------------------------------------------------------- +// Flags for the CDisplay and CSurface methods +//----------------------------------------------------------------------------- +#define DSURFACELOCK_READ +#define DSURFACELOCK_WRITE + + + + +//----------------------------------------------------------------------------- +// Name: class CDisplay +// Desc: Class to handle all DDraw aspects of a display, including creation of +//       front and back buffers, creating offscreen surfaces and palettes, +//       and blitting surface and displaying bitmaps. +//----------------------------------------------------------------------------- +class CDisplay +{ +protected: +    LPDIRECTDRAW7        m_pDD; +    LPDIRECTDRAWSURFACE7 m_pddsFrontBuffer; +    LPDIRECTDRAWSURFACE7 m_pddsBackBuffer; +    LPDIRECTDRAWSURFACE7 m_pddsBackBufferLeft; // For stereo modes + +    HWND                 m_hWnd; +    RECT                 m_rcWindow; +    BOOL                 m_bWindowed; +    BOOL                 m_bStereo; + +public: +    CDisplay(); +    ~CDisplay(); + +    // Access functions +    HWND                 GetHWnd()           { return m_hWnd; } +    LPDIRECTDRAW7        GetDirectDraw()     { return m_pDD; } +    LPDIRECTDRAWSURFACE7 GetFrontBuffer()    { return m_pddsFrontBuffer; } +    LPDIRECTDRAWSURFACE7 GetBackBuffer()     { return m_pddsBackBuffer; } +    LPDIRECTDRAWSURFACE7 GetBackBufferLeft() { return m_pddsBackBufferLeft; } + +    // Status functions +    BOOL    IsWindowed()                     { return m_bWindowed; } +    BOOL    IsStereo()                       { return m_bStereo; } + +    // Creation/destruction methods +    HRESULT CreateFullScreenDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight, +		                             DWORD dwBPP ); +    HRESULT CreateWindowedDisplay( HWND hWnd, DWORD dwWidth, DWORD dwHeight ); +    HRESULT InitClipper(); +    HRESULT UpdateBounds(); +    virtual HRESULT DestroyObjects(); + +    // Methods to create child objects +    HRESULT CreateSurface( CSurface** ppSurface, DWORD dwWidth, +		                   DWORD dwHeight ); +    HRESULT CreateSurfaceFromBitmap( CSurface** ppSurface, TCHAR* strBMP, +		                             DWORD dwDesiredWidth, +									 DWORD dwDesiredHeight ); +    HRESULT CreateSurfaceFromText( CSurface** ppSurface, HFONT hFont, +		                           TCHAR* strText,  +								   COLORREF crBackground, +								   COLORREF crForeground ); +    HRESULT CreatePaletteFromBitmap( LPDIRECTDRAWPALETTE* ppPalette, const TCHAR* strBMP ); + +    // Display methods +    HRESULT Clear( DWORD dwColor = 0L ); +    HRESULT ColorKeyBlt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, +                         RECT* prc = NULL ); +    HRESULT Blt( DWORD x, DWORD y, LPDIRECTDRAWSURFACE7 pdds, +		         RECT* prc=NULL, DWORD dwFlags=0 ); +    HRESULT Blt( DWORD x, DWORD y, CSurface* pSurface, RECT* prc = NULL ); +    HRESULT ShowBitmap( HBITMAP hbm, LPDIRECTDRAWPALETTE pPalette=NULL ); +    HRESULT SetPalette( LPDIRECTDRAWPALETTE pPalette ); +    HRESULT Present(); +}; + + + + +//----------------------------------------------------------------------------- +// Name: class CSurface +// Desc: Class to handle aspects of a DirectDrawSurface. +//----------------------------------------------------------------------------- +class CSurface +{ +    LPDIRECTDRAWSURFACE7 m_pdds; +    DDSURFACEDESC2       m_ddsd; +    BOOL                 m_bColorKeyed; + +public: +    LPDIRECTDRAWSURFACE7 GetDDrawSurface() { return m_pdds; } +    BOOL                 IsColorKeyed()    { return m_bColorKeyed; } + +    HRESULT DrawBitmap( HBITMAP hBMP, DWORD dwBMPOriginX = 0, DWORD dwBMPOriginY = 0,  +		                DWORD dwBMPWidth = 0, DWORD dwBMPHeight = 0 ); +    HRESULT DrawBitmap( TCHAR* strBMP, DWORD dwDesiredWidth, DWORD dwDesiredHeight ); +    HRESULT DrawText( HFONT hFont, TCHAR* strText, DWORD dwOriginX, DWORD dwOriginY, +		              COLORREF crBackground, COLORREF crForeground ); + +    HRESULT SetColorKey( DWORD dwColorKey ); +    DWORD   ConvertGDIColor( COLORREF dwGDIColor ); +    static HRESULT GetBitMaskInfo( DWORD dwBitMask, DWORD* pdwShift, DWORD* pdwBits ); + +    HRESULT Create( LPDIRECTDRAW7 pDD, DDSURFACEDESC2* pddsd ); +    HRESULT Create( LPDIRECTDRAWSURFACE7 pdds ); +    HRESULT Destroy(); + +    CSurface(); +    ~CSurface(); +}; + + + + +#endif // DDUTIL_H + diff --git a/sword2/driver/driver96.h b/sword2/driver/driver96.h new file mode 100644 index 0000000000..87c40c3fbd --- /dev/null +++ b/sword2/driver/driver96.h @@ -0,0 +1,1665 @@ +/* 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	:	driver96.h +//	Created		:	6th August 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This include file defines all interfaces to the Revolution +//					driver96 system.  All game code which requires driver +//					functions should simlply include this file. +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		12-Sep-96	PRP		Initial drivers include file - with utypes.h! +// +//	1.1		17-Sep-96	PRP		screenWide and screenDeep made available to the +//								game engine. +// +//	1.2		18-Sep-96	PRP		Mouse functions added.  The _mouseEvent struct +//								is made visible to the game engine, and the +//								function prototype for getting a mouse event +//								from the queue has been added.  Also, filename +//								in macro for driver error reporting is fixed. +// +//	1.3		19-Sep-96	PRP		Interface to keyboard functions added.  Also, +//								removed references to bool which is not  +//								allowed by the cpp compiler. +// +//	1.4		19-Sep-96	PRP		Fix definition of MouseEvent() and make the +//								rderror variable static. +// +//	1.5		20-Sep-96	PRP		Added interface to console functions. +// +//	1.6		23-Sep-96	PRP		Removed console functions from drivers! +// +//	1.7		25-Sep-96	PRP		Added interface to sprite drawing functions. +//								RenderScreen changed so that the drawing offset +//								is not passed in.  This is now calculated from +//								SetScrollTarget, and the number of frames we +//								are going to render in the next game cycle. +// +//	1.8		26-Sep-96	PRP		Moved the screen drawing and scrolling code +//								to render.c for clarity.  Changed the mouse +//								coordinates to be relative to the top left +//								corner of the game screen and removed the mouse +//								position from the log. +// +//	1.9		09-Oct-96	PRP		Defined SOFTWARE_SCREEN_BUFFER in here so that +//								all of the drivers can use it, and the game +//								engine will know what's going on! +// +//	1.10	28-Oct-96	PRP		DrawSprite has changed.  There are now flags to +//								describe whether the sprite is compressed,  +//								transparent or displayed from the top left +//								corner of the screen as opposed to the top left +//								corner of the background. +// +//	1.11	29-Oct-96	PRP		Naming of RDSPR_DISPLAYALIGN fixed in header! +// +//	1.12	01-Nov-96	PRP		Added compression type, RDSPR_SPRITECOMPRESSION,  +//								and increased the size of the parameter passed +//								to DrawSprite so up to eight compression types +//								can be defined. +//								Added functions to mouse.c for animating mouse +//								pointers.  Interface to functions put in here.. +// +//	1.13	07-Nov-96	PRP		Added RDERR_GOFULLSCREEN as a return error for +//								creating the primary surface on a screen +//								which is not in 8bpp mode.  Also, made it so +//								sprite drawing is passed a structure with  +//								all of the sprite parameters in, rather than +//								the individual values passed. +//								When setting up the screen display/resolution +//								you should now specify whether you want the +//								game to run in full screen mode or in a window. +// +//	1.14	15-Nov-96	PRP		Added menubar code into drivers. +// +//	1.15	21-Nov-96	PRP		Changed the interface to the DrawLine function. +// +//	1.16	25-Nov-96	PRP		Added a function to set the Luggage animation. +// +//	1.17	25-Nov-96	PRP		Added functions to palette.c which create +//								match tables, and match rgb values to palette +//								indeces - and new error messages +// +//	1.18	26-Nov-96	PRP		Added error - RDERR_INVALIDSCALING which will +//								be used when sprites are drawn with a scaling +//								value outside of the range 0 .. s .. 512 +// +//	1.19	29-Nov-96	PRP		Added timing information to be referenced by +//								the game engine.  Also implemented palette +//								fading with new functions added! +// +//	1.20	03-Dec-96	PRP		Sound driver functions added.  It is now  +//								possible to play speech. +// +//	1.21	05-Dec-96	PRP		SetPalette changed so that the palette can +//								be realized immediately or later when fading +//								is called. +// +//	1.22	05-Dec-96	PRP		Added sound driver functions for dealing with +//								sound fx. +// +//	1.23	09-Dec-96	PRP		Changed the UpdatePaletteMatchTable to take +//								a pointer rather than a filename. +// +//	1.24	19-Dec-96	PRP		Changed the sound system functions to add +//								volume and pan position.  Also, added a flag +//								to the fx player for looping. +// +//	1.25	27-Jan-97	PRP		Changed the call to render parallax, to define +//								which layer is to be rendered.  Also, added +//								the RDBLTFX_ equates for how the rendering +//								engine works.  There are new functions to  +//								initialise and close the background layers +//								which need to be called at the start and end +//								of a room. +// +//	1.26	10-Feb-97	PRP		Changed the direct draw error reporting calls, +//								and added new return error codes. +// +//	1.27	11-Feb-97	PRP		Added the blending value into the spriteInfo +//								structure. +// +//	1.28	12-Feb-97	PRP		Added set and clear blt effects functions. +// +//	1.29	06-Mar-97	PRP		Added error return code RDERR_LOCKFAILED for +//								failing to lock the front buffer when trying +//								to write a screen shot.  Also, added definition +//								of _pcxHeader. +// +//	1.30	17-Mar-97	PRP		Added RDFADE_BLACK as a return value for the +//								GetPaletteStatus() function. +// +//	1.31	18-Mar-97	PRP		Added InitialiseRenderCycle() to be called +//								before the rendering loop is entered.  This +//								resets the timers. +// +//	1.32	20-Mar-97	PRP		Added reference to ResetRenderEngine() to be +//								called upon entry to the control panel. +// +//	1.33	24-Mar-97	PRP		Added sprite drawing functions for hardware +//								utilisation. +// +//	1.34	24-Mar-97	PRP		Added return code RDERR_SURFACELOST +// +//	1.35	01-Apr-97	PRP		Added new sprite type RDSPR_RLE256FAST +// +//	1.36	04-Apr-97	PRP		Changed the prototype for InitialiseWindow. +// +//	1.37	07-Apr-97	PRP		Added function prototypes and error values +//								for the switching between the hardware and +//								software renderers. +// +//	1.38	07-Apr-97	PRP		Added function prototypes and error values +//								for the shadow masking engine. +// +//	1.39	08-Apr-97	PRP		Added reference to PlaySmacker() +// +//	1.40	09-Apr-97	PRP		Added references to the functions which play music +//								streaming it from the CD. +// +//	1.41	10-Apr-97	PRP		Added defines for mouse flashing or not.  Also +//								changed function call to SetMouseAnim to +//								include this parameter. +// +//	1.42	11-Apr-97	PRP		EraseSoftwareScreenBuffer added. +// +//	1.43	11-Apr-97	JEL		In render.c changed EraseSoftwareRenderBuffer to EraseSoftwareScreenBuffer +// +//	1.44	11-Apr-97	CJR		Added palCopy definition for use in game engine. +// +//	1.45	22-Apr-97	PRP		Added decompression error return value. +// +//	1.46	28-Apr-97	PSJ		Added members to _wavHeader structure. +// +//	1.47	21-May-97	PRP		Added the _movieTextObject data structure.  This will +//								be used in the call to PlaySmacker to define if there is any +//								text to be displayed and when. +// +//	1.48	21-May-97	PRP		Fixed the pointer to the text sprite within the movie +//								text object structure. +// +//	1.49	22-May-97	JEL		Fixed PlaySmacker for a movieTextObject parameter of NULL +// +//	1.50	29-May-97	PSJ		Added the _drvStatus data structure.  This will allow the +//								state of all the drivers globals to be passed between dlls, +//								exectuables and threads. +// +//	1.51	29-May-97	PSJ		Added the _drvSoundStatus data structure and move _drvStatus to _drvDrawStatus. +//								This will allow the	state of the drivers drawing globals and audio globals to +//								be passed between dlls,	exectuables and threads. +//								Also included ddraw.h dsound.h and mmsystem.h in this file. +// +//	1.52	29-May-97	PRP		Added reference to the DisableQuitKey function, +//								which removes the ability to press control-Q to quit +//								the game. +// +//	1.53	04-Jun-97	PRP		Changed the funtion call to PlaySmacker.  Now includes +//								a wav to lead out at the end of the smack file. +// +//	1.55	06-Jun-97	PSJ		Added GetFxVolume and SetFxVolume for fx master volume control. +//								Added GetSpeechVolume and SetSpeechVolume for speech master volume. +// +//	1.56	09-Jun-97	PSJ		Added GetMusicVolume and SetMusicVolume. +// +//	1.57	10-Jun-97	PSJ		Added MuteMusic, MuteFx, MuteSpeech, IsMusicMute, IsFxMute and Is SpeechMute +// +//	1.58	12-Jun-97	PSJ		Added PlayCompSpeech to load and play a compressed wave. +// +//	1.59	12-Jun-97	PSJ		Added GetRenderType to return the type of rendering +//								currently being used. +// +//	1.60	13-Jun-97	PRP		Added functions to set and clear shadow mask status. +// +//	1.61	26-Jun-97	PSJ		Added AmISpeaking to check for lip syncing spots in the speech. +//								Also added RDSE_QUIET and RDSE_SPEAKING as return values. +// +//	1.62	26-Jun-97	PSJ		Added PauseSpeech and UnpauseSpeech. +// +//	1.63	26-Jun-97	PRP		Added DimPalette. +// +//	1.64	27-Jun-97	PRP		Moved definition of GrabScreenShot in from +//								d_draw.h +// +//	1.65	15-Jul-97	PRP		Added functions to pause and unpause speech. +// +//	1.66	16-Jul-97	PRP		Added a speech pointer to the movieTextObject structure. +// +//	1.67	16-Jul-97	PSJ		Added GetCompSpeechSize and PreFetchSpeech +// +//	1.68	21-Jul-97	PRP		Added new FX type for sequence lead in and new function +//								to pause sound effects apart from the lead in music. +// +//	1.73	22-Jul-97	PRP		Added define to ensure DirectX 3.0 functionality used +//								under DirectX 5.0 drivers :) +// +//	1.74	23-Jul-97	JEL		Added CheckForMouseEvents() to return no. of events outstanding +// +//	1.75	30-Jul-97	PSJ		Added MusicTimeRemaining() to return time left for current tune. +// +//	1.77	06-Aug-97	PSJ		Updated Get and Set scroll SoundStatus. +// +//	1.78	07-Aug-97	PSJ		Added SetWindowName to set the name of the window. +// +//	1.79	12-Aug-97	PSJ		Added ReverseStereo. +// +//	1.80	13-Aug-97	PRP		Added CloseMenuImmediately. +// +//	1.81	13-Aug-97	PSJ		Added GetKeyStatus +// +//	1.82	13-Aug-97	PRP		Added IsFxOpen. +// +//	1.83	15-Aug-97	PRP		SetFxVolumePan added to update a sample on the fly. +// +//	1.84	15-Aug-97	PRP		SetFxIdVolume added. +// +//	1.85	22-Aug-97	PSJ		Added type RDSE_LEADOUT +// +//	Functions +//	--------- +// +//	--------------------------------------------------------------------------- +//	------------------------------- d_draw.c ---------------------------------- +//	--------------------------------------------------------------------------- +// +//	int32 InitialiseDisplay(int32 width, int32 height, int32 colourDepth, int32 windowType) +// +//	Initialises the directDraw display with the sizes and colour depths passed +//	in.  The windowType is either RD_FULLSCREEN or RD_WINDOWED depending upon +//	whether the app is to run in a window or not.  If RD_WINDOWED is selected, +//	the runction may returnRDERR_GOFULLSCREEN which implies that the window +//	size and colour depth requested is not compatible with the current +//	settings. +//	If the required display cannot be set up, then an error code is +//	returned, otherwise zero. +// +//	--------------------------------------------------------------------------- +//	 +//	int32 ResetDisplay(void) +// +//	Closes down the directDraw sub-system and resets the display back to it's +//	original size.  Returns an RD code. +// +//	--------------------------------------------------------------------------- +// +//	int32 FlipScreens(void) +// +//	Waits for the vertical retrace and then flips the front and back buffers. +//	If a vertical retrace flag is unavailable, it flips immediately.  Returns +//	an RD code. +// +//	--------------------------------------------------------------------------- +// +//	int32 EraseBackBuffer(void) +// +//	Fills the back buffer with palette colour zero.  Returns an RD code. +// +//	--------------------------------------------------------------------------- +// +//	int32 WaitForVbl(void) +// +//	This function returns when the video hardware is in vertical retrace. +// +//	--------------------------------------------------------------------------- +// +//	void InterpretDirectDrawError(int32 error) +// +//	This function is passed the pointer to a direct draw error code, and +//	translates this into a revolution driver error code.  It also reports the +//	error. +// +//	--------------------------------------------------------------------------- +// +//	int32 SetBltFx(void) +// +//	Sets the edge blend and arithmetic stretching effects. +// +//	--------------------------------------------------------------------------- +// +//	int32 ClearBltFx(void) +// +//	Clears the edge blend and arithmetic stretching effects. +// +//	--------------------------------------------------------------------------- +// +//	int32 RenderHard(void); +// +//	Turns on the hardware renderer.  Returns an error if the +//	hardware is not capable of rendering. +// +//	--------------------------------------------------------------------------- +// +//	int32 RenderSoft(void); +// +//	Turns on the software renderer.  Returns an error if it +//	is already on. +// +//	--------------------------------------------------------------------------- +// +//	int32 GetRenderType(void) +// +//	Returns the type of rendering currently being used. +//	0 = H/W rendering,	1 = S/W Rendering + BltFxOFF,  2 = S/W Rendering + BltFxON +// +//	--------------------------------------------------------------------------- +// +//	int32 PlaySmacker(char *filename) +// +//	Plays the smacker file, filename. +// +//	--------------------------------------------------------------------------- +// +//	void GetDrawStatus(_drvStatus *s) +// +//	Retrieves the value of the driver's drawing globals and stores them in s. +// +//	--------------------------------------------------------------------------- +// +//	void SetDrawStatus(_drvStatus *s) +// +//	Set the value of the driver's drawing globals from s. +// +//	--------------------------- rdwin.c --------------------------------------- +//	--------------------------------------------------------------------------- +// +//	int32 InitialiseWindow(HWND hWnd) +// +//	Creates a window!  This must be the first operation in creating the  +//	Windows 95 version. +// +//	--------------------------------------------------------------------------- +//	 +//	int32 ServiceWindows(void) +// +//	This function should be called at a high rate ( > 20 per second) to service +//	windows and the interfaces it provides. +// +//	--------------------------------------------------------------------------- +// +//	int32 CloseAppWindow(void) +// +//	Removes all windows hooks from the application. +// +//	--------------------------------------------------------------------------- +// +//	int32 ReportDriverError(int32 error) +// +//	Creates a message box and displays the error code passed to it, as well as +//	the filename and line that the function was called from +// +//	--------------------------------------------------------------------------- +// +//	int32 ReportFatalError(uint8 *error) +// +//	Creates a message box and displays the error string passed in, as well as +//	the filename and line that the function was called from +// +//	--------------------------------------------------------------------------- +// +//	void SetWindowName(const char *windowName) +// +//	Set the window name to windowName and stores this name in gameName for future +//  use. +// +//	--------------------------------------------------------------------------- +//	--------------------------------- language.c ------------------------------ +//	--------------------------------------------------------------------------- +// +//	int32 GetLanguageVersion(uint8 *version) +// +//	This function modifies the 'version' passed in to be the current language. +//	The first time this function is called, it gets the language from the  +//	version.inf file distributed on the game CD.  It returns an RD error code +//	if this file cannot be opened, or the version cannot be obtained from it. +// +//	--------------------------------------------------------------------------- +//	 +//	int32 SetLanguageVersion(uint8 version) +// +//	This function is useful for debugging.  It sets the version to the one +//	passed in. +// +//	--------------------------------------------------------------------------- +//	 +//	int32 GetGameName(uint8 *name); +// +//	Fills the string pointed to by name with the title of the game, depending +//	upon what the current language version is. +// +//	-------------------------------------------------------------------------- +//	------------------------------- palette.c -------------------------------- +//	-------------------------------------------------------------------------- +// +//	void SetPalette(int32 startEntry, int32 noEntries, uint8 *colourTable, uint8 setNow) +// +//	Sets the palette from position startEntry for noEntries, to the data  +//	pointed to by colourTable.  To set the palette immediately pass +//	RDPAL_INSTANT.  If you want to fade later, pass RDPAL_FADE. +// +//	-------------------------------------------------------------------------- +// +//	int32 UpdatePaletteMatchTable(uint8 *data) +// +//	Uses the current palCopy to create a table of palette indeces which will +//	be searched later for a quick palette match - only if NULL is passed in +//	as the data.  If a pointer to valid data is passed in, the palette match +//	table is copied from that data. +// +//	-------------------------------------------------------------------------- +// +//	uint8 QuickMatch(uint8 r, uint8 g, uint8 b) +// +//	Returns the palette index of the closest matching colour in the palette +//	to these RGB values. +// +//	-------------------------------------------------------------------------- +// +//	int32 FadeUp(float time) +// +//	Fades the palette up from black to the current palette in time. +// +//	-------------------------------------------------------------------------- +// +//	int32 FadeDown(float time) +// +//	Fades the palette down to black from the current palette in time. +// +//	-------------------------------------------------------------------------- +// +//	uint8 GetFadeStatus(void) +// +//	Returns the fade status which can be one of RDFADE_UP, RDFADE_DOWN or +//	RDFADE_NONE. +// +// +//	-------------------------------------------------------------------------- +//	-------------------------------- mouse.c --------------------------------- +//	-------------------------------------------------------------------------- +// +//  _mouseEvent *MouseEvent(void) +// +//	If there is a mouse event in the queue, a valid pointer is returned. +//	Otherwise, NULL. +// +//	-------------------------------------------------------------------------- +// +//	int32 SetMouseAnim(uint8 *ma, int32 size, int32 mouseFlash) +// +//	A pointer to a valid mouse animation is passed in, along with the size of +//	the header plus sprite data.  Remember to check that the function has  +//	successfully completed, as memory allocation is required.  When the mouse +//	animation has been set, the mouse sprite does not need to be kept in the +//	memory manager. +//	Pass NULL in to clear the mouse sprite. +//	mouseFlash should be either RDMOUSE_FLASH or RDMOUSE_NOFLASH +//	defining whether to pulse the mouse or not. +// +//	-------------------------------------------------------------------------- +// +//	int32 SetLuggageAnim(uint8 *la, int32 size) +// +//	A pointer to a valid luggage animation is passed in, along with the size of +//	the header plus sprite data.  Remember to check that the function has  +//	successfully completed, as memory allocation is required. +//	Pass NULL in to clear the luggage sprite.  Luggage sprites are of the same +//	format as mouse sprites. +// +//	-------------------------------------------------------------------------- +// +//	int32 AnimateMouse(void) +// +//	This function animates the current mouse pointer.  If no pointer is  +//	currently defined, an error code is returned. +// +// +//	-------------------------------------------------------------------------- +//	------------------------------ keyboard.c -------------------------------- +//	-------------------------------------------------------------------------- +// +//  BOOL KeyWaiting(void) +// +//	This function returns TRUE if there is an unprocessed key waiting in the +//	queue, FALSE otherwise. +// +//	-------------------------------------------------------------------------- +// +//	int32 ReadKey(char *key) +// +//	Sets the value of key passed in to the current waiting key.  If there is +//	no key waiting, an error code is returned. +// +// +//	-------------------------------------------------------------------------- +// +//	void GetKeyStatus(_drvKeyStatus *) +// +//	Retrieves the address of the keyboard buffer bits. +//	 +//	-------------------------------------------------------------------------- +//	------------------------------- sprite.c --------------------------------- +//	-------------------------------------------------------------------------- +// +//	int32 DrawSprite(_spriteInfo *s) +// +//	Draws a sprite onto the screen of the type defined in the _spriteInfo +//	structure.  The _spriteInfo structure consists of the following elements: +// +//	int16	x;				// coords for top-left of sprite +//	int16	y; +//	uint16	w;				// dimensions of sprite (before scaling) +//	uint16	h; +//	uint16	scale;			// scale at which to draw, given in 256ths  +//							   ['0' or '256' MEANS DON'T SCALE] +//	uint16	scaledWidth;	// new dimensions +//	uint16	scaledHeight;	// +//	uint16	blend			// blending value. +//	uint16	type;			// combination of the bits below +//	uint8	*data;			// pointer to the sprite data +//	uint8	*colourTable;	// pointer to 16-byte colour table - only  +//							   applicable to 16-col compression type +// +//	WARNING:  Sprites will only be drawn onto the background.  Sprites will not +//		appear over the menubar areas.  The mouse and menu drawing is treated +//		as a special case. +// +//	The type of the sprite can be any of the following: +// +//	if (RDSPR_TRANS) +//		The sprite has a transparent colour zero +//		if (RDSPR_NOCOMPRESSION) +//			The sprite data must not be compressed (slow to draw) +//			The RDSPR_DISPLAYALIGN bit may be set to draw the sprite +//				at coordinates relative to the top left corner of the +//				monitor. +//		else +//			Compression must be set as one of the following: +//				RDSPR_RLE16 +//				RDSPR_RLE256 +//				RDSPR_LAYERCOMPRESSION +//	else +//		The sprite has an opaque colour zero +//		RDSPR_NOCOMPRESSION must be set! +//		RDSPR_DISPLAYALIGN may be set to align the coordinates of the sprite +//			to the top left corner of the monitor. +// +//	--------------------------------------------------------------------------- +// +//	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 OpenLightMask(_spriteInfo *s) +// +//	Opens the light masking sprite for a room. +// +//	--------------------------------------------------------------------------- +// +//	int32 CloseLightMask(void) +// +//	Closes the light masking sprite for a room. +// +//	-------------------------------------------------------------------------- +//	------------------------------- render.c --------------------------------- +//	-------------------------------------------------------------------------- +//	 +//	int32 RenderParallax(_parallax *p) +// +//	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 InitialiseRenderCycle(void) +// +//	Initialises the timers before the render loop is entered. +// +//	-------------------------------------------------------------------------- +// +//	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. +// +//	-------------------------------------------------------------------------- +// +//	int32 EraseSoftwareScreenBuffer(void) +// +//	Clears the memory used for the software screen buffer.  This should +//	not be called every cycle because it takes time and is not necessary. +//	However, it should be called between levels and such. +// +//	-------------------------------------------------------------------------- +//	---------------------------- menu.c -------------------------------------- +//	-------------------------------------------------------------------------- +// +//	int32 ProcessMenu(void) +// +//	This function should be called regularly to process the menuber system. +//	The rate at which this function is called will dictate how smooth the menu +//	system is.  The menu cannot be drawn at a higher rate than the system +//	vbl rate. +// +//	-------------------------------------------------------------------------- +// +//	int32 ShowMenu(uint8 menu) +// +//	This function brings the menu in to view.  The choice of top or bottom menu +//	is defined by the parameter menu being either RDMENU_TOP or RDMENU_BOTTOM. +//	An error code is returned if the menu is already shown. +// +//	-------------------------------------------------------------------------- +// +//	int32 HideMenu(uint8 menu) +// +//	This function hides the menu defined by the parameter menu.  If the menu is +//	already hidden, an error code is returned. +// +//	-------------------------------------------------------------------------- +// +//	int32 SetMenuIcon(uint8 menu, uint8 pocket, uint8 *icon) +// +//	This function sets a menubar icon to that passed in.  If icon is NULL, the +//	pocket is cleared, otherwise, that icon is placed into pocket.  The menu is +//	either RDMENU_TOP or RDMENU_BOTTOM.  Valid error codes include +//	RDERR_INVALIDPOCKET if the pocket number does not exist.  Initially, there +//	are 15 pockets. +// +//	-------------------------------------------------------------------------- +// +//	uint8 GetMenuStatus(uint8 menu) +// +//	This function returns the status of the menu passed in menu.  Return values +//	are RDMENU_OPENING, RDMENU_CLOSING, RDMENU_HIDDEN and RDMENU_SHOWN. +// +// +// +//	-------------------------------------------------------------------------- +//	--------------------------- d_sound.c ------------------------------------ +//	-------------------------------------------------------------------------- +// +//	int32 InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth) +// +//	This function initialises DirectSound by specifying the parameters of the +//	primary buffer. +// +//	Freq is the sample rate - 44100, 22050 or 11025 +//	Channels should be 1 for mono, 2 for stereo +//	BitDepth should be either 8 or 16 bits per sample.	 +// +//	-------------------------------------------------------------------------- +// +//	int32 PlaySpeech(uint8 *data, uint8 vol, int8 pan) +// +//	This function plays the wav file passed into it as speech.  An error occurs +//	if speech is already playing, or directSound comes accross problems. +//	volume can be from 0 to 16. +//	pan can be from -16 (full left) to 16 (full right). +// +//	-------------------------------------------------------------------------- +// +//	int32 PreFetchCompSpeech(const char *filename, uint32 speechid, uint8 *wave) +// +//	This function loads and decompresses speech sample 'speechid' from the +//	cluster 'filename' into 'wave'.  'wave' should contain the address of +//	preallocated memory large enough for speech to fit into  +//	(see GetCompSpeechSize). +// +//	-------------------------------------------------------------------------- +// +//	int32 GetCompSpeechSize(const char *filename, uint32 speechid); +// +//	This function returns the size that speech sample 'speechid' from cluster +//	'filename' will be after it has been decompressed and had a wav header +//	added.  Returns 0 for any error. +// +//	-------------------------------------------------------------------------- +// +//	int32 PlayCompSpeech(const char *filename, uint32 id, uint8 vol, int8 pan) +// +//	This function loads, decompresses and plays the wav 'id' from the cluster +// 'filename'.  An error occurs if speech is already playing, or directSound +//  comes accross problems. 'volume' can be from 0 to 16. 'pan' can be from +//  -16 (full left) to 16 (full right). +//  id is the text line id used to reference the speech within the speech +//  cluster. +// +//	-------------------------------------------------------------------------- +// +//	int32 StopSpeech(void) +// +//	Stops the speech from playing. +// +//	-------------------------------------------------------------------------- +// +//	int32 GetSpeechStatus(void) +// +//	Returns either RDSE_SAMPLEPLAYING or RDSE_SAMPLEFINISHED +// +//	-------------------------------------------------------------------------- +// +//	int32 AmISpeaking(void) +// +//	Returns either RDSE_QUIET or RDSE_SPEAKING +// +//	-------------------------------------------------------------------------- +// +//	int32 PauseSpeech(void) +// +//	Stops the speech dead in it's tracks. +// +//	-------------------------------------------------------------------------- +// +//	int32 UnpauseSpeech(void) +// +//	Re-starts the speech from where it was stopped. +// +//	-------------------------------------------------------------------------- +// +//	int32 OpenFx(int32 id, uint8 *data) +// +//	This function opens a sound effect ready for playing.  A unique id should +//	be passed in so that each effect can be referenced individually. +// +//	WARNING: Zero is not a valid ID. +// +//	-------------------------------------------------------------------------- +// +//	int32 PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type) +// +//	This function plays a sound effect.  If the effect has already been opened +//	then *data should be NULL, and the sound effect will simply be obtained  +//	from the id passed in.  If the effect has not been opened, then the wav +//	data should be passed in data.  The sound effect will be closed when it +//	has finished playing. +//	volume can be from 0 to 16. +//	pan can be from -16 (full left) to 16 (full right). +//	type is either RDSE_FXSPOT or RDSE_FXLOOP +// +//	WARNING: Zero is not a valid ID +// +//	-------------------------------------------------------------------------- +// +//	int32 CloseFx(int32 id) +// +//	This function closes a sound effect which has been previously opened for +//	playing.  Sound effects must be closed when they are finished with, +//	otherwise you will run out of sound effect buffers. +// +//	-------------------------------------------------------------------------- +// +//	int32 ClearAllFx(void) +// +//	This function clears all of the sound effects which are currently open or +//	playing, irrespective of type. +// +//	-------------------------------------------------------------------------- +// +//	int32 StreamMusic(uint8 *filename, int32 loopFlag) +// +//	Streams music from the file defined by filename.  The loopFlag should +//	be set to RDSE_FXLOOP if the music is to loop back to the start. +//	Otherwise, it should be RDSE_FXSPOT. +//	The return value must be checked for any problems. +// +//	-------------------------------------------------------------------------- +// +//	int32 StreamCompMusic(uint8 *filename, uint32 id, int32 loopFlag) +// +//	Streams music 'id' from the cluster file 'filename'.  The loopFlag should +//	be set to RDSE_FXLOOP if the music is to loop back to the start. +//	Otherwise, it should be RDSE_FXSPOT. +//	The return value must be checked for any problems. +// +//  StreamCompMusic should not be used inconjunction with StreamMusic. +// +//	-------------------------------------------------------------------------- +// +//	void StopMusic(void) +// +//	Fades out and stops the music. +// +//	-------------------------------------------------------------------------- +// +//	int32 PauseMusic(void) +// +//	Stops the music dead in it's tracks. +// +//	-------------------------------------------------------------------------- +// +//	int32 UnpauseMusic(void) +// +//	Re-starts the music from where it was stopped. +// +//	--------------------------------------------------------------------------- +// +//	void GetSoundStatus(_drvStatus *s) +// +//	Retrieves the value of the driver's audio globals and stores them in s. +// +//	--------------------------------------------------------------------------- +// +//	void SetSoundStatus(_drvStatus *s) +// +//	Set the value of the driver's audio globals from s. +// +//	--------------------------------------------------------------------------- +// +//	void SetMusicVolume(uint8 vol) +// +//	Set the volume of any future as well as playing (but not fading) music to +//  vol.  vol is in the range of 0 to 16 with 0 being silent. +// +//	--------------------------------------------------------------------------- +// +//	uint8 GetMusicVolume(void) +// +//	Returns the volume setting for music. +// +//	--------------------------------------------------------------------------- +// +//	void SetFxVolume(uint8 vol) +// +//	Set the master volume of all fx' to vol.  The fx' still have there own +//  volume setting as well as the master volume.  vol is in the range 0 to 14 +//  with 0 being silent. +// +//	--------------------------------------------------------------------------- +// +//	uint8 GetFxVolume(void) +// +//	Returns the master volume setting for fx'. +// +//	--------------------------------------------------------------------------- +// +//	void SetSpeechVolume(uint8 vol) +// +//	Set the volume of any future as well as playing speech samples to vol. +//  vol is in the range of 0 to 14 with 0 being silent. +// +//	--------------------------------------------------------------------------- +// +//	uint8 GetSpeechVolume(void) +// +//	Returns the volume setting for speech. +// +//	--------------------------------------------------------------------------- +// +//	void MuteMusic(uint8 mute) +// +//	If mute is 0, the music volume is restored to the last set master level. +//  otherwise the music is muted (volume 0). +// +//	--------------------------------------------------------------------------- +// +//	void MuteFx(uint8 mute) +// +//  See MuteMusic(uint8). +// +//	--------------------------------------------------------------------------- +// +//	void MuteSpeech(uint8 mute) +// +//  See MuteMusic(uint8). +// +//	--------------------------------------------------------------------------- +// +//	uint8 IsMusicMute(void) +// +//	Returns the music's mute state, 1 if mute, 0 if not mute. +// +//	--------------------------------------------------------------------------- +// +//	uint8 IsFxMute(void) +// +//  See IsMusicMute(). +// +//	--------------------------------------------------------------------------- +// +//	uint8 IsMusicMute(void) +// +//  See IsMusicMute(). +// +//	--------------------------------------------------------------------------- +// +//	int32 MusicTimeRemaining(void) +// +//  Returns the time left for the current tune. +// +//	--------------------------------------------------------------------------- +// +//	int32 ReverseStereo(void) +// +//  Returns the time left for the current tune. +// +//	--------------------------------------------------------------------------- +// +//	int32 SetFxVolumePan(int32 id, uint8 vol, uint8 pan) +// +//	Sets the volume and pan of the sample which is currently playing (id) +// +//============================================================================= + +#ifndef DRIVER96_H +#define DRIVER96_H + +//#define DIRECTDRAW_VERSION 0x0300 + +//#include <windows.h> +//#include <windowsx.h> +#include <limits.h> +//#include <mmsystem.h> +#include <stdio.h> +#include <string.h> + +#include "scummsys.h" +#include "engine.h" // for warning() +#include "system.h" +#include "file.h" +//#include "ddraw.h" +//#include "dsound.h" + + +#ifdef __cplusplus +extern "C" { +#endif + + + +// +//	Defines +//	------- +// + +// defines specific to windows headers... +#ifndef _MSC_VER + +#define SEM_FAILCRITICALERRORS 1 +#define FILE_ATTRIBUTE_NORMAL 0x80 +#define _MAX_PATH 260 + +#endif +	 +//Generic error codes +#define RD_OK				0x00000000 +#define RDERR_UNKNOWN			0x00000001 +#define RDERR_INVALIDPOINTER		0x00000002 +#define RDERR_OUTOFMEMORY		0x00000003 +#define RDERR_INVALIDFILENAME		0x00000004 +#define RDERR_READERROR			0x00000005 +#define RDERR_WRITEERROR		0x00000006 +#define RDERR_NOEMULATION		0x00000007 +#define RDERR_LOCKFAILED		0x00000008 + +//Drawing error codes +#define RDERR_VIDEOMODE			0x00010000 +#define RDERR_COLOURDEPTH		0x00010001 +#define RDERR_CANNOTFLIP		0x00010002 +#define RDERR_RESTORELAYERS		0x00010003 +#define RDERR_DDRAWNOEMULATION		0X00010004 +#define RDERR_NOHARDWARE		0x00010005 +#define RDERR_ALREADYON			0x00010006 +#define RDERR_DECOMPRESSION		0x00010007 + +//Operating system error codes +#define RDERR_CREATEWINDOW		0x00020000 +#define RDERR_APPCLOSED			0x00020001 +#define RDERR_GOFULLSCREEN		0x00020002 + +//Language and version error codes +#define RDERR_OPENVERSIONFILE		0x00030000 +#define RDERR_INVALIDVERSION		0x00030001 + +//Keyboard error codes +#define RDERR_NOKEYWAITING		0x00040000 + +//Sprite drawing error codes +#define RDERR_NOCLIPPING		0x00050000 +#define RDERR_NOTIMPLEMENTED		0x00050001 +#define RDERR_UNKNOWNTYPE		0x00050002 +#define RDERR_INVALIDSCALING		0x00050003 +#define RDERR_SURFACELOST		0x00050004 +#define RDERR_NOTCLOSED			0x00050005 +#define RDERR_NOTOPEN			0x00050006 +#define RDERR_ALREADYCLOSED		0x00050007 // added for _console.cpp by khalek + +//Menubar error codes +#define RDERR_INVALIDMENU		0x00060000 +#define RDERR_INVALIDPOCKET		0x00060001 +#define RDERR_INVALIDCOMMAND		0x00060002 + +//Palette fading error codes +#define RDERR_FADEINCOMPLETE		0x00070000 + +//Sound engine error codes +#define RDERR_DSOUNDCREATE		0x00080000 +#define RDERR_DSOUNDCOOPERATE		0x00080001 +#define RDERR_DSOUNDPBUFFER		0x00080002 +#define RDERR_PRIMARYFORMAT		0x00080003 +#define RDERR_SPEECHPLAYING		0x00080004 +#define RDERR_SPEECHNOTPLAYING		0x00080005 +#define RDERR_INVALIDWAV		0x00080006 +#define RDERR_CREATESOUNDBUFFER		0x00080007 +#define RDERR_LOCKSPEECHBUFFER		0x00080008 +#define RDERR_FXALREADYOPEN		0x00080009 +#define RDERR_NOFREEBUFFERS		0x0008000A +#define RDERR_FXNOTOPEN			0x0008000B +#define RDERR_FXFUCKED			0x0008000C +#define RDERR_INVALIDID			0x0008000D + + + + +// Language codes +#define ENGLISH				0x00 +#define AMERICAN			0x01 +#define GERMAN				0x02 +#define FRENCH				0x03 +#define SPANISH				0x04 +#define ITIALIAN			0x05 +#define JAPANESE			0x06 +#define SLOVAK				0x07 + +// Key codes +#define RDKEY_ESCAPE			27 + + +// Mouse button defines +#define RD_LEFTBUTTONDOWN		0x01 +#define RD_LEFTBUTTONUP			0x02 +#define RD_RIGHTBUTTONDOWN		0x04 +#define RD_RIGHTBUTTONUP		0x08 + + +//Sprite defines +#define RDSPR_TRANS			0x0001 +#define RDSPR_BLEND			0x0004 +#define RDSPR_FLIP			0x0008 +#define RDSPR_SHADOW			0x0010 +#define RDSPR_DISPLAYALIGN		0x0020 +#define RDSPR_NOCOMPRESSION		0x0040 +#define RDSPR_EDGEBLEND			0x0080 +//This is the high byte part of the sprite type which defines what type of +//  compression is used, as long as RDSPR_NOCOMPRESSION is not defined. +#define RDSPR_RLE16			0x0000 +#define RDSPR_RLE256			0x0100 +#define RDSPR_RLE256FAST		0x0200 + + +//Rendering defines +#define RD_SOFTWARESCREENBUFFER		0x01 + + +//Windows defines +#define RD_FULLSCREEN			0x01000000 +#define RD_WINDOWED			0x01000001 + + +//Fading defines +#define RDFADE_NONE			0x00 +#define RDFADE_UP			0x01 +#define RDFADE_DOWN			0x02 +#define RDFADE_BLACK			0x03 + +//Mouse defines +#define RDMOUSE_NOFLASH			0x00 +#define RDMOUSE_FLASH			0x01 + +//Menubar defines. +#define RDMENU_TOP			0x00 +#define RDMENU_BOTTOM			0x01 +									 +#define RDMENU_HIDDEN			0x00 +#define RDMENU_SHOWN			0x01 +#define RDMENU_OPENING			0x02 +#define RDMENU_CLOSING			0x03 + +#define RDMENU_ICONWIDE			35 +#define RDMENU_ICONDEEP			30 +#define RDMENU_ICONSTART		24 +#define RDMENU_ICONSPACING		5 +#define RDMENU_MAXPOCKETS		15 +#define RDMENU_MENUDEEP			40 + +#define RDSE_SAMPLEFINISHED		0 +#define RDSE_SAMPLEPLAYING		1 +#define RDSE_FXTOCLEAR			0 +#define RDSE_FXCACHED			1 +#define RDSE_FXSPOT			0 +#define RDSE_FXLOOP			1 +#define RDSE_FXLEADIN			2 +#define RDSE_FXLEADOUT			3 +#define RDSE_QUIET			1 +#define RDSE_SPEAKING          		0 + + +#define RDPAL_FADE			0 +#define RDPAL_INSTANT			1 + +//Blitting FX defines +#define RDBLTFX_MOUSEBLT		0x01 +#define RDBLTFX_FGPARALLAX		0x02 +#define RDBLTFX_ARITHMETICSTRETCH	0x04 +#define RDBLTFX_EDGEBLEND		0x08 +#define RDBLTFX_SHADOWBLEND		0x10 +#define RDBLTFX_FLATALPHA		0x20 +#define RDBLTFX_GRADEDALPHA		0x40 +#define RDBLTFX_ALLHARDWARE		0x80 + +// Max number of sound fx +#define MAXFX 16 +#define MAXMUS 2 + +// Key buffer size +#define MAX_KEY_BUFFER 32 + +typedef int BOOL; +#define TRUE 1 +#define FALSE 0 +typedef uint32 DWORD; + +typedef long int LARGE_INTEGER; + +// +//	Structure definitions +//	--------------------- +// + +typedef struct +{ +	uint16 buttons; +} _mouseEvent; + +typedef struct +{ +	uint16	w; +	uint16	h; +	uint32	offset[2];	// 2 is arbitrary +} _parallax; + +//	The _spriteInfo structure is used to tell the driver96 code what attributes +//	are linked to a sprite for drawing.  These include position, scaling and +//	compression. +typedef struct +{ +	int16	x;				// coords for top-left of sprite +	int16	y; +	uint16	w;				// dimensions of sprite (before scaling) +	uint16	h; +	uint16	scale;			// scale at which to draw, given in 256ths ['0' or '256' MEANS DON'T SCALE] +	uint16	scaledWidth;	// new dimensions (we calc these for the mouse area, so may as well pass to you to save time) +	uint16	scaledHeight;	// +	uint16	type;			// mask containing 'RDSPR_' bits specifying compression type, flip, transparency, etc +	uint16	blend;			// holds the blending values. +	uint8	*data;			// pointer to the sprite data +	uint8	*colourTable;	// pointer to 16-byte colour table, only applicable to 16-col compression type +} _spriteInfo; + + +// This is the format of a .WAV file.  Somewhere after this header is the string +// 'DATA' followed by an int32 size which is the size of the data.  Following +// the size of the data is the data itself. +typedef struct +{ +	char riff[4]; +	uint32 fileLength; +	char wavID[4]; +	char format[4]; +	uint32 formatLen; +	uint16 formatTag; +	uint16 channels; +	uint16 samplesPerSec; +	uint16 avgBytesPerSec; +	uint16 blockAlign; +	uint16 unknown1; +	uint16 unknown2; +	uint16 bitsPerSample; +} _wavHeader; + + +//  This is the structure which is passed to the sequence player. +//	It includes the smack to play, and any text lines which are +//	to be displayed over the top of the sequence. + +typedef struct +{ +	uint16 startFrame; +	uint16 endFrame; +	_spriteInfo *textSprite; +	_wavHeader *speech; +} _movieTextObject; + + + +typedef	struct +{	uint8	manufacturer; +	uint8	version; +	uint8	encoding; +	uint8	bitsPerPixel; +	int16	xmin,ymin; +	int16	xmax,ymax; +	int16	hres; +	int16	vres; +	char	palette[48]; +	char	reserved; +	uint8	colourPlanes; +	int16	bytesPerLine; +	int16	paletteType; +	char	filler[58]; +} _pcxHeader; + + +//  This is the structure which is used to set and +//  retrieve the direct draw drivers global variables. + +typedef struct +{	 +//	HWND				hwnd; +//	LPDIRECTDRAW		lpDraw; +//	LPDIRECTDRAW2		lpDD2; +//	LPDIRECTDRAWSURFACE	lpPrimarySurface; +//	LPDIRECTDRAWSURFACE	lpBackBuffer; +//	LPDIRECTDRAWPALETTE	lpPalette; +	int16				screenDeep; +	int16				screenWide; +	int16				scrollx; +	int16				scrolly; +	int16				scrollxTarget; +	int16				scrollyTarget; +	int16				scrollxOld; +	int16				scrollyOld; +	int16				failCount; +	int32				renderCaps; +	int32				dxHalCaps; +	int32				dxHelCaps; +	BOOL				noVbl; +	BOOL				bFullScreen; +//	DDCAPS				driverCaps; +//	DDCOLORKEY			blackColorKey; +} _drvDrawStatus; + + + +//  This is the structure which is used to set and +//  retrieve the direct sound drivers global variables. + +typedef struct +{	 +//	HWND				hwnd; +//	LPDIRECTSOUND		lpDS; +//	LPDIRECTSOUNDBUFFER	dsbPrimary; +//	LPDIRECTSOUNDBUFFER	dsbSpeech; +//	LPDIRECTSOUNDBUFFER	dsbFx[MAXFX]; +	int32				fxId[MAXFX]; +	uint8				fxCached[MAXFX]; +	uint8				soundOn; +	uint8				speechStatus; +	uint8				fxPaused; +	char				musFilename[MAXMUS][256]; +	uint8				speechPaused; +	uint8				speechVol; +	uint8				fxVol; +	uint8               speechMuted; +	uint8               fxMuted; +	uint8				musicMuted; +	uint8				compressedMusic; +	uint8				fxiPaused[MAXFX]; +	uint8				fxLooped[MAXFX]; +	int16 				musStreaming[MAXMUS]; +	int16				musicPaused[MAXMUS]; +	int16 				musCounter[MAXMUS]; +	int16				musFading[MAXMUS]; +	int16				musLooping[MAXMUS]; +	int16				musLastSample[MAXMUS]; +	int32				streamCursor[MAXMUS]; +	int32				musFilePos[MAXMUS]; +	int32				musEnd[MAXMUS]; +	uint32				musId[MAXMUS]; +//	DSBUFFERDESC 		dsbdMus[MAXMUS]; +//	LPDIRECTSOUNDBUFFER lpDsbMus[MAXMUS]; +	FILE				*fpMus[MAXMUS]; +//	PCMWAVEFORMAT       wfMus[MAXMUS]; +	uint32				volMusic[2]; +} _drvSoundStatus; + +//  This is the structure which is used to retrieve +//  the keyboard driver bits. + +typedef struct +{ +	uint8 *pBacklog; +	uint8 *pPointer; +	char  *pBuffer; +} _drvKeyStatus; + + +// should probably remove this struct as it just replaces a windows struct... +typedef struct { +    DWORD dwLength; +    DWORD dwMemoryLoad; +    DWORD dwTotalPhys; +    DWORD dwAvailPhys; +    DWORD dwTotalPageFile; +    DWORD dwAvailPageFile; +    DWORD dwTotalVirtual; +    DWORD dwAvailVirtual; +} GCC_PACK MEMORYSTATUS; + +// +//	Function Prototypes +//	------------------- +// + +//----------------------------------------------------------------------------- +//  Display functions - from d_draw.c +//----------------------------------------------------------------------------- +extern int32 InitialiseDisplay(int16 width, int16 height, int16 colourDepth, int32 windowType); +extern int32 RestoreDisplay(void); +extern int32 FlipScreens(void); +extern int32 WaitForVbl(void); +extern int32 EraseBackBuffer(void); +extern int32 SetBltFx(void); +extern int32 ClearBltFx(void); +extern int32 ClearShadowFx(void); +extern int32 SetShadowFx(void); +extern int32 RenderHard(void); +extern int32 RenderSoft(void); +extern int32 GetRenderType(void); +extern int32 PlaySmacker(char *filename, _movieTextObject *textObjects[], uint8 *musicOut); +extern void  GetDrawStatus(_drvDrawStatus *s); +extern void  SetDrawStatus(_drvDrawStatus *s); +extern int32 GrabScreenShot(void); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Windows OS functions - from rdwin.c +//----------------------------------------------------------------------------- +//extern int32 InitialiseWindow(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow, char *gameName); +extern int32 CloseAppWindow(void); +extern int32 ServiceWindows(void); +extern int32 _ReportDriverError(int32 error, uint8 *filename, uint32 line); +extern int32 _ReportFatalError(uint8 *error, uint8 *filename, uint32 line); +extern int32 DisableQuitKey(void); +extern void  SetWindowName(const char *windowName); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Language functions - from language.c +//----------------------------------------------------------------------------- +extern int32 GetLanguageVersion(uint8 *version); +extern int32 SetLanguageVersion(uint8 version); +extern int32 GetGameName(uint8 *name); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Palette functions - from palette.c +//----------------------------------------------------------------------------- +extern int32 SetPalette(int16 startEntry, int16 noEntries, uint8 *palette, uint8 setNow); +extern int32 UpdatePaletteMatchTable(uint8 *data); +extern uint8 QuickMatch(uint8 r, uint8 g, uint8 b); +extern int32 FadeUp(float time); +extern int32 FadeDown(float time); +extern uint8 GetFadeStatus(void); +extern int32 DimPalette(void); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Mouse functions - from mouse.c +//----------------------------------------------------------------------------- +extern _mouseEvent *MouseEvent(void); +extern int32 SetMouseAnim(uint8 *ma, int32 size, int32 mouseFlash); +extern int32 SetLuggageAnim(uint8 *la, int32 size); +extern int32 AnimateMouse(void); +uint8 CheckForMouseEvents(void);		// (James23july97) +extern void ResetRenderEngine(void); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Keyboard functions - from keyboard.c +//----------------------------------------------------------------------------- +extern BOOL  KeyWaiting(void); +extern int32 ReadKey(char *key); +extern void  GetKeyStatus(_drvKeyStatus *s); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Sprite functions - from sprite.c +//----------------------------------------------------------------------------- +extern int32 DrawSprite(_spriteInfo *s); +extern int32 CreateSurface(_spriteInfo *s, uint32 *surface); +extern int32 DrawSurface(_spriteInfo *s, uint32 surface); +extern int32 DeleteSurface(uint32 surface); +extern int32 OpenLightMask(_spriteInfo *s); +extern int32 CloseLightMask(void); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Screen drawing and scrolling function - from render.c +//----------------------------------------------------------------------------- +extern int32 SetScrollTarget(int16 sx, int16 sy); +extern int32 InitialiseRenderCycle(void); +extern int32 StartRenderCycle(void); +extern int32 EndRenderCycle(BOOL *end); +extern int32 RenderParallax(_parallax *p, int16 layer); +extern int32 SetLocationMetrics(uint16 w, uint16 h); +extern int32 CopyScreenBuffer(void); +extern int32 PlotPoint(uint16 x, uint16 y, uint8 colour); +extern int32 DrawLine(int16 x1, int16 y1, int16 x2, int16 y2, uint8 colour); +extern int32 InitialiseBackgroundLayer(_parallax *p); +extern int32 CloseBackgroundLayer(void); +extern int32 PlotDots(int16 x, int16 y, int16 count); +extern int32 EraseSoftwareScreenBuffer(void); +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +//	Menubar control and drawing functions - from menu.c +//----------------------------------------------------------------------------- +extern int32 ProcessMenu(void); +extern int32 ShowMenu(uint8 menu); +extern int32 HideMenu(uint8 menu); +extern int32 SetMenuIcon(uint8 menu, uint8 pocket, uint8 *icon); +extern uint8 GetMenuStatus(uint8 menu); +extern int32 CloseMenuImmediately(void); + + +//----------------------------------------------------------------------------- +//	Sound driver functions - from d_sound.c +//----------------------------------------------------------------------------- +extern int32 InitialiseSound(uint16 freq, uint16 channels, uint16 bitDepth); +extern int32 PlaySpeech(uint8 *data, uint8 vol, int8 pan); +extern int32 PlayCompSpeech(const char *filename, uint32 speechid, uint8 vol, int8 pan); +extern int32 PreFetchCompSpeech(const char *filename, uint32 speechid, uint8 *waveMem); +extern int32 GetCompSpeechSize(const char *filename, uint32 speechid); +extern int32 AmISpeaking(); +extern int32 StopSpeech(void); +extern int32 GetSpeechStatus(void); +extern int32 PauseSpeech(void); +extern int32 UnpauseSpeech(void); +extern int32 OpenFx(int32 id, uint8 *data); +extern int32 PlayFx(int32 id, uint8 *data, uint8 vol, int8 pan, uint8 type); +extern int32 CloseFx(int32 id); +extern int32 ClearAllFx(void); +extern int32 PauseFx(void); +extern int32 PauseFxForSequence(void); +extern int32 UnpauseFx(void); +extern int32 PauseMusic(void); +extern int32 UnpauseMusic(void); +extern int32 StreamMusic(uint8 *filename, int32 looping); +extern int32 StreamCompMusic(const char *filename,uint32 musicId, int32 looping); +extern int32 MusicTimeRemaining(); +extern int32 ReverseStereo(void); +extern uint8 GetFxVolume(void); +extern uint8 GetSpeechVolume(void); +extern uint8 GetMusicVolume(void); +extern uint8 IsMusicMute(void); +extern uint8 IsFxMute(void); +extern uint8 IsSpeechMute(void); +extern void  StopMusic(void); +extern void  GetSoundStatus(_drvSoundStatus *s); +extern void  SetSoundStatus(_drvSoundStatus *s); +extern void  SetFxVolume(uint8 vol); +extern void  SetSpeechVolume(uint8 vol); +extern void  SetMusicVolume(uint8 vol); +extern void  MuteMusic(uint8 mute); +extern void  MuteFx(uint8 mute); +extern void  MuteSpeech(uint8 mute); +extern int32 IsFxOpen(int32 id); +extern int32 SetFxVolumePan(int32 id, uint8 vol, int8 pan); +extern int32 SetFxIdVolume(int32 id, uint8 vol); + + +//----------------------------------------------------------------------------- +//	Misc functions - from misc.cpp +//----------------------------------------------------------------------------- +extern uint32 timeGetTime(void); +extern void VirtualUnlock(uint8 *free_memman, uint32 total_free_memory); +extern void GlobalMemoryStatus(MEMORYSTATUS *memo); +extern void SetFileAttributes(char *file, uint32 atrib); +extern void DeleteFile(char *file); +extern void GetCurrentDirectory(uint32 max, char* path); +extern int32 GetVolumeInformation(char *cdPath, char *sCDName, uint32 maxPath, uint8 *, DWORD *dwMaxCompLength, DWORD *dwFSFlags, uint8 *, uint32 a); +extern void _mkdir(const char *pathname); +extern void GetModuleFileName(void *module, char *destStr, uint32 maxLen); + +//----------------------------------------------------------------------------- +//Macro for calling error handler with source filename and line. +//----------------------------------------------------------------------------- +#define ReportDriverError(f) _ReportDriverError(f, (uint8 *) __FILE__, (uint32) __LINE__) +#define ReportFatalError(f) _ReportFatalError(f, (uint8 *) __FILE__, (uint32) __LINE__) +//----------------------------------------------------------------------------- + + + +//----------------------------------------------------------------------------- +// Macro for reporting a non-fatal driver error +//----------------------------------------------------------------------------- +#ifdef _DEBUG +static  int32	rderror; +#define Driver(f)							\ +	if (rderror = f)						\ +		ReportDriverError(rderror) +#else +#define Driver(f) f +#endif +//----------------------------------------------------------------------------- + + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +extern BOOL		gotTheFocus;		// set if the game is currently displayed +extern int16	screenWide;			// Width of the screen display +extern int16	screenDeep;			// Height of the screen display +extern int16	mousex;				// Mouse screen x coordinate +extern int16	mousey;				// Mouse screen y coordinate +extern int32	renderCaps;			// Flags which determine how to render the scene. +extern uint8	palCopy[256][4];	// Current palette. +//----------------------------------------------------------------------------- + +extern LARGE_INTEGER myTimers[10][2]; + + +#ifdef __cplusplus +} +#endif + + +#endif diff --git a/sword2/driver/keyboard.cpp b/sword2/driver/keyboard.cpp new file mode 100644 index 0000000000..6f9d51c997 --- /dev/null +++ b/sword2/driver/keyboard.cpp @@ -0,0 +1,129 @@ +/* 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	:	keyboard.c +//	Created		:	19th September 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This module holds the interface to the keyboard +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		19-Sep-96	PRP		Keyboard functions.  Simple logging of +//								previous 32 keys pressed. +// +//	1.1		19-Sep-96	PRP		Fixed bug, ReadKey did not return RD_OK. +// +//	1.2		13-Aug-97	PSJ		Added GetKeyStatus +// +//	Functions +//	--------- +// +//	-------------------------------------------------------------------------- +// +//  BOOL KeyWaiting(void) +// +//	This function returns TRUE if there is an unprocessed key waiting in the +//	queue, FALSE otherwise. +// +//	-------------------------------------------------------------------------- +// +//	int32 ReadKey(char *key) +// +//	Sets the value of key passed in to the current waiting key.  If there is +//	no key waiting, an error code is returned. +//	 +//	-------------------------------------------------------------------------- +// +//	void GetKeyStatus(_drvKeyStatus *s) +// +//	Retrieves the status of the keyboard handler. +//	 +//============================================================================= + + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> + +#include "driver96.h" + +#define MAX_KEY_BUFFER 23 + +uint8	keyBacklog = 0;				// The number of key presses waiting to be processed. +uint8	keyPointer = 0;				// Index of the next key to read from the buffer. +char    keyBuffer[MAX_KEY_BUFFER];	// The keyboard buffer + + + +void WriteKey(char key) +{ +	if (keyBuffer && keyBacklog < MAX_KEY_BUFFER) +	{ +		keyBuffer[(keyPointer + keyBacklog) % MAX_KEY_BUFFER] = key; +		keyBacklog += 1; +	} +} + + + +BOOL KeyWaiting(void) + +{ + +	if (keyBacklog) +		return(TRUE); +	else +		return(FALSE); + +} + + + +int32 ReadKey(char *key) + +{ +	if (!keyBacklog) +		return(RDERR_NOKEYWAITING); + +	if (key == NULL) +		return(RDERR_INVALIDPOINTER); + +	*key = keyBuffer[keyPointer++]; +	if (keyPointer == MAX_KEY_BUFFER) +		keyPointer = 0; + +	keyBacklog -= 1; + +	return(RD_OK); + +} + +void GetKeyStatus(_drvKeyStatus *s) + +{ +	// Flush key buffer +	s->pBacklog = &keyBacklog; +	s->pPointer = &keyPointer; +	s->pBuffer =  keyBuffer; +} + diff --git a/sword2/driver/keyboard.h b/sword2/driver/keyboard.h new file mode 100644 index 0000000000..56bfad7333 --- /dev/null +++ b/sword2/driver/keyboard.h @@ -0,0 +1,46 @@ +/* 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	:	keyboard.h +//	Created		:	19th September 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		19-Sep-96	PRP		Internal driver interface to the keyboard driver +//								functions and data. +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the keyboard.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef KEYBOARD_H +#define KEYBOARD_H + + +void WriteKey(char key);		// Adds a keypress to the buffer + +#endif diff --git a/sword2/driver/language.cpp b/sword2/driver/language.cpp new file mode 100644 index 0000000000..b20eb1508c --- /dev/null +++ b/sword2/driver/language.cpp @@ -0,0 +1,134 @@ +/* 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	:	language.c +//	Created		:	20th August 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This module holds the functions which govern which language +//					version is current. +// +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		16-Sep-96	PRP		Initial language version control functions. +//								Many of the functions are currently stubs, and +//								this will be addressed shortly. +// +// +//	Functions +//	--------- +// +//	-------------------------------------------------------------------------- +// +//	int32 GetLanguageVersion(uint8 *version) +// +//	This function modifies the 'version' passed in to be the current language. +//	The first time this function is called, it gets the language from the  +//	version.inf file distributed on the game CD.  It returns an RD error code +//	if this file cannot be opened, or the version cannot be obtained from it. +// +//	--------------------------------------------------------------------------- +//	 +//	int32 SetLanguageVersion(uint8 version) +// +//	This function is useful for debugging.  It sets the version to the one +//	passed in. +// +//	--------------------------------------------------------------------------- +//	 +//	int32 GetGameName(uint8 *name); +// +//	Fills the string pointed to by name with the title of the game, depending +//	upon what the current language version is. +// +//============================================================================= + + +#include "driver96.h" + + + +uint8 languageVersion = ENGLISH; + +static uint8 versionFromFile = 0; + + + + +int32 GetLanguageVersion(uint8 *version) + +{ + +	if (versionFromFile) +	{ +		*version = languageVersion; +	} +	else +	{ +		versionFromFile = 1; +		languageVersion = AMERICAN; +		return(RDERR_OPENVERSIONFILE); +	} +	return(RD_OK); + +} + + +int32 SetLanguageVersion(uint8 version) + +{ + +	languageVersion = version; +	return(RD_OK); + +} + + +int32 GetGameName(uint8 *name) + +{ + +	uint8 version; +	int32 rv; + + +	rv = GetLanguageVersion(&version); + +	switch(version) +	{ +	case ENGLISH: +		strcpy((char *)name, "Broken Sword II"); +		break; +	case AMERICAN: +		strcpy((char *)name, "Circle of Blood II"); +		break; +	case GERMAN: +		strcpy((char *)name, "Baphomet's Fluch II"); +		break; +	default: +		strcpy((char *)name, "Some game or other, part 86"); +		return(RDERR_INVALIDVERSION); +	} + +	return(rv); + +} diff --git a/sword2/driver/menu.cpp b/sword2/driver/menu.cpp new file mode 100644 index 0000000000..564e302375 --- /dev/null +++ b/sword2/driver/menu.cpp @@ -0,0 +1,570 @@ +/* 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	:	menu.c +//	Created		:	14th November 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This module holds the code for the driver96 menu system. +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		15-Nov-96	PRP		Initial Menu functions. +// +//	1.1		20-Nov-96	PRP		Fixed the displaying of the bottom menu. +// +//	1.2		08-Nov-96	PRP		Made the speed of the menubar dependent upon +//								the number of icons displayed. +// +//	1.3		24-Jan-97	PRP		Changed the creation of menu icon sprite  +//								surfaces depending upon whether the hardware +//								can stretch blit or not.  Also, made it so +//								that the full size icon sprite is not stretch +//								blitted. +// +//	1.4		10-Feb-97	PRP		Changed the creation of menu icon sprite +//								surfaces as the capability bits for the drivers +//								have been changed.  Also, changed the error +//								reporting code (for directDraw) so that it +//								works. +// +//	1.5		04-Mar-97	PRP		Tried to fix bug where running out of video  +//								memory creating menubar icon surfaces. +// +//	1.6		16-Apr-97	PRP		Got rid of bug where task switching causes +//								failure of icon draw. +// +//	1.7		23-Jul-97	PRP		Checked error value of stretched blit. +// +//	1.8		13-Aug-97	PRP		Added CloseMenuImmediately. +// +//	1.9		13-Aug-97	PRP		Fixed spelling of above +// +// +//	Functions +//	--------- +// +//	-------------------------------------------------------------------------- +// +//	int32 ProcessMenu(void) +// +//	This function should be called regularly to process the menuber system. +//	The rate at which this function is called will dictate how smooth the menu +//	system is.  The menu cannot be drawn at a higher rate than the system +//	vbl rate. +// +//	-------------------------------------------------------------------------- +// +//	int32 ShowMenu(uint8 menu) +// +//	This function brings the menu in to view.  The choice of top or bottom menu +//	is defined by the parameter menu being either RDMENU_TOP or RDMENU_BOTTOM. +//	An error code is returned if the menu is already shown. +// +//	-------------------------------------------------------------------------- +// +//	int32 HideMenu(uint8 menu) +// +//	This function hides the menu defined by the parameter menu.  If the menu is +//	already hidden, an error code is returned. +// +//	-------------------------------------------------------------------------- +// +//	int32 SetMenuIcon(uint8 menu, uint8 pocket, uint8 *icon) +// +//	This function sets a menubar icon to that passed in.  If icon is NULL, the +//	pocket is cleared, otherwise, that icon is placed into pocket.  The menu is +//	either RDMENU_TOP or RDMENU_BOTTOM.  Valid error codes include +//	RDERR_INVALIDPOCKET if the pocket number does not exist.  Initially, there +//	are 15 pockets. +// +//	-------------------------------------------------------------------------- +// +//	uint8 GetMenuStatus(uint8 menu) +// +//	This function returns the status of the menu passed in menu.  Return values +//	are RDMENU_OPENING, RDMENU_CLOSING, RDMENU_HIDDEN and RDMENU_SHOWN. +// +//============================================================================= + + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> +//#include <mmsystem.h> + +//#include "ddraw.h" + +#include "driver96.h" +#include "menu.h" +#include "d_draw.h" +#include "render.h" + + +#define MENUDEEP 40 +#define MAXMENUANIMS 8 + + + +static uint8 menuStatus[2] =  +{ +	RDMENU_HIDDEN, RDMENU_HIDDEN +}; + +static uint8 *icons[2][RDMENU_MAXPOCKETS] = +{ +	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  +	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; + +/* +static LPDIRECTDRAWSURFACE lpIconSurface[2][RDMENU_MAXPOCKETS] =  +{ +	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,  +	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL +}; +*/ + +static uint8 pocketStatus[2][RDMENU_MAXPOCKETS] = +{ +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  +	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static uint8 menuCounter[2]; +static uint8 lastIcon[2]; +static uint8 iconCount = 0; + + + + +int32 CreateIconSurface(uint8 menu, uint8 pocket) + +{ +	warning("stub CreatIconSurface( %d, %d )", menu, pocket); +/* + +	HRESULT			hr; +	DDSURFACEDESC	ddsd; + + +	//	Set up the direct draw surface for the icon. +	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_BLTSTRETCH) +		ddsd.ddsCaps.dwCaps |= DDSCAPS_VIDEOMEMORY; +	else +		ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; + +	ddsd.dwWidth = RDMENU_ICONWIDE; +	ddsd.dwHeight = RDMENU_ICONDEEP; +	hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &lpIconSurface[menu][pocket], NULL); +	if ((dxHalCaps & RDCAPS_BLTSTRETCH) && (hr == DDERR_OUTOFVIDEOMEMORY)) +	{ +		ddsd.ddsCaps.dwCaps &= (0xffffffff - DDSCAPS_VIDEOMEMORY); +		ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY; +		hr = IDirectDraw2_CreateSurface(lpDD2, &ddsd, &lpIconSurface[menu][pocket], NULL); +	} +	if (hr != DD_OK) +	{ +		DirectDrawError("Unable to create icon surface", hr); +		return(hr); +	} +*/ +	return(RD_OK); +} + +		 +		 +int32 LoadIconSurface(int32 menu, int32 pocket) + +{ +	warning("stub LoadIconSurface( %d, %d )"); +/* + +	uint8			*src, *dst; +	int32			i; +	HRESULT			hr; +	DDSURFACEDESC	ddsd; + + +	memset(&ddsd, 0, sizeof(DDSURFACEDESC)); +	ddsd.dwSize = sizeof(DDSURFACEDESC); + +	hr = IDirectDrawSurface2_Lock(lpIconSurface[menu][pocket], NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +	if (hr != DD_OK) +	{ +		IDirectDrawSurface2_Restore(lpIconSurface[menu][pocket]); +		hr = IDirectDrawSurface2_Lock(lpIconSurface[menu][pocket], NULL, &ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL); +		if (hr != DD_OK) +		{ +			DirectDrawError("Unable to lock icon surface", hr); +			return(hr); +		} +	} + +	src = icons[menu][pocket]; +	dst = ddsd.lpSurface; +	for (i=0; i<RDMENU_ICONDEEP; i++) +	{ +		memcpy(dst, src, RDMENU_ICONWIDE); +		src += RDMENU_ICONWIDE; +		dst += ddsd.lPitch; +	} + +	IDirectDrawSurface2_Unlock(lpIconSurface[menu][pocket], ddsd.lpSurface); +*/ +	return(RD_OK); + +} + + + + +int32 ProcessMenu(void) + +{ +	warning("stub ProcessMenu"); +/* + +	uint8	menu; +	uint8	i; +	uint8	complete; +	uint8	frameCount; +//	uint8	*src, *dst; +	int32	curx, xoff; +	int32	cury, yoff; +	HRESULT	hr; +	RECT	r; +	int32	delta; +	static	int32 lastTime = 0; + +	if (lastTime == 0) +	{ +		lastTime = timeGetTime(); +		frameCount = 1; +	} +	else +	{ +		delta = timeGetTime() - lastTime; +		if (delta > 250) +		{ +			lastTime += delta; +			delta = 250; +			frameCount = 1; +		} +		else +		{ +			frameCount = (uint8) ((iconCount+8) * delta / 750); +			lastTime += frameCount * 750 / (iconCount + 8); +		} + +	} + + + +	while (frameCount-- > 0) +	{ +		for (menu = RDMENU_TOP; menu <= RDMENU_BOTTOM; menu++) +		{ +			if (menuStatus[menu] == RDMENU_OPENING) +			{ +				//	The menu is opening, so process it here +				complete = 1; + +				//	Propagate the animation from the first icon. +				for (i=RDMENU_MAXPOCKETS-1; i>0; i--) +				{ +					pocketStatus[menu][i] = pocketStatus[menu][i-1]; +					if (pocketStatus[menu][i] != MAXMENUANIMS) +					{ +						complete = 0; +					} +				} +				if (pocketStatus[menu][i] != MAXMENUANIMS) +					complete = 0; + +				//	... and animate the first icon +				if (pocketStatus[menu][0] != MAXMENUANIMS) +					pocketStatus[menu][0] += 1; + +				//	Check to see if the menu is fully open +				if (complete) +				{ +					menuStatus[menu] = RDMENU_SHOWN; +				} +			} +			else if (menuStatus[menu] == RDMENU_CLOSING) +			{ +				//	The menu is closing, so process it here +				complete = 1; + +				//	Propagate the animation from the first icon. +				for (i=RDMENU_MAXPOCKETS-1; i>0; i--) +				{ +					pocketStatus[menu][i] = pocketStatus[menu][i-1]; +					if (pocketStatus[menu][i] != 0) +					{ +						complete = 0; +					} +				} +				if (pocketStatus[menu][i] != 0) +					complete = 0; + +				//	... and animate the first icon +				if (pocketStatus[menu][0] != 0) +					pocketStatus[menu][0] -= 1; + +				//	Check to see if the menu is fully open +				if (complete) +				{ +					menuStatus[menu] = RDMENU_HIDDEN; +				} +			} +		} + +	} +	 +	//	Does the menu need to be drawn? +	for (menu = RDMENU_TOP; menu <= RDMENU_BOTTOM; menu++) +	{ +		if (menuStatus[menu] != RDMENU_HIDDEN) +		{ +			//	Draw the menu here. +			curx = RDMENU_ICONSTART + RDMENU_ICONWIDE / 2; +			cury = (MENUDEEP / 2) + (RENDERDEEP + MENUDEEP) * menu; + +			for (i=0; i<RDMENU_MAXPOCKETS; i++) +			{ +				if (lpIconSurface[menu][i]) +				{ +					if (pocketStatus[menu][i] == MAXMENUANIMS) +					{ +						xoff = (RDMENU_ICONWIDE / 2); +						r.left = curx - xoff; +						r.right = r.left + RDMENU_ICONWIDE; +						yoff = (RDMENU_ICONDEEP / 2); +						r.top = cury - yoff; +						r.bottom = r.top + RDMENU_ICONDEEP; +					} +					else +					{ +						xoff = (RDMENU_ICONWIDE / 2) * pocketStatus[menu][i] / MAXMENUANIMS; +						r.left = curx - xoff; +						r.right = curx + xoff; +						yoff = (RDMENU_ICONDEEP / 2) * pocketStatus[menu][i] / MAXMENUANIMS; +						r.top = cury - yoff; +						r.bottom = cury + yoff; +					} + +					if ((xoff != 0) && (yoff != 0)) +					{ +						hr = IDirectDrawSurface2_Blt(lpBackBuffer, &r, lpIconSurface[menu][i], NULL, DDBLT_WAIT, NULL); +						if (hr != DD_OK) +						{ +							switch (hr) +							{ +							case DDERR_GENERIC : +								hr = 0; +								break; +							case DDERR_INVALIDCLIPLIST : +								hr = 0; +								break; +							case DDERR_INVALIDOBJECT : +								hr = 0; +								break; +							case DDERR_INVALIDPARAMS : +								hr = 0; +								break; +							case DDERR_INVALIDRECT : +								hr = 0; +								break; +							case DDERR_NOALPHAHW : +								hr = 0; +								break; +							case DDERR_NOBLTHW : +								hr = 0; +								break; +							case DDERR_NOCLIPLIST : +								hr = 0; +								break; +							case DDERR_NODDROPSHW : +								hr = 0; +								break; +							case DDERR_NOMIRRORHW : +								hr = 0; +								break; +							case DDERR_NORASTEROPHW : +								hr = 0; +								break; +							case DDERR_NOROTATIONHW : +								hr = 0; +								break; +							case DDERR_NOSTRETCHHW : +								hr = 0; +								break; +							case DDERR_NOZBUFFERHW : +								hr = 0; +								break; +							case DDERR_SURFACEBUSY : +								hr = 0; +								break; +							case DDERR_SURFACELOST : +								hr = 0; +								break; +							case DDERR_UNSUPPORTED : +								hr = 0; +								break; +							default: //shit +								hr = 0; +								break; +							} +	//							if (hr == DDERR_INVALIDOBJECT) +	//							{ +								CreateIconSurface(menu, i); +								LoadIconSurface(menu, i); +								hr = IDirectDrawSurface2_Blt(lpBackBuffer, &r, lpIconSurface[menu][i], NULL, DDBLT_WAIT, NULL); +	//							} +							if (hr != DD_OK) +							{ +								if (hr != DDERR_SURFACELOST) +								{ +									DirectDrawError("Unable to blt icon", hr); +									return(hr); +								} +							} +						} +					} +				} +				curx += (RDMENU_ICONSPACING + RDMENU_ICONWIDE); +			} +		} +	} +*/ +} + + +int32 ShowMenu(uint8 menu) + +{ + +	//	Check for invalid menu parameter +	if (menu > RDMENU_BOTTOM) +		return(RDERR_INVALIDMENU); + +	//	Check that the menu is not currently shown, or in the process of being shown. +	if ((menuStatus[menu] == RDMENU_SHOWN) || (menuStatus[menu] == RDMENU_OPENING)) +		return(RDERR_INVALIDCOMMAND); + +	menuStatus[menu] = RDMENU_OPENING; + +} + + +int32 HideMenu(uint8 menu) + +{ + +	//	Check for invalid menu parameter +	if (menu > RDMENU_BOTTOM) +		return(RDERR_INVALIDMENU); + +	//	Check that the menu is not currently hidden, or in the process of being hidden. +	if ((menuStatus[menu] == RDMENU_HIDDEN) || (menuStatus[menu] == RDMENU_CLOSING)) +		return(RDERR_INVALIDCOMMAND); + +	menuStatus[menu] = RDMENU_CLOSING; + +} + + +int32 CloseMenuImmediately(void) +{ +	menuStatus[0] = RDMENU_HIDDEN; +	menuStatus[1] = RDMENU_HIDDEN; +	memset(pocketStatus, 0, sizeof(uint8) * 2 * RDMENU_MAXPOCKETS); +	return (RD_OK); +} + +int32 SetMenuIcon(uint8 menu, uint8 pocket, uint8 *icon) + +{ +	warning("stub SetMenuIcon( %d, %d )", menu, pocket); +/* + +	HRESULT			hr; + + +	//	Check for invalid menu parameter. +	if (menu > RDMENU_BOTTOM) +		return(RDERR_INVALIDMENU); +	 +	//	Check for invalid pocket parameter +	if (pocket >= RDMENU_MAXPOCKETS) +		return(RDERR_INVALIDPOCKET); + +	//	If there is an icon in the requested menu/pocket, clear it out. +	if (icons[menu][pocket]) +	{ +		iconCount--; +		free(icons[menu][pocket]); +		icons[menu][pocket] = NULL; +		IDirectDrawSurface2_Release(lpIconSurface[menu][pocket]); +		lpIconSurface[menu][pocket] = NULL; +	} + +	//	Only put the icon in the pocket if it is not NULL +	if (icon != NULL) +	{ +		iconCount++; +		icons[menu][pocket] = (uint8 *) malloc(RDMENU_ICONWIDE * RDMENU_ICONDEEP); +		if (icons[menu][pocket] == NULL) +			return(RDERR_OUTOFMEMORY); +		memcpy(icons[menu][pocket], icon, RDMENU_ICONWIDE * RDMENU_ICONDEEP); + +		hr = CreateIconSurface(menu, pocket); +		if (hr != DD_OK) +			return(hr); + +		hr = LoadIconSurface(menu, pocket); +		if (hr != RD_OK) +			return(hr); +	} +*/ +} + + +uint8 GetMenuStatus(uint8 menu) + +{ + +	if (menu > RDMENU_BOTTOM) +		return(RDMENU_HIDDEN); + +	return(menuStatus[menu]); + +} + + + diff --git a/sword2/driver/menu.h b/sword2/driver/menu.h new file mode 100644 index 0000000000..de0830030e --- /dev/null +++ b/sword2/driver/menu.h @@ -0,0 +1,47 @@ +/* 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	:	menu.h +//	Created		:	15th November 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		15-Nov-96	PRP		Internal driver interface to the menu driver +//								functions and data. +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the menu.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef MENU_H +#define MENU_H + + +#define MENUDEEP 40 + +#endif + diff --git a/sword2/driver/misc.cpp b/sword2/driver/misc.cpp new file mode 100644 index 0000000000..ce7ea76020 --- /dev/null +++ b/sword2/driver/misc.cpp @@ -0,0 +1,62 @@ +/* Copyright (C) 2003 The ScummVM project + * + * 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$ + */ + +#include "driver96.h" +#include "../sword2.h" + +uint32 timeGetTime(void) { +	return g_bs2->_syst->get_msecs(); +} + +void VirtualUnlock(uint8 *free_memman, uint32 total_free_memory) { +	warning("stub VirtualUnlock"); +} + +void GlobalMemoryStatus(MEMORYSTATUS *memo) { +	warning("stub GlobalMemoryStatus"); +	memo->dwTotalPhys = 16000*1024; // hard code 16mb for now +} + +void SetFileAttributes(char *file, uint32 atrib) { +	warning("stub SetFileAttributes"); +} + +void DeleteFile(char *file) { +	warning("stub DeleteFile"); +} + +void GetCurrentDirectory(uint32 max, char* path) { +	warning("stub GetCurrentDirectory"); +} + +int32 GetVolumeInformation(char *cdPath, char *sCDName, uint32 maxPath, uint8 *, DWORD *dwMaxCompLength, DWORD *dwFSFlags, uint8 *, uint32 a) { +	warning("stub GetVolumeInformation %s", cdPath); +	strcpy(sCDName, CD1_LABEL); +	return 1; +} + +// FIXME wrap different platform specific mkdir calls and actually do something +void _mkdir(const char *pathname) { +	warning("stub _mkdir %s", pathname); +} + +void GetModuleFileName(void *module, char *destStr, uint32 maxLen) { +	warning("stub GetModuleFileName"); +} + diff --git a/sword2/driver/palette.cpp b/sword2/driver/palette.cpp new file mode 100644 index 0000000000..5847cfff6b --- /dev/null +++ b/sword2/driver/palette.cpp @@ -0,0 +1,482 @@ +/* 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	:	palette.c +//	Created		:	22nd August 1996 +//	By			:	P.R.Porter +// +//	Summary		:	This module holds the palette functions and the interface +//					to the directDraw palette. +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		16-Sep-96	PRP		Currently holds the palette setting code.  Will +//								be modified so that the calling functions have +//								to use the correct palette format, and the +//								fading code will be added. +// +//	1.1		17-Sep-96	PRP		Removed utypes.h from include list. +// +//	1.2		03-Oct-96	PRP		Changed the palette format to RGBA 0-255. +// +//	1.3		04-Oct-96	PRP		No changes +// +//	1.4		04-Oct-96	PRP		Put direct path in for ddraw.h +// +//	1.5		08-Nov-96	PRP		Created a drivers copy of the palette so that +//								it can be restored at any time without the +//								game engine having to worry about things. +//								Currently, there is different code for setting +//								the palette in full screen and windowed mode +//								until I can get windowed mode working. +// +//	1.6		09-Nov-96	PRP		More work to get the palette to work propery +//								in windowed mode. +// +//	1.7		22-Nov-96	PRP		Made the whole of the palette available to  +//								the rest of the driver96 code. +// +//	1.8		25-Nov-96	PRP		Added a function to create a palette match +//								table from the current palette. +// +//	1.9		29-Nov-96	PRP		Made the QuickMatch function __inline for +//								speed - but didn't work.  Added functions +//								to fade the palette up and down. +// +//	1.10	05-Dec-96	PRP		Added a flag to SetPalette so that the palette +//								can be set immediately or later by the fade. +// +//	1.11	06-Dec-96	JEL		fadeStatus now initialised to 0 +// +//	1.12	09-Dec-96	PRP		Function UpdatePaletteMatchTable() changed so +//								that the data can be part of another file. +// +//	1.13	10-Feb-97	PRP		Changed the direct draw error reporting calls. +// +//	1.14	11-Feb-97	PRP		Suspended the fade server if the direct draw +//								palette object does not exist. +// +//	1.15	17-Mar-97	PRP		Added RDFADE_BLACK as a return value so the +//								engine knows the state of the palette when +//								there is no fade. +// +//	1.16	17-Mar-97	PRP		Fixed driver bug which caused FadeUp to fail +//								becuase of the introduction of RDFADE_BLACK. +// +//	1.17	26-Jun-97	PRP		Added a function to darken the palette for pausing. +// +//	1.18	26-Jun-97	PRP		Forgot to return a value. +// +//	1.19	26-Jun-97	PRP		Forgot to set the palette - DOH! +// +//	1.20	26-Jun-97	PRP		Fixed undefined symbols bugs. +// +//	1.21	09-Jul-97	JEL		Fixed palette dimming - to unsigned rather than signed RGB values! +// +//	1.22	26-Jun-97	JEL		SetPalette now always sets colour 0 to black so doesn't need setting to black from game engine +// +//	1.23	10-Jul-97	JEL		Nothing changed but new version had to be booked in anyway. +// +//	1.24	10-Jul-97	JEL		SetPalette doesn't do that any more (see above)! +// +//	Functions +//	--------- +// +//	-------------------------------------------------------------------------- +// +//	void SetPalette(int32 startEntry, int32 noEntries, uint8 *colourTable) +// +//	Sets the palette from position startEntry for noEntries, to the data  +//	pointed to by colourTable. +// +//	-------------------------------------------------------------------------- +// +//	void UpdatePaletteMatchTable(uint8 *data) +// +//	Uses the current palCopy to create a table of palette indeces which will +//	be searched later for a quick palette match, if data is NULL.  Otherwise +//	it uses the table passed in. +// +//	-------------------------------------------------------------------------- +// +//	uint8 QuickMatch(uint8 r, uint8 g, uint8 b) +// +//	Returns the palette index of the closest matching colour in the palette +//	to these RGB values. +// +//	-------------------------------------------------------------------------- +// +//	int32 FadeUp(float time) +// +//	Fades the palette up from black to the current palette in time. +// +//	-------------------------------------------------------------------------- +// +//	int32 FadeDown(float time) +// +//	Fades the palette down to black from the current palette in time. +// +//	-------------------------------------------------------------------------- +// +//	uint8 GetFadeStatus(void) +// +//	Returns the fade status which can be one of RDFADE_UP, RDFADE_DOWN or +//	RDFADE_NONE. +// +//============================================================================= + + +#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" + +#define PALTABLESIZE 64*64*64 + + +uint8 palCopy[256][4]; +uint8 fadePalette[256][4]; + +uint8 paletteMatch[PALTABLESIZE]; + +uint8 fadeStatus=0; + +static int32 fadeStartTime; +static int32 fadeTotalTime; + + +//	-------------------------------------------------------------------------- +//	int32 RestorePalette(void) +// +//	This function restores the palette, and should be called whenever the +//	screen mode changes, or something like that. +//	-------------------------------------------------------------------------- +int32 RestorePalette(void) + +{ +	warning("stub RestorePalette"); +/* +	int32 hr; + +	 +	if (bFullScreen) +		hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 0, 256, (LPPALETTEENTRY) &palCopy[0][0]); +	else +		hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 10, 236, (LPPALETTEENTRY) &palCopy[10][0]); + +	if (hr != DD_OK) +	{ +		DirectDrawError("Unable to restore palette", hr); +		return(hr); +	} + +*/ +	return(RD_OK); + +} + + +uint8 GetMatch(uint8 r, uint8 g, uint8 b) + +{ + +	int32 diff; +	int32 min; +	int16 diffred, diffgreen, diffblue; +	int16 i; +	uint8 minIndex; + + +	diffred = palCopy[0][0] - r; +	diffgreen = palCopy[0][1] - g; +	diffblue = palCopy[0][2] - b; + +	diff = diffred * diffred + diffgreen * diffgreen + diffblue * diffblue; +	min = diff; +	minIndex = 0; +	if (diff > 0) +	{ +		i = 1; +		while (i < 256) +		{ +			diffred = palCopy[i][0] - r; +			diffgreen = palCopy[i][1] - g; +			diffblue = palCopy[i][2] - b; + +			diff = diffred * diffred + diffgreen * diffgreen + diffblue * diffblue; +			if (diff < min) +			{ +				min = diff; +				minIndex = (uint8) i; +				if (min == 0) +					break; +			} +			i += 1; +		} +	} + +	// Here, minIndex is the index of the matchpalette which is closest. +	return(minIndex); + +} + + + +int32 UpdatePaletteMatchTable(uint8 *data) + +{ + +	if (data == NULL) + +	// Create palette match table +	{ +		FILE *fp; +		int16 red, green, blue; +		uint8 *p; + +		p = &paletteMatch[0]; +		for (red = 0; red < 256; red += 4) +		{ +			for (green = 0; green < 256; green += 4) +			{ +				for (blue = 0; blue < 256; blue += 4) +				{ +					*p++ = GetMatch((uint8) red, (uint8) green, (uint8) blue); +				} +			} +		} + +		// Write out palette match table +		fp = fopen("r11.rgb", "wb"); +		if (fp == NULL) +			return(RDERR_INVALIDFILENAME); +		if (fwrite(paletteMatch, 1, 64*64*64, fp) != 64*64*64) +			return(RDERR_WRITEERROR); +		fclose(fp); +	} +	else +	// Read table from file +	{ + +		memcpy(paletteMatch, data, PALTABLESIZE); +	 +/* +		FILE *fp; + +		fp = fopen(filename, "rb"); +		if (fp == NULL) +			return(RDERR_INVALIDFILENAME); +		if (fread(paletteMatch, 1, 64*64*64, fp) != 64*64*64) +			return(RDERR_READERROR); +		fclose(fp); +		return(RD_OK); +*/		 +	} +	return(RD_OK); + +} + + + +__inline uint8 QuickMatch(uint8 r, uint8 g, uint8 b) + +{ +	return(paletteMatch[((int32) (r >> 2) << 12) + ((int32) (g >> 2) << 6) + (b >> 2)]); +} + + + + +int32 SetPalette(int16 startEntry, int16 noEntries, uint8 *colourTable, uint8 fadeNow) + +{ +	warning("stub SetPalette( %d, %d, %d )", startEntry, noEntries, fadeNow); +/* + +	int32 hr; + +	if (noEntries == 0) +	{ +		RestorePalette(); +		return(RD_OK); +	} + + +	memcpy(&palCopy[startEntry][0], colourTable, noEntries * 4); + +	if ((lpPalette) && (fadeNow == RDPAL_INSTANT)) +	{ +		if (bFullScreen) +			hr = IDirectDrawPalette_SetEntries(lpPalette, 0, startEntry, noEntries, (LPPALETTEENTRY) &palCopy[startEntry][0]); +		else +			hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 10, 236, (LPPALETTEENTRY) &palCopy[10][0]); +		if (hr != DD_OK) +		{ +			DirectDrawError("Unable to set palette entries", hr); +			return(hr); +		} +	} +*/ +	return(RD_OK); + +} + + +int32 DimPalette(void) +{ +	warning("stub DimpPalette"); +/* +	uint8 *p; +	uint32 i; + +	p = (uint8*) &palCopy[0][0]; +	for (i=0; i<256*4; i++) +	{ +		*p++ /= 2; +	} +	if (lpPalette) +		IDirectDrawPalette_SetEntries(lpPalette, 0, 0, 256, (LPPALETTEENTRY) &palCopy[0][0]); +*/ +	return RD_OK; + +} + + + +int32 FadeUp(float time) + +{ + +	if ((fadeStatus != RDFADE_BLACK) && (fadeStatus != RDFADE_NONE)) +		return(RDERR_FADEINCOMPLETE); + +	fadeTotalTime = (int32) (time * 1000); +	fadeStatus = RDFADE_UP; +	fadeStartTime = timeGetTime(); + +} + + +int32 FadeDown(float time) + +{ + +	if ((fadeStatus != RDFADE_BLACK) && (fadeStatus != RDFADE_NONE)) +		return(RDERR_FADEINCOMPLETE); + +	fadeTotalTime = (int32) (time * 1000); +	fadeStatus = RDFADE_DOWN; +	fadeStartTime = timeGetTime(); + +} + + +uint8 GetFadeStatus(void) +{ +	return(fadeStatus); +} + + +void FadeServer(void) + +{ +	warning("stub FadeServer"); +/* +	int32 currentTime; +	int16 fadeMultiplier; +	int16 i; +	HRESULT hr; + + +	if (lpPalette == NULL) +		return; + +	if (fadeStatus) +	{ +		if (fadeStatus == RDFADE_UP) +		{ +			currentTime = timeGetTime(); +			if (currentTime >= fadeStartTime + fadeTotalTime) +			{ +				fadeStatus = RDFADE_NONE; +				if (bFullScreen) +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 0, 256, (LPPALETTEENTRY) &palCopy[0][0]); +				else +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 10, 236, (LPPALETTEENTRY) &palCopy[10][0]); +			} +			else +			{ +				fadeMultiplier = (int16) (((int32) (currentTime - fadeStartTime) * 256) / fadeTotalTime); +				for (i=0; i<256; i++) +				{ +					fadePalette[i][0] = (palCopy[i][0] * fadeMultiplier) >> 8; +					fadePalette[i][1] = (palCopy[i][1] * fadeMultiplier) >> 8; +					fadePalette[i][2] = (palCopy[i][2] * fadeMultiplier) >> 8; +				} +				if (bFullScreen) +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 0, 256, (LPPALETTEENTRY) &fadePalette[0][0]); +				else +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 10, 236, (LPPALETTEENTRY) &fadePalette[10][0]); +			} +		} +		else if (fadeStatus == RDFADE_DOWN) +		{ +			currentTime = timeGetTime(); +			if (currentTime >= fadeStartTime + fadeTotalTime) +			{ +				for (i=0; i<256; i++) +				{ +					fadePalette[i][0] = 0; +					fadePalette[i][1] = 0; +					fadePalette[i][2] = 0; +				} +				fadeStatus = RDFADE_BLACK; +				if (bFullScreen) +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 0, 256, (LPPALETTEENTRY) &fadePalette[0][0]); +				else +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 10, 236, (LPPALETTEENTRY) &fadePalette[10][0]); +			} +			else +			{ +				fadeMultiplier = (int16) (((int32) (fadeTotalTime - (currentTime - fadeStartTime)) * 256) / fadeTotalTime); +				for (i=0; i<256; i++) +				{ +					fadePalette[i][0] = (palCopy[i][0] * fadeMultiplier) >> 8; +					fadePalette[i][1] = (palCopy[i][1] * fadeMultiplier) >> 8; +					fadePalette[i][2] = (palCopy[i][2] * fadeMultiplier) >> 8; +				} +				if (bFullScreen) +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 0, 256, (LPPALETTEENTRY) &fadePalette[0][0]); +				else +					hr = IDirectDrawPalette_SetEntries(lpPalette, 0, 10, 236, (LPPALETTEENTRY) &fadePalette[10][0]); +			} +		} +	} +*/ +} + diff --git a/sword2/driver/palette.h b/sword2/driver/palette.h new file mode 100644 index 0000000000..3e26bd89a2 --- /dev/null +++ b/sword2/driver/palette.h @@ -0,0 +1,66 @@ +/* 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	:	palette.h +//	Created		:	8th November 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		08-Nov-96	PRP		Internal driver interface to the palette +//								functions and data. +// +//	1.1		11-Nov-96	PRP		Added internal driver reference for +//								RestorePalette which should be called by the +//								windows message handler whenever the window +//								has been minimised/maximised. +// +//	1.2		22-Nov-96	PRP		Made the palette available to the rest of the +//								driver96 library. +// +//	1.3		29-Nov-96	PRP		Made paletteMatch table available to other +//								parts of the driver library.  Also, made the +//								FadeServer available for the windows module +//								to have access. +// +//	1.4		11-Apr-97	CJR		Moved palCopy to driver96.h for use in the +//								game engine. +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the palette.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef PALETTE_H +#define PALETTE_H + +extern uint8 paletteMatch[64*64*64]; + +extern int32 RestorePalette(void); +extern void FadeServer(void); + + +#endif + diff --git a/sword2/driver/rdwin.cpp b/sword2/driver/rdwin.cpp new file mode 100644 index 0000000000..f945b3ca14 --- /dev/null +++ b/sword2/driver/rdwin.cpp @@ -0,0 +1,627 @@ +/* Copyright (C) 1994-2003 Revolution Software Ltd + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. + * + * $Header$ + */ + +#define WIN32_LEAN_AND_MEAN + +//#include <windows.h> +//#include <windowsx.h> +#include <stdio.h> + +#include "common/stdafx.h" +#include "engine.h" + +#include "driver96.h" + +#include "_mouse.h" +#include "keyboard.h" +#include "rdwin.h" +#include "d_draw.h" +#include "palette.h" +#include "render.h" +#include "menu.h" +#include "d_sound.h" +#include "../sword2.h" + + +#define MENUDEEP 40		// Temporary, until menu.h is written! + + + +static BOOL		bMouseVisible = FALSE; +static BOOL		controlKey = FALSE; +static BOOL		altKey = FALSE; +static BOOL		wasScreenSaverActive = FALSE; +static BOOL		myAppClosed = FALSE; +static BOOL		controlQDisabled = FALSE; +static uint8	gameName[80]; + + +//BOOL			gotTheFocus = FALSE; +//assume we always have focus for the time being - khalek +BOOL			gotTheFocus = TRUE;  +//HWND			hwnd; +//RECT			rcWindow; + + + +//----------------------------------------------------------------------------- + +void Zdebug(char *format,...) { +#ifdef __PALM_OS__ +	char buf[256]; // 1024 is too big overflow the stack +#else +	char buf[1024]; +#endif +	va_list va; + +	va_start(va, format); +	vsprintf(buf, format, va); +	va_end(va); + +#ifdef __GP32__ //ph0x FIXME: implement fprint? +	printf("ZDEBUG: %s\n", buf); +#else +	fprintf(stderr, "ZDEBUG: %s!\n", buf); +#endif +#if defined( USE_WINDBG ) +	strcat(buf, "\n"); +#if defined( _WIN32_WCE ) +	TCHAR buf_unicode[1024]; +	MultiByteToWideChar(CP_ACP, 0, buf, strlen(buf) + 1, buf_unicode, sizeof(buf_unicode)); +	OutputDebugString(buf_unicode); +#else +	OutputDebugString(buf); +#endif +#endif +} + +/* +void Zdebug(char *format,...)	//Tony's special debug logging file March96 +{ +	warning("stub Zdebug"); +//	Write a printf type string to a debug file + +	va_list		arg_ptr;			// Variable argument pointer +	FILE *		debug_filep=0;			// Debug file pointer +	static int	first_debug = 1;		// Flag for first time this is used + +	va_start(arg_ptr,format); + +	if (first_debug)					//First time round delete any previous debug file +	{ +		unlink("debug.txt"); +		first_debug = 0; +	} + +	debug_filep = fopen("debug.txt","a+t"); + +	if (debug_filep != NULL)	// if it could be opened +	{ +		vfprintf(debug_filep, format, arg_ptr); +		fprintf(debug_filep,"\n"); + +		fclose(debug_filep); +	} +} +*/ +//----------------------------------------------------------------------------- + +/* +void Message(LPSTR fmt, ...) +{ +    char	buff[256]; +    va_list	va; + +     +	va_start(va, fmt); + +    // +    // format message with header +    // +    lstrcpy( buff, "DRIVER96:" ); +    wvsprintf( &buff[lstrlen(buff)], fmt, va ); +    lstrcat( buff, "\r\n" ); + +    // +    // To the debugger +    // +    OutputDebugString( buff ); + +} +*/ + +//----------------------------------------------------------------------------- +//	OSystem Event Handler. Full of cross platform goodness and 99% fat free! +//----------------------------------------------------------------------------- +void BS2State::parseEvents() { +	OSystem::Event event; +	 +	while (_system->poll_event(&event)) { +		switch(event.event_code) { +		 +		case OSystem::EVENT_KEYDOWN: +			Zdebug("key %d", event.kbd.keycode); + +			if (event.kbd.flags==OSystem::KBD_CTRL) { +				if (event.kbd.keycode == 'w') +					GrabScreenShot(); +			} +			WriteKey(event.kbd.keycode); + +			break; +		case OSystem::EVENT_MOUSEMOVE: +			mousex = event.mouse.x; +			mousey = event.mouse.y; +			_syst->set_mouse_pos(event.mouse.x, event.mouse.y); +			break; +		case OSystem::EVENT_LBUTTONDOWN: +			LogMouseEvent(RD_LEFTBUTTONDOWN); +			break; +		case OSystem::EVENT_RBUTTONDOWN: +			LogMouseEvent(RD_RIGHTBUTTONDOWN); +			break; +		case OSystem::EVENT_LBUTTONUP: +			LogMouseEvent(RD_LEFTBUTTONUP); +			break; +		case OSystem::EVENT_RBUTTONUP: +			LogMouseEvent(RD_RIGHTBUTTONUP); +			break; +		case OSystem::EVENT_QUIT: +			Close_game(); +			RestoreDisplay(); +			CloseAppWindow(); +			break; +		default: +			break; +		} +	} +		 +} + + +//----------------------------------------------------------------------------- +//	Windows Message Handler.  All keyboard and mouse input is handled here. +//----------------------------------------------------------------------------- +/* +long FAR PASCAL WindowsMessageHandler(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam ) +{ + +	switch( message ) +	{ + + +	case WM_TIMER: +		switch (wParam) +		{ +		case 25: +			FadeServer(); +			return(0); +		case 1: +			FxServer(); +			return(0); +		} +		break; +		 + +    case WM_CLOSE: +		Zdebug("WM_CLOSE"); +		break; + +    case WM_SIZE: +    case WM_MOVE: +        if (IsIconic(hwnd)) +        { +            Message("minimising"); +//            PauseGame(); +        } + +        if (bFullScreen) +        { +            SetRect(&rcWindow, 0, 0, GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); +        } +        else +        { +            GetClientRect(hwnd, &rcWindow); +            ClientToScreen(hwnd, (LPPOINT)&rcWindow); +            ClientToScreen(hwnd, (LPPOINT)&rcWindow+1); +        } +        Message("WINDOW RECT: [%d,%d,%d,%d]", rcWindow.left, rcWindow.top, rcWindow.right, rcWindow.bottom); +		if (bFullScreen) +		{ +			SetCapture(hwnd); +		} +		else +		{ +			ReleaseCapture(); +		} +//		SetCursor(NULL); +//		ShowCursor(FALSE); +        break; + + + +	case WM_ACTIVATEAPP: +		gotTheFocus = wParam; +		if (gotTheFocus) +		{ +			Message("Got the focus"); +			bMouseVisible = FALSE; +			Message("Mouse invisible"); +			ShowCursor(FALSE); +		} +		else +		{ +			if (bMouseVisible == FALSE) +				ShowCursor(TRUE); +			Message("Lost the focus"); +			bMouseVisible = TRUE; +			Message("Mouse visible"); +		} +		break; + + +    case WM_SYSKEYUP: +        switch( wParam ) +        { + +//			int32 rv; + +        // handle ALT+ENTER (fullscreen) +        case VK_RETURN: +			break; +        } +        break; +  + +	case WM_DISPLAYCHANGE: +		break; + +	case WM_CREATE: +		SystemParametersInfo(SPI_GETSCREENSAVEACTIVE , 0 , &wasScreenSaverActive , 0); +		if (wasScreenSaverActive) +		{ +			SystemParametersInfo(SPI_SETSCREENSAVEACTIVE , FALSE , 0 , 0 ); +		} +    	break; + + +    case WM_QUERYNEWPALETTE: +        // +        //  we are getting the palette focus, select our palette +        // +        if (!bFullScreen && lpPalette && lpPrimarySurface) +        { +			int32 hr; + +            hr = IDirectDrawSurface_SetPalette(lpPrimarySurface, lpPalette); +            if (hr == DDERR_SURFACELOST) +            { +                IDirectDrawSurface_Restore(lpPrimarySurface); + +                hr= IDirectDrawSurface_SetPalette(lpPrimarySurface, lpPalette); +                if(hr == DDERR_SURFACELOST) +                { +                   Message("Failed to restore palette after second try"); +                } +            } + +            // +            // Restore normal title if palette is ours +            // +            if(hr == DD_OK) +            { +                SetWindowText(hwnd, gameName); +            } +        } +        break; + +    case WM_PALETTECHANGED: +        // +        //  if another app changed the palette we dont have full control +        //  of the palette. NOTE this only applies for FoxBear in a window +        //  when we are fullscreen we get all the palette all of the time. +        // +        if ((HWND)wParam != hwnd) +        { +            if( !bFullScreen ) +            { +				Message("Lost palette but continuing"); +            } +        } +        break; + + +//    case WM_SETCURSOR: +//		if (bMouseVisible) +//			SetCursor(LoadCursor(NULL, IDC_ARROW)); +//		else +//			SetCursor(NULL); +//	    return TRUE; +//		break; + +	case WM_CHAR: +		if (lParam & (1 << 30)) +			return(0); +		WriteKey((char) (wParam & 0xff)); +		return(0); + +    case WM_KEYDOWN: + +		Zdebug("key %d", wParam); + +		switch( wParam ) +		{ +			case VK_CONTROL: +				controlKey = TRUE; +				break; + +//			case VK_ALT: +//				altKey = TRUE; +//				break; + +			case 'W': +				if (controlKey) +					GrabScreenShot(); +				return 0; + +			case 'Q': +				if (controlKey && !controlQDisabled) +					DestroyWindow( hWnd ); +  				return 0; + +			case 'F4': +				DestroyWindow( hWnd ); +  				return 0; + +        } +      	break; + + +	case WM_KEYUP: +		switch(wParam) +		{ +			case VK_CONTROL: +				controlKey = FALSE; +				break; + +//			case VK_ALT: +//				altKey = FALSE; +//				break; + +		} +	    break; + + +    case WM_DESTROY: +		Zdebug("*destroy*"); + +		if (wasScreenSaverActive) +			SystemParametersInfo(SPI_SETSCREENSAVEACTIVE , TRUE , 0 , 0 ); +        PostQuitMessage( 0 ); +        break; + + +	case WM_MOUSEMOVE: +		mousex = lParam & 0xffff; + +		if (bFullScreen) +		{ +			mousey = (uint16) (lParam >> 16) - MENUDEEP; +		} +		else +		{ +			mousey = (uint16) (lParam >> 16) - MENUDEEP; + +			if (mousex < 0) +				mousex = 0; +			if (mousex >= RENDERWIDE) +				mousex = RENDERWIDE-1; +		} + +		if (mousey < -MENUDEEP) +			mousey = -MENUDEEP; +		if (mousey >= RENDERDEEP + MENUDEEP) +			mousey = RENDERDEEP + MENUDEEP - 1; + +		return(0); + +	case WM_LBUTTONDOWN: +		LogMouseEvent(RD_LEFTBUTTONDOWN); +		return(0); + +	case WM_LBUTTONUP: +		LogMouseEvent(RD_LEFTBUTTONUP); +		return(0); + +	case WM_RBUTTONDOWN: +		LogMouseEvent(RD_RIGHTBUTTONDOWN); +		return(0); + +	case WM_RBUTTONUP: +		LogMouseEvent(RD_RIGHTBUTTONUP); +		return(0); + +	case WM_LBUTTONDBLCLK: +		LogMouseEvent(RD_LEFTBUTTONDOWN); +		return(0); +		 +	case WM_RBUTTONDBLCLK: +		LogMouseEvent(RD_RIGHTBUTTONDOWN); + + +	case WM_SYSCOMMAND: +		if (gotTheFocus) +			return(0); + + + + +	} + +	return DefWindowProc(hWnd, message, wParam, lParam); + +} +*/ + + +/* +int32 InitialiseWindow(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow, char *gameName) + +{ +	 +	WNDCLASS    wc; +//	uint32		err; + + +//	hPrevInstance = hPrevInstance; +	wc.style = CS_DBLCLKS; +	wc.lpfnWndProc = WindowsMessageHandler; +	wc.cbClsExtra = 0; +	wc.cbWndExtra = 0; +	wc.hInstance = hInstance; +	wc.hIcon = LoadIcon( hInstance, "resourc1");  //IDI_APPLICATION ); +	wc.hCursor = LoadCursor( NULL, IDC_ARROW ); +	wc.hbrBackground = GetStockObject(BLACK_BRUSH); + +	wc.lpszMenuName = gameName; +	wc.lpszClassName = gameName; + +	RegisterClass( &wc ); + +	// Create a window +	hwnd = CreateWindowEx(WS_EX_APPWINDOW, gameName, gameName, WS_VISIBLE | WS_SYSMENU | WS_POPUP, 0, 0, +			GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ), +			NULL, NULL, hInstance, NULL ); + +	if(!hwnd) +	{ +	    MessageBox(hwnd, "Failed to create window", gameName, MB_OK ); +	    DestroyWindow(hwnd); +		return(RDERR_CREATEWINDOW); +	} + +//	ShowWindow(hwnd, nCmdShow); +	UpdateWindow(hwnd); +	SetFocus(hwnd); +	 +	SetTimer(hwnd, 25, 1000 / 25, NULL); +	SetTimer(hwnd, 1, 100, NULL); + +	return(RD_OK); + +} +*/ + + +int32 CloseAppWindow(void) + +{ +	warning("stub CloseAppWindow"); +/* +	DestroyWindow(hwnd); +*/ +	// just quit for now +	g_bs2->_syst->quit(); +	return(RD_OK); + +} + + + +int32 ServiceWindows(void) + +{ +	g_bs2->parseEvents(); +//	warning("stub ServiceWindows");  // too noisy +/* +	MSG msg; + +	if (myAppClosed) +		return(RDERR_APPCLOSED); + +	while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) +	{ +		if (!GetMessage(&msg, NULL, 0, 0)) +		{ +			myAppClosed = TRUE; +			return(RDERR_APPCLOSED); +		} + +		TranslateMessage(&msg); +		DispatchMessage(&msg); +  	} +*/ +	return(RD_OK); + +} + + + + +int32 _ReportDriverError(int32 error, uint8 *filename, uint32 line) + +{ +	warning("stub _ReportDriverError 0x%.8x file: %s, line: %d ", error, (char *) filename, line); +/* + +	char errorText[128]; +	char name[80]; + + +	GetGameName(name); +	sprintf(errorText, "Fatal error in %s, line %u!  Code 0x%.8x", filename, line, error); +    MessageBox(hwnd, errorText, name, MB_SYSTEMMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE); +*/	 +	return(RD_OK); + +} + + + +int32 _ReportFatalError(uint8 *error, uint8 *filename, uint32 line) + +{ + +	warning("stub _ReportFatalError"); +	char errorText[500]; +	char name[80]; + + +	GetGameName((uint8 *)name); +	sprintf(errorText, "FATAL ERROR - GAME TERMINATED\n%s", error); +	//MessageBox(hwnd, errorText, name, MB_SYSTEMMODAL | MB_ICONHAND | MB_ABORTRETRYIGNORE); +	warning("%s", errorText); + +	return(RD_OK); + +} + + +int32 DisableQuitKey(void) +{ +	controlQDisabled = TRUE; +	return(RD_OK); +} + +void SetWindowName(const char *windowName) +{ +	warning("stub SetWindowName( %s )", windowName); +//	SetWindowText(hwnd,windowName); +//	strcpy(gameName,windowName); +} diff --git a/sword2/driver/rdwin.h b/sword2/driver/rdwin.h new file mode 100644 index 0000000000..e176f9a40b --- /dev/null +++ b/sword2/driver/rdwin.h @@ -0,0 +1,56 @@ +/* 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	:	rdwin.h +//	Created		:	20th August 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		16-Sep-96	PRP		Driver interface to the rdwin functions/data +// +//	1.1		07-Nov-96	PRP		Added debug windows message handler, and RECT +//								defining the size of the current window. +// +//	1.2		04-Apr-97	PRP		Oops - no changes +// +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the rdwin.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef RDWIN_H +#define RDWIN_H + +/* +extern HWND			hwnd;			// handle to the current window +extern RECT			rcWindow;		// size of the current window. + +extern void Message(LPSTR fmt, ...); +*/ + + +#endif 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); +} diff --git a/sword2/driver/render.h b/sword2/driver/render.h new file mode 100644 index 0000000000..287e243bc8 --- /dev/null +++ b/sword2/driver/render.h @@ -0,0 +1,93 @@ +/* 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.h +//	Created		:	26th August 1996 +//	By			:	P.R.Porter +// +//	Version	Date		By		Description +//	------- ---------	---		----------------------------------------------- +//	1.0		16-Sep-96	PRP		Interface to the current scroll position. +// +//	1.1		23-Oct-96	PRP		Added definition of _parallaxLine structure. +// +//	1.2		05-Nov-96	PRP		Added definition of myScreenBuffer. +// +//	1.3		06-Nov-96	PRP		Fixed definition of myScreenBuffer. +// +//	1.4		15-Nov-96	PRP		Definition of menubar size removed, and put +//								into menu.h +// +//	1.5		24-Jan-97	PRP		Added references to parallaxScrollx and +//								parallaxScrolly.  These are used by the sprite +//								drawing code to link sprites to parallax +//								layers. +// +//	1.6		19-Mar-97	PRP		Added profiling flag for testing purposes. +// +//	1.7		24-Mar-97	PRP		Turned profiling off +// +//	1.8		08-Apr-97	JEL		Made locationWide and locationDeep accessible +//								to other drivers. +// +// +// +//	Summary		:	This include file defines links to all data which is +//					defined in the render.c module, but can be accessed by +//					other parts of the driver96 library. +// +// +//============================================================================= + + +#ifndef RENDER_H +#define RENDER_H + +#include "menu.h" + +#define RENDERWIDE 640 +#define ALIGNRENDERDEEP 480 +#define RENDERDEEP (ALIGNRENDERDEEP - (MENUDEEP * 2)) + + +#define PROFILING 0 + + +typedef struct +{ +	uint16	packets; +	uint16	offset; +} _parallaxLine; + + + +extern int16					scrollx;			// current x offset into background of display +extern int16					scrolly;			// current y offset into background of display +extern int16					parallaxScrollx;	// current x offset to link a sprite to the parallax layer +extern int16					parallaxScrolly;	// current y offset to link a sprite to the parallax layer +extern int16					locationWide; +extern int16					locationDeep; + +extern uint8 myScreenBuffer[RENDERWIDE * RENDERDEEP]; + + +#endif + 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); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + | 
