mirror of
https://github.com/jmarshall23/CnC_Remastered_Collection.git
synced 2026-08-12 08:00:55 +02:00
2157 lines
62 KiB
C++
2157 lines
62 KiB
C++
#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();
|
||
}
|
||
|