AxibugEmuOnline/virtuanessrc097-master/DirectDraw.cpp

2004 lines
102 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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"