2007-10-30 19:04:22 +00:00
|
|
|
// VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
|
|
|
|
// Copyright (C) 1999-2003 Forgotten
|
|
|
|
// Copyright (C) 2005 Forgotten and the 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"
|
2007-11-01 10:28:09 +00:00
|
|
|
#include <memory.h>
|
|
|
|
#include "VBA.H"
|
2007-10-30 19:04:22 +00:00
|
|
|
#include "MainWnd.h"
|
|
|
|
#include "UniVideoModeDlg.h"
|
|
|
|
#include "../Util.h"
|
|
|
|
#include "../Globals.h"
|
|
|
|
#include "../Util.h"
|
|
|
|
#include "../gb/gbGlobals.h"
|
2007-11-01 10:28:09 +00:00
|
|
|
// Link with Direct3D9
|
|
|
|
#pragma comment(lib, "D3d9.lib")
|
|
|
|
#pragma comment(lib, "D3dx9.lib")
|
|
|
|
#define DIRECT3D_VERSION 0x0900
|
|
|
|
#include <D3d9.h>
|
|
|
|
#include <D3dx9core.h>
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
#include "../gbafilter.h"
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
#define new DEBUG_NEW
|
2007-11-01 10:28:09 +00:00
|
|
|
#undef THIS_FILE
|
|
|
|
static char THIS_FILE[] = __FILE__;
|
2007-10-30 19:04:22 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MMX
|
|
|
|
extern "C" bool cpu_mmx;
|
|
|
|
extern bool detectMMX();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
extern int Init_2xSaI(u32);
|
|
|
|
extern void winlog(const char *,...);
|
|
|
|
extern int systemSpeed;
|
|
|
|
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
// Vertex format declarations
|
|
|
|
const DWORD D3DFVF_TEXTBOXVERTEX = D3DFVF_XYZRHW | D3DFVF_DIFFUSE;
|
|
|
|
struct TEXTBOXVERTEX {
|
2007-10-30 19:04:22 +00:00
|
|
|
FLOAT x, y, z, rhw;
|
|
|
|
D3DCOLOR color;
|
|
|
|
};
|
2007-11-01 10:28:09 +00:00
|
|
|
const DWORD D3DFVF_IMAGEVERTEX = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1;
|
|
|
|
struct IMAGEVERTEX {
|
|
|
|
FLOAT x, y, z;
|
|
|
|
D3DCOLOR color;
|
|
|
|
FLOAT u, v;
|
|
|
|
};
|
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Direct3DDisplay : public IDisplay
|
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
public: // Class
|
2007-10-30 19:04:22 +00:00
|
|
|
Direct3DDisplay();
|
|
|
|
virtual ~Direct3DDisplay();
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
|
|
|
|
public: // Interface
|
2007-10-30 19:04:22 +00:00
|
|
|
virtual bool initialize();
|
|
|
|
virtual void cleanup();
|
|
|
|
virtual void render();
|
|
|
|
virtual void renderMenu();
|
|
|
|
virtual void clear();
|
|
|
|
virtual bool changeRenderSize(int w, int h);
|
|
|
|
virtual void resize(int w, int h);
|
|
|
|
virtual DISPLAY_TYPE getType() { return DIRECT_3D; };
|
|
|
|
virtual void setOption(const char *, int);
|
2007-11-01 10:28:09 +00:00
|
|
|
virtual int selectFullScreenMode(GUID **);
|
2007-10-30 19:04:22 +00:00
|
|
|
virtual int selectFullScreenMode2();
|
2007-11-01 10:28:09 +00:00
|
|
|
|
|
|
|
|
|
|
|
private: // Functions
|
|
|
|
void restoreDeviceObjects(void);
|
|
|
|
void invalidateDeviceObjects();
|
|
|
|
void setPresentationType();
|
|
|
|
bool initializeOffscreen(unsigned int w, unsigned int h);
|
|
|
|
void updateFiltering(int);
|
|
|
|
bool resetDevice();
|
|
|
|
void initializeMatrices();
|
|
|
|
|
|
|
|
|
|
|
|
private: // Variables
|
|
|
|
int SelectedFreq, SelectedAdapter;
|
|
|
|
bool initSucessful;
|
|
|
|
bool doNotRender;
|
|
|
|
bool filterDisabled;
|
|
|
|
bool lockableBuffer;
|
|
|
|
LPDIRECT3D9 pD3D;
|
|
|
|
LPDIRECT3DDEVICE9 pDevice;
|
|
|
|
LPDIRECT3DTEXTURE9 pTexture;
|
|
|
|
LPD3DXFONT pFont;
|
|
|
|
D3DPRESENT_PARAMETERS dpp;
|
|
|
|
D3DFORMAT screenFormat;
|
|
|
|
D3DDISPLAYMODE mode;
|
|
|
|
|
|
|
|
bool fullscreen;
|
|
|
|
int width, height; // Size of the source image to display
|
|
|
|
IMAGEVERTEX verts[4]; // The coordinates for our image texture
|
|
|
|
TEXTBOXVERTEX msgBox[4];
|
|
|
|
int textureWidth; // Size of the texture,
|
|
|
|
int textureHeight; // where the source image is copied to
|
|
|
|
bool keepAspectRatio;
|
2007-10-30 19:04:22 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
Direct3DDisplay::Direct3DDisplay()
|
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
initSucessful = false;
|
|
|
|
doNotRender = true;
|
|
|
|
pD3D = NULL;
|
|
|
|
pDevice = NULL;
|
|
|
|
pTexture = NULL;
|
|
|
|
pFont = NULL;
|
|
|
|
screenFormat = D3DFMT_UNKNOWN;
|
|
|
|
width = 0;
|
|
|
|
height = 0;
|
|
|
|
filterDisabled = false;
|
2007-11-02 09:19:38 +00:00
|
|
|
keepAspectRatio = false; // theApp.d3dKeepAspectRatio;
|
2007-11-01 10:28:09 +00:00
|
|
|
lockableBuffer = false;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Direct3DDisplay::~Direct3DDisplay()
|
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
cleanup();
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
void Direct3DDisplay::setPresentationType()
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
// Change display mode
|
|
|
|
memset(&dpp, 0, sizeof(dpp));
|
|
|
|
dpp.Windowed = !fullscreen;
|
|
|
|
if (fullscreen)
|
|
|
|
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 = fullscreen ? theApp.fsWidth : theApp.surfaceSizeX;
|
|
|
|
dpp.BackBufferHeight = fullscreen ? theApp.fsHeight : theApp.surfaceSizeY;
|
|
|
|
dpp.hDeviceWindow = theApp.m_pMainWnd->GetSafeHwnd();
|
|
|
|
dpp.FullScreen_RefreshRateInHz = fullscreen ? theApp.fsFrequency : 0;
|
|
|
|
// dpp.Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
|
|
|
|
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()
|
|
|
|
{ // interface funtion
|
|
|
|
if(pD3D != NULL) {
|
|
|
|
if(pFont) {
|
|
|
|
pFont->Release();
|
|
|
|
pFont = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pTexture)
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
|
|
|
pTexture->Release();
|
|
|
|
pTexture = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pDevice) {
|
2007-11-01 10:28:09 +00:00
|
|
|
pDevice->Release();
|
|
|
|
pDevice = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pD3D->Release();
|
|
|
|
pD3D = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
initSucessful = false;
|
|
|
|
doNotRender = true;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Direct3DDisplay::initialize()
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
|
|
|
initSucessful = false;
|
|
|
|
doNotRender = true;
|
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
// Get emulated image's dimensions
|
2007-11-01 10:28:09 +00:00
|
|
|
switch(theApp.cartridgeType)
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
2007-11-01 10:28:09 +00:00
|
|
|
|
|
|
|
theApp.rect.left = 0;
|
|
|
|
theApp.rect.top = 0;
|
|
|
|
theApp.rect.right = theApp.sizeX;
|
|
|
|
theApp.rect.bottom = theApp.sizeY;
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
|
|
|
|
switch(theApp.videoOption)
|
|
|
|
{
|
|
|
|
case VIDEO_1X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY;
|
|
|
|
fullscreen = false;
|
|
|
|
break;
|
|
|
|
case VIDEO_2X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX * 2;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY * 2;
|
|
|
|
fullscreen = false;
|
|
|
|
break;
|
|
|
|
case VIDEO_3X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX * 3;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY * 3;
|
|
|
|
fullscreen = false;
|
|
|
|
break;
|
|
|
|
case VIDEO_4X:
|
|
|
|
theApp.surfaceSizeX = theApp.sizeX * 4;
|
|
|
|
theApp.surfaceSizeY = theApp.sizeY * 4;
|
|
|
|
fullscreen = false;
|
|
|
|
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.fsMaxScale)
|
|
|
|
min = min > theApp.fsMaxScale ? theApp.fsMaxScale : min;
|
|
|
|
if(theApp.fullScreenStretch)
|
|
|
|
{
|
|
|
|
theApp.surfaceSizeX = theApp.fsWidth;
|
|
|
|
theApp.surfaceSizeY = theApp.fsHeight;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
theApp.surfaceSizeX = (int)(theApp.sizeX * min);
|
|
|
|
theApp.surfaceSizeY = (int)(theApp.sizeY * min);
|
|
|
|
}
|
|
|
|
fullscreen = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
int 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,
|
|
|
|
"VisualBoyAdvance",
|
|
|
|
style,
|
|
|
|
x, y,
|
|
|
|
winSizeX, winSizeY,
|
|
|
|
NULL,
|
|
|
|
0);
|
|
|
|
|
|
|
|
if (!(HWND)*pWnd)
|
|
|
|
{
|
|
|
|
winlog("Error creating Window %08x\n", GetLastError());
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
theApp.updateMenuBar();
|
|
|
|
|
|
|
|
theApp.adjustDestRect();
|
|
|
|
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
// Create an IDirect3D9 object
|
|
|
|
pD3D = Direct3DCreate9(D3D_SDK_VERSION);
|
2007-10-30 19:04:22 +00:00
|
|
|
if(pD3D == NULL)
|
|
|
|
{
|
|
|
|
winlog("Error creating Direct3D object\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Display resolution
|
|
|
|
pD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &mode);
|
|
|
|
|
|
|
|
switch(mode.Format) {
|
|
|
|
case D3DFMT_R8G8B8:
|
|
|
|
systemColorDepth = 24;
|
|
|
|
systemRedShift = 19;
|
|
|
|
systemGreenShift = 11;
|
|
|
|
systemBlueShift = 3;
|
2007-11-01 10:28:09 +00:00
|
|
|
Init_2xSaI(32);
|
2007-10-30 19:04:22 +00:00
|
|
|
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:
|
|
|
|
systemMessage(0,"Unsupported D3D format %d", mode.Format);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
theApp.fsColorDepth = systemColorDepth;
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
// Check the available pre-defined fullscreen modes and enable menu items
|
2007-10-30 19:04:22 +00:00
|
|
|
unsigned int nModes, i;
|
|
|
|
D3DDISPLAYMODE dm;
|
|
|
|
|
|
|
|
theApp.mode320Available = false;
|
|
|
|
theApp.mode640Available = false;
|
|
|
|
theApp.mode800Available = false;
|
2007-10-31 02:33:28 +00:00
|
|
|
theApp.mode1024Available = false;
|
|
|
|
theApp.mode1280Available = false;
|
2007-10-30 19:04:22 +00:00
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
nModes = pD3D->GetAdapterModeCount(theApp.fsAdapter, mode.Format);
|
2007-10-30 19:04:22 +00:00
|
|
|
for (i = 0; i<nModes; i++)
|
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
if (D3D_OK == pD3D->EnumAdapterModes(theApp.fsAdapter, mode.Format, i, &dm) )
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
|
|
|
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;
|
2007-10-31 02:33:28 +00:00
|
|
|
if ( (dm.Width == 1024) && (dm.Height == 768) )
|
|
|
|
theApp.mode1024Available = true;
|
|
|
|
if ( (dm.Width == 1280) && (dm.Height == 1024) )
|
|
|
|
theApp.mode1280Available = true;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef MMX
|
2007-11-01 10:28:09 +00:00
|
|
|
if (!theApp.disableMMX)
|
2007-10-30 19:04:22 +00:00
|
|
|
cpu_mmx = theApp.detectMMX();
|
|
|
|
else
|
|
|
|
cpu_mmx = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
screenFormat = mode.Format;
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
setPresentationType();
|
|
|
|
|
|
|
|
|
|
|
|
DWORD BehaviorFlags;
|
|
|
|
D3DCAPS9 caps;
|
|
|
|
if (D3D_OK == pD3D->GetDeviceCaps(theApp.fsAdapter, D3DDEVTYPE_HAL, &caps)) {
|
|
|
|
if (caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) {
|
|
|
|
BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
|
|
|
|
} else {
|
|
|
|
BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
|
|
|
|
}
|
|
|
|
if (caps.DevCaps & D3DDEVCAPS_PUREDEVICE) {
|
|
|
|
BehaviorFlags |= D3DCREATE_PUREDEVICE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
winlog("Error retrieving device's D3D capabilities\n");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
HRESULT hret = pD3D->CreateDevice(theApp.fsAdapter,
|
2007-11-01 10:28:09 +00:00
|
|
|
caps.DeviceType,
|
2007-10-30 19:04:22 +00:00
|
|
|
pWnd->GetSafeHwnd(),
|
2007-11-01 10:28:09 +00:00
|
|
|
BehaviorFlags,
|
2007-10-30 19:04:22 +00:00
|
|
|
&dpp,
|
|
|
|
&pDevice);
|
2007-11-01 10:28:09 +00:00
|
|
|
#ifdef _DEBUG
|
|
|
|
switch(hret)
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
case D3DERR_DEVICELOST:
|
|
|
|
winlog("Error creating Direct3DDevice (D3DERR_DEVICELOST)\n");
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case D3DERR_INVALIDCALL:
|
|
|
|
winlog("Error creating Direct3DDevice (D3DERR_INVALIDCALL)\n");
|
|
|
|
return false;
|
|
|
|
break;
|
|
|
|
case D3DERR_NOTAVAILABLE:
|
|
|
|
winlog("Error creating Direct3DDevice (D3DERR_NOTAVAILABLE)\n");
|
2007-10-30 19:04:22 +00:00
|
|
|
return false;
|
2007-11-01 10:28:09 +00:00
|
|
|
break;
|
|
|
|
case D3DERR_OUTOFVIDEOMEMORY:
|
|
|
|
winlog("Error creating Direct3DDevice (D3DERR_OUTOFVIDEOMEMORY)\n");
|
|
|
|
return false;
|
|
|
|
break;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
2007-11-01 10:28:09 +00:00
|
|
|
#endif
|
2007-10-30 19:04:22 +00:00
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
restoreDeviceObjects();
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
// Set the status message's background vertex information, that does not need to be changed in realtime
|
|
|
|
msgBox[0].z = 0.5f;
|
|
|
|
msgBox[0].rhw = 1.0f;
|
|
|
|
msgBox[0].color = 0x7fffffff;
|
|
|
|
msgBox[1].z = 0.5f;
|
|
|
|
msgBox[1].rhw = 1.0f;
|
|
|
|
msgBox[1].color = 0x7f7f7f7f;
|
|
|
|
msgBox[2].z = 0.5f;
|
|
|
|
msgBox[2].rhw = 1.0f;
|
|
|
|
msgBox[2].color = 0x7f7f7fff;
|
|
|
|
msgBox[3].z = 0.5f;
|
|
|
|
msgBox[3].rhw = 1.0f;
|
|
|
|
msgBox[3].color = 0x7f7f7f7f;
|
2007-11-01 10:28:09 +00:00
|
|
|
|
|
|
|
// Set up the vertices of the texture
|
|
|
|
verts[0].z = verts[1].z = verts[2].z = verts[3].z = 1.0f;
|
|
|
|
verts[0].color = verts[1].color = verts[2].color = verts[3].color = D3DCOLOR_ARGB(0xff, 0xff, 0xff, 0xff);
|
|
|
|
verts[1].u = verts[2].u = 1.0f;
|
|
|
|
verts[0].u = verts[3].u = 0.0f;
|
|
|
|
verts[0].v = verts[1].v = 0.0f;
|
|
|
|
verts[2].v = verts[3].v = 1.0f;
|
|
|
|
verts[0].x = verts[3].x = 0.0f;
|
|
|
|
verts[1].x = verts[2].x = 1.0f;
|
|
|
|
verts[0].y = verts[1].y = 0.0f;
|
|
|
|
verts[2].y = verts[3].y = 1.0f;
|
|
|
|
|
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
utilUpdateSystemColorMaps(theApp.filterLCD );
|
|
|
|
theApp.updateFilter();
|
|
|
|
theApp.updateIFB();
|
|
|
|
|
|
|
|
pWnd->DragAcceptFiles(TRUE);
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
initSucessful = true;
|
|
|
|
doNotRender = false;
|
2007-10-30 19:04:22 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Direct3DDisplay::initializeOffscreen(unsigned int w, unsigned int h)
|
|
|
|
{
|
|
|
|
D3DFORMAT format = screenFormat;
|
2007-11-01 10:28:09 +00:00
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
unsigned int correctedWidth=w, correctedHeight=h;
|
|
|
|
|
|
|
|
// This function corrects the texture size automaticly
|
|
|
|
if(D3D_OK == D3DXCheckTextureRequirements(
|
|
|
|
pDevice,
|
|
|
|
&correctedWidth,
|
|
|
|
&correctedHeight,
|
|
|
|
NULL,
|
|
|
|
0,
|
|
|
|
&format,
|
|
|
|
D3DPOOL_MANAGED))
|
|
|
|
{
|
|
|
|
if( (correctedWidth < w) || (correctedHeight < h) )
|
|
|
|
{
|
|
|
|
if(theApp.filterFunction)
|
|
|
|
{
|
|
|
|
filterDisabled = true;
|
|
|
|
theApp.filterFunction = NULL;
|
|
|
|
systemMessage(0, "3D card cannot support needed texture size for filter function. Disabling it");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
systemMessage(0, "Graphics card doesn't support needed texture size for emulation.");
|
|
|
|
}
|
|
|
|
else filterDisabled = false;
|
|
|
|
|
|
|
|
if(D3D_OK == D3DXCreateTexture(
|
|
|
|
pDevice,
|
|
|
|
correctedWidth,
|
|
|
|
correctedHeight,
|
2007-11-01 10:28:09 +00:00
|
|
|
1,
|
|
|
|
D3DUSAGE_DYNAMIC,
|
2007-10-30 19:04:22 +00:00
|
|
|
format,
|
2007-11-01 10:28:09 +00:00
|
|
|
D3DPOOL_DEFAULT,
|
2007-10-30 19:04:22 +00:00
|
|
|
&pTexture) )
|
|
|
|
{
|
|
|
|
width = w;
|
|
|
|
height = h;
|
|
|
|
textureWidth = correctedWidth;
|
|
|
|
textureHeight = correctedHeight;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else systemMessage(0, "Texture creation failed");
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::updateFiltering(int filter)
|
2007-11-01 10:28:09 +00:00
|
|
|
{ //TODO: use GetSampletState before changing
|
|
|
|
if(!pDevice) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT res;
|
|
|
|
|
|
|
|
switch(filter)
|
|
|
|
{
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
// point filtering
|
|
|
|
res = pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_POINT );
|
|
|
|
if (res != D3D_OK) {
|
|
|
|
systemMessage(0, "Could not set point filtering mode: %d", res);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
res = pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_POINT );
|
|
|
|
if (res != D3D_OK) {
|
|
|
|
systemMessage(0, "Could not set point filtering mode: %d", res);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
// bilinear
|
|
|
|
res = pDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
|
|
|
|
if (res != D3D_OK) {
|
|
|
|
systemMessage(0, "Could not set bilinear filtering mode: %d", res);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
res = pDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
|
|
|
|
if (res != D3D_OK) {
|
|
|
|
systemMessage(0, "Could not set bilinear filtering mode: %d", res);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Don't wrap textures .. otherwise bottom blurs top to bottom
|
|
|
|
pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
|
|
|
|
pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Direct3DDisplay::clear()
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
|
|
|
if(!initSucessful) return;
|
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
if (pDevice)
|
|
|
|
pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,
|
|
|
|
#ifdef _DEBUG
|
|
|
|
0xffff00ff //pink
|
|
|
|
#else
|
|
|
|
0xff000000 //black
|
|
|
|
#endif
|
|
|
|
, 1.0f, 0L );
|
|
|
|
}
|
|
|
|
|
|
|
|
void Direct3DDisplay::renderMenu()
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
|
|
|
if(!initSucessful) return;
|
2007-10-30 19:04:22 +00:00
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
if(theApp.m_pMainWnd)
|
|
|
|
theApp.m_pMainWnd->DrawMenuBar();
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Direct3DDisplay::render()
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
2007-10-30 19:04:22 +00:00
|
|
|
if(!pDevice) return;
|
2007-11-01 10:28:09 +00:00
|
|
|
if(!initSucessful) return;
|
|
|
|
if(doNotRender) return;
|
|
|
|
|
|
|
|
unsigned int nBytesPerPixel = systemColorDepth >> 3; // This is the byte count of a Pixel
|
|
|
|
unsigned int pitch = (theApp.filterWidth * nBytesPerPixel) + 4; // The size of a scanline in bytes
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
// Test the cooperative level to see if it's okay to render
|
2007-11-01 10:28:09 +00:00
|
|
|
HRESULT hr;
|
2007-10-30 19:04:22 +00:00
|
|
|
hr = pDevice->TestCooperativeLevel();
|
2007-11-01 10:28:09 +00:00
|
|
|
switch(hr)
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
case D3DERR_DEVICENOTRESET:
|
|
|
|
resetDevice();
|
|
|
|
break;
|
|
|
|
case D3DERR_DEVICELOST:
|
|
|
|
winlog("Render: D3DERR_DEVICELOST\n");
|
2007-10-30 19:04:22 +00:00
|
|
|
return;
|
2007-11-01 10:28:09 +00:00
|
|
|
break;
|
|
|
|
case D3DERR_DRIVERINTERNALERROR:
|
|
|
|
winlog("Render: D3DERR_DRIVERINTERNALERROR\n");
|
|
|
|
cleanup();
|
|
|
|
if(initialize()) {
|
|
|
|
return;
|
|
|
|
} else { // reinitialize device failed
|
|
|
|
AfxPostQuitMessage(D3DERR_DRIVERINTERNALERROR);
|
|
|
|
}
|
|
|
|
break;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Clear the screen
|
|
|
|
if (pDevice)
|
|
|
|
pDevice->Clear( 0L, NULL, D3DCLEAR_TARGET,
|
|
|
|
#ifdef _DEBUG
|
|
|
|
0xffff00ff //pink
|
|
|
|
#else
|
|
|
|
0xff000000 //black
|
|
|
|
#endif
|
|
|
|
, 1.0f, 0L );
|
|
|
|
|
|
|
|
|
|
|
|
if(SUCCEEDED(pDevice->BeginScene()))
|
|
|
|
{
|
|
|
|
D3DLOCKED_RECT locked;
|
2007-11-01 10:28:09 +00:00
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
if( D3D_OK == pTexture->LockRect(0, &locked, NULL, D3DLOCK_DISCARD) )
|
|
|
|
{
|
|
|
|
if(theApp.filterFunction)
|
|
|
|
{
|
|
|
|
theApp.filterFunction(
|
|
|
|
pix + pitch,
|
|
|
|
pitch,
|
|
|
|
(u8*)theApp.delta,
|
|
|
|
(u8*)locked.pBits,
|
|
|
|
locked.Pitch,
|
|
|
|
theApp.filterWidth,
|
|
|
|
theApp.filterHeight);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// Copy the image at [pix] to the locked Direct3D texture
|
|
|
|
__asm
|
|
|
|
{
|
|
|
|
mov eax, theApp.sizeX ; Initialize
|
|
|
|
mov ebx, theApp.sizeY ;
|
|
|
|
mov edi, locked.pBits ;
|
|
|
|
mov edx, locked.Pitch ;
|
|
|
|
|
|
|
|
cmp systemColorDepth, 16 ; Check systemColorDepth==16bit
|
|
|
|
jnz gbaOtherColor ;
|
|
|
|
sub edx, eax ;
|
|
|
|
sub edx, eax ;
|
|
|
|
mov esi, pix ;
|
|
|
|
lea esi,[esi+2*eax+4] ;
|
|
|
|
shr eax, 1 ;
|
|
|
|
gbaLoop16bit:
|
|
|
|
mov ecx, eax ;
|
|
|
|
rep movsd ;
|
|
|
|
add esi, 4 ;
|
|
|
|
add edi, edx ;
|
|
|
|
dec ebx ;
|
|
|
|
jnz gbaLoop16bit ;
|
|
|
|
jmp gbaLoopEnd ;
|
|
|
|
gbaOtherColor:
|
|
|
|
cmp systemColorDepth, 32 ; Check systemColorDepth==32bit
|
|
|
|
jnz gbaOtherColor2 ;
|
|
|
|
|
|
|
|
lea esi, [eax*4] ;
|
|
|
|
sub edx, esi ;
|
|
|
|
mov esi, pix ;
|
|
|
|
lea esi, [esi+4*eax+4] ;
|
|
|
|
gbaLoop32bit:
|
|
|
|
mov ecx, eax ;
|
|
|
|
rep movsd ; ECX times: Move DWORD at [ESI] to [EDI] | ESI++ EDI++
|
|
|
|
add esi, 4 ;
|
|
|
|
add edi, edx ;
|
|
|
|
dec ebx ;
|
|
|
|
jnz gbaLoop32bit ;
|
|
|
|
jmp gbaLoopEnd ;
|
|
|
|
gbaOtherColor2:
|
|
|
|
lea eax, [eax+2*eax] ; Work like systemColorDepth==24bit
|
|
|
|
sub edx, eax ;
|
|
|
|
gbaLoop24bit:
|
|
|
|
mov ecx, eax ;
|
|
|
|
shr ecx, 2 ;
|
|
|
|
rep movsd ;
|
|
|
|
add edi, edx ;
|
|
|
|
dec ebx ;
|
|
|
|
jnz gbaLoop24bit ;
|
|
|
|
gbaLoopEnd:
|
|
|
|
}
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
//C Version of the code above
|
|
|
|
//unsigned int i;
|
|
|
|
//int x, y, srcPitch = (theApp.sizeX+1) * nBytesPerPixel;
|
2007-10-30 19:04:22 +00:00
|
|
|
//unsigned char * src = ((unsigned char*)pix)+srcPitch;
|
|
|
|
//unsigned char * dst = (unsigned char*)locked.pBits;
|
|
|
|
//for (y=0;y<theApp.sizeY;y++) //Width
|
|
|
|
// for (x=0;x<theApp.sizeX;x++) //Height
|
|
|
|
// for (i=0;i<nBytesPerPixel;i++) //Byte# Of Pixel
|
|
|
|
// *(dst+i+(x*nBytesPerPixel)+(y*locked.Pitch)) = *(src+i+(x*nBytesPerPixel)+(y*srcPitch));
|
|
|
|
}
|
|
|
|
pTexture->UnlockRect(0);
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
pDevice->SetFVF( D3DFVF_IMAGEVERTEX );
|
2007-10-30 19:04:22 +00:00
|
|
|
pDevice->SetTexture( 0, pTexture );
|
2007-11-01 10:28:09 +00:00
|
|
|
pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, verts, sizeof( IMAGEVERTEX ) );
|
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
} // SUCCEEDED(pTexture->LockRect...
|
|
|
|
else
|
|
|
|
{
|
|
|
|
systemMessage(0,"Rendering error");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Draw the screen message
|
|
|
|
if(theApp.screenMessage)
|
|
|
|
{
|
|
|
|
if( ((GetTickCount() - theApp.screenMessageTime) < 3000) &&
|
|
|
|
!theApp.disableStatusMessage && pFont )
|
|
|
|
{
|
|
|
|
CRect msgRect(
|
|
|
|
64,
|
|
|
|
dpp.BackBufferHeight - 32,
|
|
|
|
dpp.BackBufferWidth - 64,
|
|
|
|
dpp.BackBufferHeight);
|
|
|
|
|
|
|
|
msgBox[0].x = (FLOAT)msgRect.left;
|
|
|
|
msgBox[0].y = (FLOAT)msgRect.top;
|
|
|
|
msgBox[1].x = (FLOAT)msgRect.right;
|
|
|
|
msgBox[1].y = (FLOAT)msgRect.top;
|
|
|
|
msgBox[2].x = (FLOAT)msgRect.right;
|
|
|
|
msgBox[2].y = (FLOAT)msgRect.bottom;
|
|
|
|
msgBox[3].x = (FLOAT)msgRect.left;
|
|
|
|
msgBox[3].y = (FLOAT)msgRect.bottom;
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
pDevice->SetFVF( D3DFVF_TEXTBOXVERTEX );
|
2007-10-30 19:04:22 +00:00
|
|
|
pDevice->SetTexture( 0, NULL );
|
2007-11-01 10:28:09 +00:00
|
|
|
pDevice->DrawPrimitiveUP( D3DPT_TRIANGLEFAN, 2, msgBox, sizeof(TEXTBOXVERTEX));
|
2007-10-30 19:04:22 +00:00
|
|
|
|
|
|
|
pFont->DrawText(NULL, theApp.screenMessageBuffer, -1, msgRect, DT_CENTER | DT_VCENTER, 0x7fff0000);
|
|
|
|
}
|
|
|
|
else theApp.screenMessage = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Draw the speed
|
|
|
|
if( (theApp.videoOption > VIDEO_4X) && theApp.showSpeed )
|
|
|
|
{
|
|
|
|
// Create the string text
|
|
|
|
char buffer[30];
|
|
|
|
if(theApp.showSpeed == TRUE)
|
|
|
|
sprintf(buffer, "%3d%%", systemSpeed);
|
|
|
|
else
|
|
|
|
sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
|
|
|
|
systemFrameSkip,
|
|
|
|
theApp.showRenderedFrames);
|
|
|
|
|
|
|
|
//Draw the string
|
|
|
|
D3DCOLOR speedColor;
|
|
|
|
theApp.showSpeedTransparent==TRUE ? speedColor = 0x7fffffff : speedColor = 0xffffffff;
|
|
|
|
|
|
|
|
CRect speedRect(
|
|
|
|
64,
|
|
|
|
0,
|
|
|
|
dpp.BackBufferWidth - 64,
|
|
|
|
32);
|
|
|
|
|
|
|
|
pFont->DrawText(NULL, buffer, -1, speedRect, DT_CENTER | DT_VCENTER, speedColor);
|
|
|
|
}
|
|
|
|
|
|
|
|
pDevice->EndScene();
|
|
|
|
|
|
|
|
pDevice->Present( NULL, NULL, NULL, NULL ); //Draw everything to the screen
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::invalidateDeviceObjects()
|
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
|
|
|
|
if(pFont) {
|
|
|
|
pFont->Release();
|
|
|
|
pFont = NULL;
|
|
|
|
}
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Direct3DDisplay::restoreDeviceObjects()
|
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
// Create the font
|
|
|
|
D3DXCreateFont( pDevice, 24, 0, FW_BOLD, 1, FALSE, ANSI_CHARSET, OUT_DEFAULT_PRECIS, ANTIALIASED_QUALITY, FF_DONTCARE, "Arial", &pFont );
|
|
|
|
|
|
|
|
// Set texture filter
|
2007-10-30 19:04:22 +00:00
|
|
|
updateFiltering(theApp.d3dFilter);
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
// Set device settings
|
2007-10-30 19:04:22 +00:00
|
|
|
pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );
|
|
|
|
pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
|
|
|
pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
|
|
|
|
pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
2007-11-01 10:28:09 +00:00
|
|
|
pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
|
|
|
|
if (theApp.menuToggle)
|
|
|
|
pDevice->SetDialogBoxMode( TRUE );
|
|
|
|
pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
|
2007-10-30 19:04:22 +00:00
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
// Set matrices
|
|
|
|
initializeMatrices();
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Direct3DDisplay::resize(int w, int h)
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
|
|
|
if(!initSucessful) return;
|
|
|
|
|
|
|
|
if ( (w>0) && (h>0) ) {
|
|
|
|
if(pDevice)
|
|
|
|
{
|
|
|
|
dpp.BackBufferWidth = w;
|
|
|
|
dpp.BackBufferHeight = h;
|
|
|
|
setPresentationType();
|
|
|
|
if (resetDevice()) {
|
|
|
|
doNotRender = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
doNotRender = true;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
2007-11-01 10:28:09 +00:00
|
|
|
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Direct3DDisplay::changeRenderSize(int w, int h)
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
|
|
|
if(!initSucessful) return false;
|
|
|
|
|
|
|
|
// w and h is the size of the filtered image (So this could be 3xGBASize)
|
|
|
|
if(w != width || h != height)
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
if(pTexture) {
|
|
|
|
pTexture->Release();
|
|
|
|
pTexture = NULL;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
if(!initializeOffscreen(w, h)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(filterDisabled && theApp.filterFunction)
|
|
|
|
theApp.filterFunction = NULL;
|
|
|
|
|
|
|
|
// Set up 2D matrices
|
|
|
|
initializeMatrices();
|
2007-10-30 19:04:22 +00:00
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
return true;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Direct3DDisplay::setOption(const char *option, int value)
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
|
|
|
if(!initSucessful) return;
|
|
|
|
|
|
|
|
if(!strcmp(option, "d3dFilter"))
|
|
|
|
updateFiltering(theApp.d3dFilter);
|
2007-10-30 19:04:22 +00:00
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
if(!strcmp(option, "vsync"))
|
|
|
|
{
|
|
|
|
if (pDevice)
|
|
|
|
{
|
|
|
|
if (theApp.vsync)
|
|
|
|
dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; // VSync
|
|
|
|
else
|
|
|
|
dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; // No Sync
|
|
|
|
resetDevice();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!strcmp(option, "triplebuffering"))
|
|
|
|
{
|
|
|
|
if (theApp.tripleBuffering)
|
|
|
|
dpp.BackBufferCount = 3;
|
|
|
|
else
|
|
|
|
dpp.BackBufferCount = 2;
|
|
|
|
resetDevice();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!strcmp(option, "d3dKeepAspectRatio"))
|
|
|
|
keepAspectRatio = true; //theApp.d3dKeepAspectRatio;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Direct3DDisplay::selectFullScreenMode(GUID **)
|
2007-11-01 10:28:09 +00:00
|
|
|
{ // interface function
|
2007-10-30 19:04:22 +00:00
|
|
|
int w, h, b;
|
|
|
|
UniVideoModeDlg dlg(0, &w, &h, &b, &SelectedFreq, &SelectedAdapter);
|
|
|
|
|
|
|
|
if (0 == dlg.DoModal())
|
|
|
|
{
|
|
|
|
return (b<<24) + (w<<12) + h;
|
|
|
|
// Bits<<24 | Width<<12 | Height
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int Direct3DDisplay::selectFullScreenMode2()
|
|
|
|
{
|
|
|
|
return (SelectedAdapter<<16) + SelectedFreq;
|
|
|
|
}
|
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
// Reset Device and Resources
|
|
|
|
bool Direct3DDisplay::resetDevice()
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
invalidateDeviceObjects();
|
|
|
|
if(pTexture) {
|
|
|
|
pDevice->SetTexture( 0, NULL);
|
|
|
|
pTexture->Release();
|
|
|
|
pTexture = NULL;
|
|
|
|
}
|
|
|
|
if (!theApp.menuToggle)
|
|
|
|
pDevice->SetDialogBoxMode( FALSE );
|
|
|
|
|
|
|
|
HRESULT hr = pDevice->Reset(&dpp);
|
|
|
|
if (hr == D3D_OK)
|
2007-10-30 19:04:22 +00:00
|
|
|
{
|
2007-11-01 10:28:09 +00:00
|
|
|
restoreDeviceObjects();
|
|
|
|
if(!initializeOffscreen(width, height))
|
|
|
|
return false;
|
2007-10-30 19:04:22 +00:00
|
|
|
|
2007-11-01 10:28:09 +00:00
|
|
|
return true;
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
2007-11-01 10:28:09 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
switch(hr)
|
|
|
|
{
|
|
|
|
case D3DERR_DEVICELOST:
|
|
|
|
winlog("Render_DeviceLost: D3DERR_DEVICELOST\n");
|
|
|
|
break;
|
|
|
|
case D3DERR_DRIVERINTERNALERROR:
|
|
|
|
winlog("Render_DeviceLost: D3DERR_DRIVERINTERNALERROR\n");
|
|
|
|
break;
|
|
|
|
case D3DERR_INVALIDCALL:
|
|
|
|
winlog("Render_DeviceLost: D3DERR_INVALIDCALL\n");
|
|
|
|
break;
|
|
|
|
case D3DERR_OUTOFVIDEOMEMORY:
|
|
|
|
winlog("Render_DeviceLost: D3DERR_OUTOFVIDEOMEMORY\n");
|
|
|
|
break;
|
|
|
|
case E_OUTOFMEMORY:
|
|
|
|
winlog("Render_DeviceLost: E_OUTOFMEMORY\n");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
winlog("Failed to reset device: %08x\n", hr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Direct3DDisplay::initializeMatrices()
|
|
|
|
{ // Configure matrices to use standard orthogonal projection (2D)
|
|
|
|
D3DXMATRIX Ortho2D;
|
|
|
|
D3DXMATRIX Identity;
|
|
|
|
D3DXMATRIX temp1, temp2;
|
|
|
|
|
|
|
|
// Initialize an orthographic matrix which automaticly compensates the difference between image size and texture size
|
|
|
|
if (!keepAspectRatio) {
|
|
|
|
D3DXMatrixOrthoOffCenterLH(
|
|
|
|
&Ortho2D,
|
|
|
|
0.0f, // left
|
|
|
|
1.0f * (FLOAT)width / (FLOAT)textureWidth, // right
|
|
|
|
1.0f * (FLOAT)height / (FLOAT)textureHeight, // bottom
|
|
|
|
0.0f, // top
|
|
|
|
0.0f, 1.0f); // z
|
|
|
|
} else {
|
|
|
|
FLOAT l=0.0f, r=0.0f, b=0.0f, t=0.0f;
|
|
|
|
FLOAT srcAspectRatio = (FLOAT)theApp.sizeX / (FLOAT)theApp.sizeY;
|
|
|
|
FLOAT aspectRatio = (FLOAT)dpp.BackBufferWidth / (FLOAT)dpp.BackBufferHeight;
|
|
|
|
FLOAT textureImageDiffX = (FLOAT)width / (FLOAT)textureWidth;
|
|
|
|
FLOAT textureImageDiffY = (FLOAT)height / (FLOAT)textureHeight;
|
|
|
|
aspectRatio /= srcAspectRatio;
|
|
|
|
|
|
|
|
if(aspectRatio > 1.0f) {
|
|
|
|
r = 1.0f * textureImageDiffX * aspectRatio;
|
|
|
|
b = 1.0f * textureImageDiffY;
|
|
|
|
} else {
|
|
|
|
r = 1.0f * textureImageDiffX;
|
|
|
|
b = 1.0f * textureImageDiffY * (1.0f / aspectRatio);
|
|
|
|
}
|
|
|
|
|
|
|
|
D3DXMatrixOrthoOffCenterLH(
|
|
|
|
&temp1,
|
|
|
|
l,
|
|
|
|
r,
|
|
|
|
b,
|
|
|
|
t,
|
|
|
|
0.0f, 1.0f); // z
|
|
|
|
D3DXMatrixTranslation( // translate matrix > move image
|
|
|
|
&temp2,
|
|
|
|
(aspectRatio>1.0)?( (aspectRatio - 1.0f) * 0.5f * textureImageDiffX ):0.0f,
|
|
|
|
(aspectRatio<1.0)?( ((1.0f/aspectRatio) - 1.0f) * 0.5f * textureImageDiffY ):0.0f,
|
|
|
|
0.0f);
|
|
|
|
D3DXMatrixMultiply(&Ortho2D, &temp2, &temp1);
|
|
|
|
}
|
|
|
|
|
|
|
|
D3DXMatrixIdentity(&Identity); // Identity = Do not change anything
|
|
|
|
|
|
|
|
pDevice->SetTransform(D3DTS_PROJECTION, &Ortho2D);
|
|
|
|
pDevice->SetTransform(D3DTS_WORLD, &Identity);
|
|
|
|
pDevice->SetTransform(D3DTS_VIEW, &Identity);
|
2007-10-30 19:04:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
IDisplay *newDirect3DDisplay()
|
|
|
|
{
|
|
|
|
return new Direct3DDisplay();
|
|
|
|
}
|