📄 directdraw.cpp
字号:
// 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 );
}
#include "Render.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -