2007-11-14 12:28:27 +00:00
|
|
|
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
|
|
|
// Copyright (C) 1999-2003 Forgotten
|
|
|
|
// Copyright (C) 2004 Forgotten and the VBA development team
|
|
|
|
// Copyright (C) 2005-2006 VBA development team
|
|
|
|
|
|
|
|
// This program is free software; you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation; either version 2, or(at your option)
|
|
|
|
// any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software Foundation,
|
|
|
|
// Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
|
|
#include "Display.h"
|
|
|
|
|
|
|
|
#include "MainWnd.h"
|
|
|
|
|
|
|
|
#include "../System.h"
|
|
|
|
#include "../GBA.h"
|
|
|
|
#include "../Globals.h"
|
|
|
|
#include "../Text.h"
|
|
|
|
#include "../Util.h"
|
|
|
|
#include "../gb/gbGlobals.h"
|
|
|
|
|
|
|
|
// Direct3D
|
|
|
|
#define DIRECT3D_VERSION 0x0900
|
|
|
|
#include <d3d9.h> // main include file
|
|
|
|
#include <D3dx9core.h> // required for font rednering
|
|
|
|
#include <Dxerr.h> // contains debug functions
|
|
|
|
|
|
|
|
extern int Init_2xSaI(u32); // initializes all pixel filters
|
|
|
|
extern int systemSpeed;
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define new DEBUG_NEW
|
|
|
|
#undef THIS_FILE
|
|
|
|
static char THIS_FILE[] = __FILE__;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MMX
|
|
|
|
extern "C" bool cpu_mmx;
|
|
|
|
extern bool detectMMX();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern int winVideoModeSelect(CWnd *, GUID **);
|
|
|
|
|
|
|
|
class Direct3DDisplay : public IDisplay {
|
|
|
|
private:
|
|
|
|
LPDIRECT3D9 pD3D;
|
|
|
|
LPDIRECT3DDEVICE9 pDevice;
|
|
|
|
D3DDISPLAYMODE mode;
|
|
|
|
D3DPRESENT_PARAMETERS dpp;
|
|
|
|
D3DFORMAT screenFormat;
|
|
|
|
LPDIRECT3DSURFACE9 emulatedImage;
|
|
|
|
D3DTEXTUREFILTERTYPE filter;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
RECT destRect;
|
|
|
|
bool failed;
|
|
|
|
ID3DXFont *pFont;
|
|
|
|
|
|
|
|
void createFont();
|
|
|
|
void destroyFont();
|
|
|
|
void createSurface();
|
|
|
|
void destroySurface();
|
|
|
|
void calculateDestRect();
|
|
|
|
bool resetDevice();
|
|
|
|
void setPresentationType();
|
|
|
|
|
|
|
|
public:
|
|
|
|
Direct3DDisplay();
|
|
|
|
virtual ~Direct3DDisplay();
|
|
|
|
virtual DISPLAY_TYPE getType() { return DIRECT_3D; };
|
|
|
|
|
|
|
|
virtual bool initialize();
|
|
|
|
virtual void cleanup();
|
|
|
|
virtual void clear();
|
|
|
|
virtual void render();
|
|
|
|
|
|
|
|
virtual void renderMenu();
|
|
|
|
virtual bool changeRenderSize( int w, int h );
|
|
|
|
virtual void resize( int w, int h );
|
|
|
|
virtual void setOption( const char *option, int value );
|
|
|
|
virtual int selectFullScreenMode( GUID ** );
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Direct3DDisplay::Direct3DDisplay()
|
|
|
|
{
|
|
|
|
pD3D = NULL;
|
|
|
|
pDevice = NULL;
|
|
|
|
screenFormat = D3DFMT_X8R8G8B8;
|
|
|
|
width = 0;
|
|
|
|
height = 0;
|
|
|
|
failed = false;
|
|
|
|
pFont = NULL;
|
|
|
|
emulatedImage = NULL;
|
|
|
|
filter = D3DTEXF_POINT;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Direct3DDisplay::~Direct3DDisplay()
|
|
|
|
{
|
|
|
|
cleanup();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Direct3DDisplay::setPresentationType()
|
|
|
|
{
|
|
|
|
// Change display mode
|
|
|
|
memset(&dpp, 0, sizeof(dpp));
|
|
|
|
dpp.Windowed = !(theApp.videoOption>=VIDEO_320x240);
|
|
|
|
if (!dpp.Windowed)
|
|
|
|
dpp.BackBufferFormat =
|
|
|
|
(theApp.fsColorDepth == 32) ? D3DFMT_X8R8G8B8 : D3DFMT_R5G6B5;
|
|
|
|
else
|
|
|
|
dpp.BackBufferFormat = mode.Format;
|
|
|
|
dpp.BackBufferCount = 3;
|
|
|
|
dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
|
|
dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
|
|
dpp.BackBufferWidth = !dpp.Windowed ? theApp.fsWidth : theApp.surfaceSizeX;
|
|
|
|
dpp.BackBufferHeight = !dpp.Windowed ? theApp.fsHeight : theApp.surfaceSizeY;
|
|
|
|
dpp.hDeviceWindow = theApp.m_pMainWnd->GetSafeHwnd();
|
|
|
|
dpp.FullScreen_RefreshRateInHz = dpp.Windowed ? 0 : theApp.fsFrequency;
|
|
|
|
dpp.Flags = theApp.menuToggle ? D3DPRESENTFLAG_LOCKABLE_BACKBUFFER : 0;
|
|
|
|
if (theApp.vsync)
|
|
|
|
dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync
|
|
|
|
else
|
|
|
|
dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::cleanup()
|
|
|
|
{
|
|
|
|
destroyFont();
|
|
|
|
destroySurface();
|
|
|
|
|
|
|
|
if( pDevice ) {
|
|
|
|
pDevice->Release();
|
|
|
|
pDevice = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pD3D ) {
|
|
|
|
pD3D->Release();
|
|
|
|
pD3D = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Direct3DDisplay::initialize()
|
|
|
|
{
|
|
|
|
switch(theApp.cartridgeType)
|
|
|
|
{
|
|
|
|
case IMAGE_GBA:
|
|
|
|
theApp.sizeX = 240;
|
|
|
|
theApp.sizeY = 160;
|
|
|
|
break;
|
|
|
|
case IMAGE_GB:
|
|
|
|
if (gbBorderOn)
|
|
|
|
{
|
|
|
|
theApp.sizeX = 256;
|
|
|
|
theApp.sizeY = 224;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
theApp.sizeX = 160;
|
|
|
|
theApp.sizeY = 144;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
switch(theApp.videoOption)
|
|
|
|
{
|
|
|
|
case VIDEO_1X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY;
|
|
|
|
break;
|
|
|
|
case VIDEO_2X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX * 2;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY * 2;
|
|
|
|
break;
|
|
|
|
case VIDEO_3X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX * 3;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY * 3;
|
|
|
|
break;
|
|
|
|
case VIDEO_4X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX * 4;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY * 4;
|
|
|
|
break;
|
|
|
|
case VIDEO_320x240:
|
|
|
|
case VIDEO_640x480:
|
|
|
|
case VIDEO_800x600:
|
|
|
|
case VIDEO_1024x768:
|
|
|
|
case VIDEO_1280x1024:
|
|
|
|
case VIDEO_OTHER:
|
|
|
|
float scaleX = ((float)theApp.fsWidth / theApp.sizeX);
|
|
|
|
float scaleY = ((float)theApp.fsHeight / theApp.sizeY);
|
|
|
|
float min = (scaleX < scaleY) ? scaleX : scaleY;
|
|
|
|
if(theApp.fullScreenStretch) {
|
|
|
|
theApp.surfaceSizeX = theApp.fsWidth;
|
|
|
|
theApp.surfaceSizeY = theApp.fsHeight;
|
|
|
|
} else {
|
|
|
|
theApp.surfaceSizeX = (int)(theApp.sizeX * min);
|
|
|
|
theApp.surfaceSizeY = (int)(theApp.sizeY * min);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
theApp.rect.left = 0;
|
|
|
|
theApp.rect.top = 0;
|
|
|
|
theApp.rect.right = theApp.sizeX;
|
|
|
|
theApp.rect.bottom = theApp.sizeY;
|
|
|
|
|
|
|
|
theApp.dest.left = 0;
|
|
|
|
theApp.dest.top = 0;
|
|
|
|
theApp.dest.right = theApp.surfaceSizeX;
|
|
|
|
theApp.dest.bottom = theApp.surfaceSizeY;
|
|
|
|
|
|
|
|
|
|
|
|
DWORD style = WS_POPUP | WS_VISIBLE;
|
|
|
|
DWORD styleEx = 0;
|
|
|
|
|
|
|
|
if(theApp.videoOption <= VIDEO_4X) {
|
|
|
|
style |= WS_OVERLAPPEDWINDOW;
|
|
|
|
} else {
|
|
|
|
styleEx = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(theApp.videoOption <= VIDEO_4X) {
|
|
|
|
AdjustWindowRectEx(&theApp.dest, style, TRUE, styleEx);
|
|
|
|
} else {
|
|
|
|
AdjustWindowRectEx(&theApp.dest, style, FALSE, styleEx);
|
|
|
|
}
|
|
|
|
|
|
|
|
int winSizeX = theApp.dest.right-theApp.dest.left;
|
|
|
|
int winSizeY = theApp.dest.bottom-theApp.dest.top;
|
|
|
|
|
|
|
|
if(theApp.videoOption > VIDEO_4X) {
|
|
|
|
winSizeX = theApp.fsWidth;
|
|
|
|
winSizeY = theApp.fsHeight;
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = 0, y = 0;
|
|
|
|
|
|
|
|
if(theApp.videoOption <= VIDEO_4X) {
|
|
|
|
x = theApp.windowPositionX;
|
|
|
|
y = theApp.windowPositionY;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Create a window
|
|
|
|
MainWnd *pWnd = new MainWnd;
|
|
|
|
theApp.m_pMainWnd = pWnd;
|
|
|
|
|
|
|
|
pWnd->CreateEx(styleEx,
|
|
|
|
theApp.wndClass,
|
|
|
|
_T("VisualBoyAdvance"),
|
|
|
|
style,
|
|
|
|
x,y,winSizeX,winSizeY,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
|
|
|
|
if (!(HWND)*pWnd) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Error creating window"), 0 );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
pWnd->DragAcceptFiles(TRUE);
|
|
|
|
theApp.updateMenuBar();
|
|
|
|
theApp.adjustDestRect();
|
|
|
|
|
|
|
|
|
|
|
|
// load Direct3D v9
|
|
|
|
pD3D = Direct3DCreate9( D3D_SDK_VERSION );
|
|
|
|
|
|
|
|
if(pD3D == NULL) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D object"), 0 );
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
|
|
|
|
|
|
|
|
theApp.mode320Available = FALSE;
|
|
|
|
theApp.mode640Available = FALSE;
|
|
|
|
theApp.mode800Available = FALSE;
|
|
|
|
theApp.mode1024Available = FALSE;
|
|
|
|
theApp.mode1280Available = FALSE;
|
|
|
|
|
|
|
|
unsigned int nModes, i;
|
|
|
|
D3DDISPLAYMODE dm;
|
|
|
|
|
|
|
|
nModes = pD3D->GetAdapterModeCount(theApp.fsAdapter, mode.Format);
|
|
|
|
for (i = 0; i<nModes; i++)
|
|
|
|
{
|
|
|
|
if (D3D_OK == pD3D->EnumAdapterModes(theApp.fsAdapter, mode.Format, i, &dm) )
|
|
|
|
{
|
|
|
|
if ( (dm.Width == 320) && (dm.Height == 240) )
|
|
|
|
theApp.mode320Available = true;
|
|
|
|
if ( (dm.Width == 640) && (dm.Height == 480) )
|
|
|
|
theApp.mode640Available = true;
|
|
|
|
if ( (dm.Width == 800) && (dm.Height == 600) )
|
|
|
|
theApp.mode800Available = true;
|
|
|
|
if ( (dm.Width == 1024) && (dm.Height == 768) )
|
|
|
|
theApp.mode1024Available = true;
|
|
|
|
if ( (dm.Width == 1280) && (dm.Height == 1024) )
|
|
|
|
theApp.mode1280Available = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
screenFormat = mode.Format;
|
|
|
|
|
|
|
|
switch(mode.Format) {
|
|
|
|
case D3DFMT_R8G8B8:
|
|
|
|
systemColorDepth = 24;
|
|
|
|
systemRedShift = 19;
|
|
|
|
systemGreenShift = 11;
|
|
|
|
systemBlueShift = 3;
|
|
|
|
break;
|
|
|
|
case D3DFMT_X8R8G8B8:
|
|
|
|
systemColorDepth = 32;
|
|
|
|
systemRedShift = 19;
|
|
|
|
systemGreenShift = 11;
|
|
|
|
systemBlueShift = 3;
|
|
|
|
Init_2xSaI(32);
|
|
|
|
break;
|
|
|
|
case D3DFMT_R5G6B5:
|
|
|
|
systemColorDepth = 16;
|
|
|
|
systemRedShift = 11;
|
|
|
|
systemGreenShift = 6;
|
|
|
|
systemBlueShift = 0;
|
|
|
|
Init_2xSaI(565);
|
|
|
|
break;
|
|
|
|
case D3DFMT_X1R5G5B5:
|
|
|
|
systemColorDepth = 16;
|
|
|
|
systemRedShift = 10;
|
|
|
|
systemGreenShift = 5;
|
|
|
|
systemBlueShift = 0;
|
|
|
|
Init_2xSaI(555);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Unsupport D3D format"), 0 );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
theApp.fsColorDepth = systemColorDepth;
|
|
|
|
utilUpdateSystemColorMaps();
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef MMX
|
|
|
|
if(!theApp.disableMMX) {
|
|
|
|
cpu_mmx = theApp.detectMMX();
|
|
|
|
} else {
|
|
|
|
cpu_mmx = 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
theApp.updateFilter();
|
|
|
|
theApp.updateIFB();
|
|
|
|
|
|
|
|
|
|
|
|
// create device
|
|
|
|
setPresentationType();
|
|
|
|
|
|
|
|
HRESULT hret = pD3D->CreateDevice(
|
|
|
|
D3DADAPTER_DEFAULT,
|
|
|
|
D3DDEVTYPE_HAL,
|
|
|
|
pWnd->GetSafeHwnd(),
|
|
|
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
|
|
|
|
&dpp,
|
|
|
|
&pDevice);
|
|
|
|
if( FAILED( hret ) ) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D device"), hret );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
createFont();
|
|
|
|
createSurface();
|
|
|
|
calculateDestRect();
|
|
|
|
|
|
|
|
setOption( _T("d3dFilter"), theApp.d3dFilter );
|
|
|
|
|
|
|
|
if(failed) return false;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::renderMenu()
|
|
|
|
{
|
|
|
|
checkFullScreen();
|
|
|
|
if(theApp.m_pMainWnd) {
|
|
|
|
theApp.m_pMainWnd->DrawMenuBar();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::clear()
|
|
|
|
{
|
|
|
|
if( pDevice ) {
|
|
|
|
pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0x00,0x00,0x00), 0.0f, 0 );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::render()
|
|
|
|
{
|
|
|
|
if( failed ) return;
|
|
|
|
if(!pDevice) return;
|
|
|
|
if( FAILED( pDevice->TestCooperativeLevel() ) ) return;
|
|
|
|
|
|
|
|
clear();
|
|
|
|
|
|
|
|
pDevice->BeginScene();
|
|
|
|
|
|
|
|
// copy pix to emulatedImage and apply pixel filter if selected
|
|
|
|
HRESULT hr;
|
|
|
|
D3DLOCKED_RECT lr;
|
|
|
|
if( FAILED( hr = emulatedImage->LockRect( &lr, NULL, D3DLOCK_DISCARD ) ) ) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Can not lock back buffer"), hr );
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if( !theApp.filterFunction ) {
|
|
|
|
copyImage( pix, lr.pBits, theApp.sizeX, theApp.sizeY, lr.Pitch, systemColorDepth );
|
|
|
|
} else {
|
|
|
|
u32 pitch = theApp.filterWidth * (systemColorDepth>>3) + 4;
|
|
|
|
theApp.filterFunction( pix + pitch,
|
|
|
|
pitch,
|
|
|
|
(u8*)theApp.delta,
|
|
|
|
(u8*)lr.pBits,
|
|
|
|
lr.Pitch,
|
|
|
|
theApp.filterWidth,
|
|
|
|
theApp.filterHeight);
|
|
|
|
}
|
|
|
|
emulatedImage->UnlockRect();
|
|
|
|
}
|
|
|
|
|
|
|
|
// copy emulatedImage to pBackBuffer and scale with or without aspect ratio
|
|
|
|
LPDIRECT3DSURFACE9 pBackBuffer;
|
|
|
|
pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
|
|
|
|
if( theApp.fullScreenStretch ) {
|
|
|
|
pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, NULL, filter );
|
|
|
|
} else {
|
|
|
|
pDevice->StretchRect( emulatedImage, NULL, pBackBuffer, &destRect, filter );
|
|
|
|
}
|
|
|
|
pBackBuffer->Release();
|
|
|
|
pBackBuffer = NULL;
|
|
|
|
|
|
|
|
D3DCOLOR color;
|
|
|
|
RECT r;
|
|
|
|
r.left = 4;
|
|
|
|
r.right = dpp.BackBufferWidth - 4;
|
|
|
|
|
|
|
|
if( theApp.screenMessage ) {
|
|
|
|
color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0xFF, 0x00, 0x00) : D3DCOLOR_ARGB(0xFF, 0xFF, 0x00, 0x00);
|
|
|
|
if( ( ( GetTickCount() - theApp.screenMessageTime ) < 3000 ) && !theApp.disableStatusMessage && pFont ) {
|
|
|
|
r.top = dpp.BackBufferHeight - 20;
|
|
|
|
r.bottom = dpp.BackBufferHeight - 4;
|
|
|
|
pFont->DrawText( NULL, theApp.screenMessageBuffer, -1, &r, 0, color );
|
|
|
|
} else {
|
|
|
|
theApp.screenMessage = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( theApp.showSpeed && ( theApp.videoOption > VIDEO_4X ) ) {
|
|
|
|
color = theApp.showSpeedTransparent ? D3DCOLOR_ARGB(0x7F, 0x00, 0x00, 0xFF) : D3DCOLOR_ARGB(0xFF, 0x00, 0x00, 0xFF);
|
|
|
|
char buffer[30];
|
|
|
|
if( theApp.showSpeed == 1 ) {
|
|
|
|
sprintf( buffer, "%3d%%", systemSpeed );
|
|
|
|
} else {
|
|
|
|
sprintf( buffer, "%3d%%(%d, %d fps)", systemSpeed, systemFrameSkip, theApp.showRenderedFrames );
|
|
|
|
}
|
|
|
|
|
|
|
|
r.top = 4;
|
|
|
|
r.bottom = 20;
|
|
|
|
pFont->DrawText( NULL, buffer, -1, &r, 0, color );
|
|
|
|
}
|
|
|
|
|
|
|
|
pDevice->EndScene();
|
|
|
|
|
|
|
|
pDevice->Present( NULL, NULL, NULL, NULL );
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Direct3DDisplay::changeRenderSize( int w, int h )
|
|
|
|
{
|
|
|
|
if( (w != width) || (h != height) ) {
|
|
|
|
width = w; height = h;
|
|
|
|
if( pDevice ) {
|
|
|
|
destroySurface();
|
|
|
|
createSurface();
|
|
|
|
calculateDestRect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::resize( int w, int h )
|
|
|
|
{
|
|
|
|
if( (w != dpp.BackBufferWidth) || (h != dpp.BackBufferHeight) ) {
|
|
|
|
dpp.BackBufferWidth = (UINT)w;
|
|
|
|
dpp.BackBufferHeight = (UINT)h;
|
|
|
|
resetDevice();
|
|
|
|
calculateDestRect();
|
|
|
|
}
|
|
|
|
if(theApp.videoOption > VIDEO_4X)
|
|
|
|
resetDevice();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Direct3DDisplay::selectFullScreenMode( GUID **pGUID )
|
|
|
|
{
|
|
|
|
return winVideoModeSelect(theApp.m_pMainWnd, pGUID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::createFont()
|
|
|
|
{
|
|
|
|
if( !pFont ) {
|
|
|
|
HRESULT hr = D3DXCreateFont(
|
|
|
|
pDevice,
|
|
|
|
14,
|
|
|
|
0,
|
|
|
|
FW_BOLD,
|
|
|
|
1,
|
|
|
|
FALSE,
|
|
|
|
DEFAULT_CHARSET,
|
|
|
|
OUT_DEFAULT_PRECIS,
|
|
|
|
DEFAULT_QUALITY,
|
|
|
|
DEFAULT_PITCH || FF_DONTCARE,
|
|
|
|
_T("Arial"),
|
|
|
|
&pFont );
|
|
|
|
if( FAILED( hr ) ) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("createFont failed"), hr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::destroyFont()
|
|
|
|
{
|
|
|
|
if( pFont ) {
|
|
|
|
pFont->Release();
|
|
|
|
pFont = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::createSurface()
|
|
|
|
{
|
|
|
|
if( !emulatedImage ) {
|
|
|
|
HRESULT hr = pDevice->CreateOffscreenPlainSurface(
|
|
|
|
width, height,
|
|
|
|
dpp.BackBufferFormat,
|
|
|
|
D3DPOOL_DEFAULT,
|
|
|
|
&emulatedImage,
|
|
|
|
NULL );
|
|
|
|
if( FAILED( hr ) ) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("createSurface failed"), hr );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::destroySurface()
|
|
|
|
{
|
|
|
|
if( emulatedImage ) {
|
|
|
|
emulatedImage->Release();
|
|
|
|
emulatedImage = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::calculateDestRect()
|
|
|
|
{
|
|
|
|
float scaleX = (float)dpp.BackBufferWidth / (float)width;
|
|
|
|
float scaleY = (float)dpp.BackBufferHeight / (float)height;
|
|
|
|
float min = (scaleX < scaleY) ? scaleX : scaleY;
|
|
|
|
if( theApp.fsMaxScale && (min > theApp.fsMaxScale) ) {
|
|
|
|
min = (float)theApp.fsMaxScale;
|
|
|
|
}
|
|
|
|
destRect.left = 0;
|
|
|
|
destRect.top = 0;
|
|
|
|
destRect.right = (LONG)(width * min);
|
|
|
|
destRect.bottom = (LONG)(height * min);
|
|
|
|
if( destRect.right != dpp.BackBufferWidth ) {
|
|
|
|
LONG diff = (dpp.BackBufferWidth - destRect.right) / 2;
|
|
|
|
destRect.left += diff;
|
|
|
|
destRect.right += diff;
|
|
|
|
}
|
|
|
|
if( destRect.bottom != dpp.BackBufferHeight ) {
|
|
|
|
LONG diff = (dpp.BackBufferHeight - destRect.bottom) / 2;
|
|
|
|
destRect.top += diff;
|
|
|
|
destRect.bottom += diff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::setOption( const char *option, int value )
|
|
|
|
{
|
|
|
|
if( !_tcscmp( option, _T("vsync") ) ) {
|
|
|
|
theApp.vsync = true;
|
|
|
|
resetDevice();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !_tcscmp( option, _T("tripleBuffering") ) ) {
|
|
|
|
theApp.tripleBuffering = true;
|
|
|
|
resetDevice();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !_tcscmp( option, _T("d3dFilter") ) ) {
|
|
|
|
switch( value )
|
|
|
|
{
|
|
|
|
case 0: //point
|
|
|
|
filter = D3DTEXF_POINT;
|
|
|
|
break;
|
|
|
|
case 1: //linear
|
|
|
|
filter = D3DTEXF_LINEAR;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !_tcscmp( option, _T("maxScale") ) ) {
|
|
|
|
calculateDestRect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Direct3DDisplay::resetDevice()
|
|
|
|
{
|
|
|
|
if( !pDevice ) return false;
|
|
|
|
|
|
|
|
HRESULT hr;
|
|
|
|
destroyFont();
|
|
|
|
destroySurface();
|
|
|
|
setPresentationType();
|
|
|
|
if (!theApp.menuToggle)
|
|
|
|
pDevice->SetDialogBoxMode( FALSE );
|
|
|
|
|
|
|
|
if( FAILED( hr = pDevice->Reset( &dpp ) ) ) {
|
|
|
|
//DXTRACE_ERR_MSGBOX( _T("pDevice->Reset failed"), hr );
|
|
|
|
failed = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (theApp.menuToggle)
|
|
|
|
pDevice->SetDialogBoxMode( TRUE );
|
|
|
|
|
|
|
|
createFont();
|
|
|
|
createSurface();
|
|
|
|
failed = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IDisplay *newDirect3DDisplay()
|
|
|
|
{
|
|
|
|
return new Direct3DDisplay();
|
|
|
|
}
|