
// HEADER FILES ------------------------------------------------------------

#ifndef INITGUID
//#define INITGUID
#endif

#include <objbase.h>
//#include <initguid.h>
//#include <ddraw.h>
#include <mmsystem.h>
#include <stdio.h>
#include <math.h>

#define __BYTEBOOL__
#include "doomtype.h"
#include "c_dispatch.h"
#include "c_console.h"

#include "doomstat.h"
#include "cmdlib.h"
#include "i_system.h"
#include "i_input.h"
#include "i_video.h"
#include "v_video.h"
#include "v_text.h"
#include "m_argv.h"
#include "d_main.h"
#include "m_alloc.h"
#include "c_console.h"
#include "c_cvars.h"
#include "c_dispatch.h"
#include "st_stuff.h"
#include "doomdef.h"
#include "z_zone.h"

#include "win32iface.h"

// MACROS ------------------------------------------------------------------

#define true TRUE
#define false FALSE

// TYPES -------------------------------------------------------------------

// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------

// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------

// EXTERNAL DATA DECLARATIONS ----------------------------------------------

extern HWND Window;
extern BOOL vidactive;	// Checked to avoid annoying flashes on console
						// during startup if developer is true
extern BOOL setmodeneeded;
extern int	NewWidth, NewHeight, NewBits;

// PUBLIC DATA DEFINITIONS -------------------------------------------------

EXTERN_CVAR (vid_palettehack)

// PRIVATE DATA DEFINITIONS ------------------------------------------------

// CODE --------------------------------------------------------------------

Win32Video::Win32Video (int parm)
{
	m_CalledCoInitialize = false;
	m_Modes = NULL;
	m_Chain = NULL;
	m_Have320x200x8 = false;
	m_Have320x240x8 = false;
	m_DDObj = NULL;
	m_DDPalette = NULL;
	m_DDPrimary = NULL;
	m_DDBack = NULL;
	m_LastUpdatedCanvas = NULL;
	m_NeedPalChange = 0;

	I_DetectOS ();
	InitDDraw ();
}

Win32Video::~Win32Video ()
{
	FreeModes ();

	while (m_Chain)
		ReleaseSurface (m_Chain->canvas);
	
	m_Chain = NULL; // DL - fix

	if (m_DDObj)
	{
		if (m_DDPalette)
		{
			m_DDPalette->Release();
			m_DDPalette = NULL;
		}
		if (m_DDPrimary)
		{
			m_DDPrimary->Release();
			m_DDPrimary = NULL;
		}
		if (m_DDBack) // DL - fix
		{
			m_DDBack->Release(); // todo sort out crash on window destroyed
			m_DDBack = NULL;
		}
		m_DDObj->Release();
		m_DDObj = NULL;
	}

	if (m_CalledCoInitialize)
	{
		CoUninitialize ();
		m_CalledCoInitialize = false;
	}

	ShowWindow (Window, SW_HIDE);
}

void Win32Video::InitDDraw ()
{
	CBData cbdata;
	HRESULT dderr;

	CoInitialize (NULL);
	m_CalledCoInitialize = true;

	dderr = CoCreateInstance (CLSID_DirectDraw, 0, CLSCTX_INPROC_SERVER,
		IID_IDirectDraw, (void **)&m_DDObj);

	if (FAILED(dderr))
		I_FatalError ("Could not create DirectDraw object: %x", dderr);

	dderr = m_DDObj->Initialize (0);
	if (FAILED(dderr))
	{
		m_DDObj->Release ();
		I_FatalError ("Could not initialize DirectDraw object");
	}

	dderr = m_DDObj->SetCooperativeLevel (Window, DDSCL_EXCLUSIVE |
		DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX);
	if (FAILED(dderr))
	{
		m_DDObj->Release ();
		I_FatalError ("Could not set cooperative level: %x", dderr);
	}

	FreeModes ();
	cbdata.self = this;
	cbdata.modes = (ModeInfo *)&m_Modes;
	dderr = m_DDObj->EnumDisplayModes (0, NULL, &cbdata, EnumDDModesCB);
	if (FAILED(dderr))
	{
		m_DDObj->Release ();
		I_FatalError ("Could not enumerate display modes: %x", dderr);
	}
	if (m_Modes == NULL)
	{
		m_DDObj->Release ();
		I_FatalError ("DirectDraw returned no display modes. Try rebooting.");
	}
	if (OSPlatform == os_Win95)
	{
		// Windows 95 will let us use Mode X. If we didn't find any linear
		// modes in the loop above, add the Mode X modes here.

		if (!m_Have320x200x8)
			AddMode (320, 200, 8, &cbdata.modes);
		if (!m_Have320x240x8)
			AddMode (320, 240, 8, &cbdata.modes);
	}
}

HRESULT WINAPI Win32Video::EnumDDModesCB (LPDDSURFACEDESC desc, void *data)
{
	if (desc->ddpfPixelFormat.dwRGBBitCount == 8 &&
		desc->dwHeight <= 1024)
	{
		((CBData *)data)->self->AddMode
			(desc->dwWidth, desc->dwHeight, 8,
			&((CBData *)data)->modes);
	}

	return DDENUMRET_OK;
}

void Win32Video::NewDDMode (int width, int height, bool fullscreen)
{
	DDSURFACEDESC ddsd;
	DDSCAPS ddscaps;
	HRESULT err;

	if (m_DDBack)
		{m_DDBack->Release();m_DDBack = NULL;}
	if (m_DDPrimary)
		{m_DDPrimary->Release();m_DDPrimary = NULL;}
	if (m_DDPalette)
		{m_DDPalette->Release();m_DDPalette = NULL;}

	// Switch back to original display mode if switching fullcreen->windowed
	if(m_Fullscreen && !fullscreen)
	{
		m_DDObj->RestoreDisplayMode();
	}

	m_Fullscreen = fullscreen;

	if(m_Fullscreen)
	{
		err = m_DDObj->SetCooperativeLevel (Window, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_ALLOWMODEX);

		if (FAILED(err))
		{
			m_DDObj->Release ();
			I_FatalError ("Could not set cooperative level: %x", err);
		}

		err = m_DDObj->SetDisplayMode (width, height, 8);
		if (err != DD_OK)
			I_FatalError ("Could not set display mode: %x", err);

		memset (&ddsd, 0, sizeof(ddsd));
		ddsd.dwSize = sizeof(ddsd);
		ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX | DDSCAPS_VIDEOMEMORY;
		ddsd.dwBackBufferCount = 2;

		// try to get a triple buffered video memory surface.
		err = m_DDObj->CreateSurface (&ddsd, &m_DDPrimary, NULL);

		if (err != DD_OK)
		{
			// try to get a double buffered video memory surface.
			ddsd.dwBackBufferCount = 1;
			err = m_DDObj->CreateSurface (&ddsd, &m_DDPrimary, NULL);
		}

		if (err != DD_OK)
		{
			// settle for a main memory surface.
			ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
			err = m_DDObj->CreateSurface (&ddsd, &m_DDPrimary, NULL);
		}

		Printf_Bold ("%s-buffering\n", ddsd.dwBackBufferCount == 2 ? "triple" : "double");

		ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
		err = m_DDPrimary->GetAttachedSurface (&ddscaps, &m_DDBack);
		if (err != DD_OK)
			I_FatalError ("Could not get back buffer: %x", err);

		m_DisplayBits = 8;
	}
	else // DL - added windowed/fullscreen in DX
	{
		RECT rc, rcWork;

		// Release Window from Coop with DX
		err = m_DDObj->SetCooperativeLevel(NULL, DDSCL_NORMAL);

		// Set window size
		m_DisplayWidth = width;
		m_DisplayHeight = height;

		SetRect( &rc, 0, 0, width, height );

		AdjustWindowRectEx( &rc, GetWindowStyle(Window), GetMenu(Window) != NULL,
							GetWindowExStyle(Window) );

		SetWindowPos( Window, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
					SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );

		SetWindowPos( Window, HWND_NOTOPMOST, 0, 0, 0, 0,
					SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE );

		if (FAILED(err))
		{
			m_DDObj->Release ();
			I_FatalError ("Could not set cooperative level: %x", err);
		}

		//  Make sure our window does not hang outside of the work area
		SystemParametersInfo( SPI_GETWORKAREA, 0, &rcWork, 0 );

		GetWindowRect( Window, &rc );

		if( rc.left < rcWork.left ) rc.left = rcWork.left;
		if( rc.top  < rcWork.top )  rc.top  = rcWork.top;

		if( rc.right > rcWork.right ) rc.right = rcWork.right;
		if( rc.bottom  > rcWork.bottom )  rc.bottom  = rcWork.bottom;

		SetWindowPos( Window, NULL, rc.left, rc.top, 0, 0,
					SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE );

		// Coop level
		err = m_DDObj->SetCooperativeLevel (Window, DDSCL_NORMAL);

		memset (&ddsd, 0, sizeof(ddsd));
		ddsd.dwSize = sizeof(ddsd);
		ddsd.dwFlags        = DDSD_CAPS;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
		err = m_DDObj->CreateSurface (&ddsd, &m_DDPrimary, NULL);

		ddsd.dwFlags        = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
		ddsd.dwWidth        = width;
	    ddsd.dwHeight       = height;
		err = m_DDObj->CreateSurface (&ddsd, &m_DDBack, NULL);

		LPDIRECTDRAWCLIPPER pcClipper;
		err = m_DDObj->CreateClipper( 0, &pcClipper, NULL );
		err = pcClipper->SetHWnd( 0, Window );
		err = m_DDPrimary->SetClipper( pcClipper );
		pcClipper->Release();

		// DL - Work out pixel format of desktop so we know what bpp to use
		DDPIXELFORMAT ddpixel;
		memset (&ddpixel, 0, sizeof(ddpixel));
		ddpixel.dwSize = sizeof(ddpixel);
		m_DDPrimary->GetPixelFormat(&ddpixel);

		// DL - quick fix for spotting 15bit mode (2)
		//copied from the dx7 docs
		//needs to be cleaned up
		WORD wBits = NULL;
		unsigned long dwMask = ddpixel.dwGBitMask;
		while( dwMask )
			{
			dwMask = dwMask & ( dwMask - 1 ); 
			wBits++;
			}
		if (wBits == 5)
			{
			m_DisplayBits = 15;
			}
		else
			m_DisplayBits = ddpixel.dwRGBBitCount;

		ShowWindow(Window, SW_SHOW);
        GetClientRect( Window, &m_rcWindow );
        ClientToScreen( Window, (POINT*)&m_rcWindow );
        ClientToScreen( Window, (POINT*)&m_rcWindow+1 );
	}

	m_HWNDWindow = Window;

	err = m_DDObj->CreatePalette (DDPCAPS_8BIT | DDPCAPS_ALLOW256, m_PalEntries.pe,	&m_DDPalette, NULL);
	if (err != DD_OK)
		I_FatalError ("Could not create palette: %x", err);

	m_DDPrimary->SetPalette (m_DDPalette);
}

void Win32Video::AddMode (int x, int y, int bits, ModeInfo **lastmode)
{
	ModeInfo *newmode = new ModeInfo (x, y, bits);

	if (x == 320 && bits == 8)
	{
		if (y == 200)
			m_Have320x200x8 = true;
		else if (y == 240)
			m_Have320x240x8 = true;
	}
	(*lastmode)->next = newmode;
	*lastmode = newmode;
}

void Win32Video::FreeModes ()
{
	ModeInfo *mode = m_Modes;

	while (mode)
	{
		ModeInfo *tempmode = mode;
		mode = mode->next;
		delete tempmode;
	}
	m_Modes = NULL;
}

void Win32Video::MakeModesList ()
{
}

bool Win32Video::SetMode (int width, int height, int bits, bool fullscreen)
{
	if (m_DDObj)
	{
		NewDDMode(width, height, fullscreen);
	}
	return true;
}

bool Win32Video::Resize (int width, int height)
{
	if (m_DDObj && !m_Fullscreen)
	{
		//NewDDMode(width, height, m_Fullscreen);
	}
	return true;
}

void Win32Video::SetWindowedScale (float scale)
{
	// FIXME
}

//16, 24 and 32 bit color values
#define _RGB32(r,g,b) (ULONG)((UCHAR)(b)+(((UCHAR)(g))<<8)+(((UCHAR)(r))<<16))
#define _RGB24(r,g,b) (ULONG)((UCHAR)(b)+(((UCHAR)(g))<<8)+(((UCHAR)(r))<<16))
#define _RGB16(r,g,b) (USHORT)(((UCHAR)(b)>>3)+(((UCHAR)(g)>>3)<<6)+(((UCHAR)(r)>>3)<<11))
#define _RGB15(r,g,b) (USHORT)(((UCHAR)(b)>>3)+(((UCHAR)(g)>>3)<<5)+(((UCHAR)(r)>>3)<<10))

ULONG pal32[256], pal24[256];
USHORT pal16[256], pal15[256];

void Win32Video::SetPalette (DWORD *pal)
{
	if (!pal)
		return;

	if (m_DDPalette)
	{
		int i;

		for (i = 0; i < 256; i++)
		{
			m_PalEntries.pe[i].peRed = RPART(pal[i]);
			m_PalEntries.pe[i].peGreen = GPART(pal[i]);
			m_PalEntries.pe[i].peBlue = BPART(pal[i]);
		}
	}
	else
	{
		memcpy (m_PalEntries.ui, pal, 256*sizeof(int));
	}
	m_NeedPalChange++;

	for(int t = 0; t < 256; t++)
	{
		UCHAR peRed = m_PalEntries.pe[t].peRed;
		UCHAR peGreen = m_PalEntries.pe[t].peGreen;
		UCHAR peBlue = m_PalEntries.pe[t].peBlue;

		pal32[t] = _RGB32(peRed, peGreen, peBlue);
		pal24[t] = _RGB24(peRed, peGreen, peBlue);
		pal16[t] = _RGB16(peRed, peGreen, peBlue);
		pal15[t] = _RGB15(peRed, peGreen, peBlue);
	}
}

void Win32Video::UpdateScreen (DCanvas *canvas)
{
	m_LastUpdatedCanvas = canvas;
	int x, y;

	if (vid_palettehack.value)
	{
		if (m_NeedPalChange <= 0)
			m_NeedPalChange = 1;
		else
			m_NeedPalChange++;
	}

	if (!m_DDObj)
		return;

	// Using DirectDrawSurface's Blt method is horrendously slow.
	// Using it to copy an 800x600 framebuffer to the back buffer is
	// slower than using the following routine for a 960x720 surface.

	HRESULT dderr;
	DDSURFACEDESC ddsd;

	memset (&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(DDSURFACEDESC);

	do
	{
		dderr = m_DDBack->Lock (NULL, &ddsd, DDLOCK_WRITEONLY |
			DDLOCK_SURFACEMEMORYPTR, NULL);
	} while ((dderr == DDERR_WASSTILLDRAWING) || (dderr == DDERR_SURFACEBUSY));

	if (dderr == DDERR_SURFACELOST)
	{
		dderr = m_DDPrimary->Restore ();
		do
		{
			dderr = m_DDBack->Lock (NULL, &ddsd, DDLOCK_WRITEONLY |
				DDLOCK_SURFACEMEMORYPTR, NULL);
		} while ((dderr == DDERR_WASSTILLDRAWING) || (dderr == DDERR_SURFACEBUSY));
	}

	if (dderr != DD_OK)
		return;

	byte *to = (byte *)ddsd.lpSurface;
	byte *from = canvas->buffer;

	if(m_Fullscreen)
	{
		if (ddsd.lPitch == canvas->width && canvas->width == canvas->pitch)
		{
			memcpy (to, from, canvas->width * canvas->height);
		}
		else
		{
			for (y = 0; y < canvas->height; y++)
			{
				memcpy (to, from, canvas->width);
				to += ddsd.lPitch;
				from += canvas->pitch;
			}
		}
		do
		{
			dderr = m_DDBack->Unlock (ddsd.lpSurface);
		} while ((dderr == DDERR_WASSTILLDRAWING) || (dderr == DDERR_SURFACEBUSY));

		while (1)
		{
			dderr = m_DDPrimary->Flip (NULL, DDFLIP_WAIT);
			if (dderr == DDERR_SURFACELOST)
			{
				dderr = m_DDPrimary->Restore ();
				if (dderr != DD_OK)
					break;
			}
			if (dderr != DDERR_WASSTILLDRAWING)
				break;
		}
	}
	else
	{
		USHORT *uito = (USHORT *)to;
		ULONG *ulto = (ULONG *)to;

		switch(m_DisplayBits)
		{
		case 32:
			// Transfer to screen bpp
			for (y = 0; y < canvas->height; y++)
			{
				for(x = 0; x < canvas->width; x++)
				{
					*ulto = pal32[from[x]];
					
					ulto++;
				}
				from += canvas->pitch;
			}
			break;
		case 24:
			// Transfer to screen bpp
			for (y = 0; y < canvas->height; y++)
			{
				for(x = 0; x < canvas->width; x++)
				{
					*ulto = pal24[from[x]];

					ulto++;
				}
				from += canvas->pitch;
			}
			break;
		case 16:
			// Transfer to screen bpp
			for (y = 0; y < canvas->height; y++)
			{
				for(x = 0; x < canvas->width; x++)
				{
					*uito = pal16[from[x]];
					
					uito++;
				}
				from += canvas->pitch;
			}
			break;
		case 15:
			// Transfer to screen bpp
			for (y = 0; y < canvas->height; y++)
			{
				for(x = 0; x < canvas->width; x++)
				{
					*uito = pal16[from[x]];
					
					uito++;
				}
				from += canvas->pitch - canvas->width;
			}
			break;
		case 8:
			// Transfer to screen bpp
			for (y = 0; y < canvas->height; y++)
			{
				for(x = 0; x < canvas->width; x++)
				{
					*to = *from;
					
					from++;
					to++;
				}
				from += canvas->pitch - canvas->width;
			}
			break;
		default:
			I_FatalError ("Tried to display to unknown bit depth: %x", m_DisplayBits);
			return;
		}

		// Update window position
        GetClientRect( Window, &m_rcWindow );
        ClientToScreen( Window, (POINT*)&m_rcWindow );
        ClientToScreen( Window, (POINT*)&m_rcWindow+1 );

		// Compensate if the client area does not match the canvas area
		RECT rc;
		GetClientRect( Window, &rc );
		if(rc.right-rc.left != canvas->width
			|| rc.bottom-rc.top != canvas->height)
		{
			SetRect( &rc, 0, 0, canvas->width, canvas->height );

			AdjustWindowRectEx( &rc, GetWindowStyle(Window), GetMenu(Window) != NULL,
								GetWindowExStyle(Window) );

			SetWindowPos( Window, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
						SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE );
		}

		// Unlock back and blit to front
		dderr = m_DDBack->Unlock (ddsd.lpSurface);
		HRESULT err = m_DDPrimary->Blt(&m_rcWindow, m_DDBack, NULL, DDBLT_WAIT, NULL );
	}

	canvas->Unlock ();

	if (m_NeedPalChange > 0)
	{
		m_NeedPalChange--;
		m_DDPalette->SetEntries (0, 0, 256, m_PalEntries.pe);
	}
}

void Win32Video::ReadScreen (byte *block)
{
	int y;
	byte *source;

	m_LastUpdatedCanvas->Lock ();
	source = m_LastUpdatedCanvas->buffer;

	for (y = 0; y < m_LastUpdatedCanvas->height; y++)
	{
		memcpy (block, source, m_LastUpdatedCanvas->width);
		block += m_LastUpdatedCanvas->width;
		source += m_LastUpdatedCanvas->pitch;
	}

	m_LastUpdatedCanvas->Unlock ();
}

// This only changes how the iterator lists modes
bool Win32Video::FullscreenChanged (bool fs)
{
	if (m_IteratorFS != fs)
	{
		m_IteratorFS = fs;
		return true;
	}
	return false;
}

int Win32Video::GetModeCount ()
{
	int count = 0;
	ModeInfo *mode = m_Modes;

	while (mode)
	{
		count++;
		mode = mode->next;
	}
	return count;
}

void Win32Video::StartModeIterator (int bits)
{
	m_IteratorMode = m_Modes;
	m_IteratorBits = bits;
}

bool Win32Video::NextMode (int *width, int *height)
{
	if (m_IteratorMode)
	{
		while (m_IteratorMode && m_IteratorMode->bits != m_IteratorBits)
			m_IteratorMode = m_IteratorMode->next;

		if (m_IteratorMode)
		{
			*width = m_IteratorMode->width;
			*height = m_IteratorMode->height;
			m_IteratorMode = m_IteratorMode->next;
			return true;
		}
	}
	return false;
}

bool Win32Video::AllocateSurface (DCanvas *scrn, int width, int height, int bits, bool primary)
{
	if (scrn->m_Private)
		ReleaseSurface (scrn);

	scrn->width = width;
	scrn->height = height;
	scrn->is8bit = (bits == 8) ? true : false;
	scrn->bits = m_DisplayBits;
	scrn->m_LockCount = 0;
	scrn->m_Palette = NULL;

	if (m_DDObj)
	{
		DDSURFACEDESC ddsd;
		HRESULT dderr;
		LPDIRECTDRAWSURFACE surface;

		if (!scrn->is8bit)
			I_FatalError ("Only 8-bit screens are supported");

		ddsd.dwSize = sizeof(ddsd);
		ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
		ddsd.dwWidth = width;
		ddsd.dwHeight = height;

		dderr = m_DDObj->CreateSurface (&ddsd, &surface, NULL);
		if (SUCCEEDED(dderr))
		{
			Chain *tracer = new Chain (scrn);

			scrn->m_Private = surface;
			tracer->next = m_Chain;
			m_Chain = tracer;

			return true;
		}
	}
	return false;
}

void Win32Video::ReleaseSurface (DCanvas *scrn)
{
	Chain *thisone, **prev;

	if (scrn->m_Private)
	{
		if (m_DDObj)
		{
			// Make sure the surface is unlocked
			if (scrn->m_LockCount)
				((LPDIRECTDRAWSURFACE)(scrn->m_Private))->Unlock (NULL);

			((LPDIRECTDRAWSURFACE)(scrn->m_Private))->Release ();
			scrn->m_Private = NULL;
		}
	}

	scrn->DetachPalette ();

	thisone = m_Chain;
	prev = &m_Chain;
	while (thisone && thisone->canvas != scrn)
	{
		prev = &thisone->next;
		thisone = thisone->next;
	}
	if (thisone)
	{
		*prev = thisone->next;
		delete thisone;
	}
}

void Win32Video::LockSurface (DCanvas *scrn)
{
	if (scrn->m_Private)
	{
		if (m_DDObj)
		{
			DDSURFACEDESC ddsd;
			HRESULT dderr;

			memset (&ddsd, 0, sizeof(ddsd));
			ddsd.dwSize = sizeof(ddsd);
			do
			{
				dderr = ((LPDIRECTDRAWSURFACE)(scrn->m_Private))->Lock (NULL,
					&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL);
			} while (dderr == DDERR_SURFACEBUSY || dderr == DDERR_WASSTILLDRAWING);

			// the surface is always in system memory, so it should never be lost
			if (FAILED(dderr))
				I_FatalError ("Could not lock surface: %x", dderr);

			scrn->buffer = (byte *)ddsd.lpSurface;
			scrn->pitch = ddsd.lPitch;
		}
	}
	else
	{
		scrn->m_LockCount--;
	}
}

void Win32Video::UnlockSurface (DCanvas *scrn)
{
	if (scrn->m_Private)
	{
		if (m_DDObj)
		{
			((LPDIRECTDRAWSURFACE)(scrn->m_Private))->Unlock (scrn->buffer);
		}
		scrn->buffer = NULL;
	}
}

bool Win32Video::Blit (DCanvas *src, int sx, int sy, int sw, int sh,
					   DCanvas *dst, int dx, int dy, int dw, int dh)
{
	return false;
}
