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
|
2007-12-01 10:19:06 +00:00
|
|
|
// Copyright (C) 2007 VBA-M team
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
// 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.
|
|
|
|
|
2007-12-01 23:24:34 +00:00
|
|
|
#ifndef NO_D3D
|
|
|
|
|
|
|
|
#pragma comment( lib, "d3d9.lib" )
|
|
|
|
#pragma comment( lib, "d3dx9.lib" )
|
|
|
|
#pragma comment( lib, "dxerr9.lib" )
|
|
|
|
|
2007-11-14 12:28:27 +00:00
|
|
|
#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
|
2007-12-01 10:19:06 +00:00
|
|
|
#include <D3dx9core.h> // required for font rendering
|
2007-11-14 12:28:27 +00:00
|
|
|
#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__;
|
2007-12-01 10:19:06 +00:00
|
|
|
extern void log(const char *,...);
|
2007-11-14 12:28:27 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MMX
|
|
|
|
extern "C" bool cpu_mmx;
|
|
|
|
extern bool detectMMX();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern int winVideoModeSelect(CWnd *, GUID **);
|
|
|
|
|
|
|
|
class Direct3DDisplay : public IDisplay {
|
|
|
|
private:
|
2007-12-01 10:19:06 +00:00
|
|
|
bool initializing;
|
2007-11-14 12:28:27 +00:00
|
|
|
LPDIRECT3D9 pD3D;
|
|
|
|
LPDIRECT3DDEVICE9 pDevice;
|
|
|
|
D3DDISPLAYMODE mode;
|
|
|
|
D3DPRESENT_PARAMETERS dpp;
|
|
|
|
D3DFORMAT screenFormat;
|
2007-12-01 10:19:06 +00:00
|
|
|
LPDIRECT3DTEXTURE9 emulatedImage;
|
2007-11-14 12:28:27 +00:00
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
RECT destRect;
|
|
|
|
bool failed;
|
|
|
|
ID3DXFont *pFont;
|
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
struct VERTEX {
|
|
|
|
FLOAT x, y, z, rhw; // screen coordinates
|
|
|
|
FLOAT tx, ty; // texture coordinates
|
|
|
|
} Vertices[4];
|
|
|
|
// Vertices order:
|
|
|
|
// 1 3
|
|
|
|
// 0 2
|
|
|
|
|
2007-11-14 12:28:27 +00:00
|
|
|
void createFont();
|
|
|
|
void destroyFont();
|
2007-12-01 10:19:06 +00:00
|
|
|
void createTexture();
|
|
|
|
void destroyTexture();
|
2007-11-14 12:28:27 +00:00
|
|
|
void calculateDestRect();
|
|
|
|
bool resetDevice();
|
2007-12-01 10:19:06 +00:00
|
|
|
void prepareDisplayMode();
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
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()
|
|
|
|
{
|
2007-12-01 10:19:06 +00:00
|
|
|
initializing = false;
|
2007-11-14 12:28:27 +00:00
|
|
|
pD3D = NULL;
|
|
|
|
pDevice = NULL;
|
|
|
|
screenFormat = D3DFMT_X8R8G8B8;
|
|
|
|
width = 0;
|
|
|
|
height = 0;
|
|
|
|
failed = false;
|
|
|
|
pFont = NULL;
|
|
|
|
emulatedImage = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Direct3DDisplay::~Direct3DDisplay()
|
|
|
|
{
|
|
|
|
cleanup();
|
|
|
|
}
|
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
void Direct3DDisplay::prepareDisplayMode()
|
2007-11-14 12:28:27 +00:00
|
|
|
{
|
|
|
|
// Change display mode
|
|
|
|
memset(&dpp, 0, sizeof(dpp));
|
2007-12-01 10:19:06 +00:00
|
|
|
dpp.Windowed = !( theApp.videoOption >= VIDEO_320x240 );
|
|
|
|
if( !dpp.Windowed ) {
|
|
|
|
dpp.BackBufferFormat = (theApp.fsColorDepth == 32) ? D3DFMT_X8R8G8B8 : D3DFMT_R5G6B5;
|
|
|
|
} else {
|
2007-11-14 12:28:27 +00:00
|
|
|
dpp.BackBufferFormat = mode.Format;
|
2007-12-01 10:19:06 +00:00
|
|
|
}
|
|
|
|
dpp.BackBufferCount = theApp.tripleBuffering ? 2 : 1;
|
2007-11-14 12:28:27 +00:00
|
|
|
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;
|
2007-12-01 10:19:06 +00:00
|
|
|
if( ( dpp.Windowed == FALSE ) && theApp.menuToggle ) {
|
|
|
|
dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
|
|
|
|
} else {
|
|
|
|
dpp.Flags = 0;
|
|
|
|
}
|
|
|
|
dpp.PresentationInterval = theApp.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
|
|
|
|
// D3DPRESENT_INTERVAL_ONE means VSync ON
|
|
|
|
|
|
|
|
if( theApp.vsync && ( dpp.Windowed == FALSE ) && theApp.menuToggle ) {
|
|
|
|
// VSync will be disabled when the menu is opened in full screen mode
|
|
|
|
dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
TRACE( _T("prepareDisplayMode:\n") );
|
|
|
|
TRACE( _T("%i x %i @ %iHz:\n"), dpp.BackBufferWidth, dpp.BackBufferHeight, dpp.FullScreen_RefreshRateInHz );
|
|
|
|
TRACE( _T("Buffer Count: %i\n"), dpp.BackBufferCount+1 );
|
|
|
|
TRACE( _T("VSync: %i\n"), dpp.PresentationInterval==D3DPRESENT_INTERVAL_ONE );
|
|
|
|
TRACE( _T("LOCKABLE_BACKBUFFER: %i\n\n"), dpp.Flags==D3DPRESENTFLAG_LOCKABLE_BACKBUFFER );
|
|
|
|
#endif
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::cleanup()
|
|
|
|
{
|
|
|
|
destroyFont();
|
2007-12-01 10:19:06 +00:00
|
|
|
destroyTexture();
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
if( pDevice ) {
|
|
|
|
pDevice->Release();
|
|
|
|
pDevice = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if( pD3D ) {
|
|
|
|
pD3D->Release();
|
|
|
|
pD3D = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Direct3DDisplay::initialize()
|
|
|
|
{
|
2007-12-01 10:19:06 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
TRACE( _T("Initializing Direct3D renderer {\n") );
|
|
|
|
#endif
|
|
|
|
|
2007-12-02 01:46:05 +00:00
|
|
|
initializing = true;
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
// load Direct3D v9
|
|
|
|
pD3D = Direct3DCreate9( D3D_SDK_VERSION );
|
|
|
|
|
|
|
|
if(pD3D == NULL) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D object"), 0 );
|
2007-12-02 01:46:05 +00:00
|
|
|
return false;
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
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);
|
2007-12-01 10:19:06 +00:00
|
|
|
for( i = 0; i<nModes; i++ )
|
2007-11-14 12:28:27 +00:00
|
|
|
{
|
2007-12-01 10:19:06 +00:00
|
|
|
if( D3D_OK == pD3D->EnumAdapterModes(theApp.fsAdapter, mode.Format, i, &dm) )
|
2007-11-14 12:28:27 +00:00
|
|
|
{
|
2007-12-01 10:19:06 +00:00
|
|
|
if( (dm.Width == 320) && (dm.Height == 240) )
|
2007-11-14 12:28:27 +00:00
|
|
|
theApp.mode320Available = true;
|
2007-12-01 10:19:06 +00:00
|
|
|
if( (dm.Width == 640) && (dm.Height == 480) )
|
2007-11-14 12:28:27 +00:00
|
|
|
theApp.mode640Available = true;
|
2007-12-01 10:19:06 +00:00
|
|
|
if( (dm.Width == 800) && (dm.Height == 600) )
|
2007-11-14 12:28:27 +00:00
|
|
|
theApp.mode800Available = true;
|
2007-12-01 10:19:06 +00:00
|
|
|
if( (dm.Width == 1024) && (dm.Height == 768) )
|
2007-11-14 12:28:27 +00:00
|
|
|
theApp.mode1024Available = true;
|
2007-12-01 10:19:06 +00:00
|
|
|
if( (dm.Width == 1280) && (dm.Height == 1024) )
|
2007-11-14 12:28:27 +00:00
|
|
|
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
|
2007-12-01 10:19:06 +00:00
|
|
|
prepareDisplayMode();
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
HRESULT hret = pD3D->CreateDevice(
|
|
|
|
D3DADAPTER_DEFAULT,
|
|
|
|
D3DDEVTYPE_HAL,
|
2007-12-02 01:46:05 +00:00
|
|
|
theApp.m_pMainWnd->GetSafeHwnd(),
|
2007-11-14 12:28:27 +00:00
|
|
|
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
|
|
|
|
&dpp,
|
|
|
|
&pDevice);
|
|
|
|
if( FAILED( hret ) ) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Error creating Direct3D device"), hret );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
createFont();
|
2007-12-01 10:19:06 +00:00
|
|
|
createTexture();
|
|
|
|
setOption( _T("d3dFilter"), theApp.d3dFilter );
|
2007-11-14 12:28:27 +00:00
|
|
|
calculateDestRect();
|
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
initializing = false;
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
if(failed) return false;
|
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
TRACE( _T("} Finished Direct3D renderer initialization\n\n") );
|
|
|
|
#endif
|
|
|
|
|
2007-11-14 12:28:27 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::renderMenu()
|
|
|
|
{
|
2007-12-01 10:19:06 +00:00
|
|
|
//checkFullScreen();
|
2007-11-14 12:28:27 +00:00
|
|
|
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;
|
2007-12-01 14:41:48 +00:00
|
|
|
|
|
|
|
// Multi-Tasking fix
|
|
|
|
HRESULT hr = pDevice->TestCooperativeLevel();
|
|
|
|
if( FAILED( hr ) ) {
|
|
|
|
switch( hr ) {
|
|
|
|
case D3DERR_DEVICELOST:
|
|
|
|
// The device has been lost but cannot be reset at this time.
|
|
|
|
// Therefore, rendering is not possible.
|
|
|
|
return;
|
|
|
|
case D3DERR_DEVICENOTRESET:
|
|
|
|
// The device has been lost but can be reset at this time.
|
|
|
|
resetDevice();
|
|
|
|
return;
|
|
|
|
default:
|
|
|
|
DXTRACE_ERR( _T("ERROR: D3D device has serious problems"), hr );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
clear();
|
|
|
|
|
|
|
|
pDevice->BeginScene();
|
|
|
|
|
|
|
|
// copy pix to emulatedImage and apply pixel filter if selected
|
|
|
|
D3DLOCKED_RECT lr;
|
2007-12-01 10:19:06 +00:00
|
|
|
|
|
|
|
if( FAILED( hr = emulatedImage->LockRect( 0, &lr, NULL, D3DLOCK_DISCARD ) ) ) {
|
|
|
|
DXTRACE_ERR_MSGBOX( _T("Can not lock texture"), hr );
|
2007-11-14 12:28:27 +00:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
if( !theApp.filterFunction ) {
|
2007-12-02 00:13:40 +00:00
|
|
|
copyImage(
|
|
|
|
pix,
|
|
|
|
lr.pBits,
|
|
|
|
(systemColorDepth == 32) ? theApp.sizeX
|
|
|
|
: theApp.sizeX + 1, // TODO: workaround results in one pixel black border at right side
|
|
|
|
theApp.sizeY,
|
|
|
|
lr.Pitch,
|
|
|
|
systemColorDepth
|
|
|
|
);
|
2007-11-14 12:28:27 +00:00
|
|
|
} 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);
|
|
|
|
}
|
2007-12-01 10:19:06 +00:00
|
|
|
emulatedImage->UnlockRect( 0 );
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
// set emulatedImage as active texture
|
|
|
|
pDevice->SetTexture( 0, emulatedImage );
|
2007-11-14 12:28:27 +00:00
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
// render textured triangles
|
|
|
|
pDevice->SetFVF( D3DFVF_XYZRHW | D3DFVF_TEX1 );
|
|
|
|
pDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, Vertices, sizeof(VERTEX) );
|
|
|
|
|
|
|
|
// render speed and status messages
|
2007-11-14 12:28:27 +00:00
|
|
|
D3DCOLOR color;
|
|
|
|
RECT r;
|
2007-12-01 10:19:06 +00:00
|
|
|
r.left = 0;
|
|
|
|
r.top = 0;
|
|
|
|
r.right = dpp.BackBufferWidth - 1;
|
|
|
|
r.bottom = dpp.BackBufferHeight - 1;
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
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 );
|
|
|
|
}
|
|
|
|
|
2007-12-01 12:55:29 +00:00
|
|
|
pFont->DrawText( NULL, buffer, -1, &r, DT_CENTER | DT_TOP, color );
|
2007-12-01 10:19:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 ) {
|
2007-12-01 12:55:29 +00:00
|
|
|
pFont->DrawText( NULL, theApp.screenMessageBuffer, -1, &r, DT_CENTER | DT_BOTTOM, color );
|
2007-12-01 10:19:06 +00:00
|
|
|
} else {
|
|
|
|
theApp.screenMessage = false;
|
|
|
|
}
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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 ) {
|
2007-12-01 10:19:06 +00:00
|
|
|
destroyTexture();
|
|
|
|
createTexture();
|
2007-11-14 12:28:27 +00:00
|
|
|
calculateDestRect();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::resize( int w, int h )
|
|
|
|
{
|
2007-12-01 10:19:06 +00:00
|
|
|
if( initializing ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-11-14 12:28:27 +00:00
|
|
|
if( (w != dpp.BackBufferWidth) || (h != dpp.BackBufferHeight) ) {
|
|
|
|
resetDevice();
|
|
|
|
calculateDestRect();
|
|
|
|
}
|
2007-12-01 10:19:06 +00:00
|
|
|
if( theApp.videoOption > VIDEO_4X ) {
|
2007-11-14 12:28:27 +00:00
|
|
|
resetDevice();
|
2007-12-01 10:19:06 +00:00
|
|
|
}
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Direct3DDisplay::selectFullScreenMode( GUID **pGUID )
|
|
|
|
{
|
|
|
|
return winVideoModeSelect(theApp.m_pMainWnd, pGUID);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::createFont()
|
|
|
|
{
|
|
|
|
if( !pFont ) {
|
|
|
|
HRESULT hr = D3DXCreateFont(
|
|
|
|
pDevice,
|
2007-12-01 10:19:06 +00:00
|
|
|
dpp.BackBufferHeight/20, // dynamic font size
|
2007-11-14 12:28:27 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
void Direct3DDisplay::createTexture()
|
2007-11-14 12:28:27 +00:00
|
|
|
{
|
|
|
|
if( !emulatedImage ) {
|
2007-12-01 10:19:06 +00:00
|
|
|
HRESULT hr = pDevice->CreateTexture(
|
|
|
|
width, height, 1, // 1 level, no mipmaps
|
|
|
|
D3DUSAGE_DYNAMIC, dpp.BackBufferFormat,
|
|
|
|
D3DPOOL_DEFAULT, // anything else won't work
|
2007-11-14 12:28:27 +00:00
|
|
|
&emulatedImage,
|
|
|
|
NULL );
|
2007-12-01 10:19:06 +00:00
|
|
|
|
2007-11-14 12:28:27 +00:00
|
|
|
if( FAILED( hr ) ) {
|
2007-12-01 10:19:06 +00:00
|
|
|
DXTRACE_ERR_MSGBOX( _T("createTexture failed"), hr );
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-12-01 10:19:06 +00:00
|
|
|
void Direct3DDisplay::destroyTexture()
|
2007-11-14 12:28:27 +00:00
|
|
|
{
|
|
|
|
if( emulatedImage ) {
|
|
|
|
emulatedImage->Release();
|
|
|
|
emulatedImage = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::calculateDestRect()
|
|
|
|
{
|
2007-12-01 10:19:06 +00:00
|
|
|
if( theApp.fullScreenStretch ) {
|
|
|
|
destRect.left = 0;
|
|
|
|
destRect.top = 0;
|
|
|
|
destRect.right = dpp.BackBufferWidth; // for some reason there'l be a black
|
|
|
|
destRect.bottom = dpp.BackBufferHeight; // border line when using -1 at the end
|
|
|
|
} else {
|
|
|
|
// use aspect ratio
|
|
|
|
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;
|
|
|
|
}
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
2007-12-01 10:19:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// configure triangles
|
|
|
|
Vertices[0].x = (FLOAT)destRect.left;
|
|
|
|
Vertices[0].y = (FLOAT)destRect.bottom;
|
|
|
|
Vertices[0].z = 0.5f;
|
|
|
|
Vertices[0].rhw = 1.0f;
|
|
|
|
Vertices[0].tx = 0.0f;
|
|
|
|
Vertices[0].ty = 1.0f;
|
|
|
|
Vertices[1].x = (FLOAT)destRect.left;
|
|
|
|
Vertices[1].y = (FLOAT)destRect.top;
|
|
|
|
Vertices[1].z = 0.5f;
|
|
|
|
Vertices[1].rhw = 1.0f;
|
|
|
|
Vertices[1].tx = 0.0f;
|
|
|
|
Vertices[1].ty = 0.0f;
|
|
|
|
Vertices[2].x = (FLOAT)destRect.right;
|
|
|
|
Vertices[2].y = (FLOAT)destRect.bottom;
|
|
|
|
Vertices[2].z = 0.5f;
|
|
|
|
Vertices[2].rhw = 1.0f;
|
|
|
|
Vertices[2].tx = 1.0f;
|
|
|
|
Vertices[2].ty = 1.0f;
|
|
|
|
Vertices[3].x = (FLOAT)destRect.right;
|
|
|
|
Vertices[3].y = (FLOAT)destRect.top;
|
|
|
|
Vertices[3].z = 0.5f;
|
|
|
|
Vertices[3].rhw = 1.0f;
|
|
|
|
Vertices[3].tx = 1.0f;
|
|
|
|
Vertices[3].ty = 0.0f;
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::setOption( const char *option, int value )
|
|
|
|
{
|
|
|
|
if( !_tcscmp( option, _T("vsync") ) ) {
|
2007-12-01 10:19:06 +00:00
|
|
|
// theApp.vsync has already been changed by the menu handler
|
|
|
|
// 'value' has the same value as theApp.vsync
|
2007-11-14 12:28:27 +00:00
|
|
|
resetDevice();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !_tcscmp( option, _T("tripleBuffering") ) ) {
|
2007-12-01 10:19:06 +00:00
|
|
|
// theApp.tripleBuffering has already been changed by the menu handler
|
|
|
|
// 'value' has the same value as theApp.tripleBuffering
|
2007-11-14 12:28:27 +00:00
|
|
|
resetDevice();
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !_tcscmp( option, _T("d3dFilter") ) ) {
|
|
|
|
switch( value )
|
|
|
|
{
|
|
|
|
case 0: //point
|
2007-12-01 10:19:06 +00:00
|
|
|
pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
|
|
|
|
pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
|
2007-11-14 12:28:27 +00:00
|
|
|
break;
|
|
|
|
case 1: //linear
|
2007-12-01 10:19:06 +00:00
|
|
|
pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
|
|
|
|
pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
|
2007-11-14 12:28:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( !_tcscmp( option, _T("maxScale") ) ) {
|
|
|
|
calculateDestRect();
|
|
|
|
}
|
2007-12-01 10:19:06 +00:00
|
|
|
|
|
|
|
if( !_tcscmp( option, _T("fullScreenStretch") ) ) {
|
|
|
|
calculateDestRect();
|
|
|
|
}
|
2007-11-14 12:28:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Direct3DDisplay::resetDevice()
|
|
|
|
{
|
|
|
|
if( !pDevice ) return false;
|
|
|
|
|
|
|
|
HRESULT hr;
|
2007-12-01 21:22:02 +00:00
|
|
|
if( pFont ) {
|
|
|
|
// prepares font for rest
|
|
|
|
pFont->OnLostDevice();
|
|
|
|
}
|
2007-12-01 10:19:06 +00:00
|
|
|
destroyTexture();
|
|
|
|
prepareDisplayMode();
|
|
|
|
|
|
|
|
if( dpp.Windowed == FALSE ) {
|
|
|
|
// SetDialogBoxMode needs D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
|
|
|
|
if( FAILED( hr = pDevice->SetDialogBoxMode( theApp.menuToggle ? TRUE : FALSE ) ) ) {
|
|
|
|
DXTRACE_ERR( _T("can not switch to dialog box mode"), hr );
|
|
|
|
}
|
|
|
|
}
|
2007-11-14 12:28:27 +00:00
|
|
|
|
|
|
|
if( FAILED( hr = pDevice->Reset( &dpp ) ) ) {
|
2007-12-01 10:19:06 +00:00
|
|
|
DXTRACE_ERR( _T("pDevice->Reset failed\n"), hr );
|
2007-11-14 12:28:27 +00:00
|
|
|
failed = true;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-12-01 21:22:02 +00:00
|
|
|
if( pFont ) {
|
|
|
|
// re-aquires font resources
|
|
|
|
pFont->OnResetDevice();
|
|
|
|
}
|
2007-12-01 10:19:06 +00:00
|
|
|
createTexture();
|
|
|
|
setOption( _T("d3dFilter"), theApp.d3dFilter );
|
2007-11-14 12:28:27 +00:00
|
|
|
failed = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
IDisplay *newDirect3DDisplay()
|
|
|
|
{
|
|
|
|
return new Direct3DDisplay();
|
|
|
|
}
|
2007-12-01 23:24:34 +00:00
|
|
|
|
|
|
|
#endif
|