#include <stdio.h>
#include <math.h>
#include "G_ddraw.h"
#include "G_dsound.h"
#include "G_Input.h"
#include "G_main.h"
#include "resource.h"
#include "gens.h"
#include "mem_M68K.h"
#include "vdp_io.h"
#include "vdp_rend.h"
#include "misc.h"
#include "blit.h"
#include "scrshot.h"
#include "net.h"
#include "AWAKE_Std.h"
#include "cdda_mp3.h"

typedef BOOL (*PORT)(unsigned char &pDest,unsigned char &pSrc);
PORT RenderPort;

LPDIRECTDRAW7 lpDD_Init;
LPDIRECTDRAW7 lpDD;
LPDIRECTDRAWSURFACE7 lpDDS_Primary;
LPDIRECTDRAWSURFACE7 lpDDS_Flip;
LPDIRECTDRAWSURFACE7 lpDDS_Back;
LPDIRECTDRAWSURFACE7 lpDDS_Blit;
LPDIRECTDRAWCLIPPER  lpDDC_Clipper;

HBITMAP Logo_bitmap;
HINSTANCE hRenderPlug;

unsigned char ColorMap_B[65536] ={0};
unsigned char ColorMap_G[65536] ={0};
unsigned char ColorMap_R[65536] ={0};

unsigned char ColorMap_B_2p[65536] ={0};
unsigned char ColorMap_G_2p[65536] ={0};
unsigned char ColorMap_R_2p[65536] ={0};

unsigned char ColorMap_B_4p[65536] ={0};
unsigned char ColorMap_G_4p[65536] ={0};
unsigned char ColorMap_R_4p[65536] ={0};

unsigned char ColorMap_B_32X[65536] ={0};
unsigned char ColorMap_G_32X[65536] ={0};
unsigned char ColorMap_R_32X[65536] ={0};

unsigned char ColorMap_B_2p_32X[65536] ={0};
unsigned char ColorMap_G_2p_32X[65536] ={0};
unsigned char ColorMap_R_2p_32X[65536] ={0};

unsigned char ColorMap_B_4p_32X[65536] ={0};
unsigned char ColorMap_G_4p_32X[65536] ={0};
unsigned char ColorMap_R_4p_32X[65536] ={0};

unsigned char MD_Screen_16[320*240*2];

unsigned char b =0;
unsigned char g =0;
unsigned char r =0;

unsigned char Color_Mode =11;

unsigned char *pDest =NULL;

unsigned short MD_ScreenBuffer[336*240];
unsigned short Screen_DotBuffer_A =0;
unsigned short Screen_DotBuffer_B =0;
unsigned short Screen_DotBuffer_C =0;

clock_t Last_Time = 0, New_Time = 0;
clock_t Used_Time = 0;

int Flag_Clr_Scr = 0;
int Sleep_Time;
int FS_VSync;
int W_VSync;
int Stretch; 
int Blit_Soft;
int Effect_Color = 7;
int FPS_Style = EMU_MODE | BLANC;
int Message_Style = EMU_MODE | BLANC | SIZE_X2;
int Kaillera_Error = 0;
int Custom_Horizontal_FS;
int Custom_Vertical_FS;
int Custom_Horizontal_W;
int Custom_Vertical_W;
int  CustomScreen_FS =0;
int  CustomScreen_W =0;
int  Glossiness_Mode =0;

long ColorMap_L32X[65536];
long ColorMap_LMD[65536];
long MD_Screen_32[336*240];

bool RenderPlugin_Render();
bool RenderPlugin_Close();

char RenderPlugin_Path[2048] ="";
static char Info_String[1024] = "";
static int Message_Showed = 0;
static unsigned int Info_Time = 0;

void (*Blit_FS)(unsigned char *Dest, int pitch, int x, int y, int offset);
void (*Blit_W)(unsigned char *Dest, int pitch, int x, int y, int offset);

int (*Update_Frame)();
int (*Update_Frame_Fast)();

int inline Init_16bpp(HWND hWnd,int Rend);
int inline Init_32bpp(HWND hWnd,int Rend);

int inline Flip_16bpp(HWND hWnd);
int inline Flip_32bpp(HWND hWnd);

extern "C"
{
void hq2x_16(unsigned char*, unsigned char*, DWORD, DWORD, DWORD);
void hq2x_32(unsigned char*, unsigned char*, DWORD, DWORD, DWORD);
unsigned int   LUT16to32[65536];
unsigned int   RGBtoYUV[65536];
}

int InitLUTs(void)
{
  int i, j, k, r, g, b, Y, u, v;

  for (i=0; i<65536; i++)
    LUT16to32[i] = ((i & 0xF800) << 8) + ((i & 0x07E0) << 5) + ((i & 0x001F) << 3);

  for (i=0; i<32; i++)
  for (j=0; j<64; j++)
  for (k=0; k<32; k++)
  {
    r = i << 3;
    g = j << 2;
    b = k << 3;
    Y = (r + g + b) >> 2;
    u = 128 + ((r - b) >> 2);
    v = 128 + ((-r + 2*g -b)>>3);
    RGBtoYUV[ (i << 11) + (j << 5) + k ] = (Y<<16) + (u<<8) + v;
  }

  int nMMXsupport = 0;

  __asm
  {
    mov  eax, 1
    cpuid
    and  edx, 0x00800000
    mov  nMMXsupport, edx
  }

  return nMMXsupport;
}


void Put_Info(char *Message, int Duree)
{
	if (Show_Message)
	{
		strcpy(Info_String, Message);
		Info_Time = GetTickCount() + Duree;
		Message_Showed = 1;
	}
}


int Init_Fail(HWND hwnd, char *err)
{
	End_DDraw();
	MessageBox(hwnd, err, "Oups ...", MB_OK);
	DestroyWindow(hwnd);

	return 0;
}

int Init_DDraw(HWND hWnd)
{
	int Rend;

	End_DDraw();
	InitLUTs();

	if (Full_Screen) Rend = Render_FS;
	else Rend = Render_W;

    if(Rend<100)
    return Init_16bpp(hWnd,Rend);
	else
	return Init_32bpp(hWnd,Rend);

	return 1;
}

void End_DDraw()
{

	if (lpDDC_Clipper)
	{
		lpDDC_Clipper->Release();
		lpDDC_Clipper = NULL;
	}

	if (lpDDS_Back)
	{
		lpDDS_Back->Release();
		lpDDS_Back = NULL;
	}

	if (lpDDS_Flip)
	{
		lpDDS_Flip->Release();
		lpDDS_Flip = NULL;
	}

	if (lpDDS_Primary)
	{
		lpDDS_Primary->Release();
		lpDDS_Primary = NULL;
	}

	if (lpDD)
	{
		lpDD->SetCooperativeLevel(HWnd, DDSCL_NORMAL);
		lpDD->Release();
		lpDD = NULL;
	}

	lpDDS_Blit = NULL;
}


HRESULT RestoreGraphics()
{
	HRESULT rval;

	rval = lpDDS_Primary->Restore();
	rval = lpDDS_Back->Restore();

	return rval;
}


int Clear_Primary_Screen(HWND hWnd)
{
	DDSURFACEDESC2 ddsd;
	DDBLTFX ddbltfx;
	RECT RD;
	POINT p;

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

	memset(&ddbltfx, 0, sizeof(ddbltfx));
	ddbltfx.dwSize = sizeof(ddbltfx);
	ddbltfx.dwFillColor = 0;

	if (Full_Screen)
	{
		if (FS_VSync)
		{
			lpDDS_Flip->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
			lpDDS_Primary->Flip(NULL, DDFLIP_WAIT);

			lpDDS_Flip->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
			lpDDS_Primary->Flip(NULL, DDFLIP_WAIT);

			lpDDS_Flip->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
			lpDDS_Primary->Flip(NULL, DDFLIP_WAIT);
		}
		else lpDDS_Primary->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
	}
	else
	{
		p.x = p.y = 0;
		GetClientRect(hWnd, &RD);
		ClientToScreen(hWnd, &p);

		RD.left = p.x;
		RD.top = p.y;
		RD.right += p.x;
		RD.bottom += p.y;

		if (RD.top < RD.bottom)
			lpDDS_Primary->Blt(&RD, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);
	}
    memset(&MD_ScreenBuffer[0],1,336*240*2);
	return 1;
}


int Clear_Back_Screen(HWND hWnd)
{
	DDSURFACEDESC2 ddsd;
	DDBLTFX ddbltfx;

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

	memset(&ddbltfx, 0, sizeof(ddbltfx));
	ddbltfx.dwSize = sizeof(ddbltfx);
	ddbltfx.dwFillColor = 0;

	lpDDS_Back->Blt(NULL, NULL, NULL, DDBLT_WAIT | DDBLT_COLORFILL, &ddbltfx);

	return 1;
}


void Restore_Primary(void)
{
	if (lpDD && Full_Screen && FS_VSync)
	{
		while (lpDDS_Primary->GetFlipStatus(DDGFS_ISFLIPDONE) != DD_OK);
		lpDD->FlipToGDISurface();
	}
}


int Flip(HWND hWnd)
{

	if(CDP ==16)
     return Flip_16bpp(hWnd);

    if(CDP ==32)
     return Flip_32bpp(hWnd);

	return 1;
}


int Update_Gens_Logo(HWND hWnd)
{
	int i, j, m, n;
	static short tab[64000], Init = 0;
	static float renv = 0, ang = 0, zoom_x = 0, zoom_y = 0, pas;
	unsigned short c;

	if (!Init)
	{
		HBITMAP Logo;

		Logo = LoadBitmap(ghInstance,  MAKEINTRESOURCE(IDB_LOGO_BIG));
		GetBitmapBits(Logo, 64000 * 2, tab);
		pas = 0.05;
		Init = 1;
	}

	renv += pas;
	zoom_x = sin(renv);
	if (zoom_x == 0.0) zoom_x = 0.0000001;
	zoom_x = (1 / zoom_x) * 1;
	zoom_y = 1;

	if (VDP_Reg.Set4 & 0x1)
	{
		for(j = 0; j < 240; j++)
		{
			for(i = 0; i < 320; i++)
			{
				m = (float)(i - 160) * zoom_x;
				n = (float)(j - 120) * zoom_y;

				if ((m < 130) && (m >= -130) && (n < 90) && (n >= -90))
				{
					c = tab[m + 130 + (n + 90) * 260];
					if ((c > 31) || (c < 5)) MD_Screen[TAB336[j] + i + 8] = c;
				}
			}
		}
	}
	else
	{
		for(j = 0; j < 240; j++)
		{
			for(i = 0; i < 256; i++)
			{
				m = (float)(i - 128) * zoom_x;
				n = (float)(j - 120) * zoom_y;

				if ((m < 130) && (m >= -130) && (n < 90) && (n >= -90))
				{
					c = tab[m + 130 + (n + 90) * 260];
					if ((c > 31) || (c < 5)) MD_Screen[TAB336[j] + i + 8] = c;
				}
			}
		}
	}

	Half_Blur();
	Flip(hWnd);

	return 1;
}


int Update_Crazy_Effect(HWND hWnd)
{
	int i, j, offset;
	int r = 0, v = 0, b = 0, prev_l, prev_p;
	int RB, G;

 	for(offset = 336 * 240, j = 0; j < 240; j++)
	{
		for(i = 0; i < 336; i++, offset--)
		{
			prev_l = MD_Screen[offset - 336];
			prev_p = MD_Screen[offset - 1];

			if (Mode_555 & 1)
			{
				RB = ((prev_l & 0x7C1F) + (prev_p & 0x7C1F)) >> 1;
				G = ((prev_l & 0x03E0) + (prev_p & 0x03E0)) >> 1;

				if (Effect_Color & 0x4)
				{
					r = RB & 0x7C00;
					if (rand() > 0x2C00) r += 0x0400;
					else r -= 0x0400;
					if (r > 0x7C00) r = 0x7C00;
					else if (r < 0x0400) r = 0;
				}

				if (Effect_Color & 0x2)
				{
					v = G & 0x03E0;
					if (rand() > 0x2C00) v += 0x0020;
					else v -= 0x0020;
					if (v > 0x03E0) v = 0x03E0;
					else if (v < 0x0020) v = 0;
				}

				if (Effect_Color & 0x1)
				{
					b = RB & 0x001F;
					if (rand() > 0x2C00) b++;
					else b--;
					if (b > 0x1F) b = 0x1F;
					else if (b < 0) b = 0;
				}
			}
			else
			{
				RB = ((prev_l & 0xF81F) + (prev_p & 0xF81F)) >> 1;
				G = ((prev_l & 0x07C0) + (prev_p & 0x07C0)) >> 1;

				if (Effect_Color & 0x4)
				{
					r = RB & 0xF800;
					if (rand() > 0x2C00) r += 0x0800;
					else r -= 0x0800;
					if (r > 0xF800) r = 0xF800;
					else if (r < 0x0800) r = 0;
				}

				if (Effect_Color & 0x2)
				{
					v = G & 0x07C0;
					if (rand() > 0x2C00) v += 0x0040;
					else v -= 0x0040;
					if (v > 0x07C0) v = 0x07C0;
					else if (v < 0x0040) v = 0;
				}

				if (Effect_Color & 0x1)
				{
					b = RB & 0x001F;
					if (rand() > 0x2C00) b++;
					else b--;
					if (b > 0x1F) b = 0x1F;
					else if (b < 0) b = 0;
				}
			}

			MD_Screen[offset] = r + v + b;
		}
	}

	Flip(hWnd);

	return 1;
}


int Update_Emulation(HWND hWnd)
{
	static int Over_Time = 0;
	int current_div;

	if (Frame_Skip != -1)
	{
		if (Sound_Enable)
		{
			WP = (WP + 1) & (Sound_Segs - 1);

			if (WP == Get_Current_Seg())
				WP = (WP + Sound_Segs - 1) & (Sound_Segs - 1);

			Write_Sound_Buffer(NULL);
		}

		Update_Controllers();

		if (Frame_Number++ < Frame_Skip)
		{
			Update_Frame_Fast();
		}
		else
		{
			Frame_Number = 0;
			Update_Frame();
			Flip(hWnd);
		}
	}
	else
	{
		if (Sound_Enable)
		{
			while (WP == Get_Current_Seg()) Sleep(Sleep_Time);
			
			RP = Get_Current_Seg();

			while (WP != RP)
			{
				Write_Sound_Buffer(NULL);
				WP = (WP + 1) & (Sound_Segs - 1);
				Update_Controllers();

				if (WP != RP)
				{
					Update_Frame_Fast();
				}
				else
				{
					Update_Frame();
					Flip(hWnd);
				}
			}
		}
		else
		{
			if (CPU_Mode) current_div = 20;
			else current_div = 16 + (Over_Time ^= 1);

			New_Time = GetTickCount();
			Used_Time += (New_Time - Last_Time);
			Frame_Number = Used_Time / current_div;
			Used_Time %= current_div;
			Last_Time = New_Time;

			if (Frame_Number > 8) Frame_Number = 8;

			for (; Frame_Number > 1; Frame_Number--)
			{
				Update_Controllers();
				Update_Frame_Fast();
			}

			if (Frame_Number)
			{
				Update_Controllers();
				Update_Frame();
				Flip(hWnd);
			}
			else Sleep(Sleep_Time);
		}
	}

	return 1;
}


int Update_Emulation_One(HWND hWnd)
{
	Update_Controllers();
	Update_Frame();
	Flip(hWnd);

	return 1;
}


int Update_Emulation_Netplay(HWND hWnd, int player, int num_player)
{
	static int Over_Time = 0;
	int current_div;

	if (CPU_Mode) current_div = 20;
	else current_div = 16 + (Over_Time ^= 1);

	New_Time = GetTickCount();
	Used_Time += (New_Time - Last_Time);
	Frame_Number = Used_Time / current_div;
	Used_Time %= current_div;
	Last_Time = New_Time;

	if (Frame_Number > 6) Frame_Number = 6;

	for (; Frame_Number > 1; Frame_Number--)
	{
		if (Sound_Enable)
		{
			if (WP == Get_Current_Seg()) WP = (WP - 1) & (Sound_Segs - 1);
			Write_Sound_Buffer(NULL);
			WP = (WP + 1) & (Sound_Segs - 1);
		}

		Scan_Player_Net(player);
		if (Kaillera_Error != -1) Kaillera_Error = Kaillera_Modify_Play_Values((void *) (Kaillera_Keys), 2);
		//Kaillera_Error = Kaillera_Modify_Play_Values((void *) (Kaillera_Keys), 2);
		Update_Controllers_Net(num_player);
		Update_Frame_Fast();
	}

	if (Frame_Number)
	{
		if (Sound_Enable)
		{
			if (WP == Get_Current_Seg()) WP = (WP - 1) & (Sound_Segs - 1);
			Write_Sound_Buffer(NULL);
			WP = (WP + 1) & (Sound_Segs - 1);
		}

		Scan_Player_Net(player);
		if (Kaillera_Error != -1) Kaillera_Error = Kaillera_Modify_Play_Values((void *) (Kaillera_Keys), 2);
		//Kaillera_Error = Kaillera_Modify_Play_Values((void *) (Kaillera_Keys), 2);
		Update_Controllers_Net(num_player);
		Update_Frame();
		Flip(hWnd);
	}

	return 1;
}


int Eff_Screen(void)
{
	int i;

	for(i = 0; i < 336 * 240; i++) MD_Screen[i] = 0;

	return 1;
}


int Pause_Screen(void)
{
	int i, j, offset;
	int r, v, b, nr, nv, nb;

	r = v = b = nr = nv = nb = 0;

	for(offset = j = 0; j < 240; j++)
	{
		for(i = 0; i < 336; i++, offset++)
		{
			if (Mode_555 & 1)
			{
				r = (MD_Screen[offset] & 0x7C00) >> 10;
				v = (MD_Screen[offset] & 0x03E0) >> 5;
				b = (MD_Screen[offset] & 0x001F);
			}
			else
			{
				r = (MD_Screen[offset] & 0xF800) >> 11;
				v = (MD_Screen[offset] & 0x07C0) >> 6;
				b = (MD_Screen[offset] & 0x001F);
			}

			nr = nv = nb = (r + v + b) / 3;
			
			if ((nb <<= 1) > 31) nb = 31;

			nr &= 0x1E;
			nv &= 0x1E;
			nb &= 0x1E;

			if (Mode_555 & 1)
				MD_Screen[offset] = (nr << 10) + (nv << 5) + nb;
			else
				MD_Screen[offset] = (nr << 11) + (nv << 6) + nb;
		}
	}

	return 1;
}


int Show_Genesis_Screen(HWND hWnd)
{
	Do_VDP_Only();
	Flip(hWnd);

	return 1;
}


int Take_Shot()
{
	HRESULT rval;
	DDSURFACEDESC2 ddsd;
	RECT RD;
	POINT p;

	if (Full_Screen)
	{
		if (Render_FS == 0)
		{
			if ((Stretch) || (VDP_Reg.Set2 & 0x08))
			{
				RD.top = 0;
				RD.bottom = 240;
			}
			else
			{
				RD.top = 8;
				RD.bottom = 224 + 8;
			}
			if ((Stretch) || (VDP_Reg.Set4 & 0x01))
			{
				RD.left = 0;
				RD.right = 320;
			}
			else
			{
				RD.left = 32;
				RD.right = 256 + 32;
			}
		}
		else if (Render_FS == 1)
		{
			if ((Stretch) || (VDP_Reg.Set2 & 0x08))
			{
				RD.top = 0;
				RD.bottom = 480;
			}
			else
			{
				RD.top = 16;
				RD.bottom = 448 + 16;
			}
			if ((Stretch) || (VDP_Reg.Set4 & 0x01))
			{
				RD.left = 0;
				RD.right = 640;
			}
			else
			{
				RD.left = 64;
				RD.right = 512 + 64;
			}
		}
		else
		{
			if (VDP_Reg.Set2 & 0x08)
			{
				RD.top = 0;
				RD.bottom = 480;
			}
			else
			{
				RD.top = 16;
				RD.bottom = 448 + 16;
			}
			if (VDP_Reg.Set4 & 0x01)
			{
				RD.left = 0;
				RD.right = 640;
			}
			else
			{
				RD.left = 64;
				RD.right = 512 + 64;
			}
		}
	}
	else
	{
		p.x = p.y = 0;
		GetClientRect(HWnd, &RD);
		ClientToScreen(HWnd, &p);

		RD.top = p.y;
		RD.left = p.x;
		RD.bottom += p.y;
		RD.right += p.x;

		if (Render_W == 0)
		{
			if ((!Stretch) && ((VDP_Reg.Set2 & 0x08) == 0))
			{
				RD.top += 8;
				RD.bottom -= 8;
			}
			if ((!Stretch) && ((VDP_Reg.Set4 & 0x01) == 0))
			{
				RD.left += 32;
				RD.right -= 32;
			}

		}
		else
		{
			if ((!Stretch) && ((VDP_Reg.Set2 & 0x08) == 0))
			{
				RD.top += 16;
				RD.bottom -= 16;
			}
			if ((!Stretch) && ((VDP_Reg.Set4 & 0x01) == 0))
			{
				RD.left += 64;
				RD.right -= 64;
			}
		}
	}

	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	rval = lpDDS_Primary->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);

	if (rval == DD_OK)
	{
		Save_Shot((unsigned char *) ddsd.lpSurface + (RD.top * ddsd.lPitch) + (RD.left * 2), Mode_555 & 1, (RD.right - RD.left), (RD.bottom - RD.top), ddsd.lPitch);
		lpDDS_Primary->Unlock(NULL);
		return 1;
	}
	else return 0;
}

int inline Init_16bpp(HWND hWnd,int Rend)
{
    HRESULT rval;
	DDSURFACEDESC2 ddsd;

	if (DirectDrawCreateEx(NULL, (void **)&lpDD_Init,IID_IDirectDraw7, NULL) != DD_OK)
		return Init_Fail(hWnd, "Error with DirectDrawCreate !");

	if (lpDD_Init->QueryInterface(IID_IDirectDraw7, (LPVOID *) &lpDD) != DD_OK)
		return Init_Fail(hWnd, "Error with QueryInterface !\nUpgrade your DirectX version.");

	lpDD_Init->Release();
	lpDD_Init = NULL;

	if (!(Mode_555 & 2))
	{
		memset(&ddsd, 0, sizeof(ddsd));
		ddsd.dwSize = sizeof(ddsd);

		lpDD->GetDisplayMode(&ddsd);

		if (ddsd.ddpfPixelFormat.dwGBitMask == 0x03E0) Mode_555 = 1;
		else Mode_555 = 0;

		Recalculate_Palettes();
	}

	if (Full_Screen)
		rval = lpDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
	else
		rval = lpDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);

	if (rval != DD_OK)
		return Init_Fail(hWnd, "Error with lpDD->SetCooperativeLevel !");

	if (Full_Screen)
	{

		if (lpDD->SetDisplayMode(320 * ((Rend > 0)?2:1), 240 * ((Rend > 0)?2:1), 16, 0, DDSDM_STANDARDVGAMODE) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDD->SetDisplayMode !");

  }

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

	if ((Full_Screen) && (FS_VSync))
	{
		ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
		ddsd.dwBackBufferCount = 2;
	}
	else
	{
		ddsd.dwFlags = DDSD_CAPS;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	}

	if (lpDD->CreateSurface(&ddsd, &lpDDS_Primary, NULL ) != DD_OK)
		return Init_Fail(hWnd, "Error with lpDD->CreateSurface !");

	if (Full_Screen)
	{
	    if (FS_VSync)
		{
			ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

			if (lpDDS_Primary->GetAttachedSurface(&ddsd.ddsCaps, &lpDDS_Flip) != DD_OK)
				return Init_Fail(hWnd, "Error with lpDDPrimary->GetAttachedSurface !");

			lpDDS_Blit = lpDDS_Flip;
		}
		else lpDDS_Blit = lpDDS_Primary;
	}
	else
	{
		if (lpDD->CreateClipper(0, &lpDDC_Clipper, NULL ) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDD->CreateClipper !");

		if (lpDDC_Clipper->SetHWnd(0, hWnd) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDDC_Clipper->SetHWnd !");

		if (lpDDS_Primary->SetClipper(lpDDC_Clipper) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDDS_Primary->SetClipper !");
	}

	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;

	// 0: Normal mode (half resolution)
	// 1: Double mode (double screen resolution, same internal rendering resolution)
	// 2 and higher: doubled internal rendering resolution, for interpolation, etc.
	if (Rend < 2)
	{
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
		ddsd.dwWidth = 336;
		ddsd.dwHeight = 240;
	}
	else
	{
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
		ddsd.dwWidth = 640;
		ddsd.dwHeight = 480;
	}

	if (lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL) != DD_OK)
		return Init_Fail(hWnd, "Error with lpDD->CreateSurface !");

	if (!Full_Screen) lpDDS_Blit = lpDDS_Back;

	if (Rend < 2)
	{
		memset(&ddsd, 0, sizeof(ddsd));
		ddsd.dwSize = sizeof(ddsd);

		if (lpDDS_Back->GetSurfaceDesc(&ddsd) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDD_Back->GetSurfaceDesc !");

		ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PITCH | DDSD_LPSURFACE | DDSD_PIXELFORMAT;
		ddsd.dwWidth = 336;
		ddsd.dwHeight = 240;
		ddsd.lPitch = 336 * 2;
		ddsd.lpSurface = &MD_Screen[0];

		if (lpDDS_Back->SetSurfaceDesc(&ddsd, 0) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDD_Back->SetSurfaceDesc !");
	}

	return 1;
}

int inline Init_32bpp(HWND hWnd,int Rend)
{
    HRESULT rval;
	DDSURFACEDESC2 ddsd;

	if (DirectDrawCreateEx(NULL, (void **)&lpDD_Init,IID_IDirectDraw7, NULL) != DD_OK)
		return Init_Fail(hWnd, "Error with DirectDrawCreate !");

	if (lpDD_Init->QueryInterface(IID_IDirectDraw7, (LPVOID *) &lpDD) != DD_OK)
		return Init_Fail(hWnd, "Error with QueryInterface !\nUpgrade your DirectX version.");

	lpDD_Init->Release();
	lpDD_Init = NULL;

	if (!(Mode_555 & 2))
	{
		memset(&ddsd, 0, sizeof(ddsd));
		ddsd.dwSize = sizeof(ddsd);

		lpDD->GetDisplayMode(&ddsd);

		if (ddsd.ddpfPixelFormat.dwGBitMask == 0x03E0) Mode_555 = 1;
		else Mode_555 = 0;

		Recalculate_Palettes();
	}

	if (Full_Screen)
		rval = lpDD->SetCooperativeLevel(hWnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN);
	else
		rval = lpDD->SetCooperativeLevel(hWnd, DDSCL_NORMAL);

	if (rval != DD_OK)
		return Init_Fail(hWnd, "Error with lpDD->SetCooperativeLevel !");

	if (Full_Screen)
	{
        if(CustomScreen_FS)
		{
		if (lpDD->SetDisplayMode(Custom_Horizontal_FS, Custom_Vertical_FS, 32, 0, DDSDM_STANDARDVGAMODE) != DD_OK)
		    return Init_Fail(hWnd, "Error with lpDD->SetDisplayMode !");
		}
		else
		{
		if (lpDD->SetDisplayMode(320 * ((Rend > 100)?2:1), 240 * ((Rend > 100)?2:1), 32, 0, DDSDM_STANDARDVGAMODE) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDD->SetDisplayMode !");
		}
	}

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

	if ((Full_Screen) && (FS_VSync))
	{
		ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
		ddsd.dwBackBufferCount = 2;
	}
	else
	{
		ddsd.dwFlags = DDSD_CAPS;
		ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
	}

	if (lpDD->CreateSurface(&ddsd, &lpDDS_Primary, NULL ) != DD_OK)
		return Init_Fail(hWnd, "Error with lpDD->CreateSurface !");

	if (Full_Screen)
	{
	    if (FS_VSync)
		{
			ddsd.ddsCaps.dwCaps = DDSCAPS_BACKBUFFER;

			if (lpDDS_Primary->GetAttachedSurface(&ddsd.ddsCaps, &lpDDS_Flip) != DD_OK)
				return Init_Fail(hWnd, "Error with lpDDPrimary->GetAttachedSurface !");
		}
	}
	else
	{
		if (lpDD->CreateClipper(0, &lpDDC_Clipper, NULL ) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDD->CreateClipper !");

		if (lpDDC_Clipper->SetHWnd(0, hWnd) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDDC_Clipper->SetHWnd !");

		if (lpDDS_Primary->SetClipper(lpDDC_Clipper) != DD_OK)
			return Init_Fail(hWnd, "Error with lpDDS_Primary->SetClipper !");
	}

	memset(&ddsd, 0, sizeof(ddsd));
	ddsd.dwSize = sizeof(ddsd);
	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;

	// 0: Normal mode (half resolution)
	// 1: Double mode (double screen resolution, same internal rendering resolution)
	// 2 and higher: doubled internal rendering resolution, for interpolation, etc.
	if (Rend < 102)
	{
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
		ddsd.dwWidth = 336;
		ddsd.dwHeight = 240;
	}
	else
	{
		ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
		ddsd.dwWidth = 640;
		ddsd.dwHeight = 480;
	}

	if (lpDD->CreateSurface(&ddsd, &lpDDS_Back, NULL) != DD_OK)
		return Init_Fail(hWnd, "Error with lpDD->CreateSurface !");

   lpDDS_Back->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
    pDest=(unsigned char *)ddsd.lpSurface;
   lpDDS_Back->Unlock(NULL);
   InitColorMap();
	return 1;
}

int inline Flip_16bpp(HWND hWnd)
{
	HRESULT rval;
	DDSURFACEDESC2 ddsd;
	RECT RectDest, RectSrc;
	POINT p;
	float Ratio_X, Ratio_Y;
	int Dep, i;
	static float FPS = 0.0f, frames[8] = {0, 0, 0, 0, 0, 0, 0, 0};
	static unsigned int old_time = 0, view_fps = 0, index_fps = 0, freq_cpu[2] = {0, 0};
	unsigned int new_time[2];

	ddsd.dwSize = sizeof(ddsd);

	if (Message_Showed)
	{
		if (GetTickCount() > Info_Time)
		{
			Message_Showed = 0;
			strcpy(Info_String, "");
		}
		else Print_Text(Info_String, strlen(Info_String), 10, 210, Message_Style);

	}
	else if (Show_FPS)
	{	
		if (freq_cpu[0] > 1)				// accurate timer ok
		{
			if (++view_fps >= 16)
			{
				QueryPerformanceCounter((union _LARGE_INTEGER *) new_time);

				if (new_time[0] != old_time)
				{					
					FPS = (float) (freq_cpu[0]) * 16.0f / (float) (new_time[0] - old_time);
					sprintf(Info_String, "%.1f", FPS);
				}
				else
				{
					sprintf(Info_String, "too much...");
				}

				old_time = new_time[0];
				view_fps = 0;
			}
		}
		else if (freq_cpu[0] == 1)			// accurate timer not supported
		{
			if (++view_fps >= 10)
			{
				new_time[0] = GetTickCount();
		
				if (new_time[0] != old_time) frames[index_fps] = 10000 / (float)(new_time[0] - old_time);
				else frames[index_fps] = 2000;

				index_fps++;
				index_fps &= 7;
				FPS = 0.0f;

				for(i = 0; i < 8; i++) FPS += frames[i];

				FPS /= 8.0f;
				old_time = new_time[0];
				view_fps = 0;
			}

			sprintf(Info_String, "%.1f", FPS);
		}
		else
		{
			QueryPerformanceFrequency((union _LARGE_INTEGER *) freq_cpu);
			if (freq_cpu[0] == 0) freq_cpu[0] = 1;

			sprintf(Info_String, "", FPS);
		}

		Print_Text(Info_String, strlen(Info_String), 10, 210, FPS_Style);
	}

	if (Fast_Blur) Half_Blur();

	if (Full_Screen)
	{
		if ((VDP_Reg.Set4 & 0x1) || (Debug))
		{
			if (Flag_Clr_Scr != 40)
			{
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
				Flag_Clr_Scr = 40;
			}

			Dep = 0;
			RectSrc.left = 0 + 8;
			RectSrc.right = 320 + 8;
			RectDest.left = 0;
			RectDest.right = 320 << Render_FS;
		}
		else
		{
			if (Flag_Clr_Scr != 32)
			{
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
				Flag_Clr_Scr = 32;
			}

			Dep = 64;
			RectSrc.left = 0 + 8;
			RectSrc.right = 256 + 8;

			if (Stretch)
			{
				RectDest.left = 0;
				RectDest.right = 320 << Render_FS;
			}
			else
			{
				RectDest.left = 32 << Render_FS;
				RectDest.right = (256 + 32) << Render_FS;
			}
		}

		if (Render_FS < 2)
		{
			if (Blit_Soft == 1)
			{
				rval = lpDDS_Blit->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);

				if (Render_FS == 0)
					Blit_FS((unsigned char *) ddsd.lpSurface + ((ddsd.lPitch * (240 - VDP_Num_Vis_Lines) >> 1) + Dep), ddsd.lPitch, 320 - Dep, VDP_Num_Vis_Lines, 32 + Dep * 2);
				else
					Blit_FS((unsigned char *) ddsd.lpSurface + ((ddsd.lPitch * ((240 - VDP_Num_Vis_Lines) >> 1) + Dep) << 1), ddsd.lPitch, 320 - Dep, VDP_Num_Vis_Lines, 32 + Dep * 2);

				lpDDS_Blit->Unlock(NULL);

				if (FS_VSync)
				{
					lpDDS_Primary->Flip(NULL, DDFLIP_WAIT);
				}
			}
			else
			{
				RectSrc.top = 0;
				RectSrc.bottom = VDP_Num_Vis_Lines;

				if ((VDP_Num_Vis_Lines == 224) && (Stretch == 0))
				{
					RectDest.top = 8 << Render_FS;
					RectDest.bottom = (224 + 8) << Render_FS;
				}
				else
				{
					RectDest.top = 0;
					RectDest.bottom = 240 << Render_FS;
				}

				if (FS_VSync)
				{
					lpDDS_Flip->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL);
					lpDDS_Primary->Flip(NULL, DDFLIP_WAIT);
				}
				else
				{
					lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL);
				}
			}
		}
		else
		{
			rval = lpDDS_Blit->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
			if (rval != DD_OK) return 1;	// Assuming surface busy ...
			Blit_FS((unsigned char *) ddsd.lpSurface + ((ddsd.lPitch * ((240 - VDP_Num_Vis_Lines) >> 1) + Dep) << 1), ddsd.lPitch, 320 - Dep, VDP_Num_Vis_Lines, 32 + Dep * 2);
			lpDDS_Blit->Unlock(NULL);

			if (FS_VSync)
			{
				lpDDS_Primary->Flip(NULL, DDFLIP_WAIT);
			}
		}
	}
	else
	{
		p.x = p.y = 0;
		GetClientRect(hWnd, &RectDest);
		ClientToScreen(hWnd, &p);

		Ratio_X = (float) RectDest.right;
		Ratio_Y = (float) RectDest.bottom;
		Ratio_X /= 320.0;
		Ratio_Y /= 240.0;

		RectDest.left = p.x;
		RectDest.top = p.y;
		RectDest.right += p.x;
		RectDest.bottom += p.y;

		if (Render_W < 2)
		{
			RectSrc.top = 0;
			RectSrc.bottom = VDP_Num_Vis_Lines;

			if ((VDP_Num_Vis_Lines == 224) && (Stretch == 0))
			{
				RectDest.top += (int) (8 * Ratio_Y);
				RectDest.bottom -= (int) (8 * Ratio_Y);
			}
		}
		else
		{
			if (VDP_Num_Vis_Lines == 224)
			{
				RectSrc.top =  8 * 2;
				RectSrc.bottom = (224 + 8) * 2;

				if (Stretch == 0)
				{
					RectDest.top += (int) (8 * Ratio_Y);
					RectDest.bottom -= (int) (8 * Ratio_Y);
				}
			}
			else
			{
				RectSrc.top = 0 * 2;
				RectSrc.bottom = 240 * 2;
			}
		}

		if ((VDP_Reg.Set4 & 0x1) || (Debug))
		{
			Dep = 0;

			if (Flag_Clr_Scr != 40)
			{
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
				Flag_Clr_Scr = 40;
			}

			if (Render_W < 2)
			{
				RectSrc.left = 8 + 0 ;
				RectSrc.right = 8 + 320;
			}
			else
			{
				RectSrc.left = 0 * 2;
				RectSrc.right = 320 * 2;
			}
		}
		else
		{
			Dep = 64;

			if (Stretch == 0)
			{
				RectDest.left += int(32 * Ratio_X);
				RectDest.right -= int(32 * Ratio_X);
			}

			if (Flag_Clr_Scr != 32)
			{
				Flag_Clr_Scr = 32;
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
			}

			if (Render_W < 2)
			{
				RectSrc.left = 8 + 0;
				RectSrc.right = 8 + 256;
			}
			else
			{
				RectSrc.left = 32 * 2;
				RectSrc.right = (256 * 2) + (32 * 2);
			}
		}

		if (Render_W >= 2)
		{
	         if(Render_W ==10)
			 {
              int Offset_16 =0;
              int Offset_MD_Screen =0;
              for(int i=0;i<240;i++)
			  {
               memcpy(&MD_Screen_16[Offset_16+Dep],&MD_Screen[Offset_MD_Screen+8],320*2);
               Offset_16+=320*2;
               Offset_MD_Screen+=336;
			  }
			  rval = lpDDS_Back->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
			  if (rval != DD_OK) return 1;	// Assuming surface busy ...
			    hq2x_16(&MD_Screen_16[0],(unsigned char*)ddsd.lpSurface,320,240,640*2);
			  lpDDS_Back->Unlock(NULL);
			 }
			 else
			  {
			    rval = lpDDS_Blit->Lock(NULL, &ddsd, DDLOCK_WAIT, NULL);
			    if (rval != DD_OK) return 1;	// Assuming surface busy ...
			       Blit_W((unsigned char *) ddsd.lpSurface + ((ddsd.lPitch * ((240 - VDP_Num_Vis_Lines) >> 1) + Dep) << 1), ddsd.lPitch, 320 - Dep, VDP_Num_Vis_Lines, 32 + Dep * 2);
			     lpDDS_Blit->Unlock(NULL);
			  }
		}
	
		if (RectDest.top < RectDest.bottom)
		{
			if (W_VSync)
			{
				int vb;

				lpDD->GetVerticalBlankStatus(&vb);

				if (!vb) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
			}

			rval = lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL);
		}
	}

	if (rval == DDERR_SURFACELOST) rval = RestoreGraphics();
	return 1;
}

int inline Flip_32bpp(HWND hWnd)
{
	HRESULT rval;
	DDSURFACEDESC2 ddsd;
	RECT RectDest, RectSrc;
	POINT p;

    int FilterIndex =0;
	if(Full_Screen)
       FilterIndex =Render_FS;
	else
       FilterIndex =Render_W;

	float Ratio_X, Ratio_Y;
	int Dep, i;

	static float FPS = 0.0f, frames[8] = {0, 0, 0, 0, 0, 0, 0, 0};
	static unsigned int old_time = 0, view_fps = 0, index_fps = 0, freq_cpu[2] = {0, 0};
	unsigned int new_time[2];

	ddsd.dwSize = sizeof(ddsd);
	if (Message_Showed)
	{
		if (GetTickCount() > Info_Time)
		{
			Message_Showed = 0;
			strcpy(Info_String, "");
		}
		else Print_Text(Info_String, strlen(Info_String), 10, 210, Message_Style);
	}

	else if (Show_FPS)
	{	
		if (freq_cpu[0] > 1)				// accurate timer ok
		{
			if (++view_fps >= 16)
			{
				QueryPerformanceCounter((union _LARGE_INTEGER *) new_time);

				if (new_time[0] != old_time)
				{					
					FPS = (float) (freq_cpu[0]) * 16.0f / (float) (new_time[0] - old_time);
					sprintf(Info_String, "%.1f", FPS);
				}
				else
				{
					sprintf(Info_String, "too much...");
				}

				old_time = new_time[0];
				view_fps = 0;
			}
		}
		else if (freq_cpu[0] == 1)			// accurate timer not supported
		{
			if (++view_fps >= 10)
			{
				new_time[0] = GetTickCount();
		
				if (new_time[0] != old_time) frames[index_fps] = 10000 / (float)(new_time[0] - old_time);
				else frames[index_fps] = 2000;

				index_fps++;
				index_fps &= 7;
				FPS = 0.0f;

				for(i = 0; i < 8; i++) FPS += frames[i];

				FPS /= 8.0f;
				old_time = new_time[0];
				view_fps = 0;
			}

			sprintf(Info_String, "%.1f", FPS);
		}
		else
		{
			QueryPerformanceFrequency((union _LARGE_INTEGER *) freq_cpu);
			if (freq_cpu[0] == 0) freq_cpu[0] = 1;

			sprintf(Info_String, "", FPS);
		}

		Print_Text(Info_String, strlen(Info_String), 10, 210, FPS_Style);
	}
	if (Fast_Blur) Half_Blur();
//Filter;

int I=0;
int Render_Base =0;
if (Fast_Blur) Half_Blur();

/////////////////////////////////
//Normal;
if(FilterIndex<102)
{
//Unpack RGB;
       int Index =8;

       if(_32X_Started)
          {
			  for(i=0;i<336*240;i+=336)
			  {
				  for(int I=8;I<336-8;I++)
				  {
					  MD_Screen_32[i+I]   = ColorMap_L32X[MD_Screen[Index]];
					  Index++;
				  }
				  Index +=16;
			  }
		  }
	   else
	   {
		   for(i=0;i<336*240;i+=336)
		   {
			   for(int I=8;I<336-8;I++)
			   {
				   MD_Screen_32[i+I]   = ColorMap_LMD[MD_Screen[Index]];
				   Index++;
			   }
			   Index +=16;
		   }
	   }
	   memcpy(&pDest[0],&MD_Screen_32[0],336*240*4);
}
  //////////////////////////////
 //  Gens32 Fliter --Monitor //
//      2005 By DarkDancer  //
/////////////////////////////

if(FilterIndex ==102)
{
	int Index =8;

    unsigned char B_Down =0;
    unsigned char G_Down =0;
    unsigned char R_Down =0;

    unsigned char B_Right =0;
    unsigned char G_Right =0;
    unsigned char R_Right =0;

	for(i=0; i<(640*480*4); i+=640*4 *2 )
	{
		for(I =0;I<640*4;I+= 4*2)
		{

           Screen_DotBuffer_A  =MD_Screen[Index];
           Screen_DotBuffer_B  =MD_Screen[Index+1];
           Screen_DotBuffer_C  =MD_Screen[Index+336];

          if(Screen_DotBuffer_A !=MD_ScreenBuffer[Index] || Screen_DotBuffer_B !=MD_ScreenBuffer[Index+1] || Screen_DotBuffer_C !=MD_ScreenBuffer[Index+336])
		   {
           Render_Base =I+i;
		   if(_32X_Started)
		   {
           b =ColorMap_B_4p_32X[Screen_DotBuffer_A];
		   g =ColorMap_G_4p_32X[Screen_DotBuffer_A];
		   r =ColorMap_R_4p_32X[Screen_DotBuffer_A];

           B_Right =ColorMap_B_4p_32X[Screen_DotBuffer_B];
		   G_Right =ColorMap_G_4p_32X[Screen_DotBuffer_B];
		   R_Right =ColorMap_R_4p_32X[Screen_DotBuffer_B];

		   B_Down =ColorMap_B_4p_32X[Screen_DotBuffer_C];
		   G_Down =ColorMap_G_4p_32X[Screen_DotBuffer_C];
		   R_Down =ColorMap_R_4p_32X[Screen_DotBuffer_C];
		   }
	       else
		   {
				b =ColorMap_B_4p[Screen_DotBuffer_A];
		        g =ColorMap_G_4p[Screen_DotBuffer_A];
		        r =ColorMap_R_4p[Screen_DotBuffer_A];

                B_Right =ColorMap_B_4p[Screen_DotBuffer_B];
		        G_Right =ColorMap_G_4p[Screen_DotBuffer_B];
		        R_Right =ColorMap_R_4p[Screen_DotBuffer_B];

		        B_Down =ColorMap_B_4p[Screen_DotBuffer_C];
		        G_Down =ColorMap_G_4p[Screen_DotBuffer_C];
		        R_Down =ColorMap_R_4p[Screen_DotBuffer_C];
		   }

           unsigned char Bright =(b+g+r)/3;
           if(Bright <=255/4-32)
           Bright =max(b,g) -min(b,r);
        
//Start Render;
		   _asm
		   {
			   mov esi,pDest;
			   mov ebx,Render_Base;
			   mov CL,b;             //Left;
			   add CL,b;
			   add CL,b;
			   add CL,Bright;
               mov [esi+ebx],CL;
			   mov CL,g;
			   add CL,g;
			   add CL,g;
			   add CL,Bright;
			   mov [esi+ebx+1],CL;
			   mov CL,r;
			   add CL,r;
			   add CL,r;
			   add CL,Bright;
			   mov [esi+ebx+2],CL;
              
               mov CL,b;            //Right;
               add CL,B_Right;	
			   add CL,B_Right;
			   add CL,Bright;
		       mov [esi+ebx+4],CL;
               mov CL,g;
			   add CL,G_Right;
			   add CL,G_Right;
			   add CL,Bright;
			   mov [esi+ebx+5],CL;
               mov CL,r;
			   add CL,R_Right;
			   add CL,R_Right;
			   add CL,Bright;
			   mov [esi+ebx+6],CL;

               mov CL,b;            //Down;
               add CL,B_Down;	   
			   add CL,B_Down;
			   add CL,Bright;
		       mov [esi+ebx+2560],CL;
               mov CL,g;
			   add CL,G_Down;
			   add CL,G_Down;
			   add CL,Bright;
			   mov [esi+ebx+2561],CL;
               mov CL,r;
			   add CL,R_Down;
			   add CL,R_Down;
			   add CL,Bright;
			   mov [esi+ebx+2562],CL;
		   }
           pDest[Render_Base+2564] =(Bright+Bright+Bright+b+B_Right+B_Down+b+B_Right+B_Down+b+B_Right+B_Down)/3;
           pDest[Render_Base+2565] =(Bright+Bright+Bright+g+G_Right+G_Down+g+G_Right+G_Down+g+G_Right+G_Down)/3;
           pDest[Render_Base+2566] =(Bright+Bright+Bright+r+R_Right+R_Down+r+R_Right+R_Down+r+R_Right+R_Down)/3;

		  }
        Index++;
        }
		Index +=16;
	}
memcpy(&MD_ScreenBuffer[0],&MD_Screen[0],336*240*2);
}

  ///////////////////////////////////////////////////////
 //  Gens32 Fliter --LCD Screen(Without motion blur)  //
//                              2005 By DarkDancer   //
//////////////////////////////////////////////////////

if(FilterIndex ==103)
{
   int Index =8;    

	for(i=0; i<640*480*4; i+=640*4*2 )
	{
		for(I =0;I<640*4;I+= 4*2)
		{
//Start Render;
           Screen_DotBuffer_A  =MD_Screen[Index];

           if(Screen_DotBuffer_A !=MD_ScreenBuffer[Index])
		   {
             if(_32X_Started)
			 {
               b =ColorMap_B_2p_32X[Screen_DotBuffer_A];
			   g =ColorMap_G_2p_32X[Screen_DotBuffer_A];
			   r =ColorMap_R_2p_32X[Screen_DotBuffer_A];
			 }
             else
			 {
               b =ColorMap_B_2p[Screen_DotBuffer_A];
			   g =ColorMap_G_2p[Screen_DotBuffer_A];
			   r =ColorMap_R_2p[Screen_DotBuffer_A];
			 }
			Render_Base =i+I;

           unsigned char Bright =(b+g+r)/3;
           if(Bright <=255/4-32)
           Bright =max(b,g) -min(b,r);

//First Line;
			 _asm
			 {
               mov esi,pDest;
			   mov ebx,Render_Base;
			   mov CL,b;             //Center;
			   add CL,Bright;
               mov [esi+ebx],CL;
			   mov CL,g;
			   add CL,Bright;
			   mov [esi+ebx+1],CL;
			   mov CL,r;
			   add CL,Bright;
			   mov [esi+ebx+2],CL;

               mov CL,b;             //Right;
               mov [esi+ebx+4],CL;
			   mov CL,g;
			   mov [esi+ebx+5],CL;
			   mov CL,r;
			   mov [esi+ebx+6],CL;

			   mov CL,b;             //Down;
               mov [esi+ebx+2560],CL;
			   mov CL,g;
			   mov [esi+ebx+2561],CL;
			   mov CL,r;
			   mov [esi+ebx+2562],CL;

               mov CL,b;             //DownRight;
               mov [esi+ebx+2564],CL;
			   mov CL,g;
			   mov [esi+ebx+2565],CL;
			   mov CL,r;
			   mov [esi+ebx+2566],CL;
			 }

          }
         Index ++;
		}
		Index +=16;  
}   

memcpy(&MD_ScreenBuffer[0],&MD_Screen[0],336*240*2);
}

  //////////////////////////////////////
 //  Gens32 Fliter --1:1 Scanlines   //
//              2005 By DarkDancer  //
/////////////////////////////////////

if(FilterIndex == 104)
{
        int Index =8;
	for(i=0; i<(640*480*4); i+=640*4 *2 )
	{
		for(I =0;I<640*4;I+= 4*2)
		{
           Screen_DotBuffer_A  =MD_Screen[Index];
           if(Screen_DotBuffer_A !=MD_ScreenBuffer[Index])
		   {
           if(_32X_Started)
			 {
               b =ColorMap_B_2p_32X[Screen_DotBuffer_A];
			   g =ColorMap_G_2p_32X[Screen_DotBuffer_A];
			   r =ColorMap_R_2p_32X[Screen_DotBuffer_A];
			 }
             else
			 {
               b =ColorMap_B_2p[Screen_DotBuffer_A];
			   g =ColorMap_G_2p[Screen_DotBuffer_A];
			   r =ColorMap_R_2p[Screen_DotBuffer_A];
			 }

           unsigned char Bright =(b+g+r)/3;
           if(Bright <=255/4-32)
           Bright =max(b,g) -min(b,r);

           Render_Base =I+i;
//Start Render;

              _asm
			 {
               mov esi,pDest;
			   mov ebx,Render_Base;
			   mov CL,b;             //Center;
			   add CL,Bright;
               mov [esi+ebx],CL;
			   mov CL,g;
			   add CL,Bright;
			   mov [esi+ebx+1],CL;
			   mov CL,r;
			   add CL,Bright;
			   mov [esi+ebx+2],CL;

               mov CL,b;             //Right;
			   add CL,Bright;
               mov [esi+ebx+4],CL;
			   mov CL,g;
			   add CL,Bright;
			   mov [esi+ebx+5],CL;
			   mov CL,r;
			   add CL,Bright;
			   mov [esi+ebx+6],CL;


               mov CL,b;             //Down;
               mov [esi+ebx+2560],CL;
			   mov CL,g;
			   mov [esi+ebx+2561],CL;
			   mov CL,r;
			   mov [esi+ebx+2562],CL;
 

               mov CL,b;             //DownRight;
               mov [esi+ebx+2564],CL;
			   mov CL,g;
			   mov [esi+ebx+2565],CL;
			   mov CL,r;
			   mov [esi+ebx+2566],CL;
			 }
		     }
        Index++;
		}
		Index +=16;
	}
memcpy(&MD_ScreenBuffer[0],&MD_Screen[0],336*240*2);
}

  ///////////////////////////////////
 //  Gens32 Fliter --TV MODE      //
//           2005 By DarkDancer  //
//////////////////////////////////

if(FilterIndex == 105)
{
    int	Index =8;
    unsigned char ColorIndex =0;

	for(i=0; i<(640*480*4); i+=640*4 *2 )
	{
		for(I =0;I<640*4;I+= 4*2)
		{
           Screen_DotBuffer_A  =MD_Screen[Index];
           Screen_DotBuffer_B  =MD_Screen[Index+1];
           if(Screen_DotBuffer_A !=MD_ScreenBuffer[Index] || Screen_DotBuffer_B !=MD_ScreenBuffer[Index+1])
		   {
			   Render_Base =I+i;

               if(_32X_Started)
			   {
				   b =ColorMap_B_4p_32X[Screen_DotBuffer_A];
		           g =ColorMap_G_4p_32X[Screen_DotBuffer_A];
		           r =ColorMap_R_4p_32X[Screen_DotBuffer_A];
               }
               else
               {
				   b =ColorMap_B_4p[Screen_DotBuffer_A];
		           g =ColorMap_G_4p[Screen_DotBuffer_A];
		           r =ColorMap_R_4p[Screen_DotBuffer_A];
               }
		   //red/green;
		       if(ColorIndex ==0)
			   {
				   //red;
	               pDest[Render_Base] =b+b+b+b;
			       pDest[Render_Base+1] =g+g+g+b;
			       pDest[Render_Base+2] = r+r+r+b;
                   //green;
                   pDest[Render_Base+4] = b+b+b+b;
			       pDest[Render_Base+5] = g+g+g+b;
			       pDest[Render_Base+6] = r+r+r+b;


                   //Green;
                   pDest[Render_Base+2560] =   b+b+b+g;
			       pDest[Render_Base+2560+1] = g+g+g+g;
			       pDest[Render_Base+2560+2] = r+r+r+g;
                   //Blue;
                   pDest[Render_Base+2560+4] = b+b+b+r;
			       pDest[Render_Base+2560+5] = g+g+g+r;
			       pDest[Render_Base+2560+6] = r+r+r+r;

			   }

                   //blue/red;
		       if(ColorIndex ==1)
			   {
				   //blue;
	               pDest[Render_Base+2560] =b+b+b+r;
			       pDest[Render_Base+1+2560] =g+g+g+r;
			       pDest[Render_Base+2+2560] = r+r+r+r;
                   //red;
                   pDest[Render_Base+4+2560] = b+b+b+b;
			       pDest[Render_Base+5+2560] = g+g+g+b;
			       pDest[Render_Base+6+2560] = r+r+r+b;

                   //blue;
                   pDest[Render_Base] =   b+b+b+g;
			       pDest[Render_Base+1] = g+g+g+g;
			       pDest[Render_Base+2] = r+r+r+g;
                   //red;
                   pDest[Render_Base+4] = b+b+b+g;
			       pDest[Render_Base+5] = g+g+g+g;
		           pDest[Render_Base+6] = r+r+r+g;
			   }
               //green/blue;
		       if(ColorIndex ==2)
			   {
				   //Green;
	               pDest[Render_Base] =b+b+b+r;
			       pDest[Render_Base+1] =g+g+g+r;
			       pDest[Render_Base+2] = r+r+r+r;
                   //Blue;
                   pDest[Render_Base+4] = b+b+b+r;
			       pDest[Render_Base+5] = g+g+g+r;
			       pDest[Render_Base+6] = r+r+r+r;

                   //red;
                   pDest[Render_Base+2560] =   b+b+b+b;
			       pDest[Render_Base+2560+1] = g+g+g+b;
			       pDest[Render_Base+2560+2] = r+r+r+b;
                   //Green;
                   pDest[Render_Base+2560+4] = b+b+b+g;
			       pDest[Render_Base+2560+5] = g+g+g+g;
			       pDest[Render_Base+2560+6] = r+r+r+g;
			   }
		   }
           ColorIndex++;
           if(ColorIndex ==3)
           ColorIndex =0;
           Index++;
		}
        Index+=16;
	}
    memcpy(&MD_ScreenBuffer[0],&MD_Screen[0],336*240*2);
}


  ///////////////////////////////////
 //  Gens32 Fliter --Paper        //
//          2005 By DarkDancer   //
//////////////////////////////////

if(FilterIndex ==106)
{
    int Index =8;

    unsigned char B_Down =0;
    unsigned char G_Down =0;
    unsigned char R_Down =0;

    unsigned char B_Right =0;
    unsigned char G_Right =0;
    unsigned char R_Right =0;

	for(int i=0; i<(640*480*4); i+=640*4 *2 )
	{
		for(I =0;I<640*4;I+= 4*2)
		{
           Screen_DotBuffer_A  =MD_Screen[Index];
           Screen_DotBuffer_B  =MD_Screen[Index+1];
           Screen_DotBuffer_C  =MD_Screen[Index+336];

         if(Screen_DotBuffer_A !=MD_ScreenBuffer[Index] || Screen_DotBuffer_B !=MD_ScreenBuffer[Index+1] || Screen_DotBuffer_C !=MD_ScreenBuffer[Index+336])
		   {
           Render_Base =I+i;

             if(_32X_Started)
			 {
				 b =ColorMap_B_2p_32X[Screen_DotBuffer_A];
		         g =ColorMap_G_2p_32X[Screen_DotBuffer_A];
		         r =ColorMap_R_2p_32X[Screen_DotBuffer_A];

                 B_Right =ColorMap_B_2p_32X[Screen_DotBuffer_B];
		         G_Right =ColorMap_G_2p_32X[Screen_DotBuffer_B];
		         R_Right =ColorMap_R_2p_32X[Screen_DotBuffer_B];

		         B_Down =ColorMap_B_2p_32X[Screen_DotBuffer_C];
		         G_Down =ColorMap_G_2p_32X[Screen_DotBuffer_C];
		         R_Down =ColorMap_R_2p_32X[Screen_DotBuffer_C];
			 }
             else
			 {
                 b =ColorMap_B_2p[Screen_DotBuffer_A];
		         g =ColorMap_G_2p[Screen_DotBuffer_A];
		         r =ColorMap_R_2p[Screen_DotBuffer_A];

                 B_Right =ColorMap_B_2p[Screen_DotBuffer_B];
		         G_Right =ColorMap_G_2p[Screen_DotBuffer_B];
		         R_Right =ColorMap_R_2p[Screen_DotBuffer_B];

		         B_Down =ColorMap_B_2p[Screen_DotBuffer_C];
		         G_Down =ColorMap_G_2p[Screen_DotBuffer_C];
		         R_Down =ColorMap_R_2p[Screen_DotBuffer_C];
			 }

//Center;
	             pDest[Render_Base]   = b+(B_Right+B_Down)/2;
			     pDest[Render_Base+1] = g+(G_Right+G_Down)/2;
			     pDest[Render_Base+2] = r+(R_Right+R_Down)/2;
            
			_asm
			{
               mov esi,pDest;
			   mov ebx,Render_Base;        
               mov CL,b;               //Right;
			   add CL,B_Right;
               mov [esi+ebx+4],CL;
			   mov CL,g;
			   add CL,G_Right;
			   mov [esi+ebx+5],CL;
			   mov CL,r;
			   add CL,R_Right;
			   mov [esi+ebx+6],CL;

               mov CL,b;               //Down;
			   add CL,B_Down;
               mov [esi+ebx+2560],CL;
			   mov CL,g;
			   add CL,G_Down;
			   mov [esi+ebx+2561],CL;
			   mov CL,r;
			   add CL,R_Down;
			   mov [esi+ebx+2562],CL;

               mov CL,B_Right;               //DownRight;
			   add CL,B_Down;
               mov [esi+ebx+2564],CL;
			   mov CL,G_Right;
			   add CL,G_Down;
			   mov [esi+ebx+2565],CL;
			   mov CL,R_Right;
			   add CL,R_Down;
			   mov [esi+ebx+2566],CL;

			}
		 }

         Index++;
		}
        Index+=16;
	}
    memcpy(&MD_ScreenBuffer[0],&MD_Screen[0],336*240*2);
}

//Hq2x;
if(FilterIndex == 107)
{
int Offset_16 =0;
int Offset_MD_Screen =0;
for(int i=0;i<240;i++)
{
memcpy(&MD_Screen_16[Offset_16],&MD_Screen[Offset_MD_Screen+8],320*2);
Offset_16+=320*2;
Offset_MD_Screen+=336;
}

hq2x_32(&MD_Screen_16[0], pDest, 320, 240, 640*4 );
}

//Render Plugin;
if(FilterIndex == 108)
{
	if(!RenderPlugin_Render())
		return 0;
}

//DisPlay;
//////////////////////////////////////////////////
if(Full_Screen)
{

//Make Paiting Area;

        if(CustomScreen_FS)
		{
          SetRect(&RectDest,0,0,Custom_Horizontal_FS,Custom_Vertical_FS);
		}
		else
		{
        if(FilterIndex ==100)
		{
		SetRect(&RectDest,0,0,320,240);
		}

        if(FilterIndex >100)
		{
		SetRect(&RectDest,0,0,640,480);
		}
		}

		Ratio_X = (float) RectDest.right;
		Ratio_Y = (float) RectDest.bottom;
		Ratio_X /= 320.0;
		Ratio_Y /= 240.0;

		if (FilterIndex < 102)
		{
			RectSrc.top = 0;
			RectSrc.bottom = VDP_Num_Vis_Lines;

			if ((VDP_Num_Vis_Lines == 224) && (Stretch == 0))
			{
				RectDest.top += (int) (8 * Ratio_Y);
				RectDest.bottom -= (int) (8 * Ratio_Y);
			}
		}
		else
		{
			if (VDP_Num_Vis_Lines == 224)
			{
				RectSrc.top =  8 * 2;
				RectSrc.bottom = (224 + 8) * 2;

				if (Stretch == 0)
				{
					RectDest.top += (int) (8 * Ratio_Y);
					RectDest.bottom -= (int) (8 * Ratio_Y);
				}
			}
			else
			{
				RectSrc.top = 0 * 2;
				RectSrc.bottom = 240 * 2;
			}
		}

		if ((VDP_Reg.Set4 & 0x1) || (Debug))
		{
			Dep = 0;

			if (Flag_Clr_Scr != 40)
			{
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
				Flag_Clr_Scr = 40;
			}

			if (FilterIndex < 102)
			{
				RectSrc.left = 8 + 0 ;
				RectSrc.right = 8 + 320;
			}
			else
			{
				RectSrc.left = 0;
				RectSrc.right = 640;
			}
		}
		else
		{
			Dep = 64;

			if (Stretch == 0)
			{
				RectDest.left += int(32 * Ratio_X);
				RectDest.right -= int(32 * Ratio_X);
			}

			if (Flag_Clr_Scr != 32)
			{
				Flag_Clr_Scr = 32;
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
			}

			if (FilterIndex < 102)
			{
				RectSrc.left = 8 + 0;
				RectSrc.right = 8 + 256;
			}
			else
			{
				RectSrc.left = 0;
				RectSrc.right = 640-128;
			}
		}

     if(FS_VSync)
		  {
           rval =lpDDS_Flip->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC,NULL);
           rval =lpDDS_Primary->Flip(NULL, DDFLIP_WAIT);
		  }
		  else
		  {
           rval = lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC,NULL);
		  }
}

//Windowed;
///////////////
else                                             
{
	    p.x = p.y = 0;
		GetClientRect(hWnd, &RectDest);
		ClientToScreen(hWnd, &p);

		Ratio_X = (float) RectDest.right;
		Ratio_Y = (float) RectDest.bottom;
		Ratio_X /= 320.0;
		Ratio_Y /= 240.0;

		RectDest.left = p.x;
		RectDest.top = p.y;
		RectDest.right += p.x;
		RectDest.bottom += p.y;

		if (Render_W < 102)
		{
			RectSrc.top = 0;
			RectSrc.bottom = VDP_Num_Vis_Lines;

			if ((VDP_Num_Vis_Lines == 224) && (Stretch == 0))
			{
				RectDest.top += (int) (8 * Ratio_Y);
				RectDest.bottom -= (int) (8 * Ratio_Y);
			}
		}
		else
		{
			if (VDP_Num_Vis_Lines == 224)
			{
				RectSrc.top =  0;
				RectSrc.bottom = 224  * 2;

				if (Stretch == 0)
				{
					RectDest.top += (int) (8 * Ratio_Y);
					RectDest.bottom -= (int) (8 * Ratio_Y);
				}
			}
			else
			{
				RectSrc.top = 0;
				RectSrc.bottom = 240;
			}
		}

		if ((VDP_Reg.Set4 & 0x1) || (Debug))
		{
			Dep = 0;

			if (Flag_Clr_Scr != 40)
			{
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
				Flag_Clr_Scr = 40;
			}

			if (Render_W < 102)
			{
				RectSrc.left = 8 + 0 ;
				RectSrc.right = 8 + 320;
			}
			else
			{
				RectSrc.left = 0;
				RectSrc.right = 320 * 2;
			}
		}
		else
		{
			Dep = 64;

			if (Stretch == 0)
			{
				RectDest.left += int(32 * Ratio_X);
				RectDest.right -= int(32 * Ratio_X);
			}

			if (Flag_Clr_Scr != 32)
			{
				Flag_Clr_Scr = 32;
				Clear_Primary_Screen(hWnd);
				Clear_Back_Screen(hWnd);
			}

			if (Render_W < 102)
			{
				RectSrc.left = 8 + 0;
				RectSrc.right = 8 + 256;
			}
			else
			{
				RectSrc.left = 0;
				RectSrc.right = 640-128;
			}
		}
            if (W_VSync)
			{
				int vb;

				lpDD->GetVerticalBlankStatus(&vb);

				if (!vb) lpDD->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
			}
			rval = lpDDS_Primary->Blt(&RectDest, lpDDS_Back, &RectSrc, DDBLT_WAIT | DDBLT_ASYNC, NULL);

}
	return 1;
}
void InitColorMap()
{

   if(Mode_555)
   Color_Mode =10;
   else
   Color_Mode =11;

unsigned char ColorMap[256] ={0};
unsigned char ColorMap_32X[256] ={0};

if(Glossiness_Mode ==1)
{
	for(unsigned int i=0;i<32;i++)
    {
		//Init ColorMap;
        ColorMap[i] =32;
        ColorMap[i+32] =32*2;
        ColorMap[i+32*2] =32*3;
        ColorMap[i+32*3] =32*4;
        ColorMap[i+32*4] =32*5;
        ColorMap[i+32*5] =32*6;
        ColorMap[i+32*6] =32*7;
        ColorMap[i+32*7] =255;

        //Init ColorMap 32X;
        ColorMap_32X[i] =32;
        ColorMap_32X[i+32] =32*2;
        ColorMap_32X[i+32*2] =32*3;
        ColorMap_32X[i+32*3] =32*4;
        ColorMap_32X[i+32*4] =32*5;
        ColorMap_32X[i+32*5] =32*6;
        ColorMap_32X[i+32*6] =32*7;
        ColorMap_32X[i+32*7] =255;
     }
     ColorMap[0] =0;
     ColorMap_32X[0] =0;
}
else
{
   //Init ColorMap;
    for(unsigned int i=0;i<32;i++)
       {
		   ColorMap[i] =0;
           ColorMap[i+32] =32;
           ColorMap[i+32*2] =32*2;
           ColorMap[i+32*3] =32*3;
           ColorMap[i+32*4] =32*4;
           ColorMap[i+32*5] =32*5;
           ColorMap[i+32*6] =32*6;
           ColorMap[i+32*7] =255;
       }

//Init ColorMap 32X; 
     for(i=0;i<8;i++)
	  {
		  ColorMap_32X[i] =0;
          ColorMap_32X[i+8] =8;
          ColorMap_32X[i+8*2] =8*2;
          ColorMap_32X[i+8*3] =8*3;
          ColorMap_32X[i+8*4] =8*4;
          ColorMap_32X[i+8*5] =8*5;
          ColorMap_32X[i+8*6] =8*6;
          ColorMap_32X[i+8*7] =8*7;

          ColorMap_32X[i+8*8] =8*8;
          ColorMap_32X[i+8*9] =8*9;
          ColorMap_32X[i+8*10] =8*10;
          ColorMap_32X[i+8*11] =8*11;
          ColorMap_32X[i+8*12] =8*12;
          ColorMap_32X[i+8*13] =8*13;
          ColorMap_32X[i+8*14] =8*14;
          ColorMap_32X[i+8*15] =8*15;

          ColorMap_32X[i+8*16] =8*16;
          ColorMap_32X[i+8*17] =8*17;
          ColorMap_32X[i+8*18] =8*18;
          ColorMap_32X[i+8*19] =8*19;
          ColorMap_32X[i+8*20] =8*20;
          ColorMap_32X[i+8*21] =8*21;
          ColorMap_32X[i+8*22] =8*22;
          ColorMap_32X[i+8*23] =8*23;

          ColorMap_32X[i+8*24] =8*24;
          ColorMap_32X[i+8*25] =8*25;
          ColorMap_32X[i+8*26] =8*26;
          ColorMap_32X[i+8*27] =8*27;
          ColorMap_32X[i+8*28] =8*28;
          ColorMap_32X[i+8*29] =8*29;
          ColorMap_32X[i+8*30] =8*30;
          ColorMap_32X[i+8*31] =255;
}

}

//Init ColorMap32;
unsigned char *pMap_B =&ColorMap_B[0];
unsigned char *pMap_G =&ColorMap_G[0];
unsigned char *pMap_R =&ColorMap_R[0];


for(int i=0;i<=65535;i++)
{
	_asm
	  {
//Ready;
        mov eax,i;  //Current 16bit color
        mov CL,Color_Mode;  //Put Color Mode;

//Get B Value;
        mov esi,pMap_B;
		mov edx,eax; 
        sal edx,CL;
		and edx,63488;        
    	mov [esi+eax],DH;

//Get G Value;
        mov esi,pMap_G;
		mov edx,eax;
        sal edx,5;
		and edx,63488;
		mov [esi+eax],DH;    

//Get R Value;
        mov esi,pMap_R;
        mov edx,eax;
		and edx,63488;
		mov [esi+eax],DH;
}

//Format ColorMap_32X;

ColorMap_B_32X[i] =ColorMap_32X[ColorMap_B[i]];
ColorMap_G_32X[i] =ColorMap_32X[ColorMap_G[i]];
ColorMap_R_32X[i] =ColorMap_32X[ColorMap_R[i]];

ColorMap_B_2p_32X[i] =ColorMap_B_32X[i]/2;
ColorMap_G_2p_32X[i] =ColorMap_G_32X[i]/2;
ColorMap_R_2p_32X[i] =ColorMap_R_32X[i]/2;

ColorMap_B_4p_32X[i] =ColorMap_B_32X[i]/4;
ColorMap_G_4p_32X[i] =ColorMap_G_32X[i]/4;
ColorMap_R_4p_32X[i] =ColorMap_R_32X[i]/4;

//Format ColrMap;
ColorMap_B[i] =ColorMap[ColorMap_B[i]];
ColorMap_G[i] =ColorMap[ColorMap_G[i]];
ColorMap_R[i] =ColorMap[ColorMap_R[i]];

ColorMap_B_2p[i] =ColorMap_B[i]/2;
ColorMap_G_2p[i] =ColorMap_G[i]/2;
ColorMap_R_2p[i] =ColorMap_R[i]/2;

ColorMap_B_4p[i] =ColorMap_B[i]/4;
ColorMap_G_4p[i] =ColorMap_G[i]/4;
ColorMap_R_4p[i] =ColorMap_R[i]/4;

//Color Map for long;
ColorMap_L32X[i] =RGB(ColorMap_B_32X[i],ColorMap_G_32X[i],ColorMap_R_32X[i]);
ColorMap_LMD[i] =RGB(ColorMap_B[i],ColorMap_G[i],ColorMap_R[i]);

}

}

void ShowLogo(HWND hWnd)
{
HDC hdc =GetDC(hWnd);
HDC mdc =CreateCompatibleDC(NULL);
RECT rect;
GetClientRect(hWnd,&rect);
SelectObject(mdc,Logo_bitmap);
StretchBlt(hdc,0,0,rect.right,rect.bottom,mdc,0,0,640,480,SRCCOPY);
ReleaseDC(hWnd,hdc);
DeleteDC(mdc);
}

/////////////////////////////////////////
//   Render Plugin System For Gens32   //
//                2005 by DarkDancer   //
/////////////////////////////////////////

bool RenderPlugin_Link(HWND hWnd)
{
	char Name[2048];
	OPENFILENAME ofn;

	SetCurrentDirectory(Gens_Path);

	strcpy(&Name[0], "Render Plugin.grp");
	memset(&ofn, 0, sizeof(OPENFILENAME));

	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = hWnd;
	ofn.hInstance = ghInstance;
	ofn.lpstrFile = Name;
	ofn.nMaxFile = 2047;
	ofn.lpstrFilter = "Render Plugin\0*.grp\0All Files\0*.*\0\0";
	ofn.nFilterIndex = 1;
	ofn.lpstrInitialDir = Gens_Path;
	ofn.lpstrDefExt = "grp";
	ofn.Flags = 0;

   if(GetOpenFileName(&ofn))
   {
	   memcpy(&RenderPlugin_Path[0],&Name[0],2048);

	   strcpy(Str_Tmp, "Render Plugin ");
	   strcat(Str_Tmp, Name);
	   strcat(Str_Tmp, "Was Registered");
	   Put_Info(Str_Tmp, 2000);
   }
	return true;
}

bool RenderPlugin_Init()
{
    if(hRenderPlug)
	{
		if(!RenderPlugin_Close())
		   return false;
	}

	hRenderPlug =LoadLibrary(RenderPlugin_Path);

    if(hRenderPlug !=NULL)
	{
	RenderPort =(PORT)GetProcAddress(hRenderPlug,"Port");
	//Note:Version check was skinped here.
	return true;
	}

	return false;
}

bool RenderPlugin_Render()
{
   //Unpark RGB here;
	if(hRenderPlug)
	{
    unsigned char MD_Screen32[336*240*4];
    int Index =8;

     for(int i=0;i<336*240*4;i+=336*4)
	 {
		 for(int I=0;I<336*4-16*4;I+=4)
		 {
			 MD_Screen32[i+I]   = ColorMap_B[MD_Screen[Index]];
             MD_Screen32[i+I+1] = ColorMap_G[MD_Screen[Index]];
             MD_Screen32[i+I+2] = ColorMap_R[MD_Screen[Index]];
             Index++;
		 }
         Index +=16;
	 }
    RenderPort(pDest[0],MD_Screen32[0]);
	return true;
	}
	return false;
}

bool RenderPlugin_Close()
{
	if(hRenderPlug)
	{
	if(FreeLibrary(hRenderPlug))
	    return true;
	else
		return false;
	}

		return true;
}
