2004 lines
102 KiB
C++
2004 lines
102 KiB
C++
//
|
||
// DirectDraw class
|
||
//
|
||
#include "DebugOut.h"
|
||
#include "DirectDraw.h"
|
||
#include "COM.h"
|
||
|
||
CDirectDraw DirectDraw;
|
||
|
||
#define COMUSE TRUE
|
||
#define DYNDLL FALSE
|
||
|
||
CDirectDraw::BLTFUNC CDirectDraw::NormalBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Normal,
|
||
&CDirectDraw::Render16bpp_Normal,
|
||
&CDirectDraw::Render24bpp_Normal,
|
||
&CDirectDraw::Render32bpp_Normal,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::ScanlineBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Scanline,
|
||
&CDirectDraw::Render16bpp_Scanline,
|
||
&CDirectDraw::Render24bpp_Scanline,
|
||
&CDirectDraw::Render32bpp_Scanline,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::DoubleBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Double,
|
||
&CDirectDraw::Render16bpp_Double,
|
||
&CDirectDraw::Render24bpp_Double,
|
||
&CDirectDraw::Render32bpp_Double,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::DoubleScanlineBltTable[] = {
|
||
&CDirectDraw::Render8bpp_DoubleScanline,
|
||
&CDirectDraw::Render16bpp_DoubleScanline,
|
||
&CDirectDraw::Render24bpp_DoubleScanline,
|
||
&CDirectDraw::Render32bpp_DoubleScanline,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::nx2xSaIBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Double,
|
||
&CDirectDraw::nx_2xSaI_16bpp,
|
||
&CDirectDraw::Render24bpp_Double,
|
||
&CDirectDraw::nx_2xSaI_32bpp,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::nxSuper2xSaIBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Double,
|
||
&CDirectDraw::nx_Super2xSaI_16bpp,
|
||
&CDirectDraw::Render24bpp_Double,
|
||
&CDirectDraw::nx_Super2xSaI_32bpp,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::nxSuperEagleBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Double,
|
||
&CDirectDraw::nx_SuperEagle_16bpp,
|
||
&CDirectDraw::Render24bpp_Double,
|
||
&CDirectDraw::nx_SuperEagle_32bpp,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::nxScale2xBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Double,
|
||
&CDirectDraw::nx_Scale2x_16bpp,
|
||
&CDirectDraw::Render24bpp_Double,
|
||
&CDirectDraw::nx_Scale2x_32bpp,
|
||
};
|
||
|
||
CDirectDraw::BLTFUNC CDirectDraw::nxHq2xBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Double,
|
||
&CDirectDraw::nx_hq2x_16bpp,
|
||
&CDirectDraw::Render24bpp_Double,
|
||
&CDirectDraw::nx_hq2x_32bpp,
|
||
};
|
||
CDirectDraw::BLTFUNC CDirectDraw::nxLq2xBltTable[] = {
|
||
&CDirectDraw::Render8bpp_Double,
|
||
&CDirectDraw::nx_lq2x_16bpp,
|
||
&CDirectDraw::Render24bpp_Double,
|
||
&CDirectDraw::nx_lq2x_32bpp,
|
||
};
|
||
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// デフォルトパレット
|
||
//////////////////////////////////////////////////////////////////////
|
||
CDirectDraw::PALBUF CDirectDraw::m_PalDefault[] = {
|
||
0x7F, 0x7F, 0x7F, 0x20, 0x00, 0xB0, 0x28, 0x00, 0xB8, 0x60, 0x10, 0xA0, 0x98, 0x20, 0x78, 0xB0,
|
||
0x10, 0x30, 0xA0, 0x30, 0x00, 0x78, 0x40, 0x00, 0x48, 0x58, 0x00, 0x38, 0x68, 0x00, 0x38, 0x6C,
|
||
0x00, 0x30, 0x60, 0x40, 0x30, 0x50, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
||
0xBC, 0xBC, 0xBC, 0x40, 0x60, 0xF8, 0x40, 0x40, 0xFF, 0x90, 0x40, 0xF0, 0xD8, 0x40, 0xC0, 0xD8,
|
||
0x40, 0x60, 0xE0, 0x50, 0x00, 0xC0, 0x70, 0x00, 0x88, 0x88, 0x00, 0x50, 0xA0, 0x00, 0x48, 0xA8,
|
||
0x10, 0x48, 0xA0, 0x68, 0x40, 0x90, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
||
0xFF, 0xFF, 0xFF, 0x60, 0xA0, 0xFF, 0x50, 0x80, 0xFF, 0xA0, 0x70, 0xFF, 0xF0, 0x60, 0xFF, 0xFF,
|
||
0x60, 0xB0, 0xFF, 0x78, 0x30, 0xFF, 0xA0, 0x00, 0xE8, 0xD0, 0x20, 0x98, 0xE8, 0x00, 0x70, 0xF0,
|
||
0x40, 0x70, 0xE0, 0x90, 0x60, 0xD0, 0xE0, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
|
||
0xFF, 0xFF, 0xFF, 0x90, 0xD0, 0xFF, 0xA0, 0xB8, 0xFF, 0xC0, 0xB0, 0xFF, 0xE0, 0xB0, 0xFF, 0xFF,
|
||
0xB8, 0xE8, 0xFF, 0xC8, 0xB8, 0xFF, 0xD8, 0xA0, 0xFF, 0xF0, 0x90, 0xC8, 0xF0, 0x80, 0xA0, 0xF0,
|
||
0xA0, 0xA0, 0xFF, 0xC8, 0xA0, 0xFF, 0xF0, 0xA0, 0xA0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||
};
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// キャラクタ
|
||
//////////////////////////////////////////////////////////////////////
|
||
static BYTE lzSight[] = {
|
||
#include "lzSight.h"
|
||
};
|
||
static BYTE lzAscii[] = {
|
||
#include "lzAscii.h"
|
||
};
|
||
static BYTE lzTVlayer[] = {
|
||
#include "lzTVlayer.h"
|
||
};
|
||
|
||
// メモリから1バイト取ってくる
|
||
static __inline INT mgetc( LPBYTE& inbuf, INT& bufsize )
|
||
{
|
||
if( bufsize <= 0 )
|
||
return -1;
|
||
bufsize--;
|
||
return (INT)*inbuf++;
|
||
}
|
||
|
||
//
|
||
// LZSS解凍ルーチン
|
||
//
|
||
#define N 4096
|
||
#define F 18
|
||
|
||
static void LZdecode( BYTE *inbuf, BYTE *outbuf, INT length )
|
||
{
|
||
INT i, j, k, r, c;
|
||
WORD flags;
|
||
BYTE text[N+F-1];
|
||
INT outsize = 0;
|
||
|
||
for( i = 0; i < N - F; i++ )
|
||
text[i] = 0;
|
||
r = N - F;
|
||
flags = 0;
|
||
|
||
for(;;) {
|
||
if( ((flags >>= 1) & 256) == 0 ) {
|
||
if( (c = mgetc( inbuf, length )) < 0 )
|
||
break;
|
||
flags = c | 0xff00;
|
||
}
|
||
if( flags & 1 ) {
|
||
if( (c = mgetc( inbuf, length )) < 0 )
|
||
break;
|
||
*outbuf++ = c;
|
||
text[r++] = c;
|
||
r &= (N-1);
|
||
|
||
outsize++;
|
||
} else {
|
||
if( (i = mgetc( inbuf, length )) < 0 )
|
||
break;
|
||
if( (j = mgetc( inbuf, length )) < 0 )
|
||
break;
|
||
i |= ((j & 0xf0)<<4);
|
||
j = (j & 0x0f)+2;
|
||
for( k = 0; k <= j; k++ ) {
|
||
c = text[(i+k) & (N-1)];
|
||
*outbuf++ = c;
|
||
text[r++] = c;
|
||
r &= (N-1);
|
||
|
||
outsize++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// 構築/消滅
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
CDirectDraw::CDirectDraw()
|
||
{
|
||
// General
|
||
m_hWnd = NULL;
|
||
|
||
m_bUseHEL = FALSE;
|
||
m_bSystemMemory = FALSE;
|
||
|
||
m_bScreenMode = FALSE;
|
||
m_bGDI = FALSE;
|
||
m_bAspect = FALSE;
|
||
m_bAllLine = FALSE;
|
||
m_bMaxZoom = FALSE;
|
||
m_bDoubleSize = FALSE;
|
||
m_bTVFrameMode = FALSE;
|
||
m_bScanlineMode = FALSE;
|
||
m_nScanlineColor = 75;
|
||
m_bZapper = FALSE;
|
||
m_bZapperDraw = FALSE;
|
||
|
||
m_ZapperPosX = m_ZapperPosY = -1;
|
||
|
||
m_bWindowVSync = FALSE;
|
||
|
||
m_bChangeMode = FALSE;
|
||
m_bDraw = FALSE;
|
||
|
||
m_bNoRestore = FALSE;
|
||
|
||
// DirectDraw
|
||
m_hDDraw = NULL;
|
||
|
||
m_lpDD = NULL;
|
||
m_lpDDPrimary = NULL;
|
||
m_lpDDBack = NULL;
|
||
m_lpDDRender = NULL;
|
||
m_lpDDAscii = NULL;
|
||
m_lpDDZapper = NULL;
|
||
m_lpDDTV = NULL;
|
||
m_lpDDClipper = NULL;
|
||
m_lpDDClipper2 = NULL;
|
||
m_lpDDPalette = NULL;
|
||
|
||
m_lpRender = NULL;
|
||
m_lpRenderDelta = NULL;
|
||
m_bDeltaUpdate = FALSE;
|
||
|
||
m_hPalette = NULL;
|
||
|
||
m_DisplayModeNum = 0;
|
||
|
||
m_bForceWrite = FALSE;
|
||
// Filter
|
||
m_nBltFilter = 0;
|
||
|
||
// デフォルト解像度
|
||
m_dwDisplayWidth = 640;
|
||
m_dwDisplayHeight = 480;
|
||
m_dwDisplayDepth = 16;
|
||
m_dwDisplayRate = 0; // リフレッシュレート指定無し
|
||
|
||
// LineColormode
|
||
::memset( m_LineColormode, 0, sizeof(m_LineColormode) );
|
||
|
||
// パレット
|
||
m_nPaletteMode = 0;
|
||
m_bMonoMode = FALSE;
|
||
|
||
::memcpy( m_PaletteBuf, m_PalDefault, sizeof(m_PaletteBuf) );
|
||
|
||
ZEROMEMORY( m_cpPalette, sizeof(m_cpPalette) );
|
||
ZEROMEMORY( m_mpPalette, sizeof(m_mpPalette) );
|
||
ZEROMEMORY( m_cnPalette, sizeof(m_cnPalette) );
|
||
ZEROMEMORY( m_csPalette, sizeof(m_csPalette) );
|
||
ZEROMEMORY( m_mnPalette, sizeof(m_mnPalette) );
|
||
ZEROMEMORY( m_msPalette, sizeof(m_msPalette) );
|
||
|
||
// その他
|
||
m_bDiskAccessLamp = FALSE;
|
||
|
||
ZEROMEMORY( m_szInfo, sizeof(m_szInfo) );
|
||
ZEROMEMORY( m_szMess, sizeof(m_szMess) );
|
||
|
||
// MMX detect
|
||
{
|
||
m_bMMX = FALSE;
|
||
|
||
DWORD flag1, flag2;
|
||
__asm {
|
||
pushfd
|
||
pop eax
|
||
mov flag1, eax
|
||
xor eax, 0x00200000
|
||
push eax
|
||
popfd
|
||
pushfd
|
||
pop eax
|
||
mov flag2, eax
|
||
}
|
||
|
||
if( flag1 != flag2 ) {
|
||
DWORD flag;
|
||
__asm {
|
||
mov eax, 1
|
||
cpuid
|
||
mov flag, edx
|
||
}
|
||
if( flag & 0x00800000 ) {
|
||
m_bMMX = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
// TEST
|
||
// m_nBltFilter = BLTFILTER_2XSAI;
|
||
// m_nBltFilter = BLTFILTER_SUPER2XSAI;
|
||
// m_nBltFilter = BLTFILTER_SUPEREAGLE;
|
||
// m_nBltFilter = BLTFILTER_SCALE2X;
|
||
|
||
#if COMUSE
|
||
COM::AddRef();
|
||
#endif
|
||
}
|
||
|
||
CDirectDraw::~CDirectDraw()
|
||
{
|
||
ReleaseDDraw();
|
||
|
||
#if COMUSE
|
||
COM::Release();
|
||
#endif
|
||
}
|
||
|
||
//////////////////////////////////////////////////////////////////////
|
||
// メンバ関数
|
||
//////////////////////////////////////////////////////////////////////
|
||
|
||
// コールバック関数
|
||
HRESULT WINAPI CDirectDraw::EnumModesCallback( LPDDSURFACEDESC2 lpDDSurfaceDesc, LPVOID lpContext )
|
||
{
|
||
// Thisポインタを受け取る
|
||
CDirectDraw* pDD = (CDirectDraw*)lpContext;
|
||
|
||
// 256x240以下の解像度は除外(ex. 320x200)
|
||
if( lpDDSurfaceDesc->dwWidth < 256 || lpDDSurfaceDesc->dwHeight < 240 )
|
||
return DDENUMRET_OK;
|
||
|
||
// 8,16,24,32bit以外は除外(4bitがあるね^^;)
|
||
if( !(lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 8
|
||
|| lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 16
|
||
|| lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 24
|
||
|| lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount == 32) )
|
||
return DDENUMRET_OK;
|
||
|
||
// スクエアサイズの解像度以外は除外(ex. 640x400) (1280x1024は選択可能に)
|
||
// if( lpDDSurfaceDesc->dwWidth*3 != lpDDSurfaceDesc->dwHeight*4 && !(lpDDSurfaceDesc->dwWidth == 1280 && lpDDSurfaceDesc->dwHeight == 1024) )
|
||
// return DDENUMRET_OK;
|
||
|
||
// サイズ/ビット深度/リフレッシュレート/ピクセルフォーマットのコピー
|
||
DISPLAYMODE mode;
|
||
mode.dwWidth = lpDDSurfaceDesc->dwWidth;
|
||
mode.dwHeight = lpDDSurfaceDesc->dwHeight;
|
||
mode.dwDepth = lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount;
|
||
mode.dwRate = lpDDSurfaceDesc->dwRefreshRate;
|
||
pDD->m_DisplayModes.push_back( mode );
|
||
|
||
// 列挙数が超えた場合はキャンセル
|
||
if( ++pDD->m_DisplayModeNum > CDirectDraw::DD_DISPLAYMODEMAX-1 ) {
|
||
// DEBUGOUT( "CDirectDraw:Maximum display modes over.\n" );
|
||
return DDENUMRET_CANCEL;
|
||
}
|
||
return DDENUMRET_OK;
|
||
}
|
||
|
||
// DirectDrawの初期化
|
||
BOOL CDirectDraw::InitialDDraw( HWND hWnd )
|
||
{
|
||
try {
|
||
// DirectDrawオブジェクトの作成
|
||
|
||
#if !DYNDLL
|
||
#if !COMUSE
|
||
if( !m_bUseHEL ) {
|
||
if( DirectDrawCreateEx(NULL, (LPVOID*)&m_lpDD, IID_IDirectDraw7, NULL) != DD_OK ) {
|
||
m_lpDD = NULL;
|
||
throw "CDirectDraw:DirectDrawCreateEx failed.";
|
||
}
|
||
} else {
|
||
if( DirectDrawCreateEx((LPGUID)DDCREATE_EMULATIONONLY, (LPVOID*)&m_lpDD, IID_IDirectDraw7, NULL) != DD_OK ) {
|
||
m_lpDD = NULL;
|
||
throw "CDirectDraw:DirectDrawCreateEx failed.";
|
||
}
|
||
}
|
||
#else
|
||
// COM的利用(ライブラリをリンクするだけで起動が遅くなるので...)
|
||
// COM::AddRef();
|
||
|
||
// CLSID_DirectDrawでは無くCLSID_DirectDraw7を使わないと駄目
|
||
if( ::CoCreateInstance( CLSID_DirectDraw7, NULL, CLSCTX_ALL, IID_IDirectDraw7, (LPVOID*)&m_lpDD ) != S_OK ) {
|
||
m_lpDD = NULL;
|
||
throw "CDirectDraw:DirectX 7.0 or greater is required.";
|
||
// throw "CDirectDraw:CoCreateInstance failed.";
|
||
}
|
||
if( !m_bUseHEL ) {
|
||
if( m_lpDD->Initialize( NULL ) != DD_OK )
|
||
throw "CDirectDraw:IDirectDraw7->Initialize failed.";
|
||
} else {
|
||
if( m_lpDD->Initialize( (LPGUID)DDCREATE_EMULATIONONLY ) != DD_OK ) // HEL
|
||
throw "CDirectDraw:IDirectDraw7->Initialize failed.";
|
||
}
|
||
#endif
|
||
#else
|
||
// DLLを動的ロードして利用
|
||
if( !(m_hDDraw = ::LoadLibrary( "DDRAW.DLL" )) ) {
|
||
throw "CDirectDraw:DirectX 7.0 or greater is required.";
|
||
}
|
||
|
||
typedef HRESULT(WINAPI * DIRECTDRAWCREATEEX)( GUID*, VOID**, REFIID, IUnknown* );
|
||
|
||
DIRECTDRAWCREATEEX DirectDrawCreateEx = (DIRECTDRAWCREATEEX)GetProcAddress( m_hDDraw, "DirectDrawCreateEx" );
|
||
if( !DirectDrawCreateEx ) {
|
||
::FreeLibrary( m_hDDraw );
|
||
m_hDDraw = NULL;
|
||
throw "CDirectDraw:DirectX 7.0 or greater is required.";
|
||
}
|
||
|
||
if( !m_bUseHEL ) {
|
||
if( DirectDrawCreateEx(NULL, (LPVOID*)&m_lpDD, IID_IDirectDraw7, NULL) != DD_OK ) {
|
||
m_lpDD = NULL;
|
||
throw "CDirectDraw:DirectX 7.0 or greater is required.";
|
||
}
|
||
} else {
|
||
if( DirectDrawCreateEx((LPGUID)DDCREATE_EMULATIONONLY, (LPVOID*)&m_lpDD, IID_IDirectDraw7, NULL) != DD_OK ) {
|
||
m_lpDD = NULL;
|
||
throw "CDirectDraw:DirectX 7.0 or greater is required.";
|
||
}
|
||
}
|
||
#endif
|
||
// モニタ解像度の調査
|
||
DDSURFACEDESC2 ddsd;
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
if( m_lpDD->GetDisplayMode( &ddsd ) != DD_OK )
|
||
throw "CDirectDraw:GetDisplayMode failed.";
|
||
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount < 8 )
|
||
throw "CDirectDraw:Unsupported display mode.";
|
||
|
||
// 利用可能なディスプレイモードの取得
|
||
m_DisplayModeNum = 0;
|
||
if( m_lpDD->EnumDisplayModes(DDEDM_REFRESHRATES, NULL, (LPVOID)this, (LPDDENUMMODESCALLBACK2)EnumModesCallback) != DD_OK )
|
||
throw "CDirectDraw:EnumDisplayModes failed.";
|
||
if( !m_DisplayModeNum )
|
||
throw "CDirectDraw:No display modes available.";
|
||
|
||
m_hWnd = hWnd;
|
||
|
||
// デフォルトパレット設定
|
||
memcpy( m_PaletteBuf, m_PalDefault, sizeof(m_PalDefault) );
|
||
|
||
// Render screen
|
||
if( !m_lpRender ) {
|
||
if( !(m_lpRender = (LPBYTE)malloc( RENDER_WIDTH*RENDER_HEIGHT )) )
|
||
throw "CDirectDraw::Out of memory.";
|
||
|
||
}
|
||
::memset( m_lpRender, 0x3F, RENDER_WIDTH*RENDER_HEIGHT );
|
||
|
||
// Render delta screen
|
||
if( !m_lpRenderDelta ) {
|
||
if( !(m_lpRenderDelta = (LPBYTE)malloc( DELTA_WIDTH*DELTA_HEIGHT*sizeof(DWORD) )) )
|
||
throw "CDirectDraw::Out of memory.";
|
||
}
|
||
::memset( m_lpRenderDelta, 0xFF, DELTA_WIDTH*DELTA_HEIGHT*sizeof(DWORD) );
|
||
m_bDeltaUpdate = FALSE;
|
||
|
||
// LineColormode
|
||
::memset( m_LineColormode, 0, sizeof(m_LineColormode) );
|
||
} catch( char *str ) {
|
||
m_DisplayModeNum = 0;
|
||
RELEASE( m_lpDD );
|
||
::MessageBox( hWnd, str, "ERROR", MB_ICONERROR|MB_OK );
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// DirectDrawの開放
|
||
void CDirectDraw::ReleaseDDraw()
|
||
{
|
||
ReleaseSurface();
|
||
|
||
if( m_lpDD ) {
|
||
RELEASE( m_lpDD );
|
||
}
|
||
#if COMUSE
|
||
// COM::Release();
|
||
#endif
|
||
|
||
#if DYNDLL
|
||
if( m_hDDraw ) {
|
||
m_hDDraw = NULL;
|
||
::FreeLibrary( m_hDDraw );
|
||
}
|
||
#endif
|
||
|
||
FREE( m_lpRenderDelta );
|
||
FREE( m_lpRender );
|
||
// m_hWnd = NULL;
|
||
}
|
||
|
||
// サーフェスの初期化
|
||
BOOL CDirectDraw::InitialSurface( BOOL bScreenMode )
|
||
{
|
||
INT i;
|
||
DDSURFACEDESC2 ddsd;
|
||
DDSCAPS2 ddscaps;
|
||
DDBLTFX ddbltfx;
|
||
|
||
try {
|
||
if( !m_lpDD )
|
||
throw "CDirectDraw:DirectDraw object uninitialized.";
|
||
|
||
m_bGDI = FALSE;
|
||
m_bScreenMode = bScreenMode;
|
||
m_bMessage = FALSE;
|
||
|
||
if( !m_bScreenMode ) {
|
||
// ウインドウ
|
||
// 協調モード
|
||
if( m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_NORMAL ) != DD_OK )
|
||
throw "CDirectDraw:SetCooperativeLevel failed.";
|
||
|
||
// プライマリサーフェス
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_CAPS;
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
||
if( m_lpDD->CreateSurface( &ddsd, &m_lpDDPrimary, NULL ) != DD_OK )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
|
||
// クリッパーの作成
|
||
if( m_lpDD->CreateClipper( 0, &m_lpDDClipper, NULL ) != DD_OK )
|
||
throw "CDirectDraw:CreateClipper failed.";
|
||
|
||
m_lpDDClipper->SetHWnd( 0, m_hWnd );
|
||
m_lpDDPrimary->SetClipper( m_lpDDClipper );
|
||
RELEASE( m_lpDDClipper );
|
||
} else {
|
||
// フルスクリーン
|
||
// 排他モード
|
||
if( m_lpDD->SetCooperativeLevel( m_hWnd, DDSCL_ALLOWREBOOT|DDSCL_EXCLUSIVE|DDSCL_FULLSCREEN ) != DD_OK )
|
||
throw "CDirectDraw:SetCooperativeLevel error";
|
||
|
||
// 画面解像度の設定
|
||
if( m_lpDD->SetDisplayMode( m_dwDisplayWidth, m_dwDisplayHeight,
|
||
m_dwDisplayDepth, m_dwDisplayRate,
|
||
DDSDM_STANDARDVGAMODE ) != DD_OK ) {
|
||
// 失敗したらリフレッシュレート指定を無くしてもう一度やってみる
|
||
if( m_lpDD->SetDisplayMode( m_dwDisplayWidth, m_dwDisplayHeight,
|
||
m_dwDisplayDepth, 0,
|
||
DDSDM_STANDARDVGAMODE ) != DD_OK ) {
|
||
throw "CDirectDraw:SetDisplayMode failed.";
|
||
} else {
|
||
m_dwDisplayRate = 0;
|
||
}
|
||
}
|
||
|
||
// プライマリサーフェスとバックサーフェスの作成
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
|
||
ddsd.dwBackBufferCount = 1;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDPrimary, NULL) != DD_OK )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
|
||
ZEROMEMORY( &ddscaps, sizeof(DDSCAPS2) );
|
||
ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
|
||
if( m_lpDDPrimary->GetAttachedSurface(&ddscaps, &m_lpDDBack) != DD_OK )
|
||
throw "CDirectDraw:GetAttachedSurface failed.";
|
||
}
|
||
|
||
// offscreen surface
|
||
m_bForceWrite = FALSE;
|
||
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||
if( !m_bSystemMemory ) {
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||
} else {
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
m_bForceWrite = TRUE; // 多段レンダリングしない
|
||
}
|
||
ddsd.dwWidth = SCREEN_WIDTH*2;
|
||
ddsd.dwHeight = SCREEN_HEIGHT*2;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender, NULL) != DD_OK ) {
|
||
// システムメモリにも取れないってか....
|
||
if( ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
|
||
// ビデオメモリに取れない時,しょうがないのでシステムメモリに取る
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender, NULL) != DD_OK )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
|
||
m_bForceWrite = TRUE; // 多段レンダリングしない
|
||
}
|
||
if( !m_bSystemMemory ) {
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||
} else {
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
}
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender2, NULL) != DD_OK ) {
|
||
// システムメモリにも取れないってか....
|
||
if( ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
|
||
// ビデオメモリに取れない時,しょうがないのでシステムメモリに取る
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDRender2, NULL) != DD_OK )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
}
|
||
|
||
typedef struct tagDDRGNDATA {
|
||
RGNDATAHEADER rdh;
|
||
RECT rect[8];
|
||
} DDRGNDATA;
|
||
|
||
DDRGNDATA rgn;
|
||
rgn.rdh.dwSize = sizeof(RGNDATAHEADER);
|
||
rgn.rdh.iType = RDH_RECTANGLES;
|
||
rgn.rdh.nCount = 1;
|
||
rgn.rdh.nRgnSize = sizeof(RECT);
|
||
rgn.rdh.rcBound.left = 0;
|
||
rgn.rdh.rcBound.top = 0;
|
||
rgn.rdh.rcBound.right = ddsd.dwWidth;
|
||
rgn.rdh.rcBound.bottom = ddsd.dwHeight;
|
||
rgn.rect[0].left = 0;
|
||
rgn.rect[0].top = 0;
|
||
rgn.rect[0].right = ddsd.dwWidth;
|
||
rgn.rect[0].bottom = ddsd.dwHeight;
|
||
|
||
// Rendering surface clipper
|
||
if( m_lpDD->CreateClipper( 0, &m_lpDDClipper2, NULL ) != DD_OK )
|
||
throw "CDirectDraw:CreateClipper failed.";
|
||
|
||
m_lpDDClipper2->SetClipList( (LPRGNDATA)&rgn, 0 );
|
||
m_lpDDRender->SetClipper( m_lpDDClipper2 );
|
||
|
||
// Ascii surface(6x6x64character)
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||
// ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
ddsd.dwWidth = 6*8;
|
||
ddsd.dwHeight = 6*8;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDAscii, NULL) != DD_OK )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
// Color key
|
||
DDCOLORKEY ddck;
|
||
ZEROMEMORY( &ddck, sizeof(DDCOLORKEY) );
|
||
ddck.dwColorSpaceLowValue = 0;
|
||
ddck.dwColorSpaceHighValue = 0;
|
||
m_lpDDAscii->SetColorKey( DDCKEY_SRCBLT, &ddck );
|
||
|
||
// Zapper surface
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||
// ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
ddsd.dwWidth = 16;
|
||
ddsd.dwHeight = 16;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDZapper, NULL) != DD_OK )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
// Color key
|
||
ZEROMEMORY( &ddck, sizeof(DDCOLORKEY) );
|
||
ddck.dwColorSpaceLowValue = 0;
|
||
ddck.dwColorSpaceHighValue = 0;
|
||
m_lpDDZapper->SetColorKey( DDCKEY_SRCBLT, &ddck );
|
||
|
||
// TV
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
||
if( !m_bSystemMemory ) {
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
|
||
} else {
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
}
|
||
ddsd.dwWidth = 512;
|
||
ddsd.dwHeight = 480;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDTV, NULL) != DD_OK ) {
|
||
// システムメモリにも取れないってか....
|
||
if( ddsd.ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
|
||
// ビデオメモリに取れない時,しょうがないのでシステムメモリに取る
|
||
ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
||
if( m_lpDD->CreateSurface(&ddsd, &m_lpDDTV, NULL) != DD_OK )
|
||
throw "CDirectDraw:CreateSurface failed.";
|
||
}
|
||
|
||
// Color key
|
||
ZEROMEMORY( &ddck, sizeof(DDCOLORKEY) );
|
||
ddck.dwColorSpaceLowValue = 0;
|
||
ddck.dwColorSpaceHighValue = 0;
|
||
m_lpDDTV->SetColorKey( DDCKEY_SRCBLT, &ddck );
|
||
|
||
// DirectDraw/GDI Palette
|
||
ZEROMEMORY( &m_logPalette, sizeof(m_logPalette) );
|
||
m_logPalette.palVersion = 0x0300;
|
||
m_logPalette.palNumEntries = 256;
|
||
|
||
HDC hdc = ::GetDC( NULL );
|
||
GetSystemPaletteEntries( hdc, 0, 256, m_logPalette.pe );
|
||
ReleaseDC( NULL, hdc );
|
||
|
||
for( i = 0; i < 10; i++ ) {
|
||
m_logPalette.pe[i ].peFlags = PC_EXPLICIT;
|
||
m_logPalette.pe[i+246].peFlags = PC_EXPLICIT;
|
||
}
|
||
for( i = 10; i < 246; i++ ) {
|
||
m_logPalette.pe[i].peRed = 0;
|
||
m_logPalette.pe[i].peGreen = 0;
|
||
m_logPalette.pe[i].peBlue = 0;
|
||
if( i >= 0x10 && i < 0x20 ) {
|
||
m_logPalette.pe[i].peRed = (i-0x10)*0x10;
|
||
m_logPalette.pe[i].peGreen = (i-0x10)*0x10;
|
||
m_logPalette.pe[i].peBlue = (i-0x10)*0x10;
|
||
m_logPalette.pe[i].peFlags = PC_RESERVED;
|
||
} else if( i >= 0x40 && i < 0xC0 ) {
|
||
m_logPalette.pe[i].peFlags = PC_RESERVED;
|
||
} else {
|
||
m_logPalette.pe[i].peFlags = PC_NOCOLLAPSE;
|
||
}
|
||
}
|
||
|
||
// Surface clear
|
||
ddbltfx.dwSize = sizeof(DDBLTFX);
|
||
ddbltfx.dwFillColor = 0;
|
||
if( m_lpDDBack ) {
|
||
m_lpDDBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
|
||
}
|
||
m_lpDDRender->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
|
||
m_lpDDRender2->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
|
||
|
||
// Palette object
|
||
DDSURFACEDESC2 ddsd;
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
m_lpDDPrimary->GetSurfaceDesc(&ddsd);
|
||
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
|
||
if( !m_bScreenMode ) {
|
||
if( (m_hPalette = CreatePalette( (LOGPALETTE *)&m_logPalette )) == NULL )
|
||
throw "CDirectDraw:CreatePalette failed.";
|
||
} else {
|
||
if( m_lpDD->CreatePalette( DDPCAPS_8BIT, m_logPalette.pe, &m_lpDDPalette, NULL ) != DD_OK )
|
||
throw "CDirectDraw:CreatePalette error";
|
||
if( m_lpDDPrimary->SetPalette( m_lpDDPalette ) != DD_OK )
|
||
throw "CDirectDraw:SetPalette failed.";
|
||
}
|
||
}
|
||
|
||
// Palette calculate
|
||
CalcPaletteTable();
|
||
// Palette Realize
|
||
RealizePalette();
|
||
m_bPaletteUpdate = TRUE;
|
||
|
||
// Character setup
|
||
SetLZSSChar( lzAscii, m_lpDDAscii );
|
||
SetLZSSChar( lzSight, m_lpDDZapper );
|
||
SetLZSSChar( lzTVlayer, m_lpDDTV );
|
||
|
||
// 再描画の為
|
||
m_bDeltaUpdate = TRUE;
|
||
} catch( char *str ) {
|
||
ReleaseSurface();
|
||
|
||
// DEBUGOUT( "%s\n", str );
|
||
::MessageBox( m_hWnd, str, "ERROR", MB_ICONERROR|MB_OK );
|
||
|
||
return FALSE;
|
||
}
|
||
// DEBUGOUT( "CDirectDraw:InitialSurface complete.\n" );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// サーフェスの開放
|
||
BOOL CDirectDraw::ReleaseSurface( void )
|
||
{
|
||
if( !m_lpDD )
|
||
return FALSE;
|
||
|
||
GDIDELETE( m_hPalette );
|
||
RELEASE( m_lpDDPalette );
|
||
|
||
RELEASE( m_lpDDClipper2 );
|
||
RELEASE( m_lpDDClipper );
|
||
|
||
RELEASE( m_lpDDTV );
|
||
RELEASE( m_lpDDZapper );
|
||
RELEASE( m_lpDDAscii );
|
||
RELEASE( m_lpDDRender2 );
|
||
RELEASE( m_lpDDRender );
|
||
RELEASE( m_lpDDBack );
|
||
RELEASE( m_lpDDPrimary );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// サーフェスのリストアサブ
|
||
BOOL CDirectDraw::RestoreSurfaceSub( LPDIRECTDRAWSURFACE7 lpSurface )
|
||
{
|
||
if( lpSurface ) {
|
||
if( lpSurface->IsLost() == DDERR_SURFACELOST ) {
|
||
// ロストしていたらリストアする
|
||
// DEBUGOUT( "CDirectDraw:Restore surface...." );
|
||
if( lpSurface->Restore() == DD_OK ) {
|
||
// DEBUGOUT( "Ok.\n" );
|
||
} else {
|
||
// DEBUGOUT( "Failed.\n" );
|
||
}
|
||
return FALSE;
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
// サーフェスのリストア
|
||
BOOL CDirectDraw::RestoreSurface()
|
||
{
|
||
if( !m_lpDD ) return FALSE;
|
||
|
||
if( m_bNoRestore )
|
||
return FALSE;
|
||
|
||
BOOL bRet = TRUE;
|
||
|
||
// ロストしてたら内容は失われているので描画をキャンセルしてね
|
||
if( !RestoreSurfaceSub( m_lpDDRender ) ) {
|
||
bRet = FALSE;
|
||
}
|
||
if( !RestoreSurfaceSub( m_lpDDRender2 ) ) {
|
||
bRet = FALSE;
|
||
}
|
||
if( !RestoreSurfaceSub( m_lpDDBack ) ) {
|
||
bRet = FALSE;
|
||
}
|
||
if( !RestoreSurfaceSub( m_lpDDPrimary ) ) {
|
||
bRet = FALSE;
|
||
}
|
||
if( !RestoreSurfaceSub( m_lpDDAscii ) ) {
|
||
SetLZSSChar( lzAscii, m_lpDDAscii );
|
||
bRet = FALSE;
|
||
}
|
||
if( !RestoreSurfaceSub( m_lpDDZapper ) ) {
|
||
SetLZSSChar( lzSight, m_lpDDZapper );
|
||
bRet = FALSE;
|
||
}
|
||
if( !RestoreSurfaceSub( m_lpDDTV ) ) {
|
||
SetLZSSChar( lzTVlayer, m_lpDDTV );
|
||
bRet = FALSE;
|
||
}
|
||
|
||
if( !bRet ) {
|
||
// 再描画の為
|
||
m_bDeltaUpdate = TRUE;
|
||
}
|
||
|
||
return bRet;
|
||
}
|
||
|
||
//
|
||
// ディスプレイモード変更開始
|
||
//
|
||
BOOL CDirectDraw::BeginDisplayChange()
|
||
{
|
||
if( !m_lpDD )
|
||
return FALSE;
|
||
|
||
// 既に変更中やないか
|
||
if( m_bChangeMode )
|
||
return FALSE;
|
||
|
||
// 変更中じゃ
|
||
m_bChangeMode = TRUE;
|
||
|
||
if( m_bScreenMode ) {
|
||
m_lpDD->RestoreDisplayMode();
|
||
}
|
||
|
||
// サーフェスの開放
|
||
ReleaseSurface();
|
||
|
||
// 協調モード
|
||
m_lpDD->SetCooperativeLevel( NULL, DDSCL_NORMAL );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// ディスプレイモード変更終了とサーフェスの再構築
|
||
//
|
||
BOOL CDirectDraw::EndDisplayChange()
|
||
{
|
||
if( !m_lpDD || !m_bChangeMode )
|
||
return FALSE;
|
||
|
||
// Rebuild surface
|
||
if( !InitialSurface( m_bScreenMode ) ) {
|
||
m_bChangeMode = FALSE;
|
||
return FALSE;
|
||
}
|
||
|
||
// Wait
|
||
::Sleep( 250 );
|
||
|
||
// Change mode complete
|
||
m_bChangeMode = FALSE;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// WM_DISPLAYCHANGEハンドラから呼ばれる
|
||
//
|
||
BOOL CDirectDraw::OnChangeDisplayMode()
|
||
{
|
||
// 自分自身で変更している時はキャンセル
|
||
if( m_bChangeMode )
|
||
return TRUE;
|
||
|
||
// DirectDrawオブジェクトが無ければ意味無し
|
||
if( !m_lpDD )
|
||
return FALSE;
|
||
|
||
// DEBUGOUT( "CDirectDraw:OnChangeDisplayMode\n" );
|
||
|
||
// 協調モードのチェック
|
||
HRESULT hr = m_lpDD->TestCooperativeLevel();
|
||
|
||
if( !m_bScreenMode ) {
|
||
// ウインドウ
|
||
if( hr == DDERR_EXCLUSIVEMODEALREADYSET ) {
|
||
// 他に排他モード野郎がおるのでおしまい
|
||
// DEBUGOUT( "CDirectDraw:DDERR_EXCLUSIVEMODEALREADYSET\n" );
|
||
// リストアしちゃいやん
|
||
m_bNoRestore = TRUE;
|
||
return TRUE;
|
||
} else if( hr == DDERR_WRONGMODE || hr == DD_OK ) {
|
||
// 普通のディスプレイモードの変更(何故かWindowメッセージだとDD_OKな時がある)
|
||
// DEBUGOUT( "CDirectDraw:DDERR_WRONGMODE\n" );
|
||
// リストアしてええよ
|
||
m_bNoRestore = FALSE;
|
||
|
||
// サーフェスの開放
|
||
ReleaseSurface();
|
||
|
||
// サーフェスの初期化
|
||
BOOL bRet = InitialSurface( m_bScreenMode );
|
||
|
||
if( bRet ) {
|
||
// DEBUGOUT( "CDirectDraw:InitialSurface ok.\n" );
|
||
} else {
|
||
// DEBUGOUT( "CDirectDraw:InitialSurface failed.\n" );
|
||
}
|
||
|
||
return bRet;
|
||
} else if( hr == DDERR_INVALIDOBJECT ) {
|
||
// DEBUGOUT( "CDirectDraw:DDERR_INVALIDOBJECT\n" );
|
||
return FALSE;
|
||
} else if( hr == DDERR_NOEXCLUSIVEMODE ) {
|
||
// DEBUGOUT( "CDirectDraw:DDERR_NOEXCLUSIVEMODE\n" );
|
||
} else {
|
||
// DEBUGOUT( "CDirectDraw:Unknown error. hr=%08Xた\n", hr );
|
||
}
|
||
// 良く分からんのでとりあえずサーフェスをリストア
|
||
m_bNoRestore = FALSE;
|
||
RestoreSurface();
|
||
|
||
return TRUE;
|
||
} else {
|
||
// フルスクリーン
|
||
if( hr == DDERR_NOEXCLUSIVEMODE ) {
|
||
// フルスクリーンモードから抜けた時
|
||
// DEBUGOUT( "CDirectDraw:DDERR_NOEXCLUSIVEMODE\n" );
|
||
return TRUE;
|
||
}
|
||
|
||
if( hr == DD_OK ) {
|
||
// リストアしろって事か...
|
||
// サーフェスをリストア
|
||
RestoreSurface();
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// 不明な原因
|
||
return FALSE;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void CDirectDraw::SetDisplayMode( DWORD dwWidth, DWORD dwHeight, DWORD dwDepth, DWORD dwRate )
|
||
{
|
||
m_dwDisplayWidth = dwWidth;
|
||
m_dwDisplayHeight = dwHeight;
|
||
m_dwDisplayDepth = dwDepth;
|
||
m_dwDisplayRate = dwRate;
|
||
}
|
||
|
||
void CDirectDraw::GetDisplayMode( DWORD& dwWidth, DWORD& dwHeight, DWORD& dwDepth, DWORD& dwRate )
|
||
{
|
||
dwWidth = m_dwDisplayWidth;
|
||
dwHeight = m_dwDisplayHeight;
|
||
dwDepth = m_dwDisplayDepth;
|
||
dwRate = m_dwDisplayRate;
|
||
}
|
||
|
||
BOOL CDirectDraw::GetDisplayMode( INT no, DWORD& dwWidth, DWORD& dwHeight, DWORD& dwDepth, DWORD& dwRate )
|
||
{
|
||
if( m_DisplayModes.size() < no )
|
||
return FALSE;
|
||
|
||
dwWidth = m_DisplayModes[no].dwWidth;
|
||
dwHeight = m_DisplayModes[no].dwHeight;
|
||
dwDepth = m_DisplayModes[no].dwDepth;
|
||
dwRate = m_DisplayModes[no].dwRate;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
INT CDirectDraw::GetMatchDisplayMode( DWORD dwWidth, DWORD dwHeight, DWORD dwDepth, DWORD dwRate )
|
||
{
|
||
for( int i = 0; i < m_DisplayModes.size(); i++ ) {
|
||
if( m_DisplayModes[i].dwWidth == dwWidth
|
||
|| m_DisplayModes[i].dwHeight == dwHeight
|
||
|| m_DisplayModes[i].dwDepth == dwDepth
|
||
|| m_DisplayModes[i].dwRate == dwRate )
|
||
return i;
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
BOOL CDirectDraw::IsNowDisplayMode( DWORD dwWidth, DWORD dwHeight, DWORD dwDepth, DWORD dwRate )
|
||
{
|
||
if( m_dwDisplayWidth == dwWidth && m_dwDisplayHeight == dwHeight
|
||
&& m_dwDisplayDepth == dwDepth && m_dwDisplayRate == dwRate )
|
||
return TRUE;
|
||
return FALSE;
|
||
}
|
||
|
||
// ビット位置の取得
|
||
void CDirectDraw::GetBitMask( DWORD val, int& shift, int& bits )
|
||
{
|
||
shift = 0;
|
||
while( !(val & (1<<shift)) && (shift<32) ) {
|
||
shift++;
|
||
}
|
||
|
||
bits = 32;
|
||
while( !(val & (1<<(bits-1))) && (bits>0) ) {
|
||
bits--;
|
||
}
|
||
bits = bits - shift;
|
||
}
|
||
|
||
static float PalConvTbl[][3] = {
|
||
1.00f, 1.00f, 1.00f,
|
||
1.00f, 0.80f, 0.73f,
|
||
0.73f, 1.00f, 0.70f,
|
||
0.76f, 0.78f, 0.58f,
|
||
0.86f, 0.80f, 1.00f,
|
||
0.83f, 0.68f, 0.85f,
|
||
0.67f, 0.77f, 0.83f,
|
||
0.68f, 0.68f, 0.68f,
|
||
// 1.00f, 1.00f, 1.00f,
|
||
};
|
||
|
||
// パレットテーブルの計算
|
||
BOOL CDirectDraw::CalcPaletteTable()
|
||
{
|
||
INT i, j;
|
||
|
||
if( !m_lpDD || !m_lpDDPrimary )
|
||
return FALSE;
|
||
|
||
DDSURFACEDESC2 ddsd;
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
ddsd.dwFlags = DDSD_PIXELFORMAT;
|
||
if( m_lpDDPrimary->GetSurfaceDesc(&ddsd) != DD_OK )
|
||
throw "CDirectDraw:GetSurfaceDesc error";
|
||
|
||
INT Rbit, Gbit, Bbit;
|
||
INT Rsft, Gsft, Bsft;
|
||
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount != 8 ) {
|
||
GetBitMask( ddsd.ddpfPixelFormat.dwRBitMask, Rsft, Rbit );
|
||
GetBitMask( ddsd.ddpfPixelFormat.dwGBitMask, Gsft, Gbit );
|
||
GetBitMask( ddsd.ddpfPixelFormat.dwBBitMask, Bsft, Bbit );
|
||
}
|
||
|
||
for( j = 0; j < 8; j++ ) {
|
||
for( i = 0; i < 64; i++ ) {
|
||
DWORD Rn, Gn, Bn;
|
||
DWORD Rs, Gs, Bs;
|
||
|
||
// Normal
|
||
Rn = (DWORD)(PalConvTbl[j][0]*m_PaletteBuf[i].r);
|
||
Gn = (DWORD)(PalConvTbl[j][1]*m_PaletteBuf[i].g);
|
||
Bn = (DWORD)(PalConvTbl[j][2]*m_PaletteBuf[i].b);
|
||
// Scanline
|
||
Rs = (DWORD)(PalConvTbl[j][0]*m_PaletteBuf[i].r*m_nScanlineColor/100.0f);
|
||
Gs = (DWORD)(PalConvTbl[j][1]*m_PaletteBuf[i].g*m_nScanlineColor/100.0f);
|
||
Bs = (DWORD)(PalConvTbl[j][2]*m_PaletteBuf[i].b*m_nScanlineColor/100.0f);
|
||
|
||
m_cpPalette[j][i+0x00].rgbRed = (BYTE)Rn;
|
||
m_cpPalette[j][i+0x00].rgbGreen = (BYTE)Gn;
|
||
m_cpPalette[j][i+0x00].rgbBlue = (BYTE)Bn;
|
||
m_cpPalette[j][i+0x40].rgbRed = (BYTE)Rs;
|
||
m_cpPalette[j][i+0x40].rgbGreen = (BYTE)Gs;
|
||
m_cpPalette[j][i+0x40].rgbBlue = (BYTE)Bs;
|
||
|
||
m_cnPalette[j][i] = ((Rn>>(8-Rbit))<<Rsft)|((Gn>>(8-Gbit))<<Gsft)|((Bn>>(8-Bbit))<<Bsft);
|
||
m_csPalette[j][i] = ((Rs>>(8-Rbit))<<Rsft)|((Gs>>(8-Gbit))<<Gsft)|((Bs>>(8-Bbit))<<Bsft);
|
||
|
||
// RGB555
|
||
if( Rsft > Bsft ) {
|
||
// RGB555->RGB888の時
|
||
m_cfPalette[j][i] = ((Rn>>(8-5))<<10)|((Gn>>(8-5))<<5)|((Bn>>(8-5))<<0);
|
||
} else {
|
||
// BGR555->BGR888の時
|
||
m_cfPalette[j][i] = ((Rn>>(8-5))<<0)|((Gn>>(8-5))<<5)|((Bn>>(8-5))<<10);
|
||
}
|
||
|
||
// Monochrome
|
||
Rn = (DWORD)(m_PaletteBuf[i&0x30].r);
|
||
Gn = (DWORD)(m_PaletteBuf[i&0x30].g);
|
||
Bn = (DWORD)(m_PaletteBuf[i&0x30].b);
|
||
Rn =
|
||
Gn =
|
||
Bn = (DWORD)(0.299f * Rn + 0.587f * Gn + 0.114f * Bn);
|
||
Rn = (DWORD)(PalConvTbl[j][0]*Rn);
|
||
Gn = (DWORD)(PalConvTbl[j][1]*Gn);
|
||
Bn = (DWORD)(PalConvTbl[j][2]*Bn);
|
||
if( Rn > 0xFF ) Rs = 0xFF;
|
||
if( Gn > 0xFF ) Gs = 0xFF;
|
||
if( Bn > 0xFF ) Bs = 0xFF;
|
||
// Scanline
|
||
Rs = (DWORD)(m_PaletteBuf[i&0x30].r*m_nScanlineColor/100.0f);
|
||
Gs = (DWORD)(m_PaletteBuf[i&0x30].g*m_nScanlineColor/100.0f);
|
||
Bs = (DWORD)(m_PaletteBuf[i&0x30].b*m_nScanlineColor/100.0f);
|
||
Rs =
|
||
Gs =
|
||
Bs = (DWORD)(0.299f * Rs + 0.587f * Gs + 0.114f * Bs);
|
||
Rs = (DWORD)(PalConvTbl[j][0]*Rs);
|
||
Gs = (DWORD)(PalConvTbl[j][1]*Gs);
|
||
Bs = (DWORD)(PalConvTbl[j][2]*Bs);
|
||
if( Rs > 0xFF ) Rs = 0xFF;
|
||
if( Gs > 0xFF ) Gs = 0xFF;
|
||
if( Bs > 0xFF ) Bs = 0xFF;
|
||
|
||
m_mpPalette[j][i+0x00].rgbRed = (BYTE)Rn;
|
||
m_mpPalette[j][i+0x00].rgbGreen = (BYTE)Gn;
|
||
m_mpPalette[j][i+0x00].rgbBlue = (BYTE)Bn;
|
||
m_mpPalette[j][i+0x40].rgbRed = (BYTE)Rs;
|
||
m_mpPalette[j][i+0x40].rgbGreen = (BYTE)Gs;
|
||
m_mpPalette[j][i+0x40].rgbBlue = (BYTE)Bs;
|
||
|
||
m_mnPalette[j][i] = ((Rn>>(8-Rbit))<<Rsft)|((Gn>>(8-Gbit))<<Gsft)|((Bn>>(8-Bbit))<<Bsft);
|
||
m_msPalette[j][i] = ((Rs>>(8-Rbit))<<Rsft)|((Gs>>(8-Gbit))<<Gsft)|((Bs>>(8-Bbit))<<Bsft);
|
||
|
||
// RGB555
|
||
if( Rsft > Bsft ) {
|
||
// RGB555->RGB888の時
|
||
m_mfPalette[j][i] = ((Rn>>(8-5))<<10)|((Gn>>(8-5))<<5)|((Bn>>(8-5))<<0);
|
||
} else {
|
||
// BGR555->BGR888の時
|
||
m_mfPalette[j][i] = ((Rn>>(8-5))<<0)|((Gn>>(8-5))<<5)|((Bn>>(8-5))<<10);
|
||
}
|
||
}
|
||
}
|
||
|
||
// 再描画の為
|
||
m_bDeltaUpdate = TRUE;
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
// パレットテーブルの設定
|
||
void CDirectDraw::SetPaletteTable( LPBYTE pal )
|
||
{
|
||
if( pal )
|
||
memcpy( m_PaletteBuf, pal, sizeof(m_PaletteBuf) );
|
||
else
|
||
memcpy( m_PaletteBuf, m_PalDefault, sizeof(m_PaletteBuf) );
|
||
|
||
CalcPaletteTable();
|
||
|
||
m_bPaletteUpdate = TRUE;
|
||
}
|
||
|
||
// パレットテーブルの設定
|
||
void CDirectDraw::SetPaletteTable( RGBQUAD* rgb )
|
||
{
|
||
for( INT i = 0; i < 64; i++ ) {
|
||
m_PaletteBuf[i].r = rgb[i].rgbRed;
|
||
m_PaletteBuf[i].g = rgb[i].rgbGreen;
|
||
m_PaletteBuf[i].b = rgb[i].rgbBlue;
|
||
}
|
||
|
||
CalcPaletteTable();
|
||
|
||
m_bPaletteUpdate = TRUE;
|
||
}
|
||
|
||
// パレットテーブルの取得
|
||
void CDirectDraw::GetPaletteTable( RGBQUAD* rgb )
|
||
{
|
||
for( INT i = 0; i < 64; i++ ) {
|
||
rgb[i].rgbRed = m_PaletteBuf[i].r;
|
||
rgb[i].rgbGreen = m_PaletteBuf[i].g;
|
||
rgb[i].rgbBlue = m_PaletteBuf[i].b;
|
||
rgb[i].rgbReserved = 0;
|
||
}
|
||
}
|
||
|
||
// パレットファイルの更新
|
||
void CDirectDraw::SetPaletteFile( LPCTSTR fname )
|
||
{
|
||
// パレットファイルの更新
|
||
if( strlen( fname ) > 0 ) {
|
||
FILE *fp;
|
||
if( (fp = ::fopen( fname, "rb" )) ) {
|
||
BYTE palbuf[192];
|
||
// サイズ分読み込み
|
||
if( ::fread( palbuf, 192, 1, fp ) == 1 ) {
|
||
// パレットの変更と計算
|
||
SetPaletteTable( palbuf );
|
||
} else {
|
||
// 読みきれなかった時はデフォルト
|
||
SetPaletteTable( (LPBYTE)NULL );
|
||
}
|
||
FCLOSE(fp);
|
||
} else {
|
||
// 開けなかった時はデフォルト
|
||
SetPaletteTable( (LPBYTE)NULL );
|
||
}
|
||
} else {
|
||
// 名前が無い時はデフォルト
|
||
SetPaletteTable( (LPBYTE)NULL );
|
||
}
|
||
}
|
||
|
||
// フルスクリーンモードでのGDIウインドウ表示設定
|
||
BOOL CDirectDraw::SetFullScreenGDI( BOOL bMode )
|
||
{
|
||
// 念の為チェック
|
||
if( !m_lpDD || !m_lpDDPrimary )
|
||
return FALSE;
|
||
|
||
if( m_bScreenMode ) {
|
||
if( !m_bGDI ) {
|
||
if( bMode ) {
|
||
RELEASE( m_lpDDClipper ); // 一応
|
||
if( m_lpDD->CreateClipper(0, &m_lpDDClipper, NULL) == DD_OK ) {
|
||
m_lpDDClipper->SetHWnd( 0, m_hWnd );
|
||
m_lpDDPrimary->SetClipper( m_lpDDClipper );
|
||
if( m_lpDD->FlipToGDISurface() == DD_OK ) {
|
||
m_bGDI = TRUE;
|
||
} else {
|
||
RELEASE( m_lpDDClipper );
|
||
return FALSE;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
if( !bMode ) {
|
||
RELEASE( m_lpDDClipper );
|
||
m_bGDI = FALSE;
|
||
}
|
||
}
|
||
}
|
||
return TRUE;
|
||
}
|
||
|
||
void CDirectDraw::RealizePalette()
|
||
{
|
||
if( !m_lpDD || !m_lpDDPrimary )
|
||
return;
|
||
|
||
if( !m_bScreenMode ) {
|
||
DDSURFACEDESC2 ddsd;
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
m_lpDDPrimary->GetSurfaceDesc(&ddsd);
|
||
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
|
||
HDC hdc;
|
||
hdc = ::GetDC( m_hWnd );
|
||
::SelectPalette( hdc, m_hPalette, FALSE );
|
||
::RealizePalette( hdc );
|
||
::ReleaseDC( m_hWnd, hdc );
|
||
|
||
m_bPaletteUpdate = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
// 描画(Windowsメッセージ用)
|
||
void CDirectDraw::OnScreenDraw()
|
||
{
|
||
if( !m_bScreenMode ) {
|
||
// Window mode
|
||
Blt();
|
||
Flip();
|
||
} else {
|
||
// Fullscreen mode
|
||
if( m_bGDI ) {
|
||
Blt();
|
||
Flip();
|
||
}
|
||
}
|
||
}
|
||
|
||
void CDirectDraw::SetPaletteMode( INT nMode, BOOL bMono )
|
||
{
|
||
if( (m_nPaletteMode != nMode) || (m_bMonoMode != bMono) ) {
|
||
m_bPaletteUpdate = TRUE;
|
||
}
|
||
m_nPaletteMode = nMode;
|
||
m_bMonoMode = bMono;
|
||
}
|
||
|
||
// 表示中のパレットテーブルの取得
|
||
void CDirectDraw::GetPaletteData( RGBQUAD* rgb )
|
||
{
|
||
if( !m_bMonoMode ) {
|
||
for( INT i = 0; i < 64; i++ ) {
|
||
rgb[i ] = m_cpPalette[m_nPaletteMode][i];
|
||
rgb[i+0x40] = m_mpPalette[m_nPaletteMode][i];
|
||
}
|
||
} else {
|
||
for( INT i = 0; i < 64; i++ ) {
|
||
rgb[i ] = m_mpPalette[m_nPaletteMode][i];
|
||
rgb[i+0x40] = m_mpPalette[m_nPaletteMode][i];
|
||
}
|
||
}
|
||
}
|
||
|
||
void CDirectDraw::GetPaletteData2( RGBQUAD* rgb )
|
||
{
|
||
for( INT j = 0; j < 8; j++ ) {
|
||
for( INT i = 0; i < 64; i++ ) {
|
||
rgb[j*256+i ] = m_cpPalette[j][i];
|
||
rgb[j*256+i+0x40] = m_mpPalette[j][i];
|
||
}
|
||
}
|
||
}
|
||
|
||
void CDirectDraw::Blt()
|
||
{
|
||
INT i;
|
||
DDSURFACEDESC2 ddsd;
|
||
|
||
if( !m_lpDD || !m_lpDDPrimary )
|
||
return;
|
||
// ScreenMode changing?
|
||
if( m_bChangeMode )
|
||
return;
|
||
// Surface lost check & restore
|
||
if( !RestoreSurface() )
|
||
return;
|
||
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
if( m_lpDDPrimary->GetSurfaceDesc(&ddsd) != DD_OK )
|
||
return;
|
||
|
||
// Palette copy
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
|
||
static BYTE linecolor = 0;
|
||
|
||
if( m_LineColormode[1] != linecolor ) {
|
||
linecolor = m_LineColormode[1];
|
||
m_bPaletteUpdate = TRUE;
|
||
}
|
||
|
||
if( !(m_LineColormode[1]&0x80) ) {
|
||
for( i = 0; i < 128; i++ ) {
|
||
m_logPalette.pe[i+0x40].peRed = m_cpPalette[m_nPaletteMode][i].rgbRed;
|
||
m_logPalette.pe[i+0x40].peGreen = m_cpPalette[m_nPaletteMode][i].rgbGreen;
|
||
m_logPalette.pe[i+0x40].peBlue = m_cpPalette[m_nPaletteMode][i].rgbBlue;
|
||
}
|
||
} else {
|
||
for( i = 0; i < 128; i++ ) {
|
||
m_logPalette.pe[i+0x40].peRed = m_mpPalette[m_nPaletteMode][i].rgbRed;
|
||
m_logPalette.pe[i+0x40].peGreen = m_mpPalette[m_nPaletteMode][i].rgbGreen;
|
||
m_logPalette.pe[i+0x40].peBlue = m_mpPalette[m_nPaletteMode][i].rgbBlue;
|
||
}
|
||
}
|
||
if( !m_bScreenMode ) {
|
||
::AnimatePalette( m_hPalette, 0, 256, m_logPalette.pe );
|
||
}
|
||
}
|
||
|
||
// Size calculate
|
||
BOOL bDoubleWidth = FALSE;
|
||
BOOL bDoubleHeight = FALSE;
|
||
|
||
RECT rcW;
|
||
rcW.left = 0;
|
||
rcW.top = 0;
|
||
rcW.right = SCREEN_WIDTH;
|
||
rcW.bottom = SCREEN_HEIGHT;
|
||
if( m_bDoubleSize || (m_nBltFilter && IsMMX()) ) {
|
||
rcW.right *= 2;
|
||
rcW.bottom *= 2;
|
||
bDoubleWidth = TRUE;
|
||
bDoubleHeight = TRUE;
|
||
} else if( m_bScanlineMode ) {
|
||
rcW.bottom *= 2;
|
||
bDoubleHeight = TRUE;
|
||
}
|
||
|
||
// Render function
|
||
BLTFUNC* bltfunc;
|
||
if( !m_nBltFilter || !IsMMX() ) {
|
||
if( !m_bDoubleSize ) {
|
||
if( !m_bScanlineMode ) {
|
||
bltfunc = NormalBltTable;
|
||
} else {
|
||
bltfunc = ScanlineBltTable;
|
||
}
|
||
} else {
|
||
if( !m_bScanlineMode ) {
|
||
bltfunc = DoubleBltTable;
|
||
} else {
|
||
bltfunc = DoubleScanlineBltTable;
|
||
}
|
||
}
|
||
} else {
|
||
switch( m_nBltFilter ) {
|
||
case BLTFILTER_2XSAI:
|
||
bltfunc = nx2xSaIBltTable;
|
||
break;
|
||
case BLTFILTER_SUPER2XSAI:
|
||
bltfunc = nxSuper2xSaIBltTable;
|
||
break;
|
||
case BLTFILTER_SUPEREAGLE:
|
||
bltfunc = nxSuperEagleBltTable;
|
||
break;
|
||
case BLTFILTER_SCALE2X:
|
||
bltfunc = nxScale2xBltTable;
|
||
break;
|
||
case BLTFILTER_HQ2X:
|
||
bltfunc = nxHq2xBltTable;
|
||
break;
|
||
case BLTFILTER_LQ2X:
|
||
bltfunc = nxLq2xBltTable;
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
BOOL bFilter = FALSE;
|
||
LPBYTE lpRdr = m_lpRender+8;
|
||
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
|
||
if( m_bForceWrite ) {
|
||
// 多段レンダリング無し
|
||
if( m_lpDDRender->Lock( NULL, &ddsd, 0, NULL ) == DD_OK ) {
|
||
switch( ddsd.ddpfPixelFormat.dwRGBBitCount ) {
|
||
case 8:
|
||
(this->*bltfunc[0])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, TRUE );
|
||
break;
|
||
case 16:
|
||
(this->*bltfunc[1])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, TRUE );
|
||
break;
|
||
case 24:
|
||
(this->*bltfunc[2])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, TRUE );
|
||
break;
|
||
case 32:
|
||
(this->*bltfunc[3])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, TRUE );
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
m_lpDDRender->Unlock( NULL );
|
||
m_bDeltaUpdate = FALSE;
|
||
}
|
||
} else {
|
||
if( m_lpDDRender2->Lock( NULL, &ddsd, 0, NULL ) == DD_OK ) {
|
||
switch( ddsd.ddpfPixelFormat.dwRGBBitCount ) {
|
||
case 8:
|
||
(this->*bltfunc[0])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, m_bDeltaUpdate );
|
||
break;
|
||
case 16:
|
||
(this->*bltfunc[1])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, m_bDeltaUpdate );
|
||
break;
|
||
case 24:
|
||
(this->*bltfunc[2])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, m_bDeltaUpdate );
|
||
break;
|
||
case 32:
|
||
(this->*bltfunc[3])( lpRdr, &m_lpRenderDelta[DELTA_WIDTH*2*sizeof(DWORD)], ddsd, m_bDeltaUpdate );
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
|
||
m_lpDDRender2->Unlock( NULL );
|
||
m_bDeltaUpdate = FALSE;
|
||
|
||
m_lpDDRender->Blt( &rcW, m_lpDDRender2, &rcW, 0, NULL );
|
||
}
|
||
}
|
||
|
||
// TV枠
|
||
if( m_bTVFrameMode ) {
|
||
m_lpDDRender->Blt( &rcW, m_lpDDTV, NULL, DDBLT_KEYSRC, NULL );
|
||
}
|
||
|
||
// Infomation string
|
||
if( strlen(m_szInfo) > 0 ) {
|
||
INT x, y, o;
|
||
|
||
x = bDoubleWidth ? 16 : 8;
|
||
o = m_bAllLine ? 0 : 8;
|
||
y = bDoubleHeight ? 8+o*2 : 4+o;
|
||
|
||
RenderString( x, y, m_szInfo );
|
||
}
|
||
// Message string
|
||
if( m_bMessage ) {
|
||
if( timeGetTime()-m_dwMessageTime > 1500 ) {
|
||
m_bMessage = FALSE;
|
||
}
|
||
if( strlen(m_szMess) > 0 ) {
|
||
INT x, y, o;
|
||
|
||
x = bDoubleWidth ? 16 : 8;
|
||
o = m_bAllLine ? 8 : 0;
|
||
y = bDoubleHeight ? (SCREEN_HEIGHT*2-36+o*2) : (SCREEN_HEIGHT-18+o);
|
||
|
||
RenderString( x, y, m_szMess );
|
||
}
|
||
}
|
||
// DiskAccessLamp
|
||
if( m_bDiskAccessLamp ) {
|
||
INT x, y, o;
|
||
|
||
x = bDoubleWidth ? SCREEN_WIDTH*2-20 : SCREEN_WIDTH-10;
|
||
o = m_bAllLine ? 0 : 8;
|
||
y = bDoubleHeight ? 8+o*2 : 4+o;
|
||
|
||
RenderString( x, y, "\\" );
|
||
}
|
||
|
||
if( m_bZapper && m_bZapperDraw ) {
|
||
if( m_ZapperPosX >= 0 && m_ZapperPosX < SCREEN_WIDTH && m_ZapperPosY >= 0 && m_ZapperPosY < SCREEN_HEIGHT ) {
|
||
RECT rcS, rcZ;
|
||
|
||
SetRect( &rcZ, 0, 0, 16, 16 );
|
||
if( !bDoubleWidth ) {
|
||
rcS.left = m_ZapperPosX-(rcZ.right-rcZ.left)/2;
|
||
rcS.right = m_ZapperPosX+(rcZ.right-rcZ.left)/2;
|
||
} else {
|
||
rcS.left = m_ZapperPosX*2-(rcZ.right-rcZ.left);
|
||
rcS.right = m_ZapperPosX*2+(rcZ.right-rcZ.left);
|
||
}
|
||
if( !bDoubleHeight ) {
|
||
rcS.top = m_ZapperPosY-(rcZ.bottom-rcZ.top)/2;
|
||
rcS.bottom = m_ZapperPosY+(rcZ.bottom-rcZ.top)/2;
|
||
} else {
|
||
rcS.top = m_ZapperPosY*2-(rcZ.bottom-rcZ.top);
|
||
rcS.bottom = m_ZapperPosY*2+(rcZ.bottom-rcZ.top);
|
||
}
|
||
|
||
m_lpDDRender->Blt( &rcS, m_lpDDZapper, &rcZ, DDBLT_KEYSRC, NULL );
|
||
}
|
||
}
|
||
}
|
||
|
||
void CDirectDraw::Flip()
|
||
{
|
||
if( !m_lpDD || !m_lpDDPrimary )
|
||
return;
|
||
// ScreenMode changing?
|
||
if( m_bChangeMode )
|
||
return;
|
||
// Surface lost check & restore
|
||
if( !RestoreSurface() )
|
||
return;
|
||
|
||
DDSURFACEDESC2 ddsd;
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
m_lpDDPrimary->GetSurfaceDesc(&ddsd);
|
||
|
||
// Size calculate
|
||
BOOL bDoubleWidth = FALSE;
|
||
BOOL bDoubleHeight = FALSE;
|
||
if( m_bDoubleSize || (m_nBltFilter && IsMMX()) ) {
|
||
bDoubleWidth = TRUE;
|
||
bDoubleHeight = TRUE;
|
||
} else if( m_bScanlineMode ) {
|
||
bDoubleHeight = TRUE;
|
||
}
|
||
|
||
RECT rcS, rcC;
|
||
if( !bDoubleWidth ) {
|
||
rcS.left = 0;
|
||
rcS.right = SCREEN_WIDTH;
|
||
} else {
|
||
rcS.left = 0;
|
||
rcS.right = SCREEN_WIDTH*2;
|
||
}
|
||
if( !m_bAllLine ) {
|
||
rcS.top = 8;
|
||
rcS.bottom = SCREEN_HEIGHT-8;
|
||
} else {
|
||
rcS.top = 0;
|
||
rcS.bottom = SCREEN_HEIGHT;
|
||
}
|
||
if( bDoubleHeight ) {
|
||
rcS.top *= 2;
|
||
rcS.bottom *= 2;
|
||
}
|
||
|
||
if( !m_bScreenMode ) {
|
||
// Window mode
|
||
::GetClientRect( m_hWnd, &rcC );
|
||
::ClientToScreen( m_hWnd, (POINT*)&rcC.left );
|
||
::ClientToScreen( m_hWnd, (POINT*)&rcC.right );
|
||
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
|
||
HDC hdc;
|
||
if( m_lpDDPrimary->GetDC( &hdc ) == DD_OK ) {
|
||
::SelectPalette( hdc, m_hPalette, FALSE );
|
||
::RealizePalette( hdc );
|
||
m_lpDDPrimary->ReleaseDC( hdc );
|
||
}
|
||
}
|
||
} else {
|
||
// Fullscreen mode
|
||
if( !m_bMaxZoom ) {
|
||
DDBLTFX ddbltfx;
|
||
ddbltfx.dwSize = sizeof(DDBLTFX);
|
||
ddbltfx.dwFillColor = 0;
|
||
m_lpDDBack->Blt(NULL, NULL, NULL, DDBLT_COLORFILL|DDBLT_WAIT, &ddbltfx);
|
||
|
||
// Position offset caluclate
|
||
LONG swidth, sheight;
|
||
LONG dwidth, dheight;
|
||
LONG hmul, vmul;
|
||
|
||
if( !m_bAspect ) swidth = SCREEN_WIDTH;
|
||
else swidth = 320;
|
||
if( !m_bAllLine ) sheight = SCREEN_HEIGHT-16;
|
||
else sheight = SCREEN_HEIGHT;
|
||
|
||
dwidth = (LONG)ddsd.dwWidth;
|
||
dheight = (LONG)ddsd.dwHeight;
|
||
hmul = dwidth / swidth;
|
||
vmul = dheight / sheight;
|
||
|
||
if( vmul < hmul ) hmul = vmul;
|
||
else vmul = hmul;
|
||
|
||
rcC.left = (dwidth -swidth *hmul)/2;
|
||
rcC.top = (dheight-sheight*vmul)/2;
|
||
rcC.right = rcC.left+swidth *hmul;
|
||
rcC.bottom = rcC.top +sheight*vmul;
|
||
} else {
|
||
// Maximum zoom
|
||
rcC.left = 0;
|
||
rcC.top = 0;
|
||
rcC.right = (LONG)ddsd.dwWidth;
|
||
rcC.bottom = (LONG)ddsd.dwHeight;
|
||
}
|
||
}
|
||
|
||
if( !m_bScreenMode ) {
|
||
// Window mode
|
||
if( m_bWindowVSync ) {
|
||
HRESULT hr;
|
||
while( TRUE ) {
|
||
hr = m_lpDD->WaitForVerticalBlank( DDWAITVB_BLOCKBEGIN, NULL );
|
||
if( hr == DD_OK )
|
||
break;
|
||
if( hr == DDERR_SURFACELOST ) {
|
||
break;
|
||
}
|
||
if( hr != DDERR_WASSTILLDRAWING ) {
|
||
break;
|
||
}
|
||
}
|
||
// m_lpDDPrimary->Blt( NULL, m_lpDDBack, NULL, DDBLT_WAIT, NULL );
|
||
}
|
||
|
||
m_lpDDPrimary->Blt( &rcC, m_lpDDRender, &rcS, DDBLT_WAIT, NULL );
|
||
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
|
||
if( m_bPaletteUpdate ) {
|
||
m_bPaletteUpdate = FALSE;
|
||
::AnimatePalette( m_hPalette, 0, 256, m_logPalette.pe );
|
||
}
|
||
}
|
||
} else {
|
||
// Fullscreen mode
|
||
m_lpDDBack->Blt( &rcC, m_lpDDRender, &rcS, DDBLT_WAIT, NULL );
|
||
|
||
if( ddsd.ddpfPixelFormat.dwRGBBitCount == 8 ) {
|
||
if( m_bPaletteUpdate ) {
|
||
m_bPaletteUpdate = FALSE;
|
||
m_lpDDPalette->SetEntries( 0, 0, 256, m_logPalette.pe );
|
||
}
|
||
}
|
||
|
||
if( m_bFlip ) {
|
||
if( !m_bGDI ) {
|
||
HRESULT hr;
|
||
while( TRUE ) {
|
||
hr = m_lpDDPrimary->Flip( NULL, DDFLIP_WAIT );
|
||
if( hr == DD_OK )
|
||
break;
|
||
if( hr == DDERR_SURFACELOST ) {
|
||
break;
|
||
}
|
||
if( hr != DDERR_WASSTILLDRAWING ) {
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
HRESULT hr;
|
||
while( TRUE ) {
|
||
hr = m_lpDD->WaitForVerticalBlank( DDWAITVB_BLOCKBEGIN, NULL );
|
||
if( hr == DD_OK )
|
||
break;
|
||
if( hr == DDERR_SURFACELOST ) {
|
||
break;
|
||
}
|
||
if( hr != DDERR_WASSTILLDRAWING ) {
|
||
break;
|
||
}
|
||
}
|
||
m_lpDDPrimary->Blt( NULL, m_lpDDBack, NULL, DDBLT_WAIT, NULL );
|
||
}
|
||
} else {
|
||
m_lpDDPrimary->Blt( NULL, m_lpDDBack, NULL, DDBLT_WAIT, NULL );
|
||
}
|
||
}
|
||
}
|
||
|
||
BYTE CDirectDraw::GetZapperHit()
|
||
{
|
||
if( m_bZapper ) {
|
||
if( m_ZapperPosX >= 0 && m_ZapperPosX < SCREEN_WIDTH && m_ZapperPosY >= 0 && m_ZapperPosY < SCREEN_HEIGHT ) {
|
||
BYTE c = m_lpRender[8+m_ZapperPosX+RENDER_WIDTH*m_ZapperPosY];
|
||
DWORD Yn = (DWORD)(0.299f * m_cpPalette[0][c].rgbRed + 0.587f * m_cpPalette[0][c].rgbGreen + 0.114f * m_cpPalette[0][c].rgbBlue);
|
||
if( Yn > 0xFF )
|
||
Yn = 0xFF;
|
||
return (BYTE)Yn;
|
||
}
|
||
}
|
||
return 0x00;
|
||
}
|
||
|
||
void CDirectDraw::GetZapperPos( LONG& x, LONG& y )
|
||
{
|
||
x = y = -1;
|
||
|
||
if( !m_lpDD || !m_lpDDPrimary )
|
||
return;
|
||
// ScreenMode changing?
|
||
if( m_bChangeMode )
|
||
return;
|
||
|
||
if( !m_bZapper )
|
||
return;
|
||
|
||
RECT rcS, rcC;
|
||
|
||
// Size calculate
|
||
rcS.left = 0;
|
||
rcS.right = SCREEN_WIDTH;
|
||
if( !m_bAllLine ) {
|
||
rcS.top = 8;
|
||
rcS.bottom = SCREEN_HEIGHT-8;
|
||
} else {
|
||
rcS.top = 0;
|
||
rcS.bottom = SCREEN_HEIGHT;
|
||
}
|
||
if( m_bScanlineMode ) {
|
||
rcS.top *= 2;
|
||
rcS.bottom *= 2;
|
||
}
|
||
|
||
if( !m_bScreenMode ) {
|
||
// Window mode
|
||
::GetClientRect( m_hWnd, &rcC );
|
||
::ClientToScreen( m_hWnd, (POINT*)&rcC.left );
|
||
::ClientToScreen( m_hWnd, (POINT*)&rcC.right );
|
||
} else {
|
||
// Fullscreen mode
|
||
DDSURFACEDESC2 ddsd;
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
if( m_lpDDPrimary->GetSurfaceDesc(&ddsd) != DD_OK )
|
||
return;
|
||
|
||
if( !m_bMaxZoom ) {
|
||
// Position offset caluclate
|
||
LONG swidth, sheight;
|
||
LONG dwidth, dheight;
|
||
LONG hmul, vmul;
|
||
|
||
if( !m_bAspect ) swidth = SCREEN_WIDTH;
|
||
else swidth = 320;
|
||
if( !m_bAllLine ) sheight = SCREEN_HEIGHT-16;
|
||
else sheight = SCREEN_HEIGHT;
|
||
|
||
dwidth = (LONG)ddsd.dwWidth;
|
||
dheight = (LONG)ddsd.dwHeight;
|
||
hmul = dwidth / swidth;
|
||
vmul = dheight / sheight;
|
||
|
||
if( vmul < hmul ) hmul = vmul;
|
||
else vmul = hmul;
|
||
|
||
rcC.left = (dwidth -swidth *hmul)/2;
|
||
rcC.top = (dheight-sheight*vmul)/2;
|
||
rcC.right = rcC.left+swidth *hmul;
|
||
rcC.bottom = rcC.top +sheight*vmul;
|
||
} else {
|
||
// Maximum zoom
|
||
rcC.left = 0;
|
||
rcC.top = 0;
|
||
rcC.right = (LONG)ddsd.dwWidth;
|
||
rcC.bottom = (LONG)ddsd.dwHeight;
|
||
}
|
||
|
||
}
|
||
|
||
POINT mp;
|
||
FLOAT hz, vz;
|
||
|
||
::GetCursorPos( &mp );
|
||
|
||
if( mp.x >= rcC.left && mp.x < rcC.right
|
||
&& mp.y >= rcC.top && mp.y < rcC.bottom ) {
|
||
hz = (FLOAT)(rcS.right-rcS.left)/(rcC.right-rcC.left);
|
||
vz = (FLOAT)(rcS.bottom-rcS.top)/(rcC.bottom-rcC.top);
|
||
x = (LONG)((mp.x-rcC.left)*hz)+rcS.left;
|
||
if( !m_bScanlineMode ) {
|
||
y = (LONG)((mp.y-rcC.top) *vz)+rcS.top;
|
||
} else {
|
||
y = (LONG)(((mp.y-rcC.top) *vz)+rcS.top)/2;
|
||
}
|
||
|
||
if( x > SCREEN_WIDTH-1 )
|
||
x = SCREEN_WIDTH-1;
|
||
if( y > SCREEN_HEIGHT-1 )
|
||
y = SCREEN_HEIGHT-1;
|
||
} else {
|
||
x = y = -1;
|
||
}
|
||
|
||
m_ZapperPosX = x;
|
||
m_ZapperPosY = y;
|
||
}
|
||
|
||
void CDirectDraw::SetZapperPos( LONG x, LONG y )
|
||
{
|
||
m_ZapperPosX = x;
|
||
m_ZapperPosY = y;
|
||
}
|
||
|
||
// Infomation string
|
||
void CDirectDraw::SetInfoString( LPCSTR str )
|
||
{
|
||
if( str ) {
|
||
if( strlen(str) > INFOSTR_SIZE ) {
|
||
memcpy( m_szInfo, str, INFOSTR_SIZE );
|
||
m_szInfo[INFOSTR_SIZE] = '\0';
|
||
} else {
|
||
strcpy( m_szInfo, str );
|
||
}
|
||
} else {
|
||
m_szInfo[0] = '\0';
|
||
}
|
||
}
|
||
|
||
// Message string
|
||
void CDirectDraw::SetMessageString( LPCSTR str )
|
||
{
|
||
if( str ) {
|
||
if( strlen(str) > INFOSTR_SIZE ) {
|
||
memcpy( m_szMess, str, INFOSTR_SIZE );
|
||
m_szMess[INFOSTR_SIZE] = '\0';
|
||
} else {
|
||
strcpy( m_szMess, str );
|
||
}
|
||
m_bMessage = TRUE;
|
||
m_dwMessageTime = ::timeGetTime();
|
||
} else {
|
||
m_bMessage = FALSE;
|
||
m_szMess[0] = '\0';
|
||
}
|
||
}
|
||
|
||
void CDirectDraw::RenderString( INT x, INT y, LPCSTR str )
|
||
{
|
||
if( !m_lpDD || !m_lpDDPrimary )
|
||
return;
|
||
// ScreenMode changing?
|
||
if( m_bChangeMode )
|
||
return;
|
||
|
||
if( !str )
|
||
return;
|
||
|
||
// Size calculate
|
||
BOOL bDoubleWidth = FALSE;
|
||
BOOL bDoubleHeight = FALSE;
|
||
if( m_bDoubleSize || (m_nBltFilter && IsMMX()) ) {
|
||
bDoubleWidth = TRUE;
|
||
bDoubleHeight = TRUE;
|
||
} else if( m_bScanlineMode ) {
|
||
bDoubleHeight = TRUE;
|
||
}
|
||
|
||
RECT rcS, rcW;
|
||
INT ch;
|
||
INT xadd;
|
||
|
||
rcW.left = x;
|
||
rcW.top = y;
|
||
if( !bDoubleWidth ) {
|
||
rcW.right = x+6;
|
||
xadd = 6;
|
||
} else {
|
||
rcW.right = x+12;
|
||
xadd = 12;
|
||
}
|
||
if( !bDoubleHeight ) {
|
||
rcW.bottom = y+6;
|
||
} else {
|
||
rcW.bottom = y+12;
|
||
}
|
||
|
||
while( *str ) {
|
||
ch = toupper(*str)-0x20;
|
||
rcS.left = (ch%8)*6;
|
||
rcS.right = rcS.left+6;
|
||
rcS.top = (ch/8)*6;
|
||
rcS.bottom = rcS.top+6;
|
||
|
||
m_lpDDRender->Blt( &rcW, m_lpDDAscii, &rcS, DDBLT_KEYSRC, NULL );
|
||
|
||
rcW.left += xadd;
|
||
rcW.right += xadd;
|
||
str++;
|
||
}
|
||
}
|
||
|
||
// LZSS BMPからサーフェスへのコピー
|
||
void CDirectDraw::SetLZSSChar( LPBYTE lpLZ, LPDIRECTDRAWSURFACE7 lpDDSurface )
|
||
{
|
||
LPBYTE lpBuf = NULL;
|
||
LPBITMAPINFOHEADER pbi;
|
||
LPBYTE lpPix;
|
||
HDC hDC;
|
||
|
||
if( !(lpBuf = (LPBYTE)malloc( *((LONG*)lpLZ) )) )
|
||
throw "Out of memory.";
|
||
|
||
LZdecode( &lpLZ[8], lpBuf, *((LONG*)&lpLZ[4]) );
|
||
|
||
pbi = (LPBITMAPINFOHEADER)lpBuf;
|
||
if( pbi->biBitCount < 16 )
|
||
lpPix = ((LPBYTE)pbi)+pbi->biSize+(1<<pbi->biBitCount)*sizeof(RGBQUAD);
|
||
else
|
||
lpPix = (LPBYTE)pbi+pbi->biSize;
|
||
|
||
DDSURFACEDESC2 ddsd;
|
||
ZEROMEMORY( &ddsd, sizeof(DDSURFACEDESC2) );
|
||
ddsd.dwSize = sizeof(DDSURFACEDESC2);
|
||
lpDDSurface->GetSurfaceDesc(&ddsd);
|
||
|
||
// BMPは高さがマイナスな事があるので....
|
||
LONG height = pbi->biHeight;
|
||
if( height < 0 )
|
||
height = -height;
|
||
|
||
if( lpDDSurface->GetDC( &hDC ) == DD_OK ) {
|
||
StretchDIBits( hDC, 0, 0, ddsd.dwWidth, ddsd.dwHeight,
|
||
0, 0, pbi->biWidth, height, lpPix, (LPBITMAPINFO)lpBuf, DIB_RGB_COLORS, SRCCOPY );
|
||
lpDDSurface->ReleaseDC( hDC );
|
||
}
|
||
FREE( lpBuf );
|
||
}
|
||
|
||
BYTE CDirectDraw::GetPixel( INT x, INT y )
|
||
{
|
||
if( x >= 0 && x < SCREEN_WIDTH && y >= 0 && y < SCREEN_HEIGHT ) {
|
||
BYTE c = m_lpRender[8+(x)+RENDER_WIDTH*y];
|
||
return c;
|
||
}
|
||
|
||
return 0x00;
|
||
}
|
||
|
||
#include "Render.h"
|