Files
CnC_Remastered_Collection/ddraw/ddrawwrapper/DirectDrawWrapper.cpp
T

2157 lines
62 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#define UNICODE
#include "DirectDrawWrapper.h"
//#include "resource.h"
/*******************
**IUnknown methods**
********************/
// Retrieves pointers to the supported interfaces on an object.
HRESULT __stdcall IDirectDrawWrapper::QueryInterface(REFIID riid, LPVOID FAR * ppvObj)
{
debugMessage(1, "IDirectDrawWrapper::QueryInterface", "Partially Implemented");
// Provide the directdraw interface for all versions up to 7
if(riid == IID_IDirectDraw || riid == IID_IDirectDraw2 || riid == IID_IDirectDraw4 || riid == IID_IDirectDraw7)
{
// Set pointer to this interface
ppvObj = (LPVOID *)this;
// Increment reference count
AddRef();
// Return success
return S_OK;
}
//interface not supported
return E_NOINTERFACE;
}
// Increments the reference count for an interface on an object.
ULONG __stdcall IDirectDrawWrapper::AddRef()
{
debugMessage(1, "IDirectDrawWrapper::AddRef", "Partially Implemented");
// Increment reference count
ReferenceCount++;
// Return current reference count
return ReferenceCount;
}
// Decrements the reference count for an interface on an object.
ULONG __stdcall IDirectDrawWrapper::Release()
{
debugMessage(1, "IDirectDrawWrapper::Release", "Partially Implemented");
// Decrement reference count
ReferenceCount--;
// If reference count reaches 0 then free object
if(ReferenceCount == 0)
{
// Should free objects
}
// Return new reference count
return ReferenceCount;
}
/**********************
**IDirectDraw methods**
***********************/
// This method is not currently implemented.
HRESULT __stdcall IDirectDrawWrapper::Compact()
{
debugMessage(0, "IDirectDrawWrapper::Compact", "Unsupported in DirectDraw");
return DD_OK;
}
// Creates a DirectDrawClipper object.
HRESULT __stdcall IDirectDrawWrapper::CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR *lplpDDClipper, IUnknown FAR *pUnkOuter)
{
char message[2048] = "\0";
sprintf_s(message, 2048, "Partially Supported dwFlags: %d", dwFlags);
debugMessage(1, "IDirectDrawWrapper::CreateClipper", message);
// Create new IDirectDrawClipperWrapper with the given flags
IDirectDrawClipperWrapper *lpDDClipper = new IDirectDrawClipperWrapper();
if(lpDDClipper == NULL) return DDERR_OUTOFMEMORY; //OOM Fail
// Initialize the clipper wrapper
HRESULT hr = lpDDClipper->WrapperInitialize(dwFlags);
// If fail then return result
if(hr != DD_OK) return hr;
// Set the address to the new object
*lplpDDClipper = (LPDIRECTDRAWCLIPPER)lpDDClipper;
// If creation was successful
if(lpDDClipper != NULL)
return DD_OK;
else
return DDERR_OUTOFMEMORY; //OOM Fail
}
// Creates a DirectDrawPalette object for this DirectDraw object.
HRESULT __stdcall IDirectDrawWrapper::CreatePalette(DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, LPDIRECTDRAWPALETTE FAR *lplpDDPalette, IUnknown FAR *pUnkOuter)
{
char message[2048] = "\0";
sprintf_s(message, 2048, "Created dwFlags: %d", dwFlags);
// Create new IDirectDrawPaletteWrapper with the given flags and palette entries
IDirectDrawPaletteWrapper *lpDDPalette = new IDirectDrawPaletteWrapper();
if(lpDDPalette == NULL) return DDERR_OUTOFMEMORY; //OOM Fail
// Initialize the palette wrapper
HRESULT hr = lpDDPalette->WrapperInitialize(dwFlags, lpDDColorArray, lplpDDPalette);
// If fail then return result
if(hr != DD_OK) return hr;
// Set the address to the new object
*lplpDDPalette = (LPDIRECTDRAWPALETTE)lpDDPalette;
debugMessage(2, "IDirectDrawWrapper::CreatePalette", message);
// If creation was successful
return DD_OK;
}
// Creates a DirectDrawSurface object for this DirectDraw object.
HRESULT __stdcall IDirectDrawWrapper::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE FAR *lplpDDSurface, IUnknown FAR *pUnkOuter)
{
char message[2048] = "\0";
sprintf_s(message, 2048, "lpDDSurfaceDesc->dwFlags:: %d", lpDDSurfaceDesc->dwFlags);
// Create our surface wrapper and return success
lpAttachedSurface = new IDirectDrawSurfaceWrapper(this);
if(lpAttachedSurface == NULL) return DDERR_OUTOFMEMORY; //OOM Fail
// Initialize the surface wrapper
HRESULT hr = lpAttachedSurface->WrapperInitialize(lpDDSurfaceDesc, displayModeWidth, displayModeHeight, displayWidth, displayHeight);
// If fail then return result
if(hr != DD_OK) return hr;
// Set the address to the new object
*lplpDDSurface = (LPDIRECTDRAWSURFACE)lpAttachedSurface;
debugMessage(2, "IDirectDrawWrapper::CreateSurface", message);
// If creation was successful
return DD_OK;
}
// Duplicates a DirectDrawSurface object.
HRESULT __stdcall IDirectDrawWrapper::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE FAR *lplpDupDDSurface)
{
//***Unimplemented***
debugMessage(0, "DirectDrawWrapper::DuplicateSurface", "Not Implemented");
return DDERR_GENERIC;
/*
DDERR_CANTDUPLICATE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DDERR_SURFACELOST
*/
}
// Enumerates all the display modes that the hardware exposes through the
// DirectDraw object and that are compatible with a provided surface description.
HRESULT __stdcall IDirectDrawWrapper::EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::EnumDisplayModes", "Not Implemented");
if(lpDDSurfaceDesc == NULL)
{
//enumerate all available display modes
//call lpEnumModesCallback on each match
//HRESULT WINAPI EnumModesCallback2(LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext);
//lpEnumModesCallback(<surface desc for video mode>, lpContext);
//if returns DDENUMRET_OK continue
//else if returns DDENUMRET_CANCEL cancel enumeration
//if dwFlags & DDEDM_REFRESHRATES, modes with different refresh rates are unique
//if dwFlags & DDEDM_STANDARDVGAMODES, include Mode 13 and 320x200x8 Mode X
}
else
{
//check available display modes against lpDDSurfaceDesc
//call lpEnumModesCallback on each match
//HRESULT WINAPI EnumModesCallback2(LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext);
//lpEnumModesCallback(<surface desc for video mode>, lpContext);
//if returns DDENUMRET_OK continue
//else if returns DDENUMRET_CANCEL cancel enumeration
//if dwFlags & DDEDM_REFRESHRATES, modes with different refresh rates are unique
//if dwFlags & DDEDM_STANDARDVGAMODES, include Mode 13 and 320x200x8 Mode X
}
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
*/
}
// Enumerates all the existing or possible surfaces that
// meet the specified surface description.
HRESULT __stdcall IDirectDrawWrapper::EnumSurfaces(DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::EnumSurfaces", "Not Implemented");
if(dwFlags & DDENUMSURFACES_CANBECREATED)
{
if(dwFlags & DDENUMSURFACES_MATCH)
{
//Searches for any surface that matches the surface description in lpDDSD.
//EnumSurfacesCallback7
//lpEnumSurfacesCallback(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, lpContext);
}
//CANBECREATED must be used with MATCH
else
{
return DDERR_INVALIDPARAMS;
}
}
else if(dwFlags & DDENUMSURFACES_DOESEXIST)
{
if(dwFlags & DDENUMSURFACES_ALL)
{
//Enumerates all surfaces that meet the search criterion.
//EnumSurfacesCallback7
//lpEnumSurfacesCallback(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, lpContext);
}
else if(dwFlags & DDENUMSURFACES_MATCH)
{
//Searches for any surface that matches the surface description.
//EnumSurfacesCallback7
//lpEnumSurfacesCallback(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, lpContext);
}
else if(dwFlags & DDENUMSURFACES_NOMATCH)
{
//Searches for any surface that does not match the surface description.
//EnumSurfacesCallback7
//lpEnumSurfacesCallback(LPDIRECTDRAWSURFACE7 lpDDSurface, LPDDSURFACEDESC2 lpDDSurfaceDesc, lpContext);
}
}
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
*/
}
// Makes the surface that the GDI writes to the primary surface.
HRESULT __stdcall IDirectDrawWrapper::FlipToGDISurface()
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::FlipToGDISurface", "Not Implemented");
/*
You can call FlipToGDISurface at the end of a page-flipping
application to ensure that the display memory that the GDI
writes to is visible.
You can also use FlipToGDISurface to make the GDI surface
the primary surface so that normal windows, such as dialog
boxes, can be displayed in full-screen mode. The hardware
must have the DDCAPS2_CANRENDERWINDOWED capability.
*/
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTFOUND
*/
}
// Retrieves the capabilities of the device driver for the hardware and the hardware emulation layer (HEL).
HRESULT __stdcall IDirectDrawWrapper::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetCaps", "Not Implemented");
//both params cannot be null
if(lpDDDriverCaps == NULL && lpDDHELCaps == NULL) return DDERR_INVALIDPARAMS;
//if driver caps is not null
if(lpDDDriverCaps != NULL)
{
//lpDDDriverCaps receives the capabilities of the hardware, as reported by the device driver
}
//if HEL caps is not null
if(lpDDHELCaps != NULL)
{
//lpDDHELCaps receives the capabilities of the HEL
}
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
*/
}
// Retrieves the current display mode.
HRESULT __stdcall IDirectDrawWrapper::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetDisplayMode", "Not Implemented");
// lpDDSurfaceDesc cannot be null
if(lpDDSurfaceDesc == NULL) return DDERR_INVALIDPARAMS;
// lpDDSurfaceDesc receives a description of the current surface
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_UNSUPPORTEDMODE
*/
}
// Retrieves the four-character codes (FOURCC) that are supported by the
// DirectDraw object. This method can also retrieve the number of codes that are supported.
HRESULT __stdcall IDirectDrawWrapper::GetFourCCCodes(LPDWORD lpNumCodes, LPDWORD lpCodes)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetFourCCCodes", "Not Implemented");
// lpNumCodes cannot be null
if(lpNumCodes == NULL) return DDERR_INVALIDPARAMS;
// if no array is provided to hold FOURCC codes then return the count
if(lpCodes == NULL)
{
//lpNumCodes = number of supported FOURCCs
}
else
{
//lpNumCodes is less than the total number of FOURCC codes
//if(lpNumCodes < <FOURCC code count>)
//{
// fill lpCodes with the first lpNumCodes we have
// set lpNumCodes to the number of available FOURCC codes
//}
//else
//{
// fill lpCodes with all FOURCC codes we have
// [should lpNumCodes be set to the true number of FOURCC codes?]
//}
}
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
*/
}
// Retrieves the DirectDrawSurface object that currently represents
// the surface memory that GDI is treating as the primary surface.
HRESULT __stdcall IDirectDrawWrapper::GetGDISurface(LPDIRECTDRAWSURFACE FAR *lplpGDIDDSSurface)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetGDISurface", "Not Implemented");
// lplpGDIDDSSurface cannot be null
if(lplpGDIDDSSurface == NULL) return DDERR_INVALIDPARAMS;
// set lplpGDIDDSSurface to the interface for the surface
// that currently controls the GDI's primary surface memory.
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_NOTFOUND
*/
}
//Retrieves the frequency of the monitor that the DirectDraw object controls.
HRESULT __stdcall IDirectDrawWrapper::GetMonitorFrequency(LPDWORD lpdwFrequency)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetMonitorFrequency", "Not Implemented");
// lpdwFrequency cannot be null
if(lpdwFrequency == NULL) return DDERR_INVALIDPARAMS;
// lpdwFrequency receives the monitor frequency, in Hz
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_UNSUPPORTED
*/
}
//Retrieves the scan line that is currently being drawn on the monitor.
HRESULT __stdcall IDirectDrawWrapper::GetScanLine(LPDWORD lpdwScanLine)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetScanLine", "Not Implemented");
// lpdwScanLine cannot be null
if(lpdwScanLine == NULL) return DDERR_INVALIDPARAMS;
// lpdwScanLine receives the scan line that the display is currently drawing.
/*
Scan lines are reported as zero-based integers. The returned scan line value
is in the range from 0 through n, where 0 is the first visible scan line on
the screen and n is the last visible scan line, plus any scan lines that occur
during the vertical blank period. So, in a case where an application is running
at a resolution of 640×480 and there are 12 scan lines during vblank, the values
returned by this method range from 0 through 491.
*/
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_UNSUPPORTED
DDERR_VERTICALBLANKINPROGRESS
*/
}
//Retrieves the status of the vertical blank.
HRESULT __stdcall IDirectDrawWrapper::GetVerticalBlankStatus(LPBOOL lpbIsInVB)
{
// NOTE: Disabled for performance
// debugMessage(1, "IDirectDrawWrapper::GetVerticalBlankStatus", "Partially Implemented");
// lpbIsInVB cannot be null
if(lpbIsInVB == NULL) return DDERR_INVALIDPARAMS;
// lpbIsInVB is TRUE if a vertical blank is occurring, and FALSE otherwise.
// since vertical blank drawing is handled by the VSYNC in d3d9 we are never in vertical blank
lpbIsInVB = FALSE;
return DD_OK;
/*
DDERR_INVALIDOBJECT
*/
}
// Initializes a DirectDraw object that was created by using the CoCreateInstance COM function.
HRESULT __stdcall IDirectDrawWrapper::Initialize(GUID FAR *lpGUID)
{
debugMessage(1, "IDirectDrawWrapper::Initialize", "Partially Implemented");
// If you already used the DirectDrawCreate function to create a
// DirectDraw object, this method returns DDERR_ALREADYINITIALIZED
return DDERR_ALREADYINITIALIZED;
/*
DDERR_ALREADYINITIALIZED
DDERR_DIRECTDRAWALREADYCREATED
DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NODIRECTDRAWHW
DDERR_NODIRECTDRAWSUPPORT
DDERR_OUTOFMEMORY
*/
}
// Resets the mode of the display device hardware for the primary
// surface to what it was before the IDirectDraw7::SetDisplayMode
// method was called. Exclusive-level access is required to use this method.
HRESULT __stdcall IDirectDrawWrapper::RestoreDisplayMode()
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::RestoreDisplayMode", "Not Implemented");
return DDERR_GENERIC;
/*
DDERR_GENERIC
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_LOCKEDSURFACES
DDERR_NOEXCLUSIVEMODE
*/
}
//Determines the top-level behavior of the application.
HRESULT __stdcall IDirectDrawWrapper::SetCooperativeLevel(HWND in_hWnd, DWORD dwFlags)
{
char message[2048] = "\0";
sprintf_s(message, 2048, "Completed in_hWnd: 0x%X, dwFlags: %d", in_hWnd, dwFlags);
if(in_hWnd == NULL)
{
// message[0] = 0;
debugMessage(0, "IDirectDrawWrapper::SetCooperativeLevel", "Unimplemented for NULL window handle");
return DDERR_GENERIC;
}
// Set display window
hWnd = in_hWnd;
// Install new wndproc
lpPrevWndFunc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
if(SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WndProc) == 0)
{
debugMessage(0, "IDirectDrawWrapper::SetCooperativeLevel", "Failed to overload WNDPROC");
}
// Adjust the display window to match the current display mode
AdjustWindow();
// Create the requested d3d device for this display mode, report error on failure
if(!CreateD3DDevice())
{
MessageBox(NULL, TEXT("Error creating Direct3D9 Device"), TEXT("Error"), MB_OK | MB_ICONERROR);
return DDERR_GENERIC;
}
debugMessage(2, "IDirectDrawWrapper::SetCooperativeLevel", message);
return DD_OK;
/*
DDSCL_ALLOWMODEX
Allows the use of Mode X display modes. This flag can be used only if the DDSCL_EXCLUSIVE and DDSCL_FULLSCREEN flags are present.
DDSCL_ALLOWREBOOT
Allows CTRL+ALT+DEL to function while in exclusive (full-screen) mode.
DDSCL_CREATEDEVICEWINDOW
This flag is supported in Windows 98 and Windows 2000 only. Indicates that DirectDraw will create and manage a default device window for this DirectDraw object.
DDSCL_EXCLUSIVE
Requests the exclusive level. This flag must be used with the DDSCL_FULLSCREEN flag.
DDSCL_FPUPRESERVE
The calling application cares about the FPU state and does not want Direct3D to modify it in ways visible to the application. In this mode, Direct3D saves and restores the FPU state every time that it needs to modify the FPU state.
DDSCL_FPUSETUP
The calling application is likely to keep the FPU set up for optimal Direct3D performance (single precision and exceptions disabled), so Direct3D does not need to explicitly set the FPU each time. This is the default state.
DDSCL_FULLSCREEN
The exclusive-mode owner is responsible for the entire primary surface. The GDI can be ignored. This flag must be used with the DDSCL_EXCLUSIVE flag.
DDSCL_MULTITHREADED
Requests multithread-safe DirectDraw behavior. This causes Direct3D to take the global critical section more frequently.
DDSCL_NORMAL
The application functions as a typical Windows application. This flag cannot be used with the DDSCL_ALLOWMODEX, DDSCL_EXCLUSIVE, or DDSCL_FULLSCREEN flags.
DDSCL_NOWINDOWCHANGES
DirectDraw is not allowed to minimize or restore the application window on activation.
DDSCL_SETDEVICEWINDOW
This flag is supported in Windows 98 and Windows 2000 only. Indicates that the hWnd parameter is the window handle of the device window for this DirectDraw object. This flag cannot be used with the DDSCL_SETFOCUSWINDOW flag.
DDSCL_SETFOCUSWINDOW
This flag is supported in Windows 98 and Windows 2000 only. Indicates that the hWnd parameter is the window handle of the focus window for this DirectDraw object. This flag cannot be used with the DDSCL_SETDEVICEWINDOW flag.
*/
/*
DDERR_EXCLUSIVEMODEALREADYSET
DDERR_HWNDALREADYSET
DDERR_HWNDSUBCLASSED
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
*/
}
// Sets the mode of the display-device hardware.
HRESULT __stdcall IDirectDrawWrapper::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
{
char message[2048] = "\0";
sprintf_s(message, "Complete dwWidth: %d, dwHeight: %d, dwBPP: %d", dwWidth, dwHeight, dwBPP);
// Set display mode to dwWidth x dwHeight with dwBPP color depth
displayModeWidth = dwWidth;
displayModeHeight = dwHeight;
// Ignore color depth
// Init textures to new display mode
if(!CreateSurfaceTexture())
{
MessageBox(NULL, TEXT("Error creating Direct3D9 surface texture"), TEXT("Error"), MB_OK | MB_ICONERROR);
return DDERR_GENERIC;
}
debugMessage(2, "IDirectDrawWrapper::SetDisplayMode", message);
return DD_OK;
/*
DDERR_GENERIC
DDERR_INVALIDMODE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_LOCKEDSURFACES
DDERR_NOEXCLUSIVEMODE
DDERR_SURFACEBUSY
DDERR_UNSUPPORTED
DDERR_UNSUPPORTEDMODE
DDERR_WASSTILLDRAWING
*/
}
// Sets the mode of the display-device hardware(IDirectDraw2 or higher).
/*HRESULT __stdcall IDirectDrawWrapper::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP, DWORD dwRefreshRate, DWORD dwFlags)
{
message[0] = 0;
sprintf_s(message, 2048, "dwWidth: %d, dwHeight: %d, dwBPP: %d, swRefreshRate: %d, ", dwWidth, dwHeight, dwBPP, dwRefreshRate);
if(dwFlags & DDSDM_STANDARDVGAMODE) strcat_s(message, 2048, ", DDSDM_STANDARDVGAMODE");
location[0] = 0;
sprintf_s(location, 2048, "IDirectDrawWrapper::SetDisplayMode");
debugCallback(2, location, message);
if(dwFlags & DDSDM_STANDARDVGAMODE)
{
//use Mode 13 instead of Mode X 320x200x8 mode
}
if(dwRefreshRate == 0)
{
//set display mode to dwWidth x dwHeight with dwBPP color depth with default refresh rate
}
else
{
//set display mode to dwWidth x dwHeight with dwBPP color depth with dwRefreshRate refresh rate
}
displayModeWidth = dwWidth;
displayModeHeight = dwHeight;
//ignore color depth
return DD_OK;
DDERR_GENERIC
DDERR_INVALIDMODE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_LOCKEDSURFACES
DDERR_NOEXCLUSIVEMODE
DDERR_SURFACEBUSY
DDERR_UNSUPPORTED
DDERR_UNSUPPORTEDMODE
DDERR_WASSTILLDRAWING
}*/
// Helps the application synchronize itself with the vertical-blank interval.
HRESULT __stdcall IDirectDrawWrapper::WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent)
{
// NOTE: Disabled for performance
// debugMessage(1, "IDirectDrawWrapper::WaitForVerticalBlank", "Partially Supported");
if(dwFlags & DDWAITVB_BLOCKBEGIN)
{
// Return when vertical blank begins
}
else if(dwFlags & DDWAITVB_BLOCKBEGINEVENT)
{
// Triggers an event when the vertical blank begins. This value is not currently supported.
return DDERR_UNSUPPORTED;
}
else if(dwFlags & DDWAITVB_BLOCKEND)
{
// Return when the vertical-blank interval ends and the display begins.
}
// Vblank supported by vsync so just immediately return
return DD_OK;
/*
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_UNSUPPORTED
DDERR_WASSTILLDRAWING
*/
}
/****************************
**Added in the V2 interface**
*****************************/
// Retrieves the total amount of display memory available and the
// amount of display memory currently free for a given type of surface.
HRESULT __stdcall IDirectDrawWrapper::GetAvailableVideoMem(LPDDSCAPS2 lpDDSCaps2, LPDWORD lpdwTotal, LPDWORD lpdwFree)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetAvailableVideoMem", "Not Implemented");
//no parameters may be null
if(lpDDSCaps2 == NULL || lpdwTotal == NULL || lpdwFree == NULL) return DDERR_INVALIDPARAMS;
//lpdwTotal receives the total amount of display memory available, in bytes.
//The value received reflects the total video memory, minus the video memory
//required for the primary surface and any private caches that the display driver reserves.
//lpdwFree receives the amount of display memory currently free that can be allocated for
//a surface that matches the capabilities specified by the structure at lpDDSCaps2
return DDERR_GENERIC;
/*
DDERR_INVALIDCAPS
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NODIRECTDRAWHW
*/
}
/****************************
**Added in the V4 interface**
*****************************/
// Used after a call to IDirectDraw7::StartModeTest to pass or fail each mode that the
// test presents and to step through the modes until the test is complete.
HRESULT __stdcall IDirectDrawWrapper::EvaluateMode(DWORD dwFlags, DWORD *pSecondsUntilTimeout)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::EvaluateMode", "Not Implemented");
//pSecondsUntilTimeout cannot be null
if(pSecondsUntilTimeout == NULL) return DDERR_INVALIDPARAMS;
/*
DDEM_MODEPASSED
The mode being tested has passed.
DDEM_MODEFAILED
The mode being tested has failed.
*/
/*
You can use EvaluateMode in conjunction with the IDirectDraw7::StartModeTest method to determine
the maximum refresh rate that an EDID monitor and display adapter combination can support for each
screen resolution.
Specifically, a call to IDirectDraw7::StartModeTest directs DirectDraw to establish a set of testable
resolutions and to display a mode based on the first resolution in the set. Subsequent calls to
EvaluateMode can be used to pass or fail each mode and to advance the test to the next display mode.
The method steps through the testable resolutions starting with the highest refresh rate supported for
a given resolution. After a refresh rate for a given resolution passes, testing of lower refresh rates
for that resolution is skipped.
When the test is initiated, or whenever a mode is passed or failed, DirectDraw begins a 15 second timeout.
An application can monitor the time remaining without passing or failing the current mode by calling
EvaluateMode with a value of 0 for the dwFlags argument. Note that DirectDraw only changes modes or
terminates the test when EvaluateMode is called. However, if an application calls EvaluateMode after
the timeout period has elapsed, the current mode fails, regardless of the value passed to the dwFlags
parameter.
*/
return DDERR_GENERIC;
/*
DDERR_TESTFINISHED
DDERR_NEWMODE
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOTFOUND
*/
}
// Obtains information about the device driver. This method can be used, with caution,
// to recognize specific hardware installations to implement workarounds for poor driver or chipset behavior.
HRESULT __stdcall IDirectDrawWrapper::GetDeviceIdentifier(LPDDDEVICEIDENTIFIER2 lpdddi, DWORD dwFlags)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetDeviceIdentifier", "Not Implemented");
// lpdddi cannot be null
if(lpdddi == NULL) return DDERR_INVALIDPARAMS;
// Only valid flag
if(dwFlags == DDGDI_GETHOSTIDENTIFIER)
{
//Causes GetDeviceIdentifier to return information about the host (typically 2-D) adapter in a
//system equipped with a stacked secondary 3-D adapter. Such an adapter appears to the application
//as if it were part of the host adapter, but is typically located on a separate card.
}
else
{
//information on the stacked secondary is returned because this most accurately reflects the
//qualities of the DirectDraw object involved.
}
return DDERR_GENERIC;
}
// Retrieves the IDirectDrawSurface7 interface for a surface, based on its GDI device context handle.
HRESULT __stdcall IDirectDrawWrapper::GetSurfaceFromDC(HDC hdc, LPDIRECTDRAWSURFACE7 *lpDDS)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::GetSurfaceFromDC", "Not Implemented");
// lpDDS cannot be null
if(lpDDS == NULL) return DDERR_INVALIDPARAMS;
// lpDDS is filled with a pointer to the IDirectDrawSurface7 interface
// for the surface if the call succeeds for the display device context hdc
// This method succeeds only for device context handles that identify
// surfaces already associated with the DirectDraw object.
return DDERR_GENERIC;
/*
DDERR_GENERIC
DDERR_INVALIDPARAMS
DDERR_OUTOFMEMORY
DDERR_NOTFOUND
*/
}
// Restores all the surfaces that were created for the DirectDraw object, in the order that they were created.
HRESULT __stdcall IDirectDrawWrapper::RestoreAllSurfaces()
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::RestoreAllSurfaces", "Not Implemented");
// This method is provided for convenience. Effectively, this method calls the IDirectDrawSurface7::Restore
// method for each surface that is created by this DirectDraw object.
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
*/
}
// Initiates a test to update the system registry with refresh rate information for the current display adapter
// and monitor combination. A call to this method is typically followed by calls to IDirectDraw7::EvaluateMode to
// pass or fail modes displayed by the test.
HRESULT __stdcall IDirectDrawWrapper::StartModeTest(LPSIZE lpModesToTest, DWORD dwNumEntries, DWORD dwFlags)
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::StartModeTest", "Not Implemented");
if(lpModesToTest == NULL && dwNumEntries == 0 && dwFlags == 0)
{
// Clear existing refresh rate information from the registry.
}
/*
You can use the StartModeTest method together with the IDirectDraw7::EvaluateMode method to determine
the maximum refresh rate that an EDID monitor and display adapter combination can support for each screen
resolution. The results of the testing are stored in the system registry and affect the operation of
IDirectDraw7::EnumDisplayModes when that method is called with the DDEDM_REFRESHRATES flag set.
*/
/*
StartModeTest succeeds only with monitors that contain EDID data. If the monitor is not EDID-compliant,
StartModeTest returns DDERR_TESTFINISHED without testing any modes. If the EDID table does not contain values
higher than 60 Hz, no modes are tested. Refresh rates higher than 100 Hz are tested only if the EDID table
contains values higher than 85 Hz.
*/
if(dwFlags & DDSMT_ISTESTREQUIRED)
{
//StartModeTest does not initiate a test, but instead returns a value that indicates whether
//it is possible or necessary to test the resolutions that the lpModesToTest and dwNumEntries
//parameters identify.
/*
DDERR_NEWMODE
DDERR_NODRIVERSUPPORT
DDERR_NOMONITORINFORMATION
DDERR_TESTFINISHED
*/
}
else
{
//lpModesToTest is an array of dwNumEntries elements that describe, in terms of screen resolutions, the modes that should be tested.
}
return DDERR_GENERIC;
/*
DDERR_CURRENTLYNOTAVAIL
DDERR_INVALIDOBJECT
DDERR_INVALIDPARAMS
DDERR_NOEXCLUSIVEMODE
DDERR_NOTFOUND
DDERR_TESTFINISHED
*/
}
// Reports the current cooperative-level status of the DirectDraw device for a windowed or full-screen application.
HRESULT __stdcall IDirectDrawWrapper::TestCooperativeLevel()
{
//***Unimplemented***
debugMessage(0, "IDirectDrawWrapper::TestCooperativeLevel", "Not Implemented");
// If the calling application can continue then return OK
return DDERR_GENERIC;
/*
DDERR_INVALIDOBJECT
DDERR_EXCLUSIVEMODEALREADYSET
DDERR_NOEXCLUSIVEMODE
DDERR_WRONGMODE
*/
}
// Default constructor
IDirectDrawWrapper::IDirectDrawWrapper()
{
// Init vars
hWnd = NULL;
WndProc = NULL;
lpPrevWndFunc = NULL;
hModule = NULL;
ReferenceCount = 0;
lpAttachedSurface = NULL;
// Init objects
d3d9Object = NULL;
d3d9Device = NULL;
surfaceTexture = NULL;
vertexBuffer = NULL;
// Sprite Info
d3dSprite = NULL;
menuTexture = NULL;
curMenuFrame = 0;
menuLocations[0] = 117;
menuLocations[1] = 162;
menuLocations[2] = 208;
menuLocations[3] = 253;
menuLocations[4] = 298;
//0
menuSprites[0].left = 0;
menuSprites[0].top = 0;
menuSprites[0].right = 30;
menuSprites[0].bottom = 32;
//1
menuSprites[1].left = menuSprites[0].right;
menuSprites[1].top = 0;
menuSprites[1].right = menuSprites[1].left + 14;
menuSprites[1].bottom = 32;
//2
menuSprites[2].left = menuSprites[1].right;
menuSprites[2].top = 0;
menuSprites[2].right = menuSprites[2].left + 22;
menuSprites[2].bottom = 32;
//3
menuSprites[3].left = menuSprites[2].right;
menuSprites[3].top = 0;
menuSprites[3].right = menuSprites[3].left + 21;
menuSprites[3].bottom = 32;
//4
menuSprites[4].left = menuSprites[3].right;
menuSprites[4].top = 0;
menuSprites[4].right = menuSprites[4].left + 23;
menuSprites[4].bottom = 32;
//5
menuSprites[5].left = menuSprites[4].right;
menuSprites[5].top = 0;
menuSprites[5].right = menuSprites[5].left + 21;
menuSprites[5].bottom = 32;
//6
menuSprites[6].left = menuSprites[5].right;
menuSprites[6].top = 0;
menuSprites[6].right = menuSprites[6].left + 20;
menuSprites[6].bottom = 32;
//7
menuSprites[7].left = menuSprites[6].right;
menuSprites[7].top = 0;
menuSprites[7].right = menuSprites[7].left + 21;
menuSprites[7].bottom = 32;
//8
menuSprites[8].left = menuSprites[7].right;
menuSprites[8].top = 0;
menuSprites[8].right = menuSprites[8].left + 20;
menuSprites[8].bottom = 32;
//9
menuSprites[9].left = menuSprites[8].right;
menuSprites[9].top = 0;
menuSprites[9].right = menuSprites[9].left + 21;
menuSprites[9].bottom = 32;
//x
menuSprites[10].left = menuSprites[9].right;
menuSprites[10].top = 0;
menuSprites[10].right = menuSprites[10].left + 25;
menuSprites[10].bottom = 32;
//RESOLUTION
menuSprites[11].left = 0;
menuSprites[11].top = 32;
menuSprites[11].right = 246;
menuSprites[11].bottom = 64;
//FULLSCREEN:
menuSprites[12].left = 0;
menuSprites[12].top = 64;
menuSprites[12].right = 243;
menuSprites[12].bottom = 96;
//VSYNC:
menuSprites[13].left = 0;
menuSprites[13].top = 96;
menuSprites[13].right = 144;
menuSprites[13].bottom = 128;
//ACCEPT
menuSprites[14].left = 0;
menuSprites[14].top = 128;
menuSprites[14].right = 151;
menuSprites[14].bottom = 160;
//ON
menuSprites[15].left = 160;
menuSprites[15].top = 96;
menuSprites[15].right = menuSprites[15].left + 55;
menuSprites[15].bottom = 128;
//OFF
menuSprites[16].left = 160;
menuSprites[16].top = 128;
menuSprites[16].right = menuSprites[15].left + 69;
menuSprites[16].bottom = 160;
//Diablo Logo
menuSprites[17].left = 0;
menuSprites[17].top = 256;
menuSprites[17].right = 295;
menuSprites[17].bottom = 356;
inMenu = false;
curMenu = 0;
// Resolutions
windowedResolutions = new POINT[10];
windowedResolutionCount = 10;
windowedResolutions[0].x = 640;
windowedResolutions[0].y = 480;
windowedResolutions[1].x = 800;
windowedResolutions[1].y = 600;
windowedResolutions[2].x = 960;
windowedResolutions[2].y = 720;
windowedResolutions[3].x = 1024;
windowedResolutions[3].y = 768;
windowedResolutions[4].x = 1152;
windowedResolutions[4].y = 864;
windowedResolutions[5].x = 1280;
windowedResolutions[5].y = 960;
windowedResolutions[6].x = 1400;
windowedResolutions[6].y = 1050;
windowedResolutions[7].x = 1440;
windowedResolutions[7].y = 1080;
windowedResolutions[8].x = 1600;
windowedResolutions[8].y = 1200;
windowedResolutions[9].x = 1920;
windowedResolutions[9].y = 1440;
fullscreenResolutionCount = 0;
fullscreenResolutions = NULL;
fullscreenRefreshes = NULL;
// Load settings from ini file
wchar_t curPath[MAX_PATH];
wchar_t filename[MAX_PATH];
wchar_t temp[1024];
// Get current working directory
GetCurrentDirectory(MAX_PATH, curPath);
wsprintf(filename, TEXT("%s\\ddraw_settings.ini"), curPath);
// Get windowed resolution
GetPrivateProfileString(TEXT("video"), TEXT("windowedResolution"), TEXT("640x480"), temp, 1024, filename);
for(int i = 0; i < 1024 || temp[i] == TEXT('\0'); i++)
{
// Split on x or X
if(temp[i] == TEXT('x') || temp[i] == TEXT('X'))
{
temp[i] = TEXT('\0');
// Attempt to convert to int
displayWidthWindowed = _wtoi(temp);
displayHeightWindowed = _wtoi(&(temp[i + 1]));
// Failure to convert use default
if(displayWidthWindowed == 0 || displayHeightWindowed == 0)
{
displayWidthWindowed = 640;
displayHeightWindowed = 480;
}
break;
}
}
// Get fullscreen resolution
GetPrivateProfileString(TEXT("video"), TEXT("fullscreenResolution"), TEXT("640x480"), temp, 1024, filename);
for(int i = 0; i < 1024 || temp[i] == TEXT('\0'); i++)
{
// Split on x or X
if(temp[i] == TEXT('x') || temp[i] == TEXT('X'))
{
temp[i] = TEXT('\0');
// Attempt to convert to int
displayWidthFullscreen = _wtoi(temp);
displayHeightFullscreen = _wtoi(&(temp[i + 1]));
// Failure to convert use default
if(displayWidthFullscreen == 0 || displayHeightFullscreen == 0)
{
displayWidthFullscreen = 640;
displayHeightFullscreen = 480;
}
break;
}
}
// Default to fullscreen mode?
GetPrivateProfileString(TEXT("video"), TEXT("fullscreen"), TEXT("0"), temp, 1024, filename);
if(temp[0] == TEXT('1'))
{
isWindowed = false;
}
else
{
isWindowed = true;
}
// Set the resolution
if(isWindowed)
{
displayWidth = displayWidthWindowed;
displayHeight = displayHeightWindowed;
}
else
{
displayWidth = displayWidthFullscreen;
displayHeight = displayHeightFullscreen;
}
GetPrivateProfileString(TEXT("video"), TEXT("vsync"), TEXT("1"), temp, 1024, filename);
if(temp[0] == TEXT('1'))
{
vSync = false;
}
else
{
vSync = true;
}
GetPrivateProfileString(TEXT("video"), TEXT("refresh"), TEXT("60"), temp, 1024, filename);
refreshRate = _wtoi(temp);
// Failure to convert set to default
if(refreshRate == 0)
{
refreshRate = 60;
}
// Load settings from registry or ini file or set defaults
lastPosition.x = 100;
lastPosition.y = 100;
// Increment reference count
AddRef();
debugMessage(2, "IDirectDrawWrapper::IDirectDrawWrapper", "Created");
}
// Default destructor
IDirectDrawWrapper::~IDirectDrawWrapper()
{
//**Free d3d objects**
// Release existing vertex buffer
if(vertexBuffer != NULL)
{
vertexBuffer->Release();
vertexBuffer = NULL;
}
// Release existing surface texture
if(surfaceTexture != NULL)
{
surfaceTexture->Release();
surfaceTexture = NULL;
}
if(d3dSprite != NULL)
{
d3dSprite->Release();
d3dSprite = NULL;
}
if(menuTexture != NULL)
{
menuTexture->Release();
menuTexture = NULL;
}
// Release existing d3ddevice(buggy, not in thread?)
if(d3d9Device != NULL)
{
//d3d9Device->Release();
d3d9Device = NULL;
}
// Release existing d3dobject
if(d3d9Object != NULL)
{
d3d9Object->Release();
d3d9Device = NULL;
}
// Release allocated memory
if(windowedResolutions != NULL)
{
delete windowedResolutions;
windowedResolutions = NULL;
windowedResolutionCount = 0;
}
if(fullscreenResolutions != NULL)
{
delete fullscreenResolutions;
fullscreenResolutions = NULL;
fullscreenResolutions = 0;
}
//release this reference
//Release();
// Free objects
debugMessage(2, "IDirectDrawWrapper::~IDirectDrawWrapper", "Destroyed");
}
// Initialize wrapper function
HRESULT IDirectDrawWrapper::WrapperInitialize(WNDPROC wp, HMODULE hMod)
{
// Save new wndproc
WndProc = wp;
// Save the module
hModule = hMod;
// Create Direct3D9 device
d3d9Object = Direct3DCreate9(D3D_SDK_VERSION);
if(d3d9Object == NULL)
{
debugMessage(0, "IDirectDrawWrapper::WrapperInitialize", "Failed to create Direct3D9 object");
MessageBox(NULL, TEXT("Failed to create Direct3D9 object."), TEXT("Fatal Error"), MB_OK | MB_ICONERROR);
// Error creation directdraw
return DDERR_GENERIC;
}
debugMessage(2, "IDirectDrawWrapper::WrapperInitialize", "Initialized");
// Success
return DD_OK;
}
/* Helper function to present the d3d surface
*
*/
HRESULT IDirectDrawWrapper::Present()
{
// Make sure the device exists
if(d3d9Device == NULL)
{
debugMessage(0, "IDirectDrawWrapper::Present","Present called when d3d9device doesn't exist");
return false;
}
// Make sure surface texture exists
if(surfaceTexture == NULL)
{
debugMessage(0, "IDirectDrawWrapper::Present","Present called when texture doesn't exist");
return false;
}
// Make sure the attached surface exists
if(lpAttachedSurface != NULL)
{
// Lock full dynamic texture
D3DLOCKED_RECT d3dlrect;
if(surfaceTexture->LockRect(0, &d3dlrect, NULL, D3DLOCK_DISCARD) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present","Failed to lock texture memory");
return false;
}
// Copy bits to texture by scanline observing pitch
extern byte* raw_image_buffer;
for (DWORD y = 0; y < displayModeHeight; y++)
{
memcpy((BYTE*)d3dlrect.pBits + (y * d3dlrect.Pitch), &lpAttachedSurface->rgbVideoMem[y * displayModeWidth], displayModeWidth * sizeof(UINT32));
}
// Unlock dynamic texture
if(surfaceTexture->UnlockRect(NULL) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present","Failed to unlock texture memory");
return false;
}
}
else
{
debugMessage(1, "IDirectDrawWrapper::Present","Attempt to Present with no attached surface");
}
if(d3d9Device->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present","Failed to clear device");
return false;
}
if(d3d9Device->BeginScene() != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present","Failed to begin scene");
return false;
}
// Set texture
if(d3d9Device->SetTexture(0, surfaceTexture) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present","Failed to set texture");
return false;
}
// Draw primitive
if(d3d9Device->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present","Failed to draw primitive");
return false;
}
// Display menu options
if(inMenu)
{
// Begin sprite draw
d3dSprite->Begin(D3DXSPRITE_ALPHABLEND);
// Set scaling transform for current window size, if required
if(displayWidth != displayModeWidth && displayHeight != displayModeHeight)
{
D3DXVECTOR2 scaling((FLOAT)displayWidth / (FLOAT)displayModeWidth, (FLOAT)displayHeight / (FLOAT)displayModeHeight);
D3DXMATRIX mat;
D3DXMatrixTransformation2D(&mat,NULL,0.0,&scaling,NULL,0.0,NULL);
d3dSprite->SetTransform(&mat);
}
D3DXVECTOR3 pos;
pos.z = 0.0f;
int selectionLeft, selectionRight;
// Custom Diablo Logo
pos.x = (640 - menuSprites[17].right) / 2;
pos.y = 3;
d3dSprite->Draw(menuTexture, &menuSprites[17], NULL, &pos, 0xFFFFFFFF);
// RESOLUTION
pos.x = (640 - menuSprites[11].right) / 2;
pos.y = menuLocations[0];
d3dSprite->Draw(menuTexture, &menuSprites[11], NULL, &pos, 0xFFFFFFFF);
pos.y = menuLocations[1];
// Print display string
char temp[1024];
// If windowed selected
if(menuWindowed)
sprintf_s(temp, 1024, "%dx%d", windowedResolutions[menuWindowedResolution].x, windowedResolutions[menuWindowedResolution].y);
// If fullscreen selected
else
sprintf_s(temp, 1024, "%dx%dx%d", fullscreenResolutions[menuFullscreenResolution].x, fullscreenResolutions[menuFullscreenResolution].y, fullscreenRefreshes[menuFullscreenResolution]);
// Step through resolution string and calculate string width for centering
int resolutionStringWidth = 0;
for(int i = 0; i < strlen(temp); i++)
{
// If number
if(temp[i] != 'x')
{
resolutionStringWidth += menuSprites[temp[i] - 48].right - menuSprites[temp[i] - 48].left;
}
else
{
resolutionStringWidth += menuSprites[10].right - menuSprites[10].left;
}
}
pos.x = (640 - resolutionStringWidth) / 2;
// Set location for menu selection marker
if(curMenu == 0)
{
selectionLeft = pos.x - 52;
selectionRight = pos.x + resolutionStringWidth + 10;
}
// Daw resolution string
for(int i = 0; i < strlen(temp); i++)
{
// If number
if(temp[i] != 'x')
{
d3dSprite->Draw(menuTexture, &menuSprites[temp[i] - 48], NULL, &pos, 0xFFFFFFFF);
pos.x += menuSprites[temp[i] - 48].right - menuSprites[temp[i] - 48].left;
}
else
{
d3dSprite->Draw(menuTexture, &menuSprites[10], NULL, &pos, 0xFFFFFFFF);
pos.x += menuSprites[10].right - menuSprites[10].left;
}
}
// FULLSCREEN:
pos.x = (640 - (menuSprites[12].right + (menuSprites[16].right - menuSprites[16].left) + 10)) / 2;
pos.y = menuLocations[2];
// Set location for menu selection marker
if(curMenu == 1)
{
selectionLeft = pos.x - 52;
selectionRight = pos.x + menuSprites[12].right + (menuSprites[16].right - menuSprites[16].left) + 20;
}
d3dSprite->Draw(menuTexture, &menuSprites[12], NULL, &pos, 0xFFFFFFFF);
// OFF
if(menuWindowed)
{
pos.x += menuSprites[12].right + 10;
d3dSprite->Draw(menuTexture, &menuSprites[16], NULL, &pos, 0xFFFFFFFF);
}
// ON
else
{
pos.x += menuSprites[12].right + 10 + 14;
d3dSprite->Draw(menuTexture, &menuSprites[15], NULL, &pos, 0xFFFFFFFF);
}
// VSYNC:
pos.x = (640 - (menuSprites[13].right + (menuSprites[16].right - menuSprites[16].left) + 10)) / 2;
pos.y = menuLocations[3];
// Set location for menu selection marker
if(curMenu == 2)
{
selectionLeft = pos.x - 52;
selectionRight = pos.x + menuSprites[13].right + (menuSprites[16].right - menuSprites[16].left) + 20;
}
d3dSprite->Draw(menuTexture, &menuSprites[13], NULL, &pos, 0xFFFFFFFF);
// OFF
if(!menuvSync)
{
pos.x += menuSprites[13].right + 10;
d3dSprite->Draw(menuTexture, &menuSprites[16], NULL, &pos, 0xFFFFFFFF);
}
// ON
else
{
pos.x += menuSprites[13].right + 10 + 14;
d3dSprite->Draw(menuTexture, &menuSprites[15], NULL, &pos, 0xFFFFFFFF);
}
// ACCEPT
pos.x = (640 - menuSprites[14].right) / 2;
pos.y = menuLocations[4];
// Set location for menu selection marker
if(curMenu == 3)
{
selectionLeft = pos.x - 52;
selectionRight = pos.x + menuSprites[14].right + 10;
}
d3dSprite->Draw(menuTexture, &menuSprites[14], NULL, &pos, 0xFFFFFFFF);
// Draw pentagram icon
RECT sLoc;
sLoc.left = 42 * (curMenuFrame % 4);
sLoc.top = 160 + (42 * (int)(curMenuFrame / 4));
sLoc.right = sLoc.left + 42;
sLoc.bottom = sLoc.top + 42;
curMenuFrame++;
if(curMenuFrame > 7) curMenuFrame = 0;
pos.x = selectionLeft;
pos.y = menuLocations[curMenu + 1] - 5;
d3dSprite->Draw(menuTexture,&sLoc,NULL,&pos,0xFFFFFFFF);
pos.x = selectionRight;
d3dSprite->Draw(menuTexture,&sLoc,NULL,&pos,0xFFFFFFFF);
// End sprite drawing
d3dSprite->End();
}
// And... End scene
if(d3d9Device->EndScene() != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present","Failed to end scene");
return false;
}
// Present everthing!
HRESULT hr = d3d9Device->Present( NULL, NULL, NULL, NULL );
// Device lost
if(hr == D3DERR_DEVICELOST)
{
debugMessage(1, "IDirectDrawWrapper::Present","Device lost");
// Attempt to reinit device
return ReinitDevice();
}
else if(hr != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::Present", "Failed to present scene");
return false;
}
return true;
}
/* Helper function for handling menu key press
* vKey - key pressed
*/
BOOL IDirectDrawWrapper::MenuKey(WPARAM vKey)
{
if(vKey == VK_OEM_3)
{
if(inMenu == TRUE)
// No longer in the menu
inMenu = FALSE;
else
{
curMenu = 0;
// Init to current settings
menuWindowed = isWindowed;
menuvSync = vSync;
menuWindowedResolution = 0;
menuFullscreenResolution = 0;
for(int i = 0; i < windowedResolutionCount; i++)
{
if(windowedResolutions[i].x == displayWidthWindowed && windowedResolutions[i].y == displayHeightWindowed)
{
menuWindowedResolution = i;
break;
}
}
menuFullscreenResolution = 0;
for(int i = 0; i < fullscreenResolutionCount; i++)
{
if(fullscreenResolutions[i].x == displayWidthFullscreen && fullscreenResolutions[i].y == displayHeightFullscreen && fullscreenRefreshes[i] == refreshRate)
{
menuFullscreenResolution = i;
break;
}
}
// We are in the menu
inMenu = TRUE;
}
Present();
}
else if(vKey == VK_ESCAPE)
{
inMenu = FALSE;
Present();
}
else if(vKey == VK_DOWN)
{
curMenu++;
if(curMenu > 3) curMenu = 0;
Present();
}
else if(vKey == VK_UP)
{
curMenu--;
if(curMenu < 0) curMenu = 3;
Present();
}
else if(vKey == VK_RIGHT)
{
if(curMenu == 0)
{
if(menuWindowed)
{
menuWindowedResolution++;
if(menuWindowedResolution >= windowedResolutionCount) menuWindowedResolution = 0;
}
else
{
menuFullscreenResolution++;
if(menuFullscreenResolution >= fullscreenResolutionCount) menuFullscreenResolution = 0;
}
}
else if(curMenu == 1)
{
if(menuWindowed)
menuWindowed = false;
else
menuWindowed = true;
}
else if(curMenu == 2)
{
if(menuvSync)
menuvSync = false;
else
menuvSync = true;
}
Present();
}
else if(vKey == VK_LEFT)
{
if(curMenu == 0)
{
if(menuWindowed)
{
menuWindowedResolution--;
if(menuWindowedResolution < 0) menuWindowedResolution = windowedResolutionCount - 1;
}
else
{
menuFullscreenResolution--;
if(menuFullscreenResolution < 0) menuFullscreenResolution = fullscreenResolutionCount - 1;
}
}
else if(curMenu == 1)
{
if(menuWindowed)
menuWindowed = false;
else
menuWindowed = true;
}
else if(curMenu == 2)
{
if(menuvSync)
menuvSync = false;
else
menuvSync = true;
}
Present();
}
else if(vKey == VK_RETURN)
{
inMenu = false;
// Changing from full screen to window mode
if(!isWindowed && menuWindowed)
{
// Go back to desktop resolution first so adjust window won't fail
presParams.Windowed = true;
d3d9Device->Reset(&presParams);
}
isWindowed = menuWindowed;
if(menuWindowed)
{
displayWidth = windowedResolutions[menuWindowedResolution].x;
displayHeight = windowedResolutions[menuWindowedResolution].y;
displayWidthWindowed = displayWidth;
displayHeightWindowed = displayHeight;
}
else
{
displayWidth = fullscreenResolutions[menuFullscreenResolution].x;
displayHeight = fullscreenResolutions[menuFullscreenResolution].y;
refreshRate = fullscreenRefreshes[menuFullscreenResolution];
displayWidthFullscreen = displayWidth;
displayHeightFullscreen = displayHeight;
}
vSync = menuvSync;
AdjustWindow();
CreateD3DDevice();
CreateSurfaceTexture();
Present();
// Write changes to ini file
wchar_t curPath[MAX_PATH];
wchar_t filename[MAX_PATH];
wchar_t temp[1024];
// Get current working directory
GetCurrentDirectory(MAX_PATH, curPath);
wsprintf(filename, TEXT("%s\\ddraw_settings.ini"), curPath);
temp[0] = '\0';
wsprintf(temp, TEXT("%dx%d"), displayWidthWindowed, displayHeightWindowed);
WritePrivateProfileString(TEXT("video"), TEXT("windowedResolution"), temp, filename);
temp[0] = '\0';
wsprintf(temp, TEXT("%dx%d"), displayWidthFullscreen, displayHeightFullscreen);
WritePrivateProfileString(TEXT("video"), TEXT("fullscreenResolution"), temp, filename);
temp[0] = '\0';
wsprintf(temp, TEXT("%d"), refreshRate);
WritePrivateProfileString(TEXT("video"), TEXT("refresh"), temp, filename);
temp[0] = '\0';
wsprintf(temp, TEXT("%d"), isWindowed ? 0 : 1);
WritePrivateProfileString(TEXT("video"), TEXT("fullscreen"), temp, filename);
temp[0] = '\0';
wsprintf(temp, TEXT("%d"), vSync ? 1 : 0);
WritePrivateProfileString(TEXT("video"), TEXT("vsync"), temp, filename);
}
return inMenu;
}
/* Helper function for toggling fullscreen
*
*/
void IDirectDrawWrapper::ToggleFullscreen()
{
// If windowed
if(isWindowed)
{
// Switch to full screen
isWindowed = false;
displayWidth = displayWidthFullscreen;
displayHeight = displayHeightFullscreen;
}
else
{
// Switch to windowed
isWindowed = true;
displayWidth = displayWidthWindowed;
displayHeight = displayHeightWindowed;
// Changing from full screen to window mode
// Go back to desktop resolution first so adjust window won't fail
presParams.Windowed = true;
d3d9Device->Reset(&presParams);
}
// Adjust window
AdjustWindow();
// Recreated D3D objects
CreateD3DDevice();
CreateSurfaceTexture();
Present();
}
/* Helper function for taking a screenshot
*
*/
void IDirectDrawWrapper::DoSnapshot()
{
wchar_t curPath[MAX_PATH];
// Get current working directory
GetCurrentDirectory(MAX_PATH, curPath);
// Create filename first part "Diablo_YYYYMMDD_HHMMSS.png"
wchar_t filename[MAX_PATH];
SYSTEMTIME sysTime;
GetSystemTime(&sysTime);
wchar_t title[1024];
GetWindowText(hWnd, title, 1024);
wsprintf(filename, TEXT("%s\\%s_%.4d%.2d%.2d_%.2d%.2d%.2d.png"), curPath, title, sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
// Make sure it doesn't already exist
WIN32_FIND_DATA findData;
HANDLE findHandle = FindFirstFile(filename, &findData);
int curFileNum = 1;
while(findHandle != INVALID_HANDLE_VALUE)
{
// Close find
FindClose(findHandle);
// Add (num) to end of filename
wsprintf(filename, TEXT("%s\\Diablo_%.4d%.2d%.2d_%.2d%.2d%.2d(%d).png"), curPath, sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, curFileNum);
// Increment current file
curFileNum++;
// Check if this exists
findHandle = FindFirstFile(filename, &findData);
}
// Save texture to file
if(D3DXSaveTextureToFile(filename, D3DXIFF_PNG, surfaceTexture, NULL) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::DoSnapshot", "Error saving texture to file.");
return;
}
debugMessage(2, "IDirectDrawWrapper::DoSnapshot", "Saved Screenshot");
}
/* Helper function for adjusting the window position
*
*/
void IDirectDrawWrapper::AdjustWindow()
{
// If we don't yet have the window quit without action
if(hWnd == NULL) return;
// window mode
if(isWindowed)
{
// Window with border/caption
SetWindowLong(hWnd, GWL_STYLE, WS_VISIBLE | WS_CAPTION);
// Set window size
SetWindowPos(hWnd, NULL, 0, 0, displayWidth, displayHeight, SWP_NOMOVE | SWP_NOZORDER);
// Adjust for window decoration to ensure client area matches display size
RECT tempRect;
GetClientRect(hWnd, &tempRect);
tempRect.right = (displayWidth - tempRect.right) + displayWidth;
tempRect.bottom = (displayHeight - tempRect.bottom) + displayHeight;
// Move window to last position and adjust size
SetWindowPos(hWnd, NULL, lastPosition.x, lastPosition.y, tempRect.right, tempRect.bottom, SWP_NOZORDER);
}
else
{
// Window borderless and fullscreen size
SetWindowLong(hWnd, GWL_STYLE, WS_VISIBLE);
// Set full size
SetWindowPos(hWnd, NULL, 0, 0, displayWidth, displayHeight, SWP_NOZORDER);
}
debugMessage(2, "IDirectDrawWrapper::AdjustWindow", "Complete");
}
/* Helper function to create/recreate D3D device
*
*/
bool IDirectDrawWrapper::CreateD3DDevice()
{
// Release existing vertex buffer
if(vertexBuffer != NULL)
{
vertexBuffer->Release();
vertexBuffer = NULL;
}
// Release existing surface texture
if(surfaceTexture != NULL)
{
surfaceTexture->Release();
surfaceTexture = NULL;
}
// Release sprite
if(d3dSprite != NULL)
{
d3dSprite->Release();
d3dSprite = NULL;
}
// Release texture
if(menuTexture != NULL)
{
menuTexture ->Release();
menuTexture = NULL;
}
// Release existing d3d9device
if(d3d9Device != NULL)
{
if(d3d9Device->Release() != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","Unable to release Direct3D9 device");
return false;
}
d3d9Device = NULL;
}
// Check device caps to make sure it supports dynamic textures
D3DCAPS9 d3dcaps;
ZeroMemory(&d3dcaps, sizeof(D3DCAPS9));
if(d3d9Object->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dcaps) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","Unable to retrieve device-specific information about the device");
return false;
}
// Is dynamic textures flag set?
if((d3dcaps.Caps2 & D3DCAPS2_DYNAMICTEXTURES) == 0)
{
// No dynamic textures
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","Device does not support dynamic textures");
MessageBox(NULL, TEXT("This patch requires a d3d9 driver that supports dynamic textures."), TEXT("Driver Doesn't Meet Requirements"), MB_OK);
return false;
}
ZeroMemory(&presParams,sizeof(presParams));
// Set display window
presParams.hDeviceWindow = hWnd;
// Enumerate modes for format XRGB
UINT modeCount = d3d9Object->GetAdapterModeCount(D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8);
fullscreenResolutionCount = 0;
if(fullscreenResolutions != NULL) delete fullscreenResolutions;
fullscreenResolutions = new POINT[modeCount];
if(fullscreenRefreshes != NULL) delete fullscreenRefreshes;
fullscreenRefreshes = new UINT[modeCount];
D3DDISPLAYMODE d3ddispmode;
D3DDISPLAYMODE set_d3ddispmode;
bool modeFound = false;
// Loop through all modes looking for our requested resolution
for(UINT i = 0; i < modeCount; i++)
{
// Get display modes here
ZeroMemory(&d3ddispmode, sizeof(D3DDISPLAYMODE));
if(d3d9Object->EnumAdapterModes(D3DADAPTER_DEFAULT, D3DFMT_X8R8G8B8, i, &d3ddispmode) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","EnumAdapterModes failed");
MessageBox(NULL, TEXT("Couldn't find full screen mode for requested format."), TEXT("Error Setting Mode"), MB_OK);
return false;
}
if(d3ddispmode.Width == displayWidth && d3ddispmode.Height == displayHeight && d3ddispmode.RefreshRate == refreshRate)
{
// Found a match
modeFound = true;
memcpy(&set_d3ddispmode, &d3ddispmode, sizeof(D3DDISPLAYMODE));
menuFullscreenResolution = fullscreenResolutionCount;
}
// No modes above maximum size
if(d3ddispmode.Width < 1920 && d3ddispmode.Height < 1440) {
fullscreenResolutions[fullscreenResolutionCount].x = d3ddispmode.Width;
fullscreenResolutions[fullscreenResolutionCount].y = d3ddispmode.Height;
fullscreenRefreshes[fullscreenResolutionCount] = d3ddispmode.RefreshRate;
fullscreenResolutionCount++;
}
}
// Set parameters for the current display mode
if(isWindowed)
{
// Window mode
presParams.Windowed = TRUE;
// Swap discard
presParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
// Unknown format
presParams.BackBufferFormat = D3DFMT_UNKNOWN;
}
else
{
// No mode found
if(!modeFound)
{
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","Failed to find compatible fullscreen display mode");
MessageBox(NULL, TEXT("Couldn't find full screen mode for requested format."), TEXT("Error Setting Mode"), MB_OK);
return false;
}
// Fullscreen
presParams.Windowed = FALSE;
// width/height
presParams.BackBufferWidth = set_d3ddispmode.Width;
presParams.BackBufferHeight = set_d3ddispmode.Height;
// Discard swap
presParams.SwapEffect = D3DSWAPEFFECT_DISCARD;
// Display mode fullscreen format
presParams.BackBufferFormat = set_d3ddispmode.Format;
// Display mode refresh
presParams.FullScreen_RefreshRateInHz = set_d3ddispmode.RefreshRate;
}
// Set vsync
if(vSync)
{
presParams.PresentationInterval = D3DPRESENT_INTERVAL_ONE; //VSYNC disabled
}
else
{
presParams.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; //VSYNC enabled
}
// D3DCREATE_NOWINDOWCHANGES possible for alt+tab and mouse leaving window
// create d3d device with hardware vertex processing if it's available
if(d3dcaps.VertexProcessingCaps != 0)
{
if(d3d9Object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presParams, &d3d9Device) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","Failed to create Direct3D9 device");
MessageBox(NULL, TEXT("Failed to create Direct3D9 device."), TEXT("Direct3D9 Device Error"), MB_OK);
return false;
}
}
else
{
if(d3d9Object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presParams, &d3d9Device) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","Failed to create Direct3D9 device");
MessageBox(NULL, TEXT("Failed to create Direct3D9 device."), TEXT("Direct3D9 Device Error"), MB_OK);
return false;
}
}
// Create menu sprite
if(D3DXCreateSprite(d3d9Device, &d3dSprite) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::createD3DDevice","Failed to create Direct3DX9 sprite");
MessageBox(NULL, TEXT("Failed to create Direct3DX9 sprite."), TEXT("Direct3DX9 Error"), MB_OK);
return false;
}
debugMessage(2, "IDirectDrawWrapper::createD3DDevice", "Create D3D9 Object");
// Success
return true;
}
/* Helper function to create surface texture
*
*/
bool IDirectDrawWrapper::CreateSurfaceTexture()
{
// Release existing vertex buffer
if(vertexBuffer != NULL)
{
vertexBuffer->Release();
vertexBuffer = NULL;
}
// Release existing surface texture
if(surfaceTexture != NULL)
{
surfaceTexture->Release();
surfaceTexture = NULL;
}
if(menuTexture != NULL)
{
menuTexture->Release();
menuTexture = NULL;
}
// Create managed dynamic texture to allow locking(debug as video size but change to display size)
if(d3d9Device->CreateTexture(displayModeWidth, displayModeHeight, 1, D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &surfaceTexture, NULL) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to create surface texture");
return false;
}
// Set vertex shader
if(d3d9Device->SetVertexShader(NULL) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to set vertex shader");
return false;
}
// Set fv format
if(d3d9Device->SetFVF(D3DFVF_TLVERTEX) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to set the current vertex stream format");
return false;
}
// Create vertex buffer
if(d3d9Device->CreateVertexBuffer(sizeof(TLVERTEX) * 4, NULL, D3DFVF_TLVERTEX, D3DPOOL_MANAGED, &vertexBuffer, NULL) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to create vertex buffer");
return false;
}
// Set stream source
if(d3d9Device->SetStreamSource(0, vertexBuffer, 0, sizeof(TLVERTEX)) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to set vertex buffer stream source");
return false;
}
// Set render states(no lighting)
if(d3d9Device->SetRenderState(D3DRS_LIGHTING, FALSE) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to set device render state(no lighting)");
return false;
}
// Query the device to see if it supports anything other than point filtering
if(d3d9Object->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, D3DFMT_X8R8G8B8) == D3D_OK)
{
// Set scale mode to linear
if(d3d9Device->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR) != DD_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Failed to set D3D device to LINEAR sampling");
return false;
}
}
else
{
debugMessage(1, "IDirectDrawWrapper::CreateSurfaceTexture","Device doesn't support linear sampling");
}
// Setup verticies (0,0,currentWidth,currentHeight)
TLVERTEX* vertices;
// Lock
if(vertexBuffer->Lock(0, 0, (void**)&vertices, NULL) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to lock vertex buffer");
return false;
}
// Set vertex points
// 0, 0
vertices[0].x = -0.5f;
vertices[0].y = -0.5f;
vertices[0].z = 0.0f;
vertices[0].rhw = 1.0f;
vertices[0].u = 0.0f;
vertices[0].v = 0.0f;
// currentWidth, 0
vertices[1].x = (float)displayWidth - 0.5f;
vertices[1].y = -0.5f;
vertices[1].z = 0.0f;
vertices[1].rhw = 1.0f;
vertices[1].u = 1.0f;
vertices[1].v = 0.0f;
// currentWidth, scaledHeight
vertices[2].x = (float) displayWidth - 0.5f;
vertices[2].y = (float) displayHeight - 0.5f;
vertices[2].z = 0.0f;
vertices[2].rhw = 1.0f;
vertices[2].u = 1.0f;
vertices[2].v = 1.0f;
// 0, currentHeight
vertices[3].x = -0.5f;
vertices[3].y = (float) displayHeight - 0.5f;
vertices[3].z = 0.0f;
vertices[3].rhw = 1.0f;
vertices[3].u = 0.0f;
vertices[3].v = 1.0f;
// Unlcok vertex buffer
if(vertexBuffer->Unlock() != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to unlock vertex buffer");
return false;
}
// Create menu text texture
//HRESULT hr = D3DXCreateTextureFromResource(d3d9Device, hModule, MAKEINTRESOURCE(SPRITEDATA), &menuTexture);
//if(hr != D3D_OK)
//{
// debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture","Unable to create texture from resource.");
// return false;
//}
debugMessage(2, "IDirectDrawWrapper::CreateSurfaceTexture", "D3D9 Texture Created");
return true;
}
// Helper function to reinitialize device
bool IDirectDrawWrapper::ReinitDevice()
{
// Release existing vertex buffer
if(vertexBuffer != NULL)
{
vertexBuffer->Release();
vertexBuffer = NULL;
}
// Release existing surface texture
if(surfaceTexture != NULL)
{
surfaceTexture->Release();
surfaceTexture = NULL;
}
// Release sprite
if(d3dSprite != NULL)
{
d3dSprite->Release();
d3dSprite = NULL;
}
// Release texture
if(menuTexture != NULL)
{
menuTexture->Release();
menuTexture = NULL;
}
// Attempt to reset the device
if(d3d9Device->Reset(&presParams) != D3D_OK)
{
debugMessage(0, "IDirectDrawWrapper::ReinitDevice","Failed to reset Direct3D9 device");
MessageBox(NULL, TEXT("Failed to reset Direct3D9 device."), TEXT("Direct3D9 Error"), MB_OK);
return false;
}
D3DXCreateSprite(d3d9Device, &d3dSprite);
debugMessage(2, "IDirectDrawWrapper::ReinitDevice", "Reset device, now create texture");
// Recreate the surface texutre
return CreateSurfaceTexture();
}