From dc6aa9912c73e1e03c32b6b214c5fbc46aa1eb57 Mon Sep 17 00:00:00 2001 From: Jonathan Gray Date: Mon, 28 Jul 2003 01:47:41 +0000 Subject: bs2 driver svn-id: r9212 --- sword2/driver/.cvsignore | 1 + sword2/driver/_console.cpp | 165 +++ sword2/driver/_console.h | 47 + sword2/driver/_mouse.cpp | 618 +++++++++ sword2/driver/_mouse.h | 54 + sword2/driver/d_draw.cpp | 1274 +++++++++++++++++ sword2/driver/d_draw.h | 96 ++ sword2/driver/d_sound.cpp | 3095 ++++++++++++++++++++++++++++++++++++++++++ sword2/driver/d_sound.h | 43 + sword2/driver/ddutil.h | 159 +++ sword2/driver/driver96.h | 1665 +++++++++++++++++++++++ sword2/driver/keyboard.cpp | 129 ++ sword2/driver/keyboard.h | 46 + sword2/driver/language.cpp | 134 ++ sword2/driver/menu.cpp | 570 ++++++++ sword2/driver/menu.h | 47 + sword2/driver/misc.cpp | 62 + sword2/driver/palette.cpp | 482 +++++++ sword2/driver/palette.h | 66 + sword2/driver/rdwin.cpp | 627 +++++++++ sword2/driver/rdwin.h | 56 + sword2/driver/render.cpp | 1283 ++++++++++++++++++ sword2/driver/render.h | 93 ++ sword2/driver/sprite.cpp | 3240 ++++++++++++++++++++++++++++++++++++++++++++ 24 files changed, 14052 insertions(+) create mode 100644 sword2/driver/.cvsignore create mode 100644 sword2/driver/_console.cpp create mode 100644 sword2/driver/_console.h create mode 100644 sword2/driver/_mouse.cpp create mode 100644 sword2/driver/_mouse.h create mode 100644 sword2/driver/d_draw.cpp create mode 100644 sword2/driver/d_draw.h create mode 100644 sword2/driver/d_sound.cpp create mode 100644 sword2/driver/d_sound.h create mode 100644 sword2/driver/ddutil.h create mode 100644 sword2/driver/driver96.h create mode 100644 sword2/driver/keyboard.cpp create mode 100644 sword2/driver/keyboard.h create mode 100644 sword2/driver/language.cpp create mode 100644 sword2/driver/menu.cpp create mode 100644 sword2/driver/menu.h create mode 100644 sword2/driver/misc.cpp create mode 100644 sword2/driver/palette.cpp create mode 100644 sword2/driver/palette.h create mode 100644 sword2/driver/rdwin.cpp create mode 100644 sword2/driver/rdwin.h create mode 100644 sword2/driver/render.cpp create mode 100644 sword2/driver/render.h create mode 100644 sword2/driver/sprite.cpp 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 +//#include + +//#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> 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 +//#include + +//#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; imouseh; 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; imouseh; 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; inoAnimFrames; 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 +//#include +//#include +#include + +//#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; itextSprite, &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 +//#include +#include + +#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< 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> 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; ichannels; + 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 || *sample5) // 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])<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 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 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])< 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])< 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 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])<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; ihwnd = 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; imusFilename[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; imusFilename[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 +#include + + + + +//----------------------------------------------------------------------------- +// 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 +//#include +#include +//#include +#include +#include + +#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 +//#include + +#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 +//#include +//#include + +//#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 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_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 +//#include +#include +//#include + +//#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 +//#include +#include + +#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 +//#include +//#include +#include + +//#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 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; jpackets; 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 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; jpackets; 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; iw * BLOCKHEIGHT * (i / xblocks[layer])) + BLOCKWIDTH * (i % xblocks[layer])); + for (j=0; jw - 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; jw; + 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 +//#include +#include +//#include + +//#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 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; jh; 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; iw; + 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; ih; 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; iw; + 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; ih; 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; ih; 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; iw + rs.left; + dst = (uint8 *) ddsd.lpSurface + ddsd.lPitch * (rd.top + i) + rd.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j> 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; iw + rs.left; + dst = (uint8 *) ddsd.lpSurface + ddsd.lPitch * (rd.top + i) + rd.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j> 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; ih; 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; jw/2; j++) +// { +// *dst = 0; +// *(dst+1) = *(src+1); +// dst += 2; +// src += 2; +// } + } + } + } + else + { + src = sprite; + dst = (uint8 *) ddsd.lpSurface; + for (i=0; ih; 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; idata + (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> 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; idata + (clippedSprite.top + i) * s->w + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + for (j=0; jtype >> 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; iw * 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; jw - (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; iw * 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; iw + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; j> 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; iw + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + // newSprite = (uint8 *) ddsdSystem.lpSurface + ddsdSystem.lPitch * i; + for (j=0; jblend & 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; iw + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + for (j=0; j> 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; iw + clippedSprite.left; + dst = myScreenBuffer + RENDERWIDE * (clippedTarget.top + i) + clippedTarget.left; + for (j=0; jy - 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; iy - 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> 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; jscale < 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; yscaledHeight; y++) + { + for (x=0; xscaledWidth; x++) + { + *spr++ = *(sprite + yScale[y] * s->w + xScale[x]); + } + } + } + else + { + spr = newSprite; + for (y=0; yscaledHeight; y++) + { + for (x=0; xscaledWidth; x++) + { + count = 0; + spriteCount = 0; + red = 0; + green = 0; + blue = 0; + for (j=yScale[y]; jw + 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; iy - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i+scrolly) * locationWide + s->x; + for (j=startx; j> 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; jscaledWidth > 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; yscaledHeight; y++) + { + for (x=0; xscaledWidth; 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; iy - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i + scrolly) * locationWide + s->x; + for (j=startx; j> 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; jscale > 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; yh; y++) + { + for (j=yScale[y]; jw; x++) + { + for (i=xScale[x]; iw + 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; xscaledWidth-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; iy - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i + scrolly) * locationWide + s->x; + for (j=startx; j> 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; jscaledWidth * 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; yh; y++) + { + for (j=yScale[y]; jw; x++) + { + for (i=xScale[x]; iw + 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; iy - scrolly)) * s->scaledWidth + (startx - (s->x - scrollx)); + + + + if ((lightMask) && (renderCaps & RDBLTFX_SHADOWBLEND)) + { + lightMap = lightMask + (i + scrolly) * locationWide + s->x; + for (j=startx; j> 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>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; iw; + 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); + +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3