#include <AfxWin.h>
#include <AfxExt.h>
#include <fstream.h>
#include <ddraw.h>
#include <d3d.h>
#include <d3drm.h>
#include <d3drmwin.h>
#include "RMApp.h"
#include "RMWin.h"


#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

BEGIN_MESSAGE_MAP(RMWin, CFrameWnd)
	//{{AFX_MSG_MAP(RMWin)
	ON_WM_CREATE()
	ON_WM_DESTROY()
	ON_WM_MOUSEMOVE()
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


videomode RMWin::displaymode[100];
int RMWin::totaldisplaymodes;
int RMWin::mousex;
int RMWin::mousey;
UINT RMWin::mousestate;
LPDIRECT3DRM RMWin::d3drm;
LPDIRECT3DRMFRAME RMWin::scene;
LPDIRECT3DRMFRAME RMWin::camera;
LPDIRECT3DRMDEVICE RMWin::device;
LPDIRECT3DRMVIEWPORT RMWin::viewport;
DWORD RMWin::modewidth;
DWORD RMWin::modeheight;
DWORD RMWin::modedepth;
int RMWin::curdisplaymode;


RMWin::RMWin()
{
	Initvars();
}

RMWin::RMWin(int w, int h)
{
	Initvars();
	winrect.right=w;
	winrect.bottom=h;
}

void RMWin::Initvars()
{
	ddraw=0;

	primsurf=0;
	backsurf=0;
	zbufsurf=0;
	palette=0;

	winrect=rectDefault;

	modewidth=0;
	modeheight=0;
	modedepth=0;

	curdisplaymode=-1;
	palettearray=0;

    RMApp* pApp = (RMApp*)AfxGetApp();
    pApp->rmwin = this;
}

BOOL RMWin::Create(const CString& sTitle,int icon,int)
{
	CString sClassName;
	sClassName = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW,
			LoadCursor( 0, IDC_ARROW ),
			0, LoadIcon(AfxGetInstanceHandle(), 
			MAKEINTRESOURCE(icon)) );
	BOOL r=CFrameWnd::Create( sClassName, sTitle, WS_POPUP, winrect, 
			0, 0, WS_EX_TOPMOST );
	return r;
}

int RMWin::OnCreate(LPCREATESTRUCT)
{
	ShowCursor( FALSE );

	Direct3DRMCreate( &d3drm );

	DirectDrawCreate( 0, &ddraw, 0 );

	ddraw->SetCooperativeLevel( GetSafeHwnd(), 
			DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX );

	InitDisplayMode();

	InitMainSurfaces();

	InstallPalette();

	CreateDevice();

	d3drm->CreateFrame( 0, &scene );
	CreateScene();

	return 0;
}

BOOL RMWin::InitDisplayMode()
{
	curdisplaymode=0;

	CDC* dc=GetDC();
	DWORD curdisplaydepth=dc->GetDeviceCaps( BITSPIXEL );
	dc->DeleteDC;
	
	ddraw->EnumDisplayModes( 0, 0, 0, DisplayModeAvailable );

	qsort( displaymode, totaldisplaymodes, sizeof(videomode), CompareModes );
	
	for ( int i=0; i<totaldisplaymodes; i++ )
	{
		DWORD w, h, d;
		GetDisplayModeDims( i, w, h, d );
		if (w==800 && h==600 && d==16 ) //curdisplaydepth)
			curdisplaymode=i;
	}

	GetDisplayModeDims( curdisplaymode, modewidth, modeheight, modedepth );

	ddraw->SetDisplayMode( modewidth, modeheight, modedepth );
	
	return totaldisplaymodes!=0;
}

int RMWin::CompareModes( const void *arg1, const void *arg2 )
{
	videomode* mode1=(videomode*)arg1;
	videomode* mode2=(videomode*)arg2;

	DWORD volume1=mode1->width*mode1->height;
	DWORD volume2=mode2->width*mode2->height;

	if (volume1<volume2)
		return -1;
	else if (volume1>volume2)
		return 1;

	if (mode1->depth<mode2->depth)
		return -1;
	else if (mode1->depth>mode2->depth)
		return 1;
	
	return 0;
}

BOOL RMWin::ClearSurface( LPDIRECTDRAWSURFACE surf, DWORD clr )
{
	DDBLTFX bltfx;
	memset( &bltfx, 0, sizeof(bltfx) );
	bltfx.dwSize = sizeof(bltfx);
	bltfx.dwFillColor = clr;
	surf->Blt( 0, 0, 0, DDBLT_COLORFILL | DDBLT_WAIT, &bltfx );
	return TRUE;
}

HRESULT WINAPI RMWin::DisplayModeAvailable( LPDDSURFACEDESC desc, LPVOID )
{
	int& count=totaldisplaymodes;
	if (count==MAXDISPLAYMODES)
		return DDENUMRET_CANCEL;

	displaymode[count].width=desc->dwWidth;
	displaymode[count].height=desc->dwHeight;
	displaymode[count].depth=desc->ddpfPixelFormat.dwRGBBitCount;

	count++;
	return DDENUMRET_OK;
}

void RMWin::OnDestroy()
{
	if (device)
	{
		device->Release();
		device=0;
	}
	if (ddraw)
	{
		ddraw->FlipToGDISurface();
		ddraw->RestoreDisplayMode();
		ddraw->Release();
		ddraw=0;
		primsurf=0;
		backsurf=0;
		zbufsurf=0;
	}
	if (d3drm)
	{
		d3drm->Release();
		d3drm=0;
	}
}

BOOL RMWin::GetCurDisplayModeDims( DWORD& w, DWORD& h, DWORD& d )
{
	if (curdisplaymode<0 || curdisplaymode>=totaldisplaymodes)
		return FALSE;

	w=displaymode[curdisplaymode].width;
	h=displaymode[curdisplaymode].height;
	d=displaymode[curdisplaymode].depth;

	return TRUE;
}

BOOL RMWin::GetDisplayModeDims( int index, DWORD& w, DWORD& h, DWORD& d )
{
	if (index<0 || index>=totaldisplaymodes)
		return FALSE;

	w=displaymode[index].width;
	h=displaymode[index].height;
	d=displaymode[index].depth;

	return TRUE;
}

BOOL RMWin::CreateDevice()
{
	d3drm->CreateDeviceFromSurface( GetGUID(), ddraw, backsurf, &device );
	device->SetQuality( D3DRMRENDER_GOURAUD );
	
	return TRUE;
}

void RMWin::OnMouseMove( UINT state, CPoint point )
{
	mousestate = state;
	mousex = point.x;
	mousey = point.y;
}

D3DVALUE RMWin::ScaleMesh( LPDIRECT3DRMMESHBUILDER mesh, D3DVALUE dim )
{
	D3DRMBOX box;
	mesh->GetBox( &box );
	D3DVALUE sizex = box.max.x - box.min.x;
	D3DVALUE sizey = box.max.y - box.min.y;
	D3DVALUE sizez = box.max.z - box.min.z;
	D3DVALUE largedim=D3DVALUE(0);
	if (sizex>largedim)
		largedim=sizex;
	if (sizey>largedim)
		largedim=sizey;
	if (sizez>largedim)
		largedim=sizez;
	D3DVALUE scalefactor = dim/largedim;
	mesh->Scale( scalefactor, scalefactor, scalefactor );
	return scalefactor;
}

GUID* RMWin::GetGUID()
{
	D3DFINDDEVICESEARCH searchdata;
	static D3DFINDDEVICERESULT resultdata;
	static GUID* lpguid;
	LPDIRECTDRAW ddraw;
	LPDIRECT3D d3d;
	HRESULT r;

	memset( &searchdata, 0, sizeof(searchdata) );
	searchdata.dwSize = sizeof searchdata;
	searchdata.dwFlags = D3DFDS_COLORMODEL;
	searchdata.dcmColorModel = colormodel;
	//searchdata.dwFlags = D3DFDS_HARDWARE ;
	//searchdata.bHardware = TRUE;

	memset( &resultdata, 0, sizeof(resultdata) );
	resultdata.dwSize = sizeof resultdata;

	r = DirectDrawCreate( 0, &ddraw, 0 );
	if (r!=DD_OK)
	{
		TRACE("DirectDrawCreate() failed\n");
		lpguid=0;
		return lpguid;
	}

	r = ddraw->QueryInterface( IID_IDirect3D, (void**)&d3d );
	if ( r != D3DRM_OK )
		TRACE("d3drm->QueryInterface() failed\n");

	r=d3d->FindDevice( &searchdata, &resultdata );
	if ( r == D3D_OK )
		lpguid = &resultdata.guid;
	else
	{
		TRACE("FindDevice() failed\n");
		lpguid=0;
	}
	
	d3d->Release();
	ddraw->Release();

	return lpguid;
}

void RMWin::UsePalette( CString filename )
{ 
	palettefile=filename;
	palettearray=0;
}

void RMWin::UsePalette( PALETTEENTRY* p )
{
	palettefile="";
	palettearray=p;
}

BOOL RMWin::InstallPalette()
{
	if (palettearray)
		return InstallPaletteFromArray();
	return InstallPaletteFromFile();
}

BOOL RMWin::InstallPaletteFromArray()
{
	PALETTEENTRY pe[256];

	for( int i=0; i<256; i++)
	{
		pe[i].peRed = palettearray[i].peRed;
		pe[i].peGreen = palettearray[i].peGreen;
		pe[i].peBlue = palettearray[i].peBlue;
		pe[i].peFlags = D3DPAL_READONLY;
		TRACE(" { %d, %d, %d, },\n",pe[i].peRed,pe[i].peGreen,pe[i].peBlue);
	}

	HRESULT r=ddraw->CreatePalette( DDPCAPS_8BIT, pe, &palette, 0 );
	if (r!=DD_OK)
	{
		TRACE("failed to load palette data from file\n");
		return FALSE;
	}

	primsurf->SetPalette( palette );
	backsurf->SetPalette( palette );

	return TRUE;
}

BOOL RMWin::InstallPaletteFromFile()
{
	BITMAPFILEHEADER bmpfilehdr;
	BITMAPINFOHEADER bmpinfohdr;
	RGBQUAD quad[256];
	PALETTEENTRY pe[256];
	int ncolors;

	if (palettefile.GetLength()<=0)
		return FALSE;

	if (modedepth!=8)
		return FALSE;

	if (palette)
	{
		palette->Release();
		palette=0;
	}

	ifstream bmp( palettefile, ios::binary | ios::nocreate );

	bmp.read( (char*)&bmpfilehdr, sizeof(bmpfilehdr) );
	bmp.read( (char*)&bmpinfohdr, sizeof(bmpinfohdr) );

	char* ptr=(char*)&bmpfilehdr.bfType;
	if (*ptr!='B' || *++ptr!='M')
	{
		TRACE("invalid bitmap\n");
		return FALSE;
	}

	if (bmpinfohdr.biBitCount!=8)
	{
		TRACE("not 8 bit file!\n");
		return FALSE;
	}

	if (bmpinfohdr.biClrUsed==0)
		ncolors=256;
	else
		ncolors=bmpinfohdr.biClrUsed;

	bmp.read( (char*)quad, sizeof(RGBQUAD)*ncolors );

	for( int i=0; i<ncolors; i++)
	{
		pe[i].peRed = quad[i].rgbRed;
		pe[i].peGreen = quad[i].rgbGreen;
		pe[i].peBlue = quad[i].rgbBlue;
		pe[i].peFlags = D3DPAL_READONLY;
		TRACE(" { %d, %d, %d, },\n",pe[i].peRed,pe[i].peGreen,pe[i].peBlue);
	}

	HRESULT r=ddraw->CreatePalette( DDPCAPS_8BIT, pe, &palette, 0 );
	if (r!=DD_OK)
	{
		TRACE("failed to load palette data from file\n");
		return FALSE;
	}

	primsurf->SetPalette( palette );
	backsurf->SetPalette( palette );

	return TRUE;
}

LPDIRECTDRAWSURFACE RMWin::CreateSurface( DWORD w, DWORD h )
{
	DDSURFACEDESC desc;
	memset( &desc, 0, sizeof(desc) );
	desc.dwSize = sizeof(desc);
	desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
	desc.dwWidth = w;
	desc.dwHeight = h;
    desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
	
	LPDIRECTDRAWSURFACE surf;
	HRESULT r=ddraw->CreateSurface( &desc, &surf, 0 );
	if (r!=DD_OK)
		return 0;

	return surf;
}

BOOL RMWin::ActivateDisplayMode( int index )
{
	DWORD w=displaymode[index].width;
	DWORD h=displaymode[index].height;
	DWORD d=displaymode[index].depth;

	curdisplaymode=index;
	return ActivateDisplayMode( w, h, d );
}

BOOL RMWin::ActivateDisplayMode(DWORD w,DWORD h,DWORD d)
{
	if (modewidth==w && modeheight==h && modedepth==d)
		return TRUE;
	
	modewidth=w;
	modeheight=h;
	modedepth=d;

	if (scene)
	{
		scene->Release();
		scene=0;
	}
	if (device)
	{
		device->Release();
		device=0;
	}
	if (primsurf)
	{
		primsurf->Release();
		primsurf=0;
	}
	if (zbufsurf)
	{
		zbufsurf->Release();
		zbufsurf=0;
	}

	ddraw->SetDisplayMode( modewidth, modeheight, modedepth );

	InitMainSurfaces();

	InstallPalette();

	CreateDevice();

	d3drm->CreateFrame( 0, &scene );
	CreateScene();

	return TRUE;
}

BOOL RMWin::InitMainSurfaces()
{
	if (primsurf)
	{
		primsurf->Release();
		primsurf=0;
	}
	if (zbufsurf)
	{
		zbufsurf->Release();
		zbufsurf=0;
	}

	DDSURFACEDESC desc;
	desc.dwSize = sizeof( desc );
	desc.dwFlags = DDSD_BACKBUFFERCOUNT | DDSD_CAPS;
	desc.dwBackBufferCount = 1;
	desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | 
			DDSCAPS_3DDEVICE | 
			DDSCAPS_FLIP |
			DDSCAPS_COMPLEX;
	ddraw->CreateSurface( &desc, &primsurf, 0 );

	DDSCAPS ddscaps;
	ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
	primsurf->GetAttachedSurface( &ddscaps, &backsurf );

	memset( &desc, 0, sizeof(desc) );
	desc.dwSize = sizeof(DDSURFACEDESC);
	desc.dwFlags = 
			DDSD_WIDTH | DDSD_HEIGHT | 
			DDSD_CAPS | DDSD_ZBUFFERBITDEPTH;
	desc.dwWidth = modewidth;
	desc.dwHeight = modeheight;
	desc.dwZBufferBitDepth = 16;
	desc.ddsCaps.dwCaps= DDSCAPS_ZBUFFER | DDSCAPS_SYSTEMMEMORY;
	ddraw->CreateSurface( &desc, &zbufsurf, 0 );
	backsurf->AddAttachedSurface( zbufsurf );

	return TRUE;
}

void RMWin::SaveSurface( LPDIRECTDRAWSURFACE surf, int number )
{
	HRESULT r;

	DDSURFACEDESC surfdesc;
	memset( &surfdesc, 0, sizeof(surfdesc) );
	surfdesc.dwSize = sizeof(surfdesc);
	surf->GetSurfaceDesc( &surfdesc );

	int surfwidth=surfdesc.dwWidth;
	int surfheight=surfdesc.dwHeight;

	//LPDIRECTDRAWPALETTE pal;
	//r=surf->GetPalette( &pal );
	//TRACE("GetPalette: ");
	//CheckResult( r );

	BITMAPFILEHEADER filehdr;
	BITMAPINFOHEADER infohdr;
	RGBQUAD quads[256];

	memset( &filehdr, 0, sizeof(filehdr) );
	*((char*)&filehdr.bfType)='B';
	*(((char*)&filehdr.bfType)+1)='M';
	filehdr.bfOffBits=sizeof(filehdr)+sizeof(infohdr)+sizeof(quads);

	memset( &infohdr, 0, sizeof(infohdr) );
	infohdr.biSize=sizeof(infohdr);
	infohdr.biWidth=surfwidth;
	infohdr.biHeight=surfheight;
	infohdr.biPlanes=1;
	infohdr.biBitCount=8;
	infohdr.biCompression=BI_RGB;
	infohdr.biSizeImage=surfwidth*surfheight;
	infohdr.biClrUsed=256;

	PALETTEENTRY pe[256];

	palette->GetEntries( 0, 0, 256, pe);
	for (int i=0;i<256;i++)
	{
		quads[i].rgbRed=pe[i].peRed;
		quads[i].rgbGreen=pe[i].peGreen;
		quads[i].rgbBlue=pe[i].peBlue;
	}

	char fname[13];
	sprintf( fname, "screen%.2d.bmp", number );
	FILE* fp=fopen( fname, "wb" );
	fwrite( &filehdr, sizeof(filehdr), 1, fp );
	fwrite( &infohdr, sizeof(infohdr), 1, fp );
	fwrite( quads, sizeof(RGBQUAD), 256, fp );

	DDSURFACEDESC desc;
	memset( &desc, 0, sizeof(desc) );
	desc.dwSize=sizeof(desc);
	r=surf->Lock( 0, &desc, DDLOCK_WAIT, 0 );


	for (int row=surfheight-1;row>=0;row--)
	{
		BYTE* ptr=(BYTE*)desc.lpSurface+row*desc.lPitch;
		fwrite( ptr, desc.lPitch, 1, fp );
	}

	surf->Unlock( 0 );
	fclose( fp );
}


void RMWin::CheckResult( HRESULT result )
{
#ifdef _DEBUG
	BOOL trace=afxTraceEnabled;
	afxTraceEnabled=TRUE;
#endif
	switch ( result )
	{
	case D3DRM_OK:
		TRACE("ok\n");
		break;
	case D3DRMERR_BADALLOC:
		TRACE("Out of memory\n");
		break;
	case D3DRMERR_BADDEVICE:
		TRACE("Device is not compatible with renderer\n"); 
		break;
	case D3DRMERR_BADFILE:
		TRACE("Data file is corrupt\n"); 
		break;
	case D3DRMERR_BADMAJORVERSION:
		TRACE("Bad DLL major version\n"); 
		break;
	case D3DRMERR_BADMINORVERSION:
		TRACE("Bad DLL minor version\n"); 
		break;
	case D3DRMERR_BADOBJECT:
		TRACE("Object expected in argument\n"); 
		break;
	case D3DRMERR_BADTYPE:
		TRACE("Bad argument type passed\n"); 
		break;
	case D3DRMERR_BADVALUE:
		TRACE("Bad argument value passed\n"); 
		break;
	case D3DRMERR_FACEUSED:
		TRACE("Face already used in a mesh\n"); 
		break;
	case D3DRMERR_FILENOTFOUND:
		TRACE("File cannot be opened\n"); 
		break;
	case D3DRMERR_NOTDONEYET:
		TRACE("Unimplemented\n"); 
		break;
	case D3DRMERR_NOTFOUND:
		TRACE("Object not found in specified place\n");
		break;
	case D3DRMERR_UNABLETOEXECUTE:
		TRACE("Unable to carry out procedure\n");
		break;
	default:
		TRACE("Unknown return value - checking DirectDraw values\n");
		CheckDirectDrawResult( result );
		break;
	}
#ifdef _DEBUG
	if (trace==FALSE)
		afxTraceEnabled=FALSE;
#endif
}

void RMWin::CheckDirectDrawResult( HRESULT result )
{
#ifdef _DEBUG
	BOOL trace=afxTraceEnabled;
	afxTraceEnabled=TRUE;
#endif
	TRACE("DirectDraw error: ");
	switch ( result )
	{
	case DD_OK:
		TRACE("ok\n");
		break;
	case DDERR_ALREADYINITIALIZED:
		TRACE("Already Initialized\n");
		break;
	case DDERR_WRONGMODE:
		TRACE("Wrong Mode\n"); 
		break;
	case DDERR_GENERIC:
		TRACE("Generic\n"); 
		break;
	case DDERR_INCOMPATIBLEPRIMARY:
		TRACE("Incampatible Primary\n"); 
		break;
	case DDERR_NO3D:
		TRACE("No 3D\n");
		break;
	case DDERR_NOEXCLUSIVEMODE:
		TRACE("No Exclusive Mode\n");
		break;
	case DDERR_OUTOFMEMORY:
		TRACE("Out of Memory\n");
		break;
	case DDERR_UNSUPPORTEDMODE:
		TRACE("Unsupported mode\n");
		break;
	case DDERR_TOOBIGWIDTH:
		TRACE("width too big\n");
		break;
	case DDERR_INVALIDPARAMS:
		TRACE("invalid params\n");
		break;
	default:
		TRACE("Unknown return value\n");
		break;
	}
#ifdef _DEBUG
	if (trace==FALSE)
		afxTraceEnabled=FALSE;
#endif
}

/*
LPDIRECTDRAWSURFACE RMWin::CreateSurface( CString filename )
{
	BITMAPFILEHEADER bmpfilehdr;
	BITMAPINFOHEADER bmpinfohdr;
	RGBQUAD quads[256];

	FILE* fp=fopen( filename, "rb" );
	if (!fp)
	{
		TRACE("LoadSurface() failed\n");
		return 0;
	}

	fread( &bmpfilehdr, sizeof(bmpfilehdr), 1, fp );
	fread( &bmpinfohdr, sizeof(bmpinfohdr), 1, fp );

	char* ptr=(char*)&bmpfilehdr.bfType;
	if (*ptr!='B' || *++ptr!='M')
	{
		TRACE("LoadSurface: invalid BMP\n");
		return 0;
    }

	WORD bitcount=bmpinfohdr.biBitCount;

	TRACE("BMP bit count: %d\n", bitcount );
	if (!(bitcount==8 || bitcount==24))
	{
		TRACE("LoadSurface: not an 8-bit BMP\n");
		return 0;
	}

	int ncolors;
	if (bmpinfohdr.biClrUsed==0)
		ncolors=(1<<bmpinfohdr.biBitCount);
	else
		ncolors=bmpinfohdr.biClrUsed;
	TRACE("ncolors: %d\n",ncolors);

	TRACE("distance to pixel data: %d\n",bmpfilehdr.bfOffBits);
	TRACE("ftell: %d\n",ftell(fp));

	if (bitcount==8)
		fread( quads, sizeof(RGBQUAD), ncolors, fp );

	long w=bmpinfohdr.biWidth;
	long h=bmpinfohdr.biHeight;
	long size=w*h*(bitcount==8 ? 1 : 3);

	BYTE* buf=new BYTE[size];
	fread( buf, 1, size, fp );
	fclose( fp );

	DDSURFACEDESC desc;
	memset( &desc, 0, sizeof(desc) );
	desc.dwSize = sizeof(desc);
	desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
	desc.dwWidth = w;
	desc.dwHeight = h;
    desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
	
	LPDIRECTDRAWSURFACE surf;
	HRESULT r=ddraw->CreateSurface( &desc, &surf, 0 );
	if (r!=D3DRM_OK)
	{
		TRACE("LoadSurface: failed to create surface\n");
		return 0;
	}

    r=surf->Lock( 0, &desc, 0, 0 );
	if (r!=DD_OK)
    {
		TRACE("LoadSurface: failed to Lock surface\n");
		delete [] buf;
        return 0;
    }

	if (modedepth==8)
	{
		BYTE* surfbits = (BYTE*)desc.lpSurface;
		BYTE* imagebits = (BYTE*)(&buf[(h-1)*w]);
		for( int i=0; i<h; i++ )
		{
			memcpy( surfbits, imagebits, w );
			surfbits += desc.lPitch;
			imagebits -= w;
		}
	}
	else if (modedepth==16)
	{
		BYTE* surfbits = (BYTE*)desc.lpSurface;
		BYTE* imagebits = (BYTE*)(&buf[(h-1)*w]);
		for( int i=0; i<h; i++ )
		{
			for (int j=0; j<w; j++)
			{
				unsigned short index=*(imagebits+j);
				unsigned short r=quads[index].rgbRed;
				unsigned short g=quads[index].rgbGreen;
				unsigned short b=quads[index].rgbBlue;
				unsigned short* color=(unsigned short*)(surfbits+j*2);
				*color = (r<<=10) | (g<<=5) | b;
				*color<<=1;
			}
			surfbits += desc.lPitch;
			imagebits -= w;
		}
	}

	surf->Unlock( 0 );
	
	delete [] buf;

	return surf;
}
*/

/*
BOOL RMWin::LoadSurface( LPDIRECTDRAWSURFACE surf, CString filename )
{
	BITMAPFILEHEADER bmpfilehdr;
	BITMAPINFOHEADER bmpinfohdr;
	RGBQUAD quads[256];

	FILE* fp=fopen( filename, "rb" );
	if (!fp)
	{
		TRACE("LoadSurface() failed\n");
		return 0;
	}

	fread( &bmpfilehdr, sizeof(bmpfilehdr), 1, fp );
	fread( &bmpinfohdr, sizeof(bmpinfohdr), 1, fp );

	char* ptr=(char*)&bmpfilehdr.bfType;
	if (*ptr!='B' || *++ptr!='M')
	{
		TRACE("LoadSurface: invalid BMP\n");
		return FALSE;
    }

	if (bmpinfohdr.biBitCount!=8)
	{
		TRACE("LoadSurface: not 8-bit BMP\n");
		return FALSE;
	}

	int ncolors=0;
	if (bmpinfohdr.biClrUsed==0)
		ncolors=(1<<bmpinfohdr.biBitCount);
	else
		ncolors=bmpinfohdr.biClrUsed;
	fread( quads, sizeof(RGBQUAD), ncolors, fp );

	long w=bmpinfohdr.biWidth;
	long h=bmpinfohdr.biHeight;
	long size=w*h;

	BYTE* buf=new BYTE[size];
	fread( buf, 1, size, fp );
	fclose( fp );

	DDSURFACEDESC desc;
	memset( &desc, 0, sizeof(desc) );
	desc.dwSize = sizeof(desc);
	HRESULT r=surf->Lock( 0, &desc, 0, 0 );
	if (r!=DD_OK)
    {
		TRACE("LoadSurface: Lock() failed\n");
		delete [] buf;
        return FALSE;
    }

	if (modedepth==8)
	{
		BYTE* surfbits = (BYTE*)desc.lpSurface;
		BYTE* imagebits = (BYTE*)(&buf[(h-1)*w]);
		for( int i=0; i<h; i++ )
		{
			memcpy( surfbits, imagebits, w );
			surfbits += desc.lPitch;
			imagebits -= w;
		}
	}
	else if (modedepth==16)
	{
		BYTE* surfbits = (BYTE*)desc.lpSurface;
		BYTE* imagebits = (BYTE*)(&buf[(h-1)*w]);
		for( int i=0; i<h; i++ )
		{
			for (int j=0; j<w; j++)
			{
				unsigned short index=*(imagebits+j);
				unsigned short r=quads[index].rgbRed;
				unsigned short g=quads[index].rgbGreen;
				unsigned short b=quads[index].rgbBlue;
				unsigned short* color=(unsigned short*)(surfbits+j*2);
				*color = (r<<=10) | (g<<=5) | b;
				*color<<=1;
			}
			surfbits += desc.lPitch;
			imagebits -= w;
		}
	}

	surf->Unlock( 0 );
	delete [] buf;

	return TRUE;
}
*/
