📄 directdraw.cpp
字号:
//
// 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::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"
};
// 儊儌儕偐傜侾僶僀僩庢偭偰偔傞
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 ) {
// 僂僀儞僪僂
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -