set svn:eol-style=native for Plugins/**.cpp
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1441 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -1,76 +1,76 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "CPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
// PROBLEM - matrix switching within vbuffers may be stateful!
|
||||
|
||||
void CPUpdateMatricesA()
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
CTransformEngine::SetPosNormalMatrix(
|
||||
flipmem + MatrixIndexA.PosNormalMtxIdx * 4, //CHECK
|
||||
flipmem + 0x400 + 3 * (MatrixIndexA.PosNormalMtxIdx & 31)); //CHECK
|
||||
CTransformEngine::SetTexMatrix(0,flipmem + MatrixIndexA.Tex0MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(1,flipmem + MatrixIndexA.Tex1MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(2,flipmem + MatrixIndexA.Tex2MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(3,flipmem + MatrixIndexA.Tex3MtxIdx * 4);
|
||||
}
|
||||
|
||||
void CPUpdateMatricesB()
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
CTransformEngine::SetTexMatrix(4,flipmem + MatrixIndexB.Tex4MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(5,flipmem + MatrixIndexB.Tex5MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(6,flipmem + MatrixIndexB.Tex6MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(7,flipmem + MatrixIndexB.Tex7MtxIdx * 4);
|
||||
}
|
||||
|
||||
void LoadCPReg(u32 SubCmd, u32 Value)
|
||||
{
|
||||
switch (SubCmd & 0xF0)
|
||||
{
|
||||
case 0x30:
|
||||
MatrixIndexA.Hex = Value;
|
||||
CPUpdateMatricesA();
|
||||
break;
|
||||
case 0x40:
|
||||
MatrixIndexB.Hex = Value;
|
||||
CPUpdateMatricesB();
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
VertexManager::Flush(); VertexLoader::SetVtxDesc_Lo(Value);
|
||||
break;
|
||||
case 0x60:
|
||||
VertexManager::Flush(); VertexLoader::SetVtxDesc_Hi(Value);
|
||||
break;
|
||||
|
||||
case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
|
||||
case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break;
|
||||
case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break;
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "CPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
// PROBLEM - matrix switching within vbuffers may be stateful!
|
||||
|
||||
void CPUpdateMatricesA()
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
CTransformEngine::SetPosNormalMatrix(
|
||||
flipmem + MatrixIndexA.PosNormalMtxIdx * 4, //CHECK
|
||||
flipmem + 0x400 + 3 * (MatrixIndexA.PosNormalMtxIdx & 31)); //CHECK
|
||||
CTransformEngine::SetTexMatrix(0,flipmem + MatrixIndexA.Tex0MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(1,flipmem + MatrixIndexA.Tex1MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(2,flipmem + MatrixIndexA.Tex2MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(3,flipmem + MatrixIndexA.Tex3MtxIdx * 4);
|
||||
}
|
||||
|
||||
void CPUpdateMatricesB()
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
CTransformEngine::SetTexMatrix(4,flipmem + MatrixIndexB.Tex4MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(5,flipmem + MatrixIndexB.Tex5MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(6,flipmem + MatrixIndexB.Tex6MtxIdx * 4);
|
||||
CTransformEngine::SetTexMatrix(7,flipmem + MatrixIndexB.Tex7MtxIdx * 4);
|
||||
}
|
||||
|
||||
void LoadCPReg(u32 SubCmd, u32 Value)
|
||||
{
|
||||
switch (SubCmd & 0xF0)
|
||||
{
|
||||
case 0x30:
|
||||
MatrixIndexA.Hex = Value;
|
||||
CPUpdateMatricesA();
|
||||
break;
|
||||
case 0x40:
|
||||
MatrixIndexB.Hex = Value;
|
||||
CPUpdateMatricesB();
|
||||
break;
|
||||
|
||||
case 0x50:
|
||||
VertexManager::Flush(); VertexLoader::SetVtxDesc_Lo(Value);
|
||||
break;
|
||||
case 0x60:
|
||||
VertexManager::Flush(); VertexLoader::SetVtxDesc_Hi(Value);
|
||||
break;
|
||||
|
||||
case 0x70: g_VertexLoaders[SubCmd & 7].SetVAT_group0(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
case 0x80: g_VertexLoaders[SubCmd & 7].SetVAT_group1(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
case 0x90: g_VertexLoaders[SubCmd & 7].SetVAT_group2(Value); _assert_((SubCmd & 0x0F) < 8); break;
|
||||
|
||||
case 0xA0: arraybases[SubCmd & 0xF] = Value & 0xFFFFFFFF; break;
|
||||
case 0xB0: arraystrides[SubCmd & 0xF] = Value & 0xFF; break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Config.h"
|
||||
#include "IniFile.h"
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
|
||||
iniFile.Get("Hardware", "Adapter", &iAdapter, 0);
|
||||
iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0);
|
||||
iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0);
|
||||
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0);
|
||||
iniFile.Get("Hardware", "RenderInMainframe", &renderToMainframe, false);
|
||||
iniFile.Get("Hardware", "VSync", &bVsync, 0);
|
||||
if (iAdapter == -1)
|
||||
iAdapter = 0;
|
||||
|
||||
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
|
||||
iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0);
|
||||
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
|
||||
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
|
||||
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
|
||||
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
|
||||
iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0);
|
||||
|
||||
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
|
||||
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
|
||||
|
||||
iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0);
|
||||
iniFile.Get("Enhancements", "ForceMaxAniso", &bForceMaxAniso, 0);
|
||||
|
||||
}
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
|
||||
iniFile.Set("Hardware", "Adapter", iAdapter);
|
||||
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
|
||||
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
|
||||
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
|
||||
iniFile.Set("Hardware", "VSync", bVsync);
|
||||
iniFile.Set("Hardware", "RenderInMainframe", renderToMainframe);
|
||||
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "Postprocess", iPostprocessEffect);
|
||||
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
|
||||
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
|
||||
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
|
||||
iniFile.Set("Settings", "Multisample", iMultisampleMode);
|
||||
iniFile.Set("Settings", "TexDumpPath", texDumpPath);
|
||||
|
||||
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
|
||||
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
|
||||
|
||||
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
|
||||
iniFile.Set("Enhancements", "ForceMaxAniso", bForceMaxAniso);
|
||||
iniFile.Save(FULL_CONFIG_DIR "gfx_dx9.ini");
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Config.h"
|
||||
#include "IniFile.h"
|
||||
|
||||
Config g_Config;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
}
|
||||
|
||||
void Config::Load()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
|
||||
iniFile.Get("Hardware", "Adapter", &iAdapter, 0);
|
||||
iniFile.Get("Hardware", "WindowedRes", &iWindowedRes, 0);
|
||||
iniFile.Get("Hardware", "FullscreenRes", &iFSResolution, 0);
|
||||
iniFile.Get("Hardware", "Fullscreen", &bFullscreen, 0);
|
||||
iniFile.Get("Hardware", "RenderInMainframe", &renderToMainframe, false);
|
||||
iniFile.Get("Hardware", "VSync", &bVsync, 0);
|
||||
if (iAdapter == -1)
|
||||
iAdapter = 0;
|
||||
|
||||
iniFile.Get("Settings", "OverlayStats", &bOverlayStats, false);
|
||||
iniFile.Get("Settings", "Postprocess", &iPostprocessEffect, 0);
|
||||
iniFile.Get("Settings", "DLOptimize", &iCompileDLsLevel, 0);
|
||||
iniFile.Get("Settings", "DumpTextures", &bDumpTextures, 0);
|
||||
iniFile.Get("Settings", "ShowShaderErrors", &bShowShaderErrors, 0);
|
||||
iniFile.Get("Settings", "Multisample", &iMultisampleMode, 0);
|
||||
iniFile.Get("Settings", "TexDumpPath", &texDumpPath, 0);
|
||||
|
||||
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
|
||||
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
|
||||
|
||||
iniFile.Get("Enhancements", "ForceFiltering", &bForceFiltering, 0);
|
||||
iniFile.Get("Enhancements", "ForceMaxAniso", &bForceMaxAniso, 0);
|
||||
|
||||
}
|
||||
|
||||
void Config::Save()
|
||||
{
|
||||
IniFile iniFile;
|
||||
iniFile.Load(FULL_CONFIG_DIR "gfx_dx9.ini");
|
||||
iniFile.Set("Hardware", "Adapter", iAdapter);
|
||||
iniFile.Set("Hardware", "WindowedRes", iWindowedRes);
|
||||
iniFile.Set("Hardware", "FullscreenRes", iFSResolution);
|
||||
iniFile.Set("Hardware", "Fullscreen", bFullscreen);
|
||||
iniFile.Set("Hardware", "VSync", bVsync);
|
||||
iniFile.Set("Hardware", "RenderInMainframe", renderToMainframe);
|
||||
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "OverlayStats", bOverlayStats);
|
||||
iniFile.Set("Settings", "Postprocess", iPostprocessEffect);
|
||||
iniFile.Set("Settings", "DLOptimize", iCompileDLsLevel);
|
||||
iniFile.Set("Settings", "DumpTextures", bDumpTextures);
|
||||
iniFile.Set("Settings", "ShowShaderErrors", bShowShaderErrors);
|
||||
iniFile.Set("Settings", "Multisample", iMultisampleMode);
|
||||
iniFile.Set("Settings", "TexDumpPath", texDumpPath);
|
||||
|
||||
iniFile.Set("Settings", "TexFmtOverlayEnable", bTexFmtOverlayEnable);
|
||||
iniFile.Set("Settings", "TexFmtOverlayCenter", bTexFmtOverlayCenter);
|
||||
|
||||
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
|
||||
iniFile.Set("Enhancements", "ForceMaxAniso", bForceMaxAniso);
|
||||
iniFile.Save(FULL_CONFIG_DIR "gfx_dx9.ini");
|
||||
}
|
||||
|
||||
@@ -1,389 +1,389 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "Render.h"
|
||||
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
bool fullScreen = false, nextFullScreen=false;
|
||||
LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice
|
||||
LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device
|
||||
LPDIRECT3DSURFACE9 backBuffer;
|
||||
D3DCAPS9 caps;
|
||||
int multisample;
|
||||
int resolution;
|
||||
|
||||
#define VENDOR_NVIDIA 4318
|
||||
|
||||
RECT client;
|
||||
HWND hWnd;
|
||||
int xres, yres;
|
||||
int cur_adapter;
|
||||
Shader Ps;
|
||||
Shader Vs;
|
||||
|
||||
bool bFrameInProgress = false;
|
||||
|
||||
//enum shit
|
||||
Adapter adapters[4];
|
||||
int numAdapters;
|
||||
|
||||
void Enumerate();
|
||||
|
||||
int GetNumAdapters()
|
||||
{
|
||||
return numAdapters;
|
||||
}
|
||||
|
||||
const Adapter &GetAdapter(int i)
|
||||
{
|
||||
return adapters[i];
|
||||
}
|
||||
|
||||
const Adapter &GetCurAdapter()
|
||||
{
|
||||
return adapters[cur_adapter];
|
||||
}
|
||||
|
||||
HRESULT Init()
|
||||
{
|
||||
// Create the D3D object, which is needed to create the D3DDevice.
|
||||
if( NULL == ( D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
|
||||
return E_FAIL;
|
||||
|
||||
Enumerate();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void EnableAlphaToCoverage()
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
|
||||
Renderer::SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') );
|
||||
}
|
||||
|
||||
void InitPP(int adapter, int resolution, int aa_mode, D3DPRESENT_PARAMETERS *pp)
|
||||
{
|
||||
int FSResX = adapters[adapter].resolutions[resolution].xres;
|
||||
int FSResY = adapters[adapter].resolutions[resolution].yres;
|
||||
|
||||
ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS));
|
||||
pp->hDeviceWindow = hWnd;
|
||||
pp->EnableAutoDepthStencil = TRUE;
|
||||
pp->AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
pp->BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
if (aa_mode >= (int)adapters[adapter].aa_levels.size())
|
||||
aa_mode = 0;
|
||||
|
||||
pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting;
|
||||
pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting;
|
||||
pp->Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
|
||||
|
||||
//D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
|
||||
|
||||
if (fullScreen)
|
||||
{
|
||||
xres = pp->BackBufferWidth = FSResX;
|
||||
yres = pp->BackBufferHeight = FSResY;
|
||||
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp->Windowed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = pp->BackBufferWidth = client.right - client.left;
|
||||
yres = pp->BackBufferHeight = client.bottom - client.top;
|
||||
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
pp->Windowed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void Enumerate()
|
||||
{
|
||||
numAdapters = D3D::D3D->GetAdapterCount();
|
||||
|
||||
for (int i=0; i<numAdapters; i++)
|
||||
{
|
||||
Adapter &a = adapters[i];
|
||||
D3D::D3D->GetAdapterIdentifier(i, 0, &a.ident);
|
||||
|
||||
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
|
||||
|
||||
// Add multisample modes
|
||||
a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0));
|
||||
|
||||
DWORD qlevels = 0;
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
|
||||
if (isNvidia)
|
||||
{
|
||||
// CSAA support
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 8x, 8xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2));
|
||||
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
}
|
||||
}
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 8x, 8xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4));
|
||||
a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (a.aa_levels.size() == 1)
|
||||
{
|
||||
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
|
||||
}
|
||||
|
||||
int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
|
||||
|
||||
for (int m = 0; m < numModes; m++)
|
||||
{
|
||||
D3DDISPLAYMODE mode;
|
||||
D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
|
||||
|
||||
int found = -1;
|
||||
for (int x = 0; x < (int)a.resolutions.size(); x++)
|
||||
{
|
||||
if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height)
|
||||
{
|
||||
found = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Resolution temp;
|
||||
Resolution &r = found==-1 ? temp : a.resolutions[found];
|
||||
|
||||
sprintf(r.name, "%ix%i", mode.Width, mode.Height);
|
||||
r.bitdepths.insert(mode.Format);
|
||||
r.refreshes.insert(mode.RefreshRate);
|
||||
if (found == -1 && mode.Width >= 640 && mode.Height >= 480)
|
||||
{
|
||||
r.xres = mode.Width;
|
||||
r.yres = mode.Height;
|
||||
a.resolutions.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Create(int adapter, HWND wnd, bool _fullscreen, int _resolution, int aa_mode)
|
||||
{
|
||||
hWnd = wnd;
|
||||
fullScreen = _fullscreen;
|
||||
nextFullScreen = _fullscreen;
|
||||
multisample = aa_mode;
|
||||
resolution = _resolution;
|
||||
cur_adapter = adapter;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
InitPP(adapter, resolution, aa_mode, &d3dpp);
|
||||
|
||||
if( FAILED( D3D->CreateDevice(
|
||||
adapter,
|
||||
D3DDEVTYPE_HAL,
|
||||
wnd,
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
|
||||
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
|
||||
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
|
||||
&d3dpp, &dev ) ) )
|
||||
{
|
||||
MessageBox(wnd,
|
||||
"Sorry, but it looks like your 3D accelerator is too old,\n"
|
||||
"or doesn't support features that Dolphin requires.\n"
|
||||
"Falling back to software vertex processing.\n",
|
||||
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
|
||||
if( FAILED( D3D->CreateDevice(
|
||||
adapter,
|
||||
D3DDEVTYPE_HAL,
|
||||
wnd,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
|
||||
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
|
||||
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
|
||||
&d3dpp, &dev ) ) )
|
||||
{
|
||||
MessageBox(wnd,
|
||||
"Software VP failed too. Upgrade your graphics card.",
|
||||
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
dev->GetDeviceCaps(&caps);
|
||||
dev->GetRenderTarget(0,&backBuffer);
|
||||
|
||||
Ps.Major = (D3D::caps.PixelShaderVersion >> 8) & 0xFF;
|
||||
Ps.Minor = (D3D::caps.PixelShaderVersion) & 0xFF;
|
||||
Vs.Major = (D3D::caps.VertexShaderVersion >>8) & 0xFF;
|
||||
Vs.Minor = (D3D::caps.VertexShaderVersion) & 0xFF;
|
||||
|
||||
// Device state would normally be set here
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ShaderVersion GetShaderVersion()
|
||||
{
|
||||
if (Ps.Major < 2)
|
||||
{
|
||||
return PSNONE;
|
||||
}
|
||||
|
||||
//good enough estimate - we really only
|
||||
//care about zero shader vs ps20
|
||||
return (ShaderVersion)Ps.Major;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
dev->Release();
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
D3D->Release();
|
||||
D3D = 0;
|
||||
}
|
||||
|
||||
const D3DCAPS9 &GetCaps()
|
||||
{
|
||||
return caps;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface()
|
||||
{
|
||||
return backBuffer;
|
||||
}
|
||||
|
||||
void ShowD3DError(HRESULT err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case D3DERR_DEVICELOST:
|
||||
MessageBox(0, "Device Lost", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_INVALIDCALL:
|
||||
MessageBox(0, "Invalid Call", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
MessageBox(0, "Driver Internal Error", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_OUTOFVIDEOMEMORY:
|
||||
MessageBox(0, "Out of vid mem", "D3D ERROR", 0);
|
||||
break;
|
||||
default:
|
||||
// MessageBox(0,"Other error or success","ERROR",0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (dev)
|
||||
{
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
InitPP(cur_adapter, resolution, multisample, &d3dpp);
|
||||
HRESULT hr = dev->Reset(&d3dpp);
|
||||
ShowD3DError(hr);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFullscreen()
|
||||
{
|
||||
return fullScreen;
|
||||
}
|
||||
|
||||
int GetDisplayWidth()
|
||||
{
|
||||
return xres;
|
||||
}
|
||||
int GetDisplayHeight()
|
||||
{
|
||||
return yres;
|
||||
}
|
||||
void SwitchFullscreen(bool fullscreen)
|
||||
{
|
||||
nextFullScreen = fullscreen;
|
||||
}
|
||||
|
||||
bool BeginFrame(bool clear, u32 color, float z)
|
||||
{
|
||||
if (bFrameInProgress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bFrameInProgress = true;
|
||||
|
||||
if (dev)
|
||||
{
|
||||
if (clear)
|
||||
dev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (DWORD)color, z, 0 );
|
||||
dev->BeginScene();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void EndFrame()
|
||||
{
|
||||
if (!bFrameInProgress)
|
||||
return;
|
||||
|
||||
bFrameInProgress = false;
|
||||
|
||||
if (dev)
|
||||
{
|
||||
dev->EndScene();
|
||||
dev->Present( NULL, NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
if (fullScreen != nextFullScreen)
|
||||
{
|
||||
fullScreen = nextFullScreen;
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "Render.h"
|
||||
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
bool fullScreen = false, nextFullScreen=false;
|
||||
LPDIRECT3D9 D3D = NULL; // Used to create the D3DDevice
|
||||
LPDIRECT3DDEVICE9 dev = NULL; // Our rendering device
|
||||
LPDIRECT3DSURFACE9 backBuffer;
|
||||
D3DCAPS9 caps;
|
||||
int multisample;
|
||||
int resolution;
|
||||
|
||||
#define VENDOR_NVIDIA 4318
|
||||
|
||||
RECT client;
|
||||
HWND hWnd;
|
||||
int xres, yres;
|
||||
int cur_adapter;
|
||||
Shader Ps;
|
||||
Shader Vs;
|
||||
|
||||
bool bFrameInProgress = false;
|
||||
|
||||
//enum shit
|
||||
Adapter adapters[4];
|
||||
int numAdapters;
|
||||
|
||||
void Enumerate();
|
||||
|
||||
int GetNumAdapters()
|
||||
{
|
||||
return numAdapters;
|
||||
}
|
||||
|
||||
const Adapter &GetAdapter(int i)
|
||||
{
|
||||
return adapters[i];
|
||||
}
|
||||
|
||||
const Adapter &GetCurAdapter()
|
||||
{
|
||||
return adapters[cur_adapter];
|
||||
}
|
||||
|
||||
HRESULT Init()
|
||||
{
|
||||
// Create the D3D object, which is needed to create the D3DDevice.
|
||||
if( NULL == ( D3D = Direct3DCreate9( D3D_SDK_VERSION ) ) )
|
||||
return E_FAIL;
|
||||
|
||||
Enumerate();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void EnableAlphaToCoverage()
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C'));
|
||||
Renderer::SetRenderState( D3DRS_ADAPTIVETESS_Y, (D3DFORMAT)MAKEFOURCC('A', 'T', 'O', 'C') );
|
||||
}
|
||||
|
||||
void InitPP(int adapter, int resolution, int aa_mode, D3DPRESENT_PARAMETERS *pp)
|
||||
{
|
||||
int FSResX = adapters[adapter].resolutions[resolution].xres;
|
||||
int FSResY = adapters[adapter].resolutions[resolution].yres;
|
||||
|
||||
ZeroMemory(pp, sizeof(D3DPRESENT_PARAMETERS));
|
||||
pp->hDeviceWindow = hWnd;
|
||||
pp->EnableAutoDepthStencil = TRUE;
|
||||
pp->AutoDepthStencilFormat = D3DFMT_D24S8;
|
||||
pp->BackBufferFormat = D3DFMT_A8R8G8B8;
|
||||
if (aa_mode >= (int)adapters[adapter].aa_levels.size())
|
||||
aa_mode = 0;
|
||||
|
||||
pp->MultiSampleType = adapters[adapter].aa_levels[aa_mode].ms_setting;
|
||||
pp->MultiSampleQuality = adapters[adapter].aa_levels[aa_mode].qual_setting;
|
||||
pp->Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
|
||||
|
||||
//D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
|
||||
|
||||
if (fullScreen)
|
||||
{
|
||||
xres = pp->BackBufferWidth = FSResX;
|
||||
yres = pp->BackBufferHeight = FSResY;
|
||||
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp->Windowed = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
GetClientRect(hWnd, &client);
|
||||
xres = pp->BackBufferWidth = client.right - client.left;
|
||||
yres = pp->BackBufferHeight = client.bottom - client.top;
|
||||
pp->SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
pp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
||||
pp->Windowed = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
void Enumerate()
|
||||
{
|
||||
numAdapters = D3D::D3D->GetAdapterCount();
|
||||
|
||||
for (int i=0; i<numAdapters; i++)
|
||||
{
|
||||
Adapter &a = adapters[i];
|
||||
D3D::D3D->GetAdapterIdentifier(i, 0, &a.ident);
|
||||
|
||||
bool isNvidia = a.ident.VendorId == VENDOR_NVIDIA;
|
||||
|
||||
// Add multisample modes
|
||||
a.aa_levels.push_back(AALevel("None", D3DMULTISAMPLE_NONE, 0));
|
||||
|
||||
DWORD qlevels = 0;
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("2x MSAA", D3DMULTISAMPLE_2_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_2_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("4x MSAA", D3DMULTISAMPLE_4_SAMPLES, 0));
|
||||
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
if (qlevels > 0)
|
||||
a.aa_levels.push_back(AALevel("8x MSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
|
||||
if (isNvidia)
|
||||
{
|
||||
// CSAA support
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_4_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 8x, 8xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("8x CSAA", D3DMULTISAMPLE_4_SAMPLES, 2));
|
||||
a.aa_levels.push_back(AALevel("8xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 0));
|
||||
}
|
||||
}
|
||||
if (D3DERR_NOTAVAILABLE != D3D::D3D->CheckDeviceMultiSampleType(
|
||||
i, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, TRUE, D3DMULTISAMPLE_8_SAMPLES, &qlevels))
|
||||
{
|
||||
if (qlevels > 2)
|
||||
{
|
||||
// 8x, 8xQ are available
|
||||
// See http://developer.nvidia.com/object/coverage-sampled-aa.html
|
||||
a.aa_levels.push_back(AALevel("16x CSAA", D3DMULTISAMPLE_4_SAMPLES, 4));
|
||||
a.aa_levels.push_back(AALevel("16xQ CSAA", D3DMULTISAMPLE_8_SAMPLES, 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (a.aa_levels.size() == 1)
|
||||
{
|
||||
strcpy(a.aa_levels[0].name, "(Not supported on this device)");
|
||||
}
|
||||
|
||||
int numModes = D3D::D3D->GetAdapterModeCount(i, D3DFMT_X8R8G8B8);
|
||||
|
||||
for (int m = 0; m < numModes; m++)
|
||||
{
|
||||
D3DDISPLAYMODE mode;
|
||||
D3D::D3D->EnumAdapterModes(i, D3DFMT_X8R8G8B8, m, &mode);
|
||||
|
||||
int found = -1;
|
||||
for (int x = 0; x < (int)a.resolutions.size(); x++)
|
||||
{
|
||||
if (a.resolutions[x].xres == mode.Width && a.resolutions[x].yres == mode.Height)
|
||||
{
|
||||
found = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Resolution temp;
|
||||
Resolution &r = found==-1 ? temp : a.resolutions[found];
|
||||
|
||||
sprintf(r.name, "%ix%i", mode.Width, mode.Height);
|
||||
r.bitdepths.insert(mode.Format);
|
||||
r.refreshes.insert(mode.RefreshRate);
|
||||
if (found == -1 && mode.Width >= 640 && mode.Height >= 480)
|
||||
{
|
||||
r.xres = mode.Width;
|
||||
r.yres = mode.Height;
|
||||
a.resolutions.push_back(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT Create(int adapter, HWND wnd, bool _fullscreen, int _resolution, int aa_mode)
|
||||
{
|
||||
hWnd = wnd;
|
||||
fullScreen = _fullscreen;
|
||||
nextFullScreen = _fullscreen;
|
||||
multisample = aa_mode;
|
||||
resolution = _resolution;
|
||||
cur_adapter = adapter;
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
InitPP(adapter, resolution, aa_mode, &d3dpp);
|
||||
|
||||
if( FAILED( D3D->CreateDevice(
|
||||
adapter,
|
||||
D3DDEVTYPE_HAL,
|
||||
wnd,
|
||||
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
|
||||
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
|
||||
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
|
||||
&d3dpp, &dev ) ) )
|
||||
{
|
||||
MessageBox(wnd,
|
||||
"Sorry, but it looks like your 3D accelerator is too old,\n"
|
||||
"or doesn't support features that Dolphin requires.\n"
|
||||
"Falling back to software vertex processing.\n",
|
||||
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
|
||||
if( FAILED( D3D->CreateDevice(
|
||||
adapter,
|
||||
D3DDEVTYPE_HAL,
|
||||
wnd,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED,
|
||||
// |D3DCREATE_MULTITHREADED /* | D3DCREATE_PUREDEVICE*/,
|
||||
//D3DCREATE_SOFTWARE_VERTEXPROCESSING ,
|
||||
&d3dpp, &dev ) ) )
|
||||
{
|
||||
MessageBox(wnd,
|
||||
"Software VP failed too. Upgrade your graphics card.",
|
||||
"Dolphin Direct3D plugin", MB_OK | MB_ICONERROR);
|
||||
return E_FAIL;
|
||||
}
|
||||
}
|
||||
dev->GetDeviceCaps(&caps);
|
||||
dev->GetRenderTarget(0,&backBuffer);
|
||||
|
||||
Ps.Major = (D3D::caps.PixelShaderVersion >> 8) & 0xFF;
|
||||
Ps.Minor = (D3D::caps.PixelShaderVersion) & 0xFF;
|
||||
Vs.Major = (D3D::caps.VertexShaderVersion >>8) & 0xFF;
|
||||
Vs.Minor = (D3D::caps.VertexShaderVersion) & 0xFF;
|
||||
|
||||
// Device state would normally be set here
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
ShaderVersion GetShaderVersion()
|
||||
{
|
||||
if (Ps.Major < 2)
|
||||
{
|
||||
return PSNONE;
|
||||
}
|
||||
|
||||
//good enough estimate - we really only
|
||||
//care about zero shader vs ps20
|
||||
return (ShaderVersion)Ps.Major;
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
dev->Release();
|
||||
dev = 0;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
D3D->Release();
|
||||
D3D = 0;
|
||||
}
|
||||
|
||||
const D3DCAPS9 &GetCaps()
|
||||
{
|
||||
return caps;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 GetBackBufferSurface()
|
||||
{
|
||||
return backBuffer;
|
||||
}
|
||||
|
||||
void ShowD3DError(HRESULT err)
|
||||
{
|
||||
switch (err)
|
||||
{
|
||||
case D3DERR_DEVICELOST:
|
||||
MessageBox(0, "Device Lost", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_INVALIDCALL:
|
||||
MessageBox(0, "Invalid Call", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_DRIVERINTERNALERROR:
|
||||
MessageBox(0, "Driver Internal Error", "D3D ERROR", 0);
|
||||
break;
|
||||
case D3DERR_OUTOFVIDEOMEMORY:
|
||||
MessageBox(0, "Out of vid mem", "D3D ERROR", 0);
|
||||
break;
|
||||
default:
|
||||
// MessageBox(0,"Other error or success","ERROR",0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
if (dev)
|
||||
{
|
||||
D3DPRESENT_PARAMETERS d3dpp;
|
||||
InitPP(cur_adapter, resolution, multisample, &d3dpp);
|
||||
HRESULT hr = dev->Reset(&d3dpp);
|
||||
ShowD3DError(hr);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsFullscreen()
|
||||
{
|
||||
return fullScreen;
|
||||
}
|
||||
|
||||
int GetDisplayWidth()
|
||||
{
|
||||
return xres;
|
||||
}
|
||||
int GetDisplayHeight()
|
||||
{
|
||||
return yres;
|
||||
}
|
||||
void SwitchFullscreen(bool fullscreen)
|
||||
{
|
||||
nextFullScreen = fullscreen;
|
||||
}
|
||||
|
||||
bool BeginFrame(bool clear, u32 color, float z)
|
||||
{
|
||||
if (bFrameInProgress)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bFrameInProgress = true;
|
||||
|
||||
if (dev)
|
||||
{
|
||||
if (clear)
|
||||
dev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, (DWORD)color, z, 0 );
|
||||
dev->BeginScene();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void EndFrame()
|
||||
{
|
||||
if (!bFrameInProgress)
|
||||
return;
|
||||
|
||||
bFrameInProgress = false;
|
||||
|
||||
if (dev)
|
||||
{
|
||||
dev->EndScene();
|
||||
dev->Present( NULL, NULL, NULL, NULL );
|
||||
}
|
||||
|
||||
if (fullScreen != nextFullScreen)
|
||||
{
|
||||
fullScreen = nextFullScreen;
|
||||
Reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,294 +1,294 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "Render.h"
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
namespace Postprocess
|
||||
{
|
||||
LPDIRECT3DSURFACE9 displayColorBuffer;
|
||||
LPDIRECT3DSURFACE9 displayZStencilBuffer;
|
||||
|
||||
LPDIRECT3DTEXTURE9 mainColorBufferTexture;
|
||||
LPDIRECT3DSURFACE9 mainColorBuffer;
|
||||
LPDIRECT3DSURFACE9 mainZStencilBuffer;
|
||||
|
||||
const int numScratch = 2;
|
||||
LPDIRECT3DTEXTURE9 scratch[numScratch];
|
||||
LPDIRECT3DSURFACE9 scratchSurface[numScratch];
|
||||
|
||||
const int mainWidth = 640, mainHeight=480;
|
||||
const int scratchWidth = 256, scratchHeight=256;
|
||||
|
||||
int displayWidth, displayHeight;
|
||||
|
||||
bool initialized;
|
||||
|
||||
int GetWidth() {
|
||||
return initialized ? mainWidth : displayWidth;
|
||||
}
|
||||
|
||||
int GetHeight() {
|
||||
return initialized ? mainHeight : displayHeight;
|
||||
}
|
||||
|
||||
|
||||
void CreateStuff()
|
||||
{
|
||||
mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight);
|
||||
mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer);
|
||||
mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight);
|
||||
|
||||
for (int i=0; i<numScratch; i++)
|
||||
{
|
||||
scratch[i]=D3D::CreateRenderTarget(scratchWidth,scratchHeight);
|
||||
scratch[i]->GetSurfaceLevel(0,&(scratchSurface[i]));
|
||||
}
|
||||
|
||||
initialized=true;
|
||||
}
|
||||
|
||||
void DestroyStuff()
|
||||
{
|
||||
SAFE_RELEASE(mainColorBuffer);
|
||||
SAFE_RELEASE(mainColorBufferTexture);
|
||||
SAFE_RELEASE(mainZStencilBuffer);
|
||||
|
||||
for (int i=0; i<numScratch; i++)
|
||||
{
|
||||
SAFE_RELEASE(scratch[i]);
|
||||
SAFE_RELEASE(scratchSurface[i]);
|
||||
}
|
||||
initialized=false;
|
||||
}
|
||||
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
dev->GetRenderTarget(0,&displayColorBuffer);
|
||||
dev->GetDepthStencilSurface(&displayZStencilBuffer);
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
displayColorBuffer->GetDesc(&desc);
|
||||
displayWidth = desc.Width;
|
||||
displayHeight = desc.Height;
|
||||
|
||||
if (g_Config.iPostprocessEffect)
|
||||
CreateStuff();
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
DestroyStuff();
|
||||
SAFE_RELEASE(displayColorBuffer);
|
||||
SAFE_RELEASE(displayZStencilBuffer);
|
||||
}
|
||||
|
||||
|
||||
void BeginFrame()
|
||||
{
|
||||
if (g_Config.iPostprocessEffect)
|
||||
{
|
||||
if (!initialized)
|
||||
CreateStuff();
|
||||
dev->SetRenderTarget(0,mainColorBuffer);
|
||||
dev->SetDepthStencilSurface(mainZStencilBuffer);
|
||||
|
||||
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
|
||||
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
|
||||
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
dev->SetRenderTarget(0,displayColorBuffer);
|
||||
dev->SetDepthStencilSurface(displayZStencilBuffer);
|
||||
DestroyStuff();
|
||||
}
|
||||
|
||||
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
|
||||
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //good looking almost Gaussian
|
||||
|
||||
//int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter
|
||||
|
||||
void NightGlow(bool intense, bool original)
|
||||
{
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT);
|
||||
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
|
||||
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
|
||||
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
|
||||
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
|
||||
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
||||
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
||||
|
||||
dev->SetDepthStencilSurface(0);
|
||||
|
||||
//dev->SetTexture(0,mainColorBufferTexture);
|
||||
Renderer::SetTexture( 0, mainColorBufferTexture );
|
||||
|
||||
dev->SetRenderTarget(0,scratchSurface[0]);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
|
||||
dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
|
||||
dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
|
||||
dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
|
||||
POINT pt;
|
||||
GetCursorPos(&pt);
|
||||
|
||||
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f);
|
||||
#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff);
|
||||
float f=0.008f;
|
||||
QOFF(0,0,0xa0a0a0a0);
|
||||
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
//dev->SetTexture(0,scratch[0]);
|
||||
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
|
||||
Renderer::SetTexture( 0, scratch[0] );
|
||||
|
||||
dev->SetRenderTarget(0,scratchSurface[1]);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
|
||||
float yMul = 1.33333333333f;
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
DWORD c=filterKernel[i]/2;
|
||||
c|=c<<8;
|
||||
c|=c<<16;
|
||||
QOFF(0,(i-3.5f) * f * yMul,c);
|
||||
}
|
||||
|
||||
//dev->SetTexture(0,scratch[1]);
|
||||
Renderer::SetTexture( 0, scratch[1] );
|
||||
|
||||
dev->SetRenderTarget(0,scratchSurface[0]);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
DWORD c=filterKernel[i]/(intense?3:2);
|
||||
c|=c<<8;
|
||||
c|=c<<16;
|
||||
QOFF((i-3.5f) * f,0,c);
|
||||
}
|
||||
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
|
||||
|
||||
if (intense)
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
|
||||
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA);
|
||||
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
|
||||
}
|
||||
else
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR);
|
||||
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
|
||||
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR );
|
||||
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
||||
}
|
||||
|
||||
// dev->SetTexture(0,scratch[0]);
|
||||
Renderer::SetTexture( 0, scratch[0] );
|
||||
|
||||
dev->SetRenderTarget(0,mainColorBuffer);
|
||||
quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1);
|
||||
|
||||
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
|
||||
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
|
||||
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
|
||||
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0);
|
||||
}
|
||||
|
||||
const char **GetPostprocessingNames()
|
||||
{
|
||||
static const char *names[] = {
|
||||
"None",
|
||||
"Night Glow 1",
|
||||
"Night Glow 2",
|
||||
"Night Glow 3",
|
||||
0,
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
void FinalizeFrame()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
|
||||
// dev->SetRenderState(D3DRS_ZENABLE,FALSE);
|
||||
// dev->SetRenderState(D3DRS_FOGENABLE,FALSE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
|
||||
|
||||
Renderer::SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
|
||||
Renderer::SetRenderState( D3DRS_ZENABLE, FALSE );
|
||||
Renderer::SetRenderState( D3DRS_FOGENABLE, FALSE );
|
||||
Renderer::SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
|
||||
|
||||
switch(g_Config.iPostprocessEffect) {
|
||||
case 1:
|
||||
NightGlow(true,true);
|
||||
case 2:
|
||||
NightGlow(false,true);
|
||||
break;
|
||||
case 3:
|
||||
NightGlow(false,false);
|
||||
break;
|
||||
}
|
||||
|
||||
dev->SetRenderTarget(0,displayColorBuffer);
|
||||
dev->SetDepthStencilSurface(displayZStencilBuffer);
|
||||
|
||||
// dev->SetTexture(0,mainColorBufferTexture);
|
||||
Renderer::SetTexture( 0, mainColorBufferTexture );
|
||||
|
||||
quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "Render.h"
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
namespace Postprocess
|
||||
{
|
||||
LPDIRECT3DSURFACE9 displayColorBuffer;
|
||||
LPDIRECT3DSURFACE9 displayZStencilBuffer;
|
||||
|
||||
LPDIRECT3DTEXTURE9 mainColorBufferTexture;
|
||||
LPDIRECT3DSURFACE9 mainColorBuffer;
|
||||
LPDIRECT3DSURFACE9 mainZStencilBuffer;
|
||||
|
||||
const int numScratch = 2;
|
||||
LPDIRECT3DTEXTURE9 scratch[numScratch];
|
||||
LPDIRECT3DSURFACE9 scratchSurface[numScratch];
|
||||
|
||||
const int mainWidth = 640, mainHeight=480;
|
||||
const int scratchWidth = 256, scratchHeight=256;
|
||||
|
||||
int displayWidth, displayHeight;
|
||||
|
||||
bool initialized;
|
||||
|
||||
int GetWidth() {
|
||||
return initialized ? mainWidth : displayWidth;
|
||||
}
|
||||
|
||||
int GetHeight() {
|
||||
return initialized ? mainHeight : displayHeight;
|
||||
}
|
||||
|
||||
|
||||
void CreateStuff()
|
||||
{
|
||||
mainColorBufferTexture = D3D::CreateRenderTarget(mainWidth,mainHeight);
|
||||
mainColorBufferTexture->GetSurfaceLevel(0,&mainColorBuffer);
|
||||
mainZStencilBuffer = D3D::CreateDepthStencilSurface(mainWidth,mainHeight);
|
||||
|
||||
for (int i=0; i<numScratch; i++)
|
||||
{
|
||||
scratch[i]=D3D::CreateRenderTarget(scratchWidth,scratchHeight);
|
||||
scratch[i]->GetSurfaceLevel(0,&(scratchSurface[i]));
|
||||
}
|
||||
|
||||
initialized=true;
|
||||
}
|
||||
|
||||
void DestroyStuff()
|
||||
{
|
||||
SAFE_RELEASE(mainColorBuffer);
|
||||
SAFE_RELEASE(mainColorBufferTexture);
|
||||
SAFE_RELEASE(mainZStencilBuffer);
|
||||
|
||||
for (int i=0; i<numScratch; i++)
|
||||
{
|
||||
SAFE_RELEASE(scratch[i]);
|
||||
SAFE_RELEASE(scratchSurface[i]);
|
||||
}
|
||||
initialized=false;
|
||||
}
|
||||
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
dev->GetRenderTarget(0,&displayColorBuffer);
|
||||
dev->GetDepthStencilSurface(&displayZStencilBuffer);
|
||||
|
||||
D3DSURFACE_DESC desc;
|
||||
displayColorBuffer->GetDesc(&desc);
|
||||
displayWidth = desc.Width;
|
||||
displayHeight = desc.Height;
|
||||
|
||||
if (g_Config.iPostprocessEffect)
|
||||
CreateStuff();
|
||||
}
|
||||
|
||||
void Cleanup()
|
||||
{
|
||||
DestroyStuff();
|
||||
SAFE_RELEASE(displayColorBuffer);
|
||||
SAFE_RELEASE(displayZStencilBuffer);
|
||||
}
|
||||
|
||||
|
||||
void BeginFrame()
|
||||
{
|
||||
if (g_Config.iPostprocessEffect)
|
||||
{
|
||||
if (!initialized)
|
||||
CreateStuff();
|
||||
dev->SetRenderTarget(0,mainColorBuffer);
|
||||
dev->SetDepthStencilSurface(mainZStencilBuffer);
|
||||
|
||||
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
|
||||
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
|
||||
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,0,1,0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
dev->SetRenderTarget(0,displayColorBuffer);
|
||||
dev->SetDepthStencilSurface(displayZStencilBuffer);
|
||||
DestroyStuff();
|
||||
}
|
||||
|
||||
// dev->SetRenderState(D3DRS_ZENABLE,TRUE);
|
||||
Renderer::SetRenderState( D3DRS_ZENABLE, TRUE );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int filterKernel[8] = {0x40,0x80,0xc0,0xFF,0xFF,0xc0,0x80,0x40}; //good looking almost Gaussian
|
||||
|
||||
//int filterKernel[8] = {0xFF,0xc0,0x80,0x40,0x40,0x80,0xc0,0xFF,}; //crazy filter
|
||||
|
||||
void NightGlow(bool intense, bool original)
|
||||
{
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_SUBTRACT);
|
||||
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,TRUE);
|
||||
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
|
||||
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
|
||||
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SUBTRACT );
|
||||
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
|
||||
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
||||
|
||||
dev->SetDepthStencilSurface(0);
|
||||
|
||||
//dev->SetTexture(0,mainColorBufferTexture);
|
||||
Renderer::SetTexture( 0, mainColorBufferTexture );
|
||||
|
||||
dev->SetRenderTarget(0,scratchSurface[0]);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_CLAMP);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_CLAMP);
|
||||
dev->SetSamplerState(0,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
|
||||
dev->SetSamplerState(0,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
|
||||
dev->SetSamplerState(0,D3DSAMP_MIPFILTER,D3DTEXF_LINEAR);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
|
||||
POINT pt;
|
||||
GetCursorPos(&pt);
|
||||
|
||||
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,1.0f);
|
||||
#define QOFF(xoff,yoff,col) quad2d(-0.0f,-0.0f,scratchWidth-0.0f,scratchHeight-0.0f,col,0+xoff,0+yoff,1+xoff,1+yoff);
|
||||
float f=0.008f;
|
||||
QOFF(0,0,0xa0a0a0a0);
|
||||
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
//dev->SetTexture(0,scratch[0]);
|
||||
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
|
||||
Renderer::SetTexture( 0, scratch[0] );
|
||||
|
||||
dev->SetRenderTarget(0,scratchSurface[1]);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
|
||||
float yMul = 1.33333333333f;
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
DWORD c=filterKernel[i]/2;
|
||||
c|=c<<8;
|
||||
c|=c<<16;
|
||||
QOFF(0,(i-3.5f) * f * yMul,c);
|
||||
}
|
||||
|
||||
//dev->SetTexture(0,scratch[1]);
|
||||
Renderer::SetTexture( 0, scratch[1] );
|
||||
|
||||
dev->SetRenderTarget(0,scratchSurface[0]);
|
||||
dev->Clear(0,0,D3DCLEAR_TARGET,0,0,0);
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
DWORD c=filterKernel[i]/(intense?3:2);
|
||||
c|=c<<8;
|
||||
c|=c<<16;
|
||||
QOFF((i-3.5f) * f,0,c);
|
||||
}
|
||||
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
Renderer::SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
|
||||
|
||||
if (intense)
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_ONE);
|
||||
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_SRCALPHA);
|
||||
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
|
||||
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
|
||||
}
|
||||
else
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_SRCBLEND,D3DBLEND_INVDESTCOLOR);
|
||||
// dev->SetRenderState(D3DRS_DESTBLEND,D3DBLEND_ONE);
|
||||
Renderer::SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVDESTCOLOR );
|
||||
Renderer::SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
|
||||
}
|
||||
|
||||
// dev->SetTexture(0,scratch[0]);
|
||||
Renderer::SetTexture( 0, scratch[0] );
|
||||
|
||||
dev->SetRenderTarget(0,mainColorBuffer);
|
||||
quad2d(0,0,(float)mainWidth,(float)mainHeight,original?0xCFFFFFFF:0xFFFFFFFF,0,0,1,1);
|
||||
|
||||
// dev->SetRenderState(D3DRS_ALPHABLENDENABLE,FALSE);
|
||||
Renderer::SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
|
||||
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSU,D3DTADDRESS_WRAP);
|
||||
dev->SetSamplerState(0,D3DSAMP_ADDRESSV,D3DTADDRESS_WRAP);
|
||||
//dev->SetSamplerState(0,D3DSAMP_MIPMAPLODBIAS,0);
|
||||
}
|
||||
|
||||
const char **GetPostprocessingNames()
|
||||
{
|
||||
static const char *names[] = {
|
||||
"None",
|
||||
"Night Glow 1",
|
||||
"Night Glow 2",
|
||||
"Night Glow 3",
|
||||
0,
|
||||
};
|
||||
return names;
|
||||
}
|
||||
|
||||
void FinalizeFrame()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
// dev->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
|
||||
// dev->SetRenderState(D3DRS_ZENABLE,FALSE);
|
||||
// dev->SetRenderState(D3DRS_FOGENABLE,FALSE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
|
||||
// dev->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
|
||||
|
||||
Renderer::SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
|
||||
Renderer::SetRenderState( D3DRS_ZENABLE, FALSE );
|
||||
Renderer::SetRenderState( D3DRS_FOGENABLE, FALSE );
|
||||
Renderer::SetTextureStageState(0,D3DTSS_COLORARG1,D3DTA_TEXTURE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_COLORARG2,D3DTA_DIFFUSE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_MODULATE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_ALPHAARG2,D3DTA_DIFFUSE);
|
||||
Renderer::SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG2);
|
||||
|
||||
switch(g_Config.iPostprocessEffect) {
|
||||
case 1:
|
||||
NightGlow(true,true);
|
||||
case 2:
|
||||
NightGlow(false,true);
|
||||
break;
|
||||
case 3:
|
||||
NightGlow(false,false);
|
||||
break;
|
||||
}
|
||||
|
||||
dev->SetRenderTarget(0,displayColorBuffer);
|
||||
dev->SetDepthStencilSurface(displayZStencilBuffer);
|
||||
|
||||
// dev->SetTexture(0,mainColorBufferTexture);
|
||||
Renderer::SetTexture( 0, mainColorBufferTexture );
|
||||
|
||||
quad2d(0, 0, (float)displayWidth, (float)displayHeight, 0xFFFFFFFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,108 +1,108 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <d3dx9.h>
|
||||
#include <string>
|
||||
|
||||
#include "Config.h"
|
||||
#include "D3DShader.h"
|
||||
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len)
|
||||
{
|
||||
//try to compile
|
||||
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
|
||||
LPDIRECT3DVERTEXSHADER9 vShader = 0;
|
||||
HRESULT hr = D3DXCompileShader(code,len,0,0,"main","vs_1_1",0,&shaderBuffer,&errorBuffer,0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//let's try 2.0
|
||||
hr = D3DXCompileShader(code,len,0,0,"main","vs_2_0",0,&shaderBuffer,&errorBuffer,0);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//compilation error
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
|
||||
vShader = 0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
//create it
|
||||
HRESULT hr = E_FAIL;
|
||||
if (shaderBuffer)
|
||||
hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader);
|
||||
if (FAILED(hr) || vShader == 0)
|
||||
{
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
|
||||
return vShader;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len)
|
||||
{
|
||||
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
|
||||
LPDIRECT3DPIXELSHADER9 pShader = 0;
|
||||
static char *versions[6] = {"ERROR","ps_1_1","ps_1_4","ps_2_0","ps_3_0","ps_4_0"};
|
||||
HRESULT hr = D3DXCompileShader(code,len,0,0,
|
||||
"main","ps_2_0", // Pixel Shader 2.0 is enough for all we do
|
||||
0,&shaderBuffer,&errorBuffer,0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
pShader = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//create it
|
||||
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader);
|
||||
if (FAILED(hr) || pShader == 0)
|
||||
{
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0,"damn","error creating pixelshader",MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
|
||||
return pShader;
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <d3dx9.h>
|
||||
#include <string>
|
||||
|
||||
#include "Config.h"
|
||||
#include "D3DShader.h"
|
||||
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DVERTEXSHADER9 CompileVShader(const char *code, int len)
|
||||
{
|
||||
//try to compile
|
||||
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
|
||||
LPDIRECT3DVERTEXSHADER9 vShader = 0;
|
||||
HRESULT hr = D3DXCompileShader(code,len,0,0,"main","vs_1_1",0,&shaderBuffer,&errorBuffer,0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//let's try 2.0
|
||||
hr = D3DXCompileShader(code,len,0,0,"main","vs_2_0",0,&shaderBuffer,&errorBuffer,0);
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
//compilation error
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0, hello.c_str(), "Error compiling vertex shader", MB_ICONERROR);
|
||||
vShader = 0;
|
||||
}
|
||||
else if (SUCCEEDED(hr))
|
||||
{
|
||||
//create it
|
||||
HRESULT hr = E_FAIL;
|
||||
if (shaderBuffer)
|
||||
hr = D3D::dev->CreateVertexShader((DWORD *)shaderBuffer->GetBufferPointer(), &vShader);
|
||||
if (FAILED(hr) || vShader == 0)
|
||||
{
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0,code,(char*)errorBuffer->GetBufferPointer(),MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
|
||||
return vShader;
|
||||
}
|
||||
|
||||
LPDIRECT3DPIXELSHADER9 CompilePShader(const char *code, int len)
|
||||
{
|
||||
LPD3DXBUFFER shaderBuffer = 0, errorBuffer = 0;
|
||||
LPDIRECT3DPIXELSHADER9 pShader = 0;
|
||||
static char *versions[6] = {"ERROR","ps_1_1","ps_1_4","ps_2_0","ps_3_0","ps_4_0"};
|
||||
HRESULT hr = D3DXCompileShader(code,len,0,0,
|
||||
"main","ps_2_0", // Pixel Shader 2.0 is enough for all we do
|
||||
0,&shaderBuffer,&errorBuffer,0);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||
hello += "\n\n";
|
||||
hello += code;
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0, hello.c_str(), "Error compiling pixel shader", MB_ICONERROR);
|
||||
pShader = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
//create it
|
||||
HRESULT hr = D3D::dev->CreatePixelShader((DWORD *)shaderBuffer->GetBufferPointer(), &pShader);
|
||||
if (FAILED(hr) || pShader == 0)
|
||||
{
|
||||
if (g_Config.bShowShaderErrors)
|
||||
MessageBox(0,"damn","error creating pixelshader",MB_ICONERROR);
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup
|
||||
if (shaderBuffer)
|
||||
shaderBuffer->Release();
|
||||
if (errorBuffer)
|
||||
errorBuffer->Release();
|
||||
|
||||
return pShader;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,115 +1,115 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
|
||||
// crazy bitmagic
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
|
||||
HRESULT hr;
|
||||
// TODO(ector): allow mipmaps for non-pow textures on newer cards?
|
||||
if (!isPow2)
|
||||
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if(FAILED(hr))
|
||||
return 0;
|
||||
|
||||
int level = 0;
|
||||
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0 );
|
||||
|
||||
u32* pIn = pBuffer;
|
||||
switch(fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
int level = 0;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0 );
|
||||
u32* pIn = pBuffer;
|
||||
switch(fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits,pIn, width*4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
HRESULT hr = dev->CreateTexture(width,height,0,D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
else
|
||||
return tex;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height)
|
||||
{
|
||||
LPDIRECT3DSURFACE9 surf;
|
||||
HRESULT hr = dev->CreateDepthStencilSurface(width,height,D3DFMT_D24S8,D3DMULTISAMPLE_NONE,0,0,&surf,0);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
else
|
||||
return surf;
|
||||
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 CreateTexture2D(const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
LPDIRECT3DTEXTURE9 pTexture;
|
||||
|
||||
// crazy bitmagic
|
||||
bool isPow2 = !((width&(width-1)) || (height&(height-1)));
|
||||
|
||||
HRESULT hr;
|
||||
// TODO(ector): allow mipmaps for non-pow textures on newer cards?
|
||||
if (!isPow2)
|
||||
hr = dev->CreateTexture(width, height, 1, 0, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
else
|
||||
hr = dev->CreateTexture(width, height, 0, D3DUSAGE_AUTOGENMIPMAP, fmt, D3DPOOL_MANAGED, &pTexture, NULL);
|
||||
|
||||
if(FAILED(hr))
|
||||
return 0;
|
||||
|
||||
int level = 0;
|
||||
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0 );
|
||||
|
||||
u32* pIn = pBuffer;
|
||||
switch(fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
return pTexture;
|
||||
}
|
||||
|
||||
void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int width, const int height,const int pitch, D3DFORMAT fmt)
|
||||
{
|
||||
u32* pBuffer = (u32*)buffer;
|
||||
int level = 0;
|
||||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0 );
|
||||
u32* pIn = pBuffer;
|
||||
switch(fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
{
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u32* pBits = (u32*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits,pIn, width*4);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
}
|
||||
|
||||
LPDIRECT3DTEXTURE9 CreateRenderTarget(const int width, const int height)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
HRESULT hr = dev->CreateTexture(width,height,0,D3DUSAGE_RENDERTARGET | D3DUSAGE_AUTOGENMIPMAP,D3DFMT_A8R8G8B8,D3DPOOL_DEFAULT,&tex,NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
else
|
||||
return tex;
|
||||
}
|
||||
|
||||
LPDIRECT3DSURFACE9 CreateDepthStencilSurface(const int width, const int height)
|
||||
{
|
||||
LPDIRECT3DSURFACE9 surf;
|
||||
HRESULT hr = dev->CreateDepthStencilSurface(width,height,D3DFMT_D24S8,D3DMULTISAMPLE_NONE,0,0,&surf,0);
|
||||
|
||||
if (FAILED(hr))
|
||||
return 0;
|
||||
else
|
||||
return surf;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,397 +1,397 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "Render.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
CD3DFont font;
|
||||
|
||||
#define MAX_NUM_VERTICES 50*6
|
||||
struct FONT2DVERTEX {
|
||||
float x,y,z;
|
||||
float rhw;
|
||||
u32 color;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
|
||||
|
||||
inline FONT2DVERTEX InitFont2DVertex( float x, float y, u32 color, float tu, float tv )
|
||||
{
|
||||
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
|
||||
return v;
|
||||
}
|
||||
|
||||
CD3DFont::CD3DFont()
|
||||
{
|
||||
m_pTexture = NULL;
|
||||
m_pVB = NULL;
|
||||
}
|
||||
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
|
||||
|
||||
int CD3DFont::Init()
|
||||
{
|
||||
int hr;
|
||||
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
|
||||
// Create a new texture for the font
|
||||
hr = dev->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &m_pTexture, NULL );
|
||||
if( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
// Prepare to create a bitmap
|
||||
int *pBitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
// Create a DC and a bitmap for the font
|
||||
HDC hDC = CreateCompatibleDC( NULL );
|
||||
HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
|
||||
(VOID**)&pBitmapBits, NULL, 0 );
|
||||
SetMapMode( hDC, MM_TEXT );
|
||||
|
||||
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
|
||||
// antialiased font, but this is not guaranteed.
|
||||
// We definitely don't want to get it cleartype'd, anyway.
|
||||
int m_dwFontHeight = 36;
|
||||
|
||||
int nHeight = -MulDiv( m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
|
||||
int dwBold = FW_NORMAL; ///FW_BOLD
|
||||
HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, 0,
|
||||
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
||||
VARIABLE_PITCH, "Tahoma");
|
||||
|
||||
if (NULL == hFont)
|
||||
return E_FAIL;
|
||||
|
||||
HGDIOBJ hOldbmBitmap = SelectObject( hDC, hbmBitmap );
|
||||
HGDIOBJ hOldFont = SelectObject( hDC, hFont );
|
||||
|
||||
// Set text properties
|
||||
SetTextColor( hDC, 0xFFFFFF );
|
||||
SetBkColor ( hDC, 0 );
|
||||
SetTextAlign( hDC, TA_TOP );
|
||||
|
||||
// Loop through all printable character and output them to the bitmap..
|
||||
// Meanwhile, keep track of the corresponding tex coords for each character.
|
||||
int x = 0, y = 0;
|
||||
|
||||
char str[2] = "\0";
|
||||
SIZE size;
|
||||
|
||||
for( char c=0; c<127-32; c++ )
|
||||
{
|
||||
str[0] = c+32;
|
||||
GetTextExtentPoint32( hDC, str, 1, &size );
|
||||
|
||||
if( (int)(x+size.cx+1) > m_dwTexWidth )
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy+1;
|
||||
}
|
||||
|
||||
ExtTextOut( hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL );
|
||||
|
||||
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
|
||||
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
|
||||
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
|
||||
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
|
||||
|
||||
x += size.cx+3; //3 to avoid annoying ij conflict (part of the j ends up with the i)
|
||||
}
|
||||
|
||||
// Lock the surface and write the alpha values for the set pixels
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
|
||||
unsigned short* pDst16 = (unsigned short*)d3dlr.pBits;
|
||||
int bAlpha; // 4-bit measure of pixel intensity
|
||||
|
||||
for( y=0; y < m_dwTexHeight; y++ )
|
||||
{
|
||||
for( x=0; x < m_dwTexWidth; x++ )
|
||||
{
|
||||
bAlpha = ((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
|
||||
*pDst16++ = (bAlpha << 12) | 0x0fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Done updating texture, so clean up used objects
|
||||
m_pTexture->UnlockRect(0);
|
||||
|
||||
SelectObject( hDC, hOldbmBitmap );
|
||||
DeleteObject( hbmBitmap );
|
||||
|
||||
SelectObject( hDC, hOldFont );
|
||||
DeleteObject( hFont );
|
||||
|
||||
// Create vertex buffer for the letters
|
||||
if( FAILED( hr = dev->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
|
||||
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
|
||||
D3DPOOL_DEFAULT, &m_pVB,NULL ) ) )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CD3DFont::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE( m_pVB );
|
||||
SAFE_RELEASE( m_pTexture );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
const int RS[6][2] =
|
||||
{
|
||||
{ D3DRS_ALPHABLENDENABLE, TRUE },
|
||||
{ D3DRS_SRCBLEND, D3DBLEND_SRCALPHA },
|
||||
{ D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA },
|
||||
{ D3DRS_CULLMODE, D3DCULL_NONE },
|
||||
{ D3DRS_ZENABLE, FALSE },
|
||||
{ D3DRS_FOGENABLE, FALSE },
|
||||
};
|
||||
const int TS[6][2] =
|
||||
{
|
||||
{D3DTSS_COLOROP, D3DTOP_MODULATE},
|
||||
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
|
||||
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
|
||||
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
|
||||
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
|
||||
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
|
||||
};
|
||||
|
||||
static DWORD RS_old[6];
|
||||
static DWORD TS_old[6];
|
||||
static LPDIRECT3DBASETEXTURE9 texture_old;
|
||||
static DWORD FVF_old;
|
||||
static LPDIRECT3DVERTEXDECLARATION9 decl_old;
|
||||
static LPDIRECT3DPIXELSHADER9 ps_old;
|
||||
static LPDIRECT3DVERTEXSHADER9 vs_old;
|
||||
|
||||
void SaveRenderStates()
|
||||
{
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dev->GetRenderState((_D3DRENDERSTATETYPE)RS[i][0], &(RS_old[i]));
|
||||
dev->GetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), &(TS_old[i]));
|
||||
}
|
||||
dev->GetTexture(0, &texture_old);
|
||||
dev->GetPixelShader(&ps_old);
|
||||
dev->GetVertexShader(&vs_old);
|
||||
dev->GetVertexDeclaration(&decl_old);
|
||||
dev->GetFVF(&FVF_old);
|
||||
}
|
||||
|
||||
void CD3DFont::SetRenderStates()
|
||||
{
|
||||
// dev->SetTexture(0, m_pTexture);
|
||||
Renderer::SetTexture( 0, m_pTexture );
|
||||
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(0);
|
||||
|
||||
// dev->SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
Renderer::SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0],RS[i][1]);
|
||||
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
|
||||
|
||||
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS[i][1] );
|
||||
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1] );
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreRenderStates()
|
||||
{
|
||||
// dev->SetTexture(0, texture_old);
|
||||
Renderer::SetTexture( 0, texture_old );
|
||||
|
||||
dev->SetPixelShader(ps_old);
|
||||
dev->SetVertexShader(vs_old);
|
||||
dev->SetVertexDeclaration(decl_old);
|
||||
|
||||
// dev->SetFVF(FVF_old);
|
||||
Renderer::SetFVF(FVF_old);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS_old[i]);
|
||||
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i]);
|
||||
|
||||
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS_old[i] );
|
||||
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i] );
|
||||
}
|
||||
}
|
||||
|
||||
int CD3DFont::DrawTextScaled( float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center )
|
||||
{
|
||||
SaveRenderStates();
|
||||
SetRenderStates();
|
||||
dev->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
|
||||
|
||||
float vpWidth = 1;
|
||||
float vpHeight = 1;
|
||||
|
||||
float sx = x*vpWidth-0.5f;
|
||||
float sy = y*vpHeight-0.5f;
|
||||
|
||||
float fStartX = sx;
|
||||
|
||||
float invLineHeight = 1.0f / (( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight);
|
||||
// Fill vertex buffer
|
||||
FONT2DVERTEX* pVertices;
|
||||
int dwNumTriangles = 0L;
|
||||
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
|
||||
|
||||
const char *oldstrText=strText;
|
||||
//First, let's measure the text
|
||||
float tw=0;
|
||||
float mx=0;
|
||||
float maxx=0;
|
||||
|
||||
while( *strText )
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if( c == ('\n') )
|
||||
mx=0;
|
||||
if( c < (' ') )
|
||||
continue;
|
||||
|
||||
float tx1 = m_fTexCoords[c-32][0];
|
||||
float tx2 = m_fTexCoords[c-32][2];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
w *= (fXScale*vpHeight)*invLineHeight;
|
||||
mx += w + spacing*fXScale*vpWidth;
|
||||
if (mx>maxx) maxx=mx;
|
||||
}
|
||||
|
||||
float offset=-maxx/2;
|
||||
strText = oldstrText;
|
||||
//Then let's draw it
|
||||
if (center)
|
||||
{
|
||||
sx+=offset;
|
||||
fStartX+=offset;
|
||||
}
|
||||
|
||||
float wScale=(fXScale*vpHeight)*invLineHeight;
|
||||
float hScale=(fYScale*vpHeight)*invLineHeight;
|
||||
|
||||
while( *strText )
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if( c == ('\n') )
|
||||
{
|
||||
sx = fStartX;
|
||||
sy += fYScale*vpHeight;
|
||||
}
|
||||
if( c < (' ') )
|
||||
continue;
|
||||
|
||||
c-=32;
|
||||
float tx1 = m_fTexCoords[c][0];
|
||||
float ty1 = m_fTexCoords[c][1];
|
||||
float tx2 = m_fTexCoords[c][2];
|
||||
float ty2 = m_fTexCoords[c][3];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
float h = (ty2-ty1)*m_dwTexHeight;
|
||||
|
||||
w *= wScale;
|
||||
h *= hScale;
|
||||
|
||||
|
||||
FONT2DVERTEX v[6];
|
||||
v[0]=InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
|
||||
v[1]=InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
|
||||
v[2]=InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
|
||||
v[3]=InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
|
||||
v[4]=v[2];
|
||||
v[5]=v[1];
|
||||
|
||||
memcpy(pVertices,v,6*sizeof(FONT2DVERTEX));
|
||||
|
||||
pVertices+=6;
|
||||
dwNumTriangles += 2;
|
||||
|
||||
if( dwNumTriangles * 3 > (MAX_NUM_VERTICES-6) )
|
||||
{
|
||||
// Unlock, render, and relock the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
|
||||
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
|
||||
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
|
||||
dwNumTriangles = 0;
|
||||
}
|
||||
|
||||
sx += w + spacing*fXScale*vpWidth;
|
||||
}
|
||||
|
||||
// Unlock and render the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
if( dwNumTriangles > 0 )
|
||||
{
|
||||
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
}
|
||||
RestoreRenderStates();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
|
||||
{
|
||||
SaveRenderStates();
|
||||
struct Q2DVertex { float x,y,z,rhw; u32 color; float u, v; } coords[4] = {
|
||||
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
|
||||
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
|
||||
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
|
||||
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
|
||||
};
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(0);
|
||||
|
||||
// dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
|
||||
// dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
|
||||
Renderer::SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
||||
Renderer::DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
|
||||
|
||||
RestoreRenderStates();
|
||||
}
|
||||
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "Render.h"
|
||||
|
||||
namespace D3D
|
||||
{
|
||||
CD3DFont font;
|
||||
|
||||
#define MAX_NUM_VERTICES 50*6
|
||||
struct FONT2DVERTEX {
|
||||
float x,y,z;
|
||||
float rhw;
|
||||
u32 color;
|
||||
float tu, tv;
|
||||
};
|
||||
|
||||
#define D3DFVF_FONT2DVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1)
|
||||
#define D3DFVF_FONT3DVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE|D3DFVF_NORMAL|D3DFVF_TEX1)
|
||||
|
||||
inline FONT2DVERTEX InitFont2DVertex( float x, float y, u32 color, float tu, float tv )
|
||||
{
|
||||
FONT2DVERTEX v; v.x=x; v.y=y; v.z=0; v.rhw=1.0f; v.color = color; v.tu = tu; v.tv = tv;
|
||||
return v;
|
||||
}
|
||||
|
||||
CD3DFont::CD3DFont()
|
||||
{
|
||||
m_pTexture = NULL;
|
||||
m_pVB = NULL;
|
||||
}
|
||||
enum {m_dwTexWidth = 512, m_dwTexHeight = 512};
|
||||
|
||||
int CD3DFont::Init()
|
||||
{
|
||||
int hr;
|
||||
m_fTextScale = 1.0f; // Draw fonts into texture without scaling
|
||||
// Create a new texture for the font
|
||||
hr = dev->CreateTexture( m_dwTexWidth, m_dwTexHeight, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &m_pTexture, NULL );
|
||||
if( FAILED(hr) )
|
||||
return hr;
|
||||
|
||||
// Prepare to create a bitmap
|
||||
int *pBitmapBits;
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory( &bmi.bmiHeader, sizeof(BITMAPINFOHEADER) );
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = (int)m_dwTexWidth;
|
||||
bmi.bmiHeader.biHeight = -(int)m_dwTexHeight;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
|
||||
// Create a DC and a bitmap for the font
|
||||
HDC hDC = CreateCompatibleDC( NULL );
|
||||
HBITMAP hbmBitmap = CreateDIBSection( hDC, &bmi, DIB_RGB_COLORS,
|
||||
(VOID**)&pBitmapBits, NULL, 0 );
|
||||
SetMapMode( hDC, MM_TEXT );
|
||||
|
||||
// Create a font. By specifying ANTIALIASED_QUALITY, we might get an
|
||||
// antialiased font, but this is not guaranteed.
|
||||
// We definitely don't want to get it cleartype'd, anyway.
|
||||
int m_dwFontHeight = 36;
|
||||
|
||||
int nHeight = -MulDiv( m_dwFontHeight, int(GetDeviceCaps(hDC, LOGPIXELSY) * m_fTextScale), 72 );
|
||||
int dwBold = FW_NORMAL; ///FW_BOLD
|
||||
HFONT hFont = CreateFont( nHeight, 0, 0, 0, dwBold, 0,
|
||||
FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS,
|
||||
CLIP_DEFAULT_PRECIS, ANTIALIASED_QUALITY,
|
||||
VARIABLE_PITCH, "Tahoma");
|
||||
|
||||
if (NULL == hFont)
|
||||
return E_FAIL;
|
||||
|
||||
HGDIOBJ hOldbmBitmap = SelectObject( hDC, hbmBitmap );
|
||||
HGDIOBJ hOldFont = SelectObject( hDC, hFont );
|
||||
|
||||
// Set text properties
|
||||
SetTextColor( hDC, 0xFFFFFF );
|
||||
SetBkColor ( hDC, 0 );
|
||||
SetTextAlign( hDC, TA_TOP );
|
||||
|
||||
// Loop through all printable character and output them to the bitmap..
|
||||
// Meanwhile, keep track of the corresponding tex coords for each character.
|
||||
int x = 0, y = 0;
|
||||
|
||||
char str[2] = "\0";
|
||||
SIZE size;
|
||||
|
||||
for( char c=0; c<127-32; c++ )
|
||||
{
|
||||
str[0] = c+32;
|
||||
GetTextExtentPoint32( hDC, str, 1, &size );
|
||||
|
||||
if( (int)(x+size.cx+1) > m_dwTexWidth )
|
||||
{
|
||||
x = 0;
|
||||
y += size.cy+1;
|
||||
}
|
||||
|
||||
ExtTextOut( hDC, x+1, y+0, ETO_OPAQUE | ETO_CLIPPED, NULL, str, 1, NULL );
|
||||
|
||||
m_fTexCoords[c][0] = ((float)(x+0))/m_dwTexWidth;
|
||||
m_fTexCoords[c][1] = ((float)(y+0))/m_dwTexHeight;
|
||||
m_fTexCoords[c][2] = ((float)(x+0+size.cx))/m_dwTexWidth;
|
||||
m_fTexCoords[c][3] = ((float)(y+0+size.cy))/m_dwTexHeight;
|
||||
|
||||
x += size.cx+3; //3 to avoid annoying ij conflict (part of the j ends up with the i)
|
||||
}
|
||||
|
||||
// Lock the surface and write the alpha values for the set pixels
|
||||
D3DLOCKED_RECT d3dlr;
|
||||
m_pTexture->LockRect( 0, &d3dlr, 0, 0 );
|
||||
unsigned short* pDst16 = (unsigned short*)d3dlr.pBits;
|
||||
int bAlpha; // 4-bit measure of pixel intensity
|
||||
|
||||
for( y=0; y < m_dwTexHeight; y++ )
|
||||
{
|
||||
for( x=0; x < m_dwTexWidth; x++ )
|
||||
{
|
||||
bAlpha = ((pBitmapBits[m_dwTexWidth*y + x] & 0xff) >> 4);
|
||||
*pDst16++ = (bAlpha << 12) | 0x0fff;
|
||||
}
|
||||
}
|
||||
|
||||
// Done updating texture, so clean up used objects
|
||||
m_pTexture->UnlockRect(0);
|
||||
|
||||
SelectObject( hDC, hOldbmBitmap );
|
||||
DeleteObject( hbmBitmap );
|
||||
|
||||
SelectObject( hDC, hOldFont );
|
||||
DeleteObject( hFont );
|
||||
|
||||
// Create vertex buffer for the letters
|
||||
if( FAILED( hr = dev->CreateVertexBuffer( MAX_NUM_VERTICES*sizeof(FONT2DVERTEX),
|
||||
D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC, 0,
|
||||
D3DPOOL_DEFAULT, &m_pVB,NULL ) ) )
|
||||
{
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
int CD3DFont::Shutdown()
|
||||
{
|
||||
SAFE_RELEASE( m_pVB );
|
||||
SAFE_RELEASE( m_pTexture );
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
const int RS[6][2] =
|
||||
{
|
||||
{ D3DRS_ALPHABLENDENABLE, TRUE },
|
||||
{ D3DRS_SRCBLEND, D3DBLEND_SRCALPHA },
|
||||
{ D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA },
|
||||
{ D3DRS_CULLMODE, D3DCULL_NONE },
|
||||
{ D3DRS_ZENABLE, FALSE },
|
||||
{ D3DRS_FOGENABLE, FALSE },
|
||||
};
|
||||
const int TS[6][2] =
|
||||
{
|
||||
{D3DTSS_COLOROP, D3DTOP_MODULATE},
|
||||
{D3DTSS_COLORARG1, D3DTA_TEXTURE},
|
||||
{D3DTSS_COLORARG2, D3DTA_DIFFUSE },
|
||||
{D3DTSS_ALPHAOP, D3DTOP_MODULATE },
|
||||
{D3DTSS_ALPHAARG1, D3DTA_TEXTURE },
|
||||
{D3DTSS_ALPHAARG2, D3DTA_DIFFUSE },
|
||||
};
|
||||
|
||||
static DWORD RS_old[6];
|
||||
static DWORD TS_old[6];
|
||||
static LPDIRECT3DBASETEXTURE9 texture_old;
|
||||
static DWORD FVF_old;
|
||||
static LPDIRECT3DVERTEXDECLARATION9 decl_old;
|
||||
static LPDIRECT3DPIXELSHADER9 ps_old;
|
||||
static LPDIRECT3DVERTEXSHADER9 vs_old;
|
||||
|
||||
void SaveRenderStates()
|
||||
{
|
||||
for (int i = 0; i < 6; i++) {
|
||||
dev->GetRenderState((_D3DRENDERSTATETYPE)RS[i][0], &(RS_old[i]));
|
||||
dev->GetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), &(TS_old[i]));
|
||||
}
|
||||
dev->GetTexture(0, &texture_old);
|
||||
dev->GetPixelShader(&ps_old);
|
||||
dev->GetVertexShader(&vs_old);
|
||||
dev->GetVertexDeclaration(&decl_old);
|
||||
dev->GetFVF(&FVF_old);
|
||||
}
|
||||
|
||||
void CD3DFont::SetRenderStates()
|
||||
{
|
||||
// dev->SetTexture(0, m_pTexture);
|
||||
Renderer::SetTexture( 0, m_pTexture );
|
||||
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(0);
|
||||
|
||||
// dev->SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
Renderer::SetFVF(D3DFVF_FONT2DVERTEX);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0],RS[i][1]);
|
||||
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1]);
|
||||
|
||||
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS[i][1] );
|
||||
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS[i][1] );
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreRenderStates()
|
||||
{
|
||||
// dev->SetTexture(0, texture_old);
|
||||
Renderer::SetTexture( 0, texture_old );
|
||||
|
||||
dev->SetPixelShader(ps_old);
|
||||
dev->SetVertexShader(vs_old);
|
||||
dev->SetVertexDeclaration(decl_old);
|
||||
|
||||
// dev->SetFVF(FVF_old);
|
||||
Renderer::SetFVF(FVF_old);
|
||||
|
||||
for (int i = 0; i < 6; i++)
|
||||
{
|
||||
// dev->SetRenderState((_D3DRENDERSTATETYPE)RS[i][0], RS_old[i]);
|
||||
// dev->SetTextureStageState(0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i]);
|
||||
|
||||
Renderer::SetRenderState( (_D3DRENDERSTATETYPE)RS[i][0], RS_old[i] );
|
||||
Renderer::SetTextureStageState( 0, (_D3DTEXTURESTAGESTATETYPE)int(TS[i][0]), TS_old[i] );
|
||||
}
|
||||
}
|
||||
|
||||
int CD3DFont::DrawTextScaled( float x, float y, float fXScale, float fYScale, float spacing, u32 dwColor, const char* strText, bool center )
|
||||
{
|
||||
SaveRenderStates();
|
||||
SetRenderStates();
|
||||
dev->SetStreamSource( 0, m_pVB, 0, sizeof(FONT2DVERTEX) );
|
||||
|
||||
float vpWidth = 1;
|
||||
float vpHeight = 1;
|
||||
|
||||
float sx = x*vpWidth-0.5f;
|
||||
float sy = y*vpHeight-0.5f;
|
||||
|
||||
float fStartX = sx;
|
||||
|
||||
float invLineHeight = 1.0f / (( m_fTexCoords[0][3] - m_fTexCoords[0][1] ) * m_dwTexHeight);
|
||||
// Fill vertex buffer
|
||||
FONT2DVERTEX* pVertices;
|
||||
int dwNumTriangles = 0L;
|
||||
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
|
||||
|
||||
const char *oldstrText=strText;
|
||||
//First, let's measure the text
|
||||
float tw=0;
|
||||
float mx=0;
|
||||
float maxx=0;
|
||||
|
||||
while( *strText )
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if( c == ('\n') )
|
||||
mx=0;
|
||||
if( c < (' ') )
|
||||
continue;
|
||||
|
||||
float tx1 = m_fTexCoords[c-32][0];
|
||||
float tx2 = m_fTexCoords[c-32][2];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
w *= (fXScale*vpHeight)*invLineHeight;
|
||||
mx += w + spacing*fXScale*vpWidth;
|
||||
if (mx>maxx) maxx=mx;
|
||||
}
|
||||
|
||||
float offset=-maxx/2;
|
||||
strText = oldstrText;
|
||||
//Then let's draw it
|
||||
if (center)
|
||||
{
|
||||
sx+=offset;
|
||||
fStartX+=offset;
|
||||
}
|
||||
|
||||
float wScale=(fXScale*vpHeight)*invLineHeight;
|
||||
float hScale=(fYScale*vpHeight)*invLineHeight;
|
||||
|
||||
while( *strText )
|
||||
{
|
||||
char c = *strText++;
|
||||
|
||||
if( c == ('\n') )
|
||||
{
|
||||
sx = fStartX;
|
||||
sy += fYScale*vpHeight;
|
||||
}
|
||||
if( c < (' ') )
|
||||
continue;
|
||||
|
||||
c-=32;
|
||||
float tx1 = m_fTexCoords[c][0];
|
||||
float ty1 = m_fTexCoords[c][1];
|
||||
float tx2 = m_fTexCoords[c][2];
|
||||
float ty2 = m_fTexCoords[c][3];
|
||||
|
||||
float w = (tx2-tx1)*m_dwTexWidth;
|
||||
float h = (ty2-ty1)*m_dwTexHeight;
|
||||
|
||||
w *= wScale;
|
||||
h *= hScale;
|
||||
|
||||
|
||||
FONT2DVERTEX v[6];
|
||||
v[0]=InitFont2DVertex(sx, sy+h, dwColor, tx1, ty2);
|
||||
v[1]=InitFont2DVertex(sx, sy, dwColor, tx1, ty1);
|
||||
v[2]=InitFont2DVertex(sx+w, sy+h, dwColor, tx2, ty2);
|
||||
v[3]=InitFont2DVertex(sx+w, sy, dwColor, tx2, ty1);
|
||||
v[4]=v[2];
|
||||
v[5]=v[1];
|
||||
|
||||
memcpy(pVertices,v,6*sizeof(FONT2DVERTEX));
|
||||
|
||||
pVertices+=6;
|
||||
dwNumTriangles += 2;
|
||||
|
||||
if( dwNumTriangles * 3 > (MAX_NUM_VERTICES-6) )
|
||||
{
|
||||
// Unlock, render, and relock the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
|
||||
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
|
||||
m_pVB->Lock( 0, 0, (void**)&pVertices, D3DLOCK_DISCARD );
|
||||
dwNumTriangles = 0;
|
||||
}
|
||||
|
||||
sx += w + spacing*fXScale*vpWidth;
|
||||
}
|
||||
|
||||
// Unlock and render the vertex buffer
|
||||
m_pVB->Unlock();
|
||||
if( dwNumTriangles > 0 )
|
||||
{
|
||||
// dev->DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
Renderer::DrawPrimitive( D3DPT_TRIANGLELIST, 0, dwNumTriangles );
|
||||
}
|
||||
RestoreRenderStates();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void quad2d(float x1, float y1, float x2, float y2, u32 color, float u1, float v1, float u2, float v2)
|
||||
{
|
||||
SaveRenderStates();
|
||||
struct Q2DVertex { float x,y,z,rhw; u32 color; float u, v; } coords[4] = {
|
||||
{x1-0.5f, y1-0.5f, 0, 1, color, u1, v1},
|
||||
{x2-0.5f, y1-0.5f, 0, 1, color, u2, v1},
|
||||
{x2-0.5f, y2-0.5f, 0, 1, color, u2, v2},
|
||||
{x1-0.5f, y2-0.5f, 0, 1, color, u1, v2},
|
||||
};
|
||||
dev->SetPixelShader(0);
|
||||
dev->SetVertexShader(0);
|
||||
dev->SetVertexDeclaration(0);
|
||||
|
||||
// dev->SetFVF(D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1);
|
||||
// dev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
|
||||
Renderer::SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1);
|
||||
Renderer::DrawPrimitiveUP(D3DPT_TRIANGLEFAN,2,coords,sizeof(Q2DVertex));
|
||||
|
||||
RestoreRenderStates();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,468 +1,468 @@
|
||||
#include "stdafx.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "DataReader.h"
|
||||
#include "BPStructs.h"
|
||||
#include "CPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "DLCompiler.h"
|
||||
#include "x86.h"
|
||||
#include "main.h"
|
||||
#include "Utils.h"
|
||||
|
||||
CompiledDList::CompiledDList(u32 _addr, u32 _size)
|
||||
{
|
||||
dataSize = 0;
|
||||
data = 0;
|
||||
code = 0;
|
||||
addr = _addr;
|
||||
size = _size;
|
||||
pass = 0;
|
||||
numBatches = 0;
|
||||
batches = 0;
|
||||
}
|
||||
|
||||
CompiledDList::~CompiledDList()
|
||||
{
|
||||
if (data)
|
||||
delete [] data;
|
||||
if (code)
|
||||
delete [] code;
|
||||
if (batches)
|
||||
delete [] batches;
|
||||
}
|
||||
|
||||
|
||||
bool CompiledDList::Call()
|
||||
{
|
||||
switch(pass) {
|
||||
case 0: // First compiling pass : find data size
|
||||
if (Pass1())
|
||||
{
|
||||
pass = 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
case 1: // Second compiling pass : actually compile
|
||||
//if pass1 succeeded, pass2 will too
|
||||
Pass2();
|
||||
pass = 2;
|
||||
return true;
|
||||
case 2: // Run pass - we have a compiled dlist, just call it
|
||||
Run();
|
||||
return true;
|
||||
default:
|
||||
//ERROR
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CompiledDList::Pass1()
|
||||
{
|
||||
/* //find the size of code + data, if the dlist is worth recompiling etc
|
||||
// at the same time, do the ordinary stuff
|
||||
g_pDataReader = &dlistReader;
|
||||
OpcodeReaders::SetDListReader(addr, addr+size);
|
||||
dataSize = 0;
|
||||
codeSize = 0;
|
||||
numBatches = 0;
|
||||
bool lastIsPrim = false;
|
||||
while (OpcodeReaders::IsDListOKToRead())
|
||||
{
|
||||
int Cmd = g_pDataReader->Read8();
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = g_pDataReader->Read8();
|
||||
u32 Value = g_pDataReader->Read32();
|
||||
LoadCPReg(SubCmd,Value);
|
||||
//COMPILER
|
||||
codeSize+=13;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = g_pDataReader->Read32();
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
DWORD dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
pData[i] = g_pDataReader->Read32();
|
||||
LoadXFReg(dwTransferSize,dwAddress,pData);
|
||||
//COMPILER
|
||||
dataSize+=dwTransferSize;
|
||||
codeSize+=17;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd=g_pDataReader->Read32();
|
||||
LoadBPReg(cmd);
|
||||
codeSize+=9;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xC);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xD);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xE);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xF);
|
||||
codeSize+=13;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
MessageBox(0,"Display lists can't recurse!!","error",0);
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
break;
|
||||
case GX_NOP:
|
||||
break;
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
if (lastIsPrim)
|
||||
{
|
||||
//join to last
|
||||
}
|
||||
else
|
||||
{
|
||||
//finish up last and commit
|
||||
}
|
||||
u16 numVertices = g_pDataReader->Read16();
|
||||
tempvarray.Reset();
|
||||
VertexLoader::SetVArray(&tempvarray);
|
||||
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
|
||||
loader->Setup();
|
||||
loader->PrepareRun();
|
||||
int vsize = loader->GetVertexSize();
|
||||
loader->RunVertices(numVertices);
|
||||
CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray);
|
||||
CVertexHandler::Flush();
|
||||
//COMPILER
|
||||
codeSize+=21;
|
||||
numBatches++;
|
||||
lastIsPrim = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastIsPrim)
|
||||
{
|
||||
//finish up last and commit
|
||||
}
|
||||
codeSize*=2;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CompiledDList::Pass2()
|
||||
{
|
||||
/* OpcodeReaders::SetDListReader(addr, addr+size);
|
||||
|
||||
data = new u32[dataSize];
|
||||
code = new u8[codeSize]; //at least
|
||||
|
||||
batches = new Batch[numBatches];
|
||||
int batchCount = 0;
|
||||
u32 *dataptr = data;
|
||||
|
||||
x86Init();
|
||||
x86SetPtr((s8*)code);
|
||||
//WC8(0xCC);
|
||||
|
||||
//actually do the recompiling, emit code and data, protect the memory
|
||||
// but again, at the same time do the ordinary stuff
|
||||
// so the compiled display list won't be run until the third time actually
|
||||
bool dump = false,lastIsGeom=false;
|
||||
FILE *f;
|
||||
|
||||
#ifndef TEASER
|
||||
if (dump)
|
||||
{
|
||||
f=fopen("D:\\dlistlogs.txt","a");
|
||||
fprintf(f,"===========================================\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
while (OpcodeReaders::IsDListOKToRead())
|
||||
{
|
||||
int Cmd = g_pDataReader->Read8();
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 SubCmd = g_pDataReader->Read8();
|
||||
u32 Value = g_pDataReader->Read32();
|
||||
if (dump)
|
||||
fprintf(f,"CP | %02x %08x\n",SubCmd,Value);
|
||||
|
||||
LoadCPReg(SubCmd,Value);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(Value);
|
||||
PUSH_WordToStack(SubCmd);
|
||||
CALLFunc((u32)LoadCPReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 Cmd2 = g_pDataReader->Read32();
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
u32 dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
|
||||
u32 *oldDataPtr = dataptr;
|
||||
|
||||
if (dump)
|
||||
{
|
||||
fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress);
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
fprintf(f, "%08x | %f\n",oldDataPtr[i], *((float*)oldDataPtr+i));
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<dwTransferSize; i++) // a little compiler here too
|
||||
*dataptr++ = g_pDataReader->Read32();
|
||||
|
||||
|
||||
LoadXFReg(dwTransferSize,dwAddress,oldDataPtr);
|
||||
|
||||
//COMPILER
|
||||
PUSH_WordToStack((u32)oldDataPtr);
|
||||
PUSH_WordToStack(dwAddress);
|
||||
PUSH_WordToStack(dwTransferSize);
|
||||
CALLFunc((u32)LoadXFReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 cmd=g_pDataReader->Read32();
|
||||
if (dump)
|
||||
fprintf(f,"BP | %08x\n",cmd);
|
||||
|
||||
LoadBPReg(cmd);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(cmd);
|
||||
CALLFunc((u32)LoadBPReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //usually used for position matrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xC);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xC);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXA | pos matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //usually used for normal matrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xD);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xD);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXB | nrm matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //usually used for postmatrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xE);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xE);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXC | post matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //usually used for lights
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xF);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xF);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXD | light\n");
|
||||
}
|
||||
break;
|
||||
case GX_CMD_CALL_DL:
|
||||
// ERORRR
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
if (dump)
|
||||
fprintf(f,"invalidate vc\n");
|
||||
break;
|
||||
case GX_NOP:
|
||||
if (dump)
|
||||
fprintf(f,"nop\n");
|
||||
break;
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
//if (lastIsGeom) INCSTAT(stats.numJoins);
|
||||
u16 numVertices = g_pDataReader->Read16();
|
||||
if (dump)
|
||||
fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices);
|
||||
DecodedVArray &va = batches[batchCount].varray;
|
||||
|
||||
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
|
||||
TVtxDesc &vd = loader->GetVtxDesc();
|
||||
|
||||
VertexLoader::SetVArray(&va);
|
||||
loader->Setup();
|
||||
loader->PrepareRun();
|
||||
// va.numColors = loader->GetNumColors();
|
||||
// va.numUVs = loader->GetNumTCs();
|
||||
// va.numNormals = loader->GetNumNormals();
|
||||
//va.num
|
||||
va.Create(numVertices,vd.PosMatIdx,
|
||||
vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+
|
||||
vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx,
|
||||
va.numNormals, va.numColors, va.numTCs);
|
||||
|
||||
int vsize = loader->GetVertexSize();
|
||||
loader->RunVertices(numVertices);
|
||||
CVertexHandler::DrawVertices(primitive, numVertices, &va);
|
||||
CVertexHandler::Flush();
|
||||
// YES we have now filled our varray
|
||||
//LETS COMPILE
|
||||
PUSH_WordToStack(primitive);
|
||||
PUSH_WordToStack(batchCount);
|
||||
PUSH_WordToStack((u32)this);
|
||||
CALLFunc((u32)DrawHelperHelper);
|
||||
batchCount++;
|
||||
lastIsGeom = true;
|
||||
if (dump)
|
||||
fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dump)
|
||||
{
|
||||
fprintf(f,"***************************************\n\n\n");
|
||||
}
|
||||
RET();
|
||||
if (dump)
|
||||
fclose(f);*/
|
||||
//we're done, next time just kick the compiled list off, much much faster than interpreting!
|
||||
}
|
||||
|
||||
void CompiledDList::DrawHelperHelper(CompiledDList *dl, int vno, int prim)
|
||||
{
|
||||
Batch &b = dl->batches[vno];
|
||||
CVertexHandler::DrawVertices(prim, b.varray.GetSize(), &b.varray);
|
||||
}
|
||||
|
||||
void CompiledDList::Run()
|
||||
{
|
||||
//run the code
|
||||
((void (*)())(code))();
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
|
||||
DListCache::DLCache DListCache::dlists;
|
||||
|
||||
|
||||
|
||||
void DListCache::Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DListCache::Shutdown()
|
||||
{
|
||||
DLCache::iterator iter = dlists.begin();
|
||||
for (;iter!=dlists.end();iter++)
|
||||
iter->second.Destroy();
|
||||
dlists.clear();
|
||||
}
|
||||
|
||||
|
||||
void DListCache::Call(u32 _addr, u32 _size)
|
||||
{
|
||||
DLCache::iterator iter;
|
||||
iter = dlists.find(_addr);
|
||||
|
||||
if (iter != dlists.end())
|
||||
{
|
||||
if (iter->second.size == _size)
|
||||
{
|
||||
iter->second.dlist->Call();
|
||||
return;
|
||||
}
|
||||
else // wrong size, need to recompile
|
||||
{
|
||||
iter->second.Destroy();
|
||||
iter=dlists.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
DLCacheEntry entry;
|
||||
entry.dlist = new CompiledDList(_addr, _size);
|
||||
entry.dlist->Call();
|
||||
entry.frameCount = frameCount;
|
||||
entry.size = _size;
|
||||
dlists[_addr] = entry;
|
||||
|
||||
INCSTAT(stats.numDListsCreated);
|
||||
SETSTAT(stats.numDListsAlive,(int)dlists.size());
|
||||
}
|
||||
|
||||
void DListCache::Cleanup()
|
||||
{
|
||||
for (DLCache::iterator iter=dlists.begin(); iter!=dlists.end();iter++)
|
||||
{
|
||||
DLCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount<frameCount-80)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = dlists.erase(iter);
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numDListsAlive,(int)dlists.size());
|
||||
}
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#if 0
|
||||
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexHandler.h"
|
||||
#include "DataReader.h"
|
||||
#include "BPStructs.h"
|
||||
#include "CPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "DLCompiler.h"
|
||||
#include "x86.h"
|
||||
#include "main.h"
|
||||
#include "Utils.h"
|
||||
|
||||
CompiledDList::CompiledDList(u32 _addr, u32 _size)
|
||||
{
|
||||
dataSize = 0;
|
||||
data = 0;
|
||||
code = 0;
|
||||
addr = _addr;
|
||||
size = _size;
|
||||
pass = 0;
|
||||
numBatches = 0;
|
||||
batches = 0;
|
||||
}
|
||||
|
||||
CompiledDList::~CompiledDList()
|
||||
{
|
||||
if (data)
|
||||
delete [] data;
|
||||
if (code)
|
||||
delete [] code;
|
||||
if (batches)
|
||||
delete [] batches;
|
||||
}
|
||||
|
||||
|
||||
bool CompiledDList::Call()
|
||||
{
|
||||
switch(pass) {
|
||||
case 0: // First compiling pass : find data size
|
||||
if (Pass1())
|
||||
{
|
||||
pass = 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
case 1: // Second compiling pass : actually compile
|
||||
//if pass1 succeeded, pass2 will too
|
||||
Pass2();
|
||||
pass = 2;
|
||||
return true;
|
||||
case 2: // Run pass - we have a compiled dlist, just call it
|
||||
Run();
|
||||
return true;
|
||||
default:
|
||||
//ERROR
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CompiledDList::Pass1()
|
||||
{
|
||||
/* //find the size of code + data, if the dlist is worth recompiling etc
|
||||
// at the same time, do the ordinary stuff
|
||||
g_pDataReader = &dlistReader;
|
||||
OpcodeReaders::SetDListReader(addr, addr+size);
|
||||
dataSize = 0;
|
||||
codeSize = 0;
|
||||
numBatches = 0;
|
||||
bool lastIsPrim = false;
|
||||
while (OpcodeReaders::IsDListOKToRead())
|
||||
{
|
||||
int Cmd = g_pDataReader->Read8();
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u32 SubCmd = g_pDataReader->Read8();
|
||||
u32 Value = g_pDataReader->Read32();
|
||||
LoadCPReg(SubCmd,Value);
|
||||
//COMPILER
|
||||
codeSize+=13;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = g_pDataReader->Read32();
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
DWORD dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
pData[i] = g_pDataReader->Read32();
|
||||
LoadXFReg(dwTransferSize,dwAddress,pData);
|
||||
//COMPILER
|
||||
dataSize+=dwTransferSize;
|
||||
codeSize+=17;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd=g_pDataReader->Read32();
|
||||
LoadBPReg(cmd);
|
||||
codeSize+=9;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xC);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xD);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xE);
|
||||
codeSize+=13;
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(g_pDataReader->Read32(),0xF);
|
||||
codeSize+=13;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
MessageBox(0,"Display lists can't recurse!!","error",0);
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
break;
|
||||
case GX_NOP:
|
||||
break;
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
if (lastIsPrim)
|
||||
{
|
||||
//join to last
|
||||
}
|
||||
else
|
||||
{
|
||||
//finish up last and commit
|
||||
}
|
||||
u16 numVertices = g_pDataReader->Read16();
|
||||
tempvarray.Reset();
|
||||
VertexLoader::SetVArray(&tempvarray);
|
||||
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
|
||||
loader->Setup();
|
||||
loader->PrepareRun();
|
||||
int vsize = loader->GetVertexSize();
|
||||
loader->RunVertices(numVertices);
|
||||
CVertexHandler::DrawVertices(primitive, numVertices, &tempvarray);
|
||||
CVertexHandler::Flush();
|
||||
//COMPILER
|
||||
codeSize+=21;
|
||||
numBatches++;
|
||||
lastIsPrim = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lastIsPrim)
|
||||
{
|
||||
//finish up last and commit
|
||||
}
|
||||
codeSize*=2;*/
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CompiledDList::Pass2()
|
||||
{
|
||||
/* OpcodeReaders::SetDListReader(addr, addr+size);
|
||||
|
||||
data = new u32[dataSize];
|
||||
code = new u8[codeSize]; //at least
|
||||
|
||||
batches = new Batch[numBatches];
|
||||
int batchCount = 0;
|
||||
u32 *dataptr = data;
|
||||
|
||||
x86Init();
|
||||
x86SetPtr((s8*)code);
|
||||
//WC8(0xCC);
|
||||
|
||||
//actually do the recompiling, emit code and data, protect the memory
|
||||
// but again, at the same time do the ordinary stuff
|
||||
// so the compiled display list won't be run until the third time actually
|
||||
bool dump = false,lastIsGeom=false;
|
||||
FILE *f;
|
||||
|
||||
#ifndef TEASER
|
||||
if (dump)
|
||||
{
|
||||
f=fopen("D:\\dlistlogs.txt","a");
|
||||
fprintf(f,"===========================================\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
while (OpcodeReaders::IsDListOKToRead())
|
||||
{
|
||||
int Cmd = g_pDataReader->Read8();
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 SubCmd = g_pDataReader->Read8();
|
||||
u32 Value = g_pDataReader->Read32();
|
||||
if (dump)
|
||||
fprintf(f,"CP | %02x %08x\n",SubCmd,Value);
|
||||
|
||||
LoadCPReg(SubCmd,Value);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(Value);
|
||||
PUSH_WordToStack(SubCmd);
|
||||
CALLFunc((u32)LoadCPReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 Cmd2 = g_pDataReader->Read32();
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
u32 dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
|
||||
u32 *oldDataPtr = dataptr;
|
||||
|
||||
if (dump)
|
||||
{
|
||||
fprintf(f,"XF | %01xx %04x\n",dwTransferSize,dwAddress);
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
fprintf(f, "%08x | %f\n",oldDataPtr[i], *((float*)oldDataPtr+i));
|
||||
}
|
||||
|
||||
|
||||
for (int i=0; i<dwTransferSize; i++) // a little compiler here too
|
||||
*dataptr++ = g_pDataReader->Read32();
|
||||
|
||||
|
||||
LoadXFReg(dwTransferSize,dwAddress,oldDataPtr);
|
||||
|
||||
//COMPILER
|
||||
PUSH_WordToStack((u32)oldDataPtr);
|
||||
PUSH_WordToStack(dwAddress);
|
||||
PUSH_WordToStack(dwTransferSize);
|
||||
CALLFunc((u32)LoadXFReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 cmd=g_pDataReader->Read32();
|
||||
if (dump)
|
||||
fprintf(f,"BP | %08x\n",cmd);
|
||||
|
||||
LoadBPReg(cmd);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(cmd);
|
||||
CALLFunc((u32)LoadBPReg);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //usually used for position matrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xC);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xC);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXA | pos matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //usually used for normal matrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xD);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xD);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXB | nrm matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //usually used for postmatrices
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xE);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xE);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXC | post matrix\n");
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //usually used for lights
|
||||
{
|
||||
lastIsGeom = false;
|
||||
u32 value = g_pDataReader->Read32();
|
||||
LoadIndexedXF(value,0xF);
|
||||
//COMPILER
|
||||
PUSH_WordToStack(0xF);
|
||||
PUSH_WordToStack(value);
|
||||
CALLFunc((u32)LoadIndexedXF);
|
||||
if (dump)
|
||||
fprintf(f,"LOADINDEXD | light\n");
|
||||
}
|
||||
break;
|
||||
case GX_CMD_CALL_DL:
|
||||
// ERORRR
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
if (dump)
|
||||
fprintf(f,"invalidate vc\n");
|
||||
break;
|
||||
case GX_NOP:
|
||||
if (dump)
|
||||
fprintf(f,"nop\n");
|
||||
break;
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
int primitive = (Cmd&GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
//if (lastIsGeom) INCSTAT(stats.numJoins);
|
||||
u16 numVertices = g_pDataReader->Read16();
|
||||
if (dump)
|
||||
fprintf(f,"DP: prim=%02x numv=%i\n",primitive,numVertices);
|
||||
DecodedVArray &va = batches[batchCount].varray;
|
||||
|
||||
VertexLoader *loader = &VertexLoader[Cmd&GX_VAT_MASK];
|
||||
TVtxDesc &vd = loader->GetVtxDesc();
|
||||
|
||||
VertexLoader::SetVArray(&va);
|
||||
loader->Setup();
|
||||
loader->PrepareRun();
|
||||
// va.numColors = loader->GetNumColors();
|
||||
// va.numUVs = loader->GetNumTCs();
|
||||
// va.numNormals = loader->GetNumNormals();
|
||||
//va.num
|
||||
va.Create(numVertices,vd.PosMatIdx,
|
||||
vd.Tex0MatIdx+vd.Tex1MatIdx+vd.Tex2MatIdx+vd.Tex3MatIdx+
|
||||
vd.Tex4MatIdx+vd.Tex5MatIdx+vd.Tex6MatIdx+vd.Tex7MatIdx,
|
||||
va.numNormals, va.numColors, va.numTCs);
|
||||
|
||||
int vsize = loader->GetVertexSize();
|
||||
loader->RunVertices(numVertices);
|
||||
CVertexHandler::DrawVertices(primitive, numVertices, &va);
|
||||
CVertexHandler::Flush();
|
||||
// YES we have now filled our varray
|
||||
//LETS COMPILE
|
||||
PUSH_WordToStack(primitive);
|
||||
PUSH_WordToStack(batchCount);
|
||||
PUSH_WordToStack((u32)this);
|
||||
CALLFunc((u32)DrawHelperHelper);
|
||||
batchCount++;
|
||||
lastIsGeom = true;
|
||||
if (dump)
|
||||
fprintf(f,"DRAW PRIMITIVE: prim=%02x numv=%i\n",primitive,numVertices);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dump)
|
||||
{
|
||||
fprintf(f,"***************************************\n\n\n");
|
||||
}
|
||||
RET();
|
||||
if (dump)
|
||||
fclose(f);*/
|
||||
//we're done, next time just kick the compiled list off, much much faster than interpreting!
|
||||
}
|
||||
|
||||
void CompiledDList::DrawHelperHelper(CompiledDList *dl, int vno, int prim)
|
||||
{
|
||||
Batch &b = dl->batches[vno];
|
||||
CVertexHandler::DrawVertices(prim, b.varray.GetSize(), &b.varray);
|
||||
}
|
||||
|
||||
void CompiledDList::Run()
|
||||
{
|
||||
//run the code
|
||||
((void (*)())(code))();
|
||||
CVertexHandler::Flush();
|
||||
}
|
||||
|
||||
DListCache::DLCache DListCache::dlists;
|
||||
|
||||
|
||||
|
||||
void DListCache::Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void DListCache::Shutdown()
|
||||
{
|
||||
DLCache::iterator iter = dlists.begin();
|
||||
for (;iter!=dlists.end();iter++)
|
||||
iter->second.Destroy();
|
||||
dlists.clear();
|
||||
}
|
||||
|
||||
|
||||
void DListCache::Call(u32 _addr, u32 _size)
|
||||
{
|
||||
DLCache::iterator iter;
|
||||
iter = dlists.find(_addr);
|
||||
|
||||
if (iter != dlists.end())
|
||||
{
|
||||
if (iter->second.size == _size)
|
||||
{
|
||||
iter->second.dlist->Call();
|
||||
return;
|
||||
}
|
||||
else // wrong size, need to recompile
|
||||
{
|
||||
iter->second.Destroy();
|
||||
iter=dlists.erase(iter);
|
||||
}
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
DLCacheEntry entry;
|
||||
entry.dlist = new CompiledDList(_addr, _size);
|
||||
entry.dlist->Call();
|
||||
entry.frameCount = frameCount;
|
||||
entry.size = _size;
|
||||
dlists[_addr] = entry;
|
||||
|
||||
INCSTAT(stats.numDListsCreated);
|
||||
SETSTAT(stats.numDListsAlive,(int)dlists.size());
|
||||
}
|
||||
|
||||
void DListCache::Cleanup()
|
||||
{
|
||||
for (DLCache::iterator iter=dlists.begin(); iter!=dlists.end();iter++)
|
||||
{
|
||||
DLCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount<frameCount-80)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = dlists.erase(iter);
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numDListsAlive,(int)dlists.size());
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,92 +1,92 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
DecodedVArray::DecodedVArray()
|
||||
{
|
||||
Zero();
|
||||
}
|
||||
|
||||
DecodedVArray::~DecodedVArray()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void DecodedVArray::Zero()
|
||||
{
|
||||
size = 0;
|
||||
count = 0;
|
||||
components = 0;
|
||||
positions = 0;
|
||||
posMtxInds = 0;
|
||||
for (int i=0; i<3; i++)
|
||||
normals[i] = 0;
|
||||
for (int i=0; i<2; i++)
|
||||
colors[i] = 0;
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
texMtxInds[i] = 0;
|
||||
uvs[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DecodedVArray::Destroy()
|
||||
{
|
||||
//,,
|
||||
delete [] positions;
|
||||
delete [] posMtxInds;
|
||||
for (int i=0; i<3; i++)
|
||||
delete [] normals[i];
|
||||
for (int i=0; i<2; i++)
|
||||
delete [] colors[i];
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
delete [] uvs[i];
|
||||
delete [] texMtxInds[i];
|
||||
}
|
||||
Zero();
|
||||
}
|
||||
|
||||
void DecodedVArray::Create(int _size, int pmcount, int tmcount, int nrmcount, int colcount, int tccount)
|
||||
{
|
||||
size = _size;
|
||||
// position matrix indices
|
||||
if (pmcount)
|
||||
posMtxInds = new DecMtxInd[size];
|
||||
// texture matrix indices
|
||||
if (tmcount)
|
||||
for (int i=0; i<tmcount; i++)
|
||||
texMtxInds[i] = new DecMtxInd[size];
|
||||
// positions (always)
|
||||
positions = new DecPos[size];
|
||||
// normals
|
||||
if (nrmcount)
|
||||
for (int i=0; i<nrmcount; i++)
|
||||
normals[i] = new DecNormal[size];
|
||||
// colors
|
||||
if (colcount)
|
||||
for (int i=0; i<colcount; i++)
|
||||
colors[i] = new DecColor[size];
|
||||
|
||||
if (tccount)
|
||||
for (int i=0; i<tccount; i++)
|
||||
uvs[i] = new DecUV[size];
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
#include "main.h"
|
||||
|
||||
DecodedVArray::DecodedVArray()
|
||||
{
|
||||
Zero();
|
||||
}
|
||||
|
||||
DecodedVArray::~DecodedVArray()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void DecodedVArray::Zero()
|
||||
{
|
||||
size = 0;
|
||||
count = 0;
|
||||
components = 0;
|
||||
positions = 0;
|
||||
posMtxInds = 0;
|
||||
for (int i=0; i<3; i++)
|
||||
normals[i] = 0;
|
||||
for (int i=0; i<2; i++)
|
||||
colors[i] = 0;
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
texMtxInds[i] = 0;
|
||||
uvs[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void DecodedVArray::Destroy()
|
||||
{
|
||||
//,,
|
||||
delete [] positions;
|
||||
delete [] posMtxInds;
|
||||
for (int i=0; i<3; i++)
|
||||
delete [] normals[i];
|
||||
for (int i=0; i<2; i++)
|
||||
delete [] colors[i];
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
delete [] uvs[i];
|
||||
delete [] texMtxInds[i];
|
||||
}
|
||||
Zero();
|
||||
}
|
||||
|
||||
void DecodedVArray::Create(int _size, int pmcount, int tmcount, int nrmcount, int colcount, int tccount)
|
||||
{
|
||||
size = _size;
|
||||
// position matrix indices
|
||||
if (pmcount)
|
||||
posMtxInds = new DecMtxInd[size];
|
||||
// texture matrix indices
|
||||
if (tmcount)
|
||||
for (int i=0; i<tmcount; i++)
|
||||
texMtxInds[i] = new DecMtxInd[size];
|
||||
// positions (always)
|
||||
positions = new DecPos[size];
|
||||
// normals
|
||||
if (nrmcount)
|
||||
for (int i=0; i<nrmcount; i++)
|
||||
normals[i] = new DecNormal[size];
|
||||
// colors
|
||||
if (colcount)
|
||||
for (int i=0; i<colcount; i++)
|
||||
colors[i] = new DecColor[size];
|
||||
|
||||
if (tccount)
|
||||
for (int i=0; i<tccount; i++)
|
||||
uvs[i] = new DecUV[size];
|
||||
}
|
||||
|
||||
@@ -1,246 +1,246 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "resource.h"
|
||||
#include "W32Util/PropertySheet.h"
|
||||
#include "W32Util/ShellUtil.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DPostprocess.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "TextureCache.h"
|
||||
|
||||
#define NUMWNDRES 6
|
||||
int g_Res[NUMWNDRES][2] =
|
||||
{
|
||||
{640,480},
|
||||
{800,600},
|
||||
{1024,768},
|
||||
{1280,960},
|
||||
{1280,1024},
|
||||
{1600,1200},
|
||||
};
|
||||
|
||||
struct TabDirect3D : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
for (int i=0; i<D3D::GetNumAdapters(); i++)
|
||||
{
|
||||
const D3D::Adapter &adapter = D3D::GetAdapter(i);
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_ADAPTER),adapter.ident.Description);
|
||||
}
|
||||
|
||||
const D3D::Adapter &adapter = D3D::GetAdapter(g_Config.iAdapter);
|
||||
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ADAPTER),g_Config.iAdapter);
|
||||
|
||||
for (int i = 0; i < (int)adapter.aa_levels.size(); i++)
|
||||
{
|
||||
ComboBox_AddString(GetDlgItem(hDlg, IDC_ANTIALIASMODE), adapter.aa_levels[i].name);
|
||||
}
|
||||
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE), g_Config.iMultisampleMode);
|
||||
if (adapter.aa_levels.size() == 1)
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_ANTIALIASMODE), FALSE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)adapter.resolutions.size(); i++)
|
||||
{
|
||||
const D3D::Resolution &r = adapter.resolutions[i];
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTION), r.name);
|
||||
}
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION), g_Config.iFSResolution);
|
||||
|
||||
for (int i = 0; i < NUMWNDRES; i++)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%ix%i",g_Res[i][0],g_Res[i][1]);
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),temp);
|
||||
}
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),g_Config.iWindowedRes);
|
||||
|
||||
CheckDlgButton(hDlg, IDC_FULLSCREENENABLE, g_Config.bFullscreen ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_VSYNC, g_Config.bVsync ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_RENDER_TO_MAINWINDOW, g_Config.renderToMainframe ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.iAdapter = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ADAPTER));
|
||||
g_Config.iWindowedRes = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_RESOLUTIONWINDOWED));
|
||||
g_Config.iMultisampleMode = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE));
|
||||
g_Config.iFSResolution = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION));
|
||||
g_Config.bFullscreen = Button_GetCheck(GetDlgItem(hDlg, IDC_FULLSCREENENABLE)) ? true : false;
|
||||
g_Config.bVsync = Button_GetCheck(GetDlgItem(hDlg, IDC_VSYNC)) ? true : false;
|
||||
g_Config.renderToMainframe = Button_GetCheck(GetDlgItem(hDlg, IDC_RENDER_TO_MAINWINDOW)) ? true : false;
|
||||
g_Config.Save();
|
||||
}
|
||||
};
|
||||
|
||||
struct TabAdvanced : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
HWND opt = GetDlgItem(hDlg,IDC_DLOPTLEVEL);
|
||||
ComboBox_AddString(opt,"0: Interpret (slowest, most compatible)");
|
||||
ComboBox_AddString(opt,"1: Compile lists and decode vertex lists");
|
||||
//ComboBox_AddString(opt,"2: Compile+decode to vbufs and use hw xform");
|
||||
//ComboBox_AddString(opt,"Recompile to vbuffers and shaders");
|
||||
ComboBox_SetCurSel(opt,g_Config.iCompileDLsLevel);
|
||||
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS), g_Config.bOverlayStats);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_WIREFRAME), g_Config.bWireFrame);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXDUMP), g_Config.bDumpTextures);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS), g_Config.bShowShaderErrors);
|
||||
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY), g_Config.bTexFmtOverlayEnable);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), g_Config.bTexFmtOverlayCenter);
|
||||
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
|
||||
|
||||
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),g_Config.texDumpPath.c_str());
|
||||
Edit_LimitText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),255);
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_BROWSETEXDUMPPATH:
|
||||
{
|
||||
std::string path = W32Util::BrowseForFolder(hDlg,"Choose texture dump path:");
|
||||
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),path.c_str());
|
||||
}
|
||||
break;
|
||||
case IDC_TEXFMT_OVERLAY:
|
||||
{
|
||||
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.bTexFmtOverlayEnable = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? true : false;
|
||||
g_Config.bTexFmtOverlayCenter = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER)) ? true : false;
|
||||
|
||||
g_Config.bOverlayStats = Button_GetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS)) ? true : false;
|
||||
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg,IDC_WIREFRAME)) ? true : false;
|
||||
g_Config.bDumpTextures = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXDUMP)) ? true : false;
|
||||
g_Config.iCompileDLsLevel = (int)ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_DLOPTLEVEL));
|
||||
g_Config.bShowShaderErrors = Button_GetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS)) ? true : false;
|
||||
char temp[MAX_PATH];
|
||||
GetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH), temp, MAX_PATH);
|
||||
g_Config.texDumpPath = temp;
|
||||
}
|
||||
};
|
||||
|
||||
struct TabDebug : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TabEnhancements : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING),g_Config.bForceFiltering);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEANISOTROPY),g_Config.bForceMaxAniso);
|
||||
HWND pp = GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT);
|
||||
const char **names = Postprocess::GetPostprocessingNames();
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!names[i])
|
||||
break;
|
||||
|
||||
ComboBox_AddString(pp, names[i]);
|
||||
i++;
|
||||
}
|
||||
ComboBox_SetCurSel(pp, g_Config.iPostprocessEffect);
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.bForceMaxAniso = Button_GetCheck(GetDlgItem(hDlg, IDC_FORCEANISOTROPY)) ? true : false;
|
||||
g_Config.bForceFiltering = Button_GetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING)) ? true : false;
|
||||
g_Config.iPostprocessEffect = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void DlgSettings_Show(HINSTANCE hInstance, HWND _hParent)
|
||||
{
|
||||
bool tfoe = g_Config.bTexFmtOverlayEnable;
|
||||
bool tfoc = g_Config.bTexFmtOverlayCenter;
|
||||
|
||||
g_Config.Load();
|
||||
W32Util::PropSheet sheet;
|
||||
sheet.Add(new TabDirect3D,(LPCTSTR)IDD_SETTINGS,"Direct3D");
|
||||
sheet.Add(new TabEnhancements,(LPCTSTR)IDD_ENHANCEMENTS,"Enhancements");
|
||||
sheet.Add(new TabAdvanced,(LPCTSTR)IDD_ADVANCED,"Advanced");
|
||||
//sheet.Add(new TabDebug,(LPCTSTR)IDD_DEBUGGER,"Debugger");
|
||||
sheet.Show(hInstance,_hParent,"Graphics Plugin");
|
||||
g_Config.Save();
|
||||
|
||||
if(( tfoe != g_Config.bTexFmtOverlayEnable) ||
|
||||
((g_Config.bTexFmtOverlayEnable) && ( tfoc != g_Config.bTexFmtOverlayCenter)))
|
||||
{
|
||||
TextureCache::Invalidate();
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <windowsx.h>
|
||||
|
||||
#include "resource.h"
|
||||
#include "W32Util/PropertySheet.h"
|
||||
#include "W32Util/ShellUtil.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DPostprocess.h"
|
||||
|
||||
#include "Config.h"
|
||||
|
||||
#include "TextureCache.h"
|
||||
|
||||
#define NUMWNDRES 6
|
||||
int g_Res[NUMWNDRES][2] =
|
||||
{
|
||||
{640,480},
|
||||
{800,600},
|
||||
{1024,768},
|
||||
{1280,960},
|
||||
{1280,1024},
|
||||
{1600,1200},
|
||||
};
|
||||
|
||||
struct TabDirect3D : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
for (int i=0; i<D3D::GetNumAdapters(); i++)
|
||||
{
|
||||
const D3D::Adapter &adapter = D3D::GetAdapter(i);
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_ADAPTER),adapter.ident.Description);
|
||||
}
|
||||
|
||||
const D3D::Adapter &adapter = D3D::GetAdapter(g_Config.iAdapter);
|
||||
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ADAPTER),g_Config.iAdapter);
|
||||
|
||||
for (int i = 0; i < (int)adapter.aa_levels.size(); i++)
|
||||
{
|
||||
ComboBox_AddString(GetDlgItem(hDlg, IDC_ANTIALIASMODE), adapter.aa_levels[i].name);
|
||||
}
|
||||
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE), g_Config.iMultisampleMode);
|
||||
if (adapter.aa_levels.size() == 1)
|
||||
{
|
||||
EnableWindow(GetDlgItem(hDlg, IDC_ANTIALIASMODE), FALSE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < (int)adapter.resolutions.size(); i++)
|
||||
{
|
||||
const D3D::Resolution &r = adapter.resolutions[i];
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTION), r.name);
|
||||
}
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION), g_Config.iFSResolution);
|
||||
|
||||
for (int i = 0; i < NUMWNDRES; i++)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%ix%i",g_Res[i][0],g_Res[i][1]);
|
||||
ComboBox_AddString(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),temp);
|
||||
}
|
||||
ComboBox_SetCurSel(GetDlgItem(hDlg,IDC_RESOLUTIONWINDOWED),g_Config.iWindowedRes);
|
||||
|
||||
CheckDlgButton(hDlg, IDC_FULLSCREENENABLE, g_Config.bFullscreen ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_VSYNC, g_Config.bVsync ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_RENDER_TO_MAINWINDOW, g_Config.renderToMainframe ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.iAdapter = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ADAPTER));
|
||||
g_Config.iWindowedRes = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_RESOLUTIONWINDOWED));
|
||||
g_Config.iMultisampleMode = ComboBox_GetCurSel(GetDlgItem(hDlg, IDC_ANTIALIASMODE));
|
||||
g_Config.iFSResolution = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_RESOLUTION));
|
||||
g_Config.bFullscreen = Button_GetCheck(GetDlgItem(hDlg, IDC_FULLSCREENENABLE)) ? true : false;
|
||||
g_Config.bVsync = Button_GetCheck(GetDlgItem(hDlg, IDC_VSYNC)) ? true : false;
|
||||
g_Config.renderToMainframe = Button_GetCheck(GetDlgItem(hDlg, IDC_RENDER_TO_MAINWINDOW)) ? true : false;
|
||||
g_Config.Save();
|
||||
}
|
||||
};
|
||||
|
||||
struct TabAdvanced : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
HWND opt = GetDlgItem(hDlg,IDC_DLOPTLEVEL);
|
||||
ComboBox_AddString(opt,"0: Interpret (slowest, most compatible)");
|
||||
ComboBox_AddString(opt,"1: Compile lists and decode vertex lists");
|
||||
//ComboBox_AddString(opt,"2: Compile+decode to vbufs and use hw xform");
|
||||
//ComboBox_AddString(opt,"Recompile to vbuffers and shaders");
|
||||
ComboBox_SetCurSel(opt,g_Config.iCompileDLsLevel);
|
||||
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS), g_Config.bOverlayStats);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_WIREFRAME), g_Config.bWireFrame);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXDUMP), g_Config.bDumpTextures);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS), g_Config.bShowShaderErrors);
|
||||
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY), g_Config.bTexFmtOverlayEnable);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), g_Config.bTexFmtOverlayCenter);
|
||||
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
|
||||
|
||||
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),g_Config.texDumpPath.c_str());
|
||||
Edit_LimitText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),255);
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
case IDC_BROWSETEXDUMPPATH:
|
||||
{
|
||||
std::string path = W32Util::BrowseForFolder(hDlg,"Choose texture dump path:");
|
||||
SetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH),path.c_str());
|
||||
}
|
||||
break;
|
||||
case IDC_TEXFMT_OVERLAY:
|
||||
{
|
||||
Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), true) : Button_Enable(GetDlgItem(hDlg,IDC_TEXFMT_CENTER), false);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.bTexFmtOverlayEnable = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_OVERLAY)) ? true : false;
|
||||
g_Config.bTexFmtOverlayCenter = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXFMT_CENTER)) ? true : false;
|
||||
|
||||
g_Config.bOverlayStats = Button_GetCheck(GetDlgItem(hDlg,IDC_OVERLAYSTATS)) ? true : false;
|
||||
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg,IDC_WIREFRAME)) ? true : false;
|
||||
g_Config.bDumpTextures = Button_GetCheck(GetDlgItem(hDlg,IDC_TEXDUMP)) ? true : false;
|
||||
g_Config.iCompileDLsLevel = (int)ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_DLOPTLEVEL));
|
||||
g_Config.bShowShaderErrors = Button_GetCheck(GetDlgItem(hDlg,IDC_SHOWSHADERERRORS)) ? true : false;
|
||||
char temp[MAX_PATH];
|
||||
GetWindowText(GetDlgItem(hDlg,IDC_TEXDUMPPATH), temp, MAX_PATH);
|
||||
g_Config.texDumpPath = temp;
|
||||
}
|
||||
};
|
||||
|
||||
struct TabDebug : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
struct TabEnhancements : public W32Util::Tab
|
||||
{
|
||||
void Init(HWND hDlg)
|
||||
{
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING),g_Config.bForceFiltering);
|
||||
Button_SetCheck(GetDlgItem(hDlg,IDC_FORCEANISOTROPY),g_Config.bForceMaxAniso);
|
||||
HWND pp = GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT);
|
||||
const char **names = Postprocess::GetPostprocessingNames();
|
||||
int i = 0;
|
||||
while (true)
|
||||
{
|
||||
if (!names[i])
|
||||
break;
|
||||
|
||||
ComboBox_AddString(pp, names[i]);
|
||||
i++;
|
||||
}
|
||||
ComboBox_SetCurSel(pp, g_Config.iPostprocessEffect);
|
||||
}
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
{
|
||||
/*
|
||||
switch (LOWORD(wParam))
|
||||
{
|
||||
default:
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
void Apply(HWND hDlg)
|
||||
{
|
||||
g_Config.bForceMaxAniso = Button_GetCheck(GetDlgItem(hDlg, IDC_FORCEANISOTROPY)) ? true : false;
|
||||
g_Config.bForceFiltering = Button_GetCheck(GetDlgItem(hDlg,IDC_FORCEFILTERING)) ? true : false;
|
||||
g_Config.iPostprocessEffect = ComboBox_GetCurSel(GetDlgItem(hDlg,IDC_POSTPROCESSEFFECT));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void DlgSettings_Show(HINSTANCE hInstance, HWND _hParent)
|
||||
{
|
||||
bool tfoe = g_Config.bTexFmtOverlayEnable;
|
||||
bool tfoc = g_Config.bTexFmtOverlayCenter;
|
||||
|
||||
g_Config.Load();
|
||||
W32Util::PropSheet sheet;
|
||||
sheet.Add(new TabDirect3D,(LPCTSTR)IDD_SETTINGS,"Direct3D");
|
||||
sheet.Add(new TabEnhancements,(LPCTSTR)IDD_ENHANCEMENTS,"Enhancements");
|
||||
sheet.Add(new TabAdvanced,(LPCTSTR)IDD_ADVANCED,"Advanced");
|
||||
//sheet.Add(new TabDebug,(LPCTSTR)IDD_DEBUGGER,"Debugger");
|
||||
sheet.Show(hInstance,_hParent,"Graphics Plugin");
|
||||
g_Config.Save();
|
||||
|
||||
if(( tfoe != g_Config.bTexFmtOverlayEnable) ||
|
||||
((g_Config.bTexFmtOverlayEnable) && ( tfoc != g_Config.bTexFmtOverlayCenter)))
|
||||
{
|
||||
TextureCache::Invalidate();
|
||||
}
|
||||
}
|
||||
@@ -1,173 +1,173 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "../../Core/Src/Core.h"
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
#include "EmuWindow.h"
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
HWND m_hWnd = NULL;
|
||||
HWND m_hParent = NULL;
|
||||
HINSTANCE m_hInstance = NULL;
|
||||
WNDCLASSEX wndClass;
|
||||
const TCHAR m_szClassName[] = "DolphinEmuWnd";
|
||||
int g_winstyle;
|
||||
|
||||
HWND GetWnd()
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
HWND GetParentWnd()
|
||||
{
|
||||
return m_hParent;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
switch( iMsg )
|
||||
{
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint( hWnd, &ps );
|
||||
EndPaint( hWnd, &ps );
|
||||
return 0;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
case VK_ESCAPE: /* Pressing esc quits */
|
||||
//DestroyWindow(hWnd);
|
||||
//PostQuitMessage(0);
|
||||
break;
|
||||
/*
|
||||
case MY_KEYS:
|
||||
hypotheticalScene->sendMessage(KEYDOWN...);
|
||||
*/
|
||||
}
|
||||
g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0);
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
//Core::SetState(Core::CORE_UNINITIALIZED);
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
//Shutdown();
|
||||
//PostQuitMessage( 0 );
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
// Reset the D3D Device here
|
||||
// Also make damn sure that this is not called from inside rendering a frame :P
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam)
|
||||
{
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
|
||||
{
|
||||
wndClass.cbSize = sizeof( wndClass );
|
||||
wndClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndClass.lpfnWndProc = WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = m_szClassName;
|
||||
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
|
||||
|
||||
m_hInstance = hInstance;
|
||||
RegisterClassEx( &wndClass );
|
||||
|
||||
if (parent)
|
||||
{
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
WS_CHILD,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
parent, NULL, hInstance, NULL );
|
||||
|
||||
m_hParent = parent;
|
||||
|
||||
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;
|
||||
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, style, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
style,
|
||||
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
|
||||
parent, NULL, hInstance, NULL );
|
||||
|
||||
g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
||||
g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style
|
||||
|
||||
}
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_SHOW);
|
||||
BringWindowToTop(m_hWnd);
|
||||
UpdateWindow(m_hWnd);
|
||||
}
|
||||
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
|
||||
{
|
||||
return OpenWindow(hParent, hInstance, 640, 480, title);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
DestroyWindow(m_hWnd);
|
||||
UnregisterClass(m_szClassName, m_hInstance);
|
||||
}
|
||||
|
||||
|
||||
void SetSize(int width, int height)
|
||||
{
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
::MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "../../Core/Src/Core.h"
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
#include "EmuWindow.h"
|
||||
|
||||
namespace EmuWindow
|
||||
{
|
||||
HWND m_hWnd = NULL;
|
||||
HWND m_hParent = NULL;
|
||||
HINSTANCE m_hInstance = NULL;
|
||||
WNDCLASSEX wndClass;
|
||||
const TCHAR m_szClassName[] = "DolphinEmuWnd";
|
||||
int g_winstyle;
|
||||
|
||||
HWND GetWnd()
|
||||
{
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
HWND GetParentWnd()
|
||||
{
|
||||
return m_hParent;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
HDC hdc;
|
||||
PAINTSTRUCT ps;
|
||||
switch( iMsg )
|
||||
{
|
||||
case WM_PAINT:
|
||||
hdc = BeginPaint( hWnd, &ps );
|
||||
EndPaint( hWnd, &ps );
|
||||
return 0;
|
||||
|
||||
case WM_KEYDOWN:
|
||||
switch( LOWORD( wParam ))
|
||||
{
|
||||
case VK_ESCAPE: /* Pressing esc quits */
|
||||
//DestroyWindow(hWnd);
|
||||
//PostQuitMessage(0);
|
||||
break;
|
||||
/*
|
||||
case MY_KEYS:
|
||||
hypotheticalScene->sendMessage(KEYDOWN...);
|
||||
*/
|
||||
}
|
||||
g_VideoInitialize.pKeyPress(LOWORD(wParam), GetAsyncKeyState(VK_SHIFT) != 0, GetAsyncKeyState(VK_CONTROL) != 0);
|
||||
break;
|
||||
|
||||
case WM_CLOSE:
|
||||
//Core::SetState(Core::CORE_UNINITIALIZED);
|
||||
return 0;
|
||||
|
||||
case WM_DESTROY:
|
||||
//Shutdown();
|
||||
//PostQuitMessage( 0 );
|
||||
break;
|
||||
|
||||
case WM_SIZE:
|
||||
// Reset the D3D Device here
|
||||
// Also make damn sure that this is not called from inside rendering a frame :P
|
||||
break;
|
||||
|
||||
case WM_SYSCOMMAND:
|
||||
switch (wParam)
|
||||
{
|
||||
case SC_SCREENSAVE:
|
||||
case SC_MONITORPOWER:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return DefWindowProc(hWnd, iMsg, wParam, lParam);
|
||||
}
|
||||
|
||||
|
||||
HWND OpenWindow(HWND parent, HINSTANCE hInstance, int width, int height, const TCHAR *title)
|
||||
{
|
||||
wndClass.cbSize = sizeof( wndClass );
|
||||
wndClass.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wndClass.lpfnWndProc = WndProc;
|
||||
wndClass.cbClsExtra = 0;
|
||||
wndClass.cbWndExtra = 0;
|
||||
wndClass.hInstance = hInstance;
|
||||
wndClass.hIcon = LoadIcon( NULL, IDI_APPLICATION );
|
||||
wndClass.hCursor = LoadCursor( NULL, IDC_ARROW );
|
||||
wndClass.hbrBackground = (HBRUSH)GetStockObject( BLACK_BRUSH );
|
||||
wndClass.lpszMenuName = NULL;
|
||||
wndClass.lpszClassName = m_szClassName;
|
||||
wndClass.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
|
||||
|
||||
m_hInstance = hInstance;
|
||||
RegisterClassEx( &wndClass );
|
||||
|
||||
if (parent)
|
||||
{
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
WS_CHILD,
|
||||
CW_USEDEFAULT, CW_USEDEFAULT,CW_USEDEFAULT, CW_USEDEFAULT,
|
||||
parent, NULL, hInstance, NULL );
|
||||
|
||||
m_hParent = parent;
|
||||
|
||||
ShowWindow(m_hWnd, SW_SHOWMAXIMIZED);
|
||||
}
|
||||
else
|
||||
{
|
||||
DWORD style = g_Config.bFullscreen ? WS_POPUP : WS_OVERLAPPEDWINDOW;
|
||||
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, style, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
|
||||
|
||||
m_hWnd = CreateWindow(m_szClassName, title,
|
||||
style,
|
||||
rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top,
|
||||
parent, NULL, hInstance, NULL );
|
||||
|
||||
g_winstyle = GetWindowLong( m_hWnd, GWL_STYLE );
|
||||
g_winstyle &= ~WS_MAXIMIZE & ~WS_MINIMIZE; // remove minimize/maximize style
|
||||
|
||||
}
|
||||
|
||||
return m_hWnd;
|
||||
}
|
||||
|
||||
void Show()
|
||||
{
|
||||
ShowWindow(m_hWnd, SW_SHOW);
|
||||
BringWindowToTop(m_hWnd);
|
||||
UpdateWindow(m_hWnd);
|
||||
}
|
||||
|
||||
HWND Create(HWND hParent, HINSTANCE hInstance, const TCHAR *title)
|
||||
{
|
||||
return OpenWindow(hParent, hInstance, 640, 480, title);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
DestroyWindow(m_hWnd);
|
||||
UnregisterClass(m_szClassName, m_hInstance);
|
||||
}
|
||||
|
||||
|
||||
void SetSize(int width, int height)
|
||||
{
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
|
||||
|
||||
int w = rc.right - rc.left;
|
||||
int h = rc.bottom - rc.top;
|
||||
|
||||
rc.left = (1280 - w)/2;
|
||||
rc.right = rc.left + w;
|
||||
rc.top = (1024 - h)/2;
|
||||
rc.bottom = rc.top + h;
|
||||
::MoveWindow(m_hWnd, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,130 +1,130 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IndexGenerator.h"
|
||||
|
||||
/*
|
||||
*
|
||||
QUAD simulator
|
||||
|
||||
0 2 4 6
|
||||
1 3 5 7
|
||||
021231 243453
|
||||
*/
|
||||
|
||||
|
||||
void IndexGenerator::Start(unsigned short *startptr)
|
||||
{
|
||||
ptr=startptr;
|
||||
index=0;
|
||||
numPrims=0;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddList(int numVerts)
|
||||
{
|
||||
int numTris = numVerts/3;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index+i*3;
|
||||
*ptr++ = index+i*3+1;
|
||||
*ptr++ = index+i*3+2;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddStrip(int numVerts)
|
||||
{
|
||||
int numTris = numVerts-2;
|
||||
if (numTris<=0) return;
|
||||
bool wind = false;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index+i;
|
||||
*ptr++ = index+i+(wind?2:1);
|
||||
*ptr++ = index+i+(wind?1:2);
|
||||
wind = !wind;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineList(int numVerts)
|
||||
{
|
||||
int numLines= numVerts/2;
|
||||
if (numLines<=0) return;
|
||||
for (int i=0; i<numLines; i++)
|
||||
{
|
||||
*ptr++ = index+i*2;
|
||||
*ptr++ = index+i*2+1;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineStrip(int numVerts)
|
||||
{
|
||||
int numLines = numVerts-1;
|
||||
if (numLines<=0) return;
|
||||
for (int i=0; i<numLines; i++)
|
||||
{
|
||||
*ptr++ = index+i;
|
||||
*ptr++ = index+i+1;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddFan(int numVerts)
|
||||
{
|
||||
int numTris = numVerts-2;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index;
|
||||
*ptr++ = index+i+1;
|
||||
*ptr++ = index+i+2;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddQuads(int numVerts)
|
||||
{
|
||||
int numTris = (numVerts/4)*2;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris/2; i++)
|
||||
{
|
||||
*ptr++=index+i*4;
|
||||
*ptr++=index+i*4+1;
|
||||
*ptr++=index+i*4+3;
|
||||
*ptr++=index+i*4+1;
|
||||
*ptr++=index+i*4+2;
|
||||
*ptr++=index+i*4+3;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddPointList(int numVerts)
|
||||
{
|
||||
index += numVerts;
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "IndexGenerator.h"
|
||||
|
||||
/*
|
||||
*
|
||||
QUAD simulator
|
||||
|
||||
0 2 4 6
|
||||
1 3 5 7
|
||||
021231 243453
|
||||
*/
|
||||
|
||||
|
||||
void IndexGenerator::Start(unsigned short *startptr)
|
||||
{
|
||||
ptr=startptr;
|
||||
index=0;
|
||||
numPrims=0;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddList(int numVerts)
|
||||
{
|
||||
int numTris = numVerts/3;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index+i*3;
|
||||
*ptr++ = index+i*3+1;
|
||||
*ptr++ = index+i*3+2;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddStrip(int numVerts)
|
||||
{
|
||||
int numTris = numVerts-2;
|
||||
if (numTris<=0) return;
|
||||
bool wind = false;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index+i;
|
||||
*ptr++ = index+i+(wind?2:1);
|
||||
*ptr++ = index+i+(wind?1:2);
|
||||
wind = !wind;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineList(int numVerts)
|
||||
{
|
||||
int numLines= numVerts/2;
|
||||
if (numLines<=0) return;
|
||||
for (int i=0; i<numLines; i++)
|
||||
{
|
||||
*ptr++ = index+i*2;
|
||||
*ptr++ = index+i*2+1;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineStrip(int numVerts)
|
||||
{
|
||||
int numLines = numVerts-1;
|
||||
if (numLines<=0) return;
|
||||
for (int i=0; i<numLines; i++)
|
||||
{
|
||||
*ptr++ = index+i;
|
||||
*ptr++ = index+i+1;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddFan(int numVerts)
|
||||
{
|
||||
int numTris = numVerts-2;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris; i++)
|
||||
{
|
||||
*ptr++ = index;
|
||||
*ptr++ = index+i+1;
|
||||
*ptr++ = index+i+2;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddQuads(int numVerts)
|
||||
{
|
||||
int numTris = (numVerts/4)*2;
|
||||
if (numTris<=0) return;
|
||||
for (int i=0; i<numTris/2; i++)
|
||||
{
|
||||
*ptr++=index+i*4;
|
||||
*ptr++=index+i*4+1;
|
||||
*ptr++=index+i*4+3;
|
||||
*ptr++=index+i*4+1;
|
||||
*ptr++=index+i*4+2;
|
||||
*ptr++=index+i*4+3;
|
||||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddPointList(int numVerts)
|
||||
{
|
||||
index += numVerts;
|
||||
}
|
||||
@@ -1,354 +1,354 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
//DL facts:
|
||||
// Ikaruga uses (nearly) NO display lists!
|
||||
// Zelda WW uses TONS of display lists
|
||||
// Zelda TP uses almost 100% display lists except menus (we like this!)
|
||||
|
||||
// Note that it IS NOT GENERALLY POSSIBLE to precompile display lists! You can compile them as they are
|
||||
// and hope that the vertex format doesn't change, though, if you do it just when they are
|
||||
// called. The reason is that the vertex format affects the sizes of the vertices.
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexManager.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "ShaderManager.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Utils.h"
|
||||
#include "Fifo.h"
|
||||
#include "DataReader.h"
|
||||
|
||||
DecodedVArray tempvarray;
|
||||
u8 *g_pVideoData = 0;
|
||||
|
||||
extern u8* FAKE_GetFifoStartPtr();
|
||||
extern u8* FAKE_GetFifoEndPtr();
|
||||
|
||||
static void Decode();
|
||||
|
||||
static void ExecuteDisplayList(u32 address, u32 size)
|
||||
{
|
||||
u8* old_pVideoData = g_pVideoData;
|
||||
|
||||
u8* startAddress = Memory_GetPtr(address);
|
||||
|
||||
//Avoid the crash if Memory_GetPtr failed ..
|
||||
if (startAddress!=0)
|
||||
{
|
||||
g_pVideoData = startAddress;
|
||||
|
||||
// temporarily swap dl and non-dl(small "hack" for the stats)
|
||||
Statistics::SwapDL();
|
||||
|
||||
while((u32)(g_pVideoData - startAddress) < size)
|
||||
{
|
||||
Decode();
|
||||
}
|
||||
INCSTAT(stats.numDListsCalled);
|
||||
INCSTAT(stats.thisFrame.numDListsCalled);
|
||||
|
||||
// un-swap
|
||||
Statistics::SwapDL();
|
||||
|
||||
// reset to the old pointer
|
||||
g_pVideoData = old_pVideoData;
|
||||
}
|
||||
}
|
||||
|
||||
bool FifoCommandRunnable()
|
||||
{
|
||||
u32 iBufferSize = (u32)(FAKE_GetFifoEndPtr()-g_pVideoData);
|
||||
if (iBufferSize == 0)
|
||||
return false; // can't peek
|
||||
|
||||
u8 Cmd = DataPeek8(0);
|
||||
u32 iCommandSize = 0;
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
// Hm, this means that we scan over nop streams pretty slowly...
|
||||
iCommandSize = 1;
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
iCommandSize = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A:
|
||||
case GX_LOAD_INDX_B:
|
||||
case GX_LOAD_INDX_C:
|
||||
case GX_LOAD_INDX_D:
|
||||
iCommandSize = 5;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
iCommandSize = 9;
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
iCommandSize = 1;
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC: // invalid vertex cache - no parameter?
|
||||
iCommandSize = 1;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG:
|
||||
iCommandSize = 5;
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
// check if we can read the header
|
||||
if (iBufferSize >= 5)
|
||||
{
|
||||
iCommandSize = 1 + 4;
|
||||
u32 Cmd2 = DataPeek32(1);
|
||||
int dwTransferSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
iCommandSize += dwTransferSize * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
// check if we can read the header
|
||||
if (iBufferSize >= 3)
|
||||
{
|
||||
iCommandSize = 1 + 2;
|
||||
u16 numVertices = DataPeek16(1);
|
||||
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
|
||||
vtxLoader.Setup();
|
||||
int vsize = vtxLoader.GetVertexSize();
|
||||
iCommandSize += numVertices * vsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char szTemp[1024];
|
||||
sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n"
|
||||
"This means one of the following:\n"
|
||||
"* The emulated GPU got desynced, disabling dual core can help\n"
|
||||
"* Command stream corrupted by some spurious memory bug\n"
|
||||
"* This really is an unknown opcode (unlikely)\n\n"
|
||||
"* Some other sort of bug\n\n"
|
||||
"Dolphin will now likely crash or hang. Enjoy.", Cmd);
|
||||
MessageBox(NULL, szTemp, "Video-Plugin", MB_OK);
|
||||
g_VideoInitialize.pLog(szTemp, TRUE);
|
||||
|
||||
{
|
||||
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
|
||||
|
||||
char szTmp[256];
|
||||
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
|
||||
sprintf(szTmp, "Illegal command %02x\n"
|
||||
"CPBase: 0x%08x\n"
|
||||
"CPEnd: 0x%08x\n"
|
||||
"CPHiWatermark: 0x%08x\n"
|
||||
"CPLoWatermark: 0x%08x\n"
|
||||
"CPReadWriteDistance: 0x%08x\n"
|
||||
"CPWritePointer: 0x%08x\n"
|
||||
"CPReadPointer: 0x%08x\n"
|
||||
"CPBreakpoint: 0x%08x\n"
|
||||
"bFF_GPReadEnable: %s\n"
|
||||
"bFF_BPEnable: %s\n"
|
||||
"bFF_GPLinkEnable: %s\n"
|
||||
"bFF_Breakpoint: %s\n"
|
||||
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
|
||||
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
|
||||
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
|
||||
,fifo.bFF_Breakpoint ? "true" : "false");
|
||||
|
||||
g_VideoInitialize.pLog(szTmp, TRUE);
|
||||
MessageBox(0,szTmp,"GFX ERROR",0);
|
||||
// _assert_msg_(0,szTmp,"");
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (iCommandSize > iBufferSize)
|
||||
return false;
|
||||
|
||||
#ifdef _DEBUG
|
||||
char temp[256];
|
||||
sprintf(temp, "OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Decode(void)
|
||||
{
|
||||
int Cmd = DataReadU8();
|
||||
switch (Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
{
|
||||
u32 SubCmd = DataReadU8();
|
||||
u32 Value = DataReadU32();
|
||||
LoadCPReg(SubCmd,Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
u32 dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
pData[i] = DataReadU32();
|
||||
LoadXFReg(dwTransferSize,dwAddress,pData);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(),0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(),0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(),0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(),0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = DataReadU32();
|
||||
u32 dwCount = DataReadU32();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DebugLog("Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd = DataReadU32();
|
||||
LoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
// load vertices
|
||||
u16 numVertices = DataReadU16();
|
||||
tempvarray.Reset();
|
||||
VertexLoader::SetVArray(&tempvarray);
|
||||
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
|
||||
vtxLoader.Setup();
|
||||
vtxLoader.PrepareRun();
|
||||
int vsize = vtxLoader.GetVertexSize();
|
||||
vtxLoader.RunVertices(numVertices);
|
||||
|
||||
// add vertices
|
||||
int primitive = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
VertexManager::AddVertices(primitive, numVertices, &tempvarray);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
|
||||
|
||||
char szTmp[256];
|
||||
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
|
||||
sprintf(szTmp, "Illegal command %02x\n"
|
||||
"CPBase: 0x%08x\n"
|
||||
"CPEnd: 0x%08x\n"
|
||||
"CPHiWatermark: 0x%08x\n"
|
||||
"CPLoWatermark: 0x%08x\n"
|
||||
"CPReadWriteDistance: 0x%08x\n"
|
||||
"CPWritePointer: 0x%08x\n"
|
||||
"CPReadPointer: 0x%08x\n"
|
||||
"CPBreakpoint: 0x%08x\n"
|
||||
"bFF_GPReadEnable: %s\n"
|
||||
"bFF_BPEnable: %s\n"
|
||||
"bFF_GPLinkEnable: %s\n"
|
||||
"bFF_Breakpoint: %s\n"
|
||||
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
|
||||
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
|
||||
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
|
||||
,fifo.bFF_Breakpoint ? "true" : "false");
|
||||
|
||||
g_VideoInitialize.pLog(szTmp, TRUE);
|
||||
MessageBox(0,szTmp,"GFX ERROR",0);
|
||||
// _assert_msg_(0,szTmp,"");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Init()
|
||||
{
|
||||
g_pVideoData = FAKE_GetFifoStartPtr();
|
||||
tempvarray.Create(65536*3, 1, 8, 3, 2, 8);
|
||||
}
|
||||
|
||||
|
||||
void OpcodeDecoder_Shutdown()
|
||||
{
|
||||
//VirtualFree((LPVOID)buffer,0,MEM_RELEASE);
|
||||
tempvarray.Destroy();
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Run()
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
while (FifoCommandRunnable())
|
||||
{
|
||||
Decode();
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
//DL facts:
|
||||
// Ikaruga uses (nearly) NO display lists!
|
||||
// Zelda WW uses TONS of display lists
|
||||
// Zelda TP uses almost 100% display lists except menus (we like this!)
|
||||
|
||||
// Note that it IS NOT GENERALLY POSSIBLE to precompile display lists! You can compile them as they are
|
||||
// and hope that the vertex format doesn't change, though, if you do it just when they are
|
||||
// called. The reason is that the vertex format affects the sizes of the vertices.
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexManager.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "ShaderManager.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Utils.h"
|
||||
#include "Fifo.h"
|
||||
#include "DataReader.h"
|
||||
|
||||
DecodedVArray tempvarray;
|
||||
u8 *g_pVideoData = 0;
|
||||
|
||||
extern u8* FAKE_GetFifoStartPtr();
|
||||
extern u8* FAKE_GetFifoEndPtr();
|
||||
|
||||
static void Decode();
|
||||
|
||||
static void ExecuteDisplayList(u32 address, u32 size)
|
||||
{
|
||||
u8* old_pVideoData = g_pVideoData;
|
||||
|
||||
u8* startAddress = Memory_GetPtr(address);
|
||||
|
||||
//Avoid the crash if Memory_GetPtr failed ..
|
||||
if (startAddress!=0)
|
||||
{
|
||||
g_pVideoData = startAddress;
|
||||
|
||||
// temporarily swap dl and non-dl(small "hack" for the stats)
|
||||
Statistics::SwapDL();
|
||||
|
||||
while((u32)(g_pVideoData - startAddress) < size)
|
||||
{
|
||||
Decode();
|
||||
}
|
||||
INCSTAT(stats.numDListsCalled);
|
||||
INCSTAT(stats.thisFrame.numDListsCalled);
|
||||
|
||||
// un-swap
|
||||
Statistics::SwapDL();
|
||||
|
||||
// reset to the old pointer
|
||||
g_pVideoData = old_pVideoData;
|
||||
}
|
||||
}
|
||||
|
||||
bool FifoCommandRunnable()
|
||||
{
|
||||
u32 iBufferSize = (u32)(FAKE_GetFifoEndPtr()-g_pVideoData);
|
||||
if (iBufferSize == 0)
|
||||
return false; // can't peek
|
||||
|
||||
u8 Cmd = DataPeek8(0);
|
||||
u32 iCommandSize = 0;
|
||||
|
||||
switch(Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
// Hm, this means that we scan over nop streams pretty slowly...
|
||||
iCommandSize = 1;
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
iCommandSize = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A:
|
||||
case GX_LOAD_INDX_B:
|
||||
case GX_LOAD_INDX_C:
|
||||
case GX_LOAD_INDX_D:
|
||||
iCommandSize = 5;
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
iCommandSize = 9;
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
iCommandSize = 1;
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC: // invalid vertex cache - no parameter?
|
||||
iCommandSize = 1;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG:
|
||||
iCommandSize = 5;
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
// check if we can read the header
|
||||
if (iBufferSize >= 5)
|
||||
{
|
||||
iCommandSize = 1 + 4;
|
||||
u32 Cmd2 = DataPeek32(1);
|
||||
int dwTransferSize = ((Cmd2 >> 16) & 15) + 1;
|
||||
iCommandSize += dwTransferSize * 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
// check if we can read the header
|
||||
if (iBufferSize >= 3)
|
||||
{
|
||||
iCommandSize = 1 + 2;
|
||||
u16 numVertices = DataPeek16(1);
|
||||
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
|
||||
vtxLoader.Setup();
|
||||
int vsize = vtxLoader.GetVertexSize();
|
||||
iCommandSize += numVertices * vsize;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char szTemp[1024];
|
||||
sprintf(szTemp, "GFX: Unknown Opcode (0x%x).\n"
|
||||
"This means one of the following:\n"
|
||||
"* The emulated GPU got desynced, disabling dual core can help\n"
|
||||
"* Command stream corrupted by some spurious memory bug\n"
|
||||
"* This really is an unknown opcode (unlikely)\n\n"
|
||||
"* Some other sort of bug\n\n"
|
||||
"Dolphin will now likely crash or hang. Enjoy.", Cmd);
|
||||
MessageBox(NULL, szTemp, "Video-Plugin", MB_OK);
|
||||
g_VideoInitialize.pLog(szTemp, TRUE);
|
||||
|
||||
{
|
||||
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
|
||||
|
||||
char szTmp[256];
|
||||
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
|
||||
sprintf(szTmp, "Illegal command %02x\n"
|
||||
"CPBase: 0x%08x\n"
|
||||
"CPEnd: 0x%08x\n"
|
||||
"CPHiWatermark: 0x%08x\n"
|
||||
"CPLoWatermark: 0x%08x\n"
|
||||
"CPReadWriteDistance: 0x%08x\n"
|
||||
"CPWritePointer: 0x%08x\n"
|
||||
"CPReadPointer: 0x%08x\n"
|
||||
"CPBreakpoint: 0x%08x\n"
|
||||
"bFF_GPReadEnable: %s\n"
|
||||
"bFF_BPEnable: %s\n"
|
||||
"bFF_GPLinkEnable: %s\n"
|
||||
"bFF_Breakpoint: %s\n"
|
||||
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
|
||||
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
|
||||
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
|
||||
,fifo.bFF_Breakpoint ? "true" : "false");
|
||||
|
||||
g_VideoInitialize.pLog(szTmp, TRUE);
|
||||
MessageBox(0,szTmp,"GFX ERROR",0);
|
||||
// _assert_msg_(0,szTmp,"");
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (iCommandSize > iBufferSize)
|
||||
return false;
|
||||
|
||||
#ifdef _DEBUG
|
||||
char temp[256];
|
||||
sprintf(temp, "OP detected: Cmd 0x%x size %i buffer %i",Cmd, iCommandSize, iBufferSize);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void Decode(void)
|
||||
{
|
||||
int Cmd = DataReadU8();
|
||||
switch (Cmd)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
{
|
||||
u32 SubCmd = DataReadU8();
|
||||
u32 Value = DataReadU32();
|
||||
LoadCPReg(SubCmd,Value);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
|
||||
int dwTransferSize = ((Cmd2>>16)&15) + 1;
|
||||
u32 dwAddress = Cmd2 & 0xFFFF;
|
||||
static u32 pData[16];
|
||||
for (int i=0; i<dwTransferSize; i++)
|
||||
pData[i] = DataReadU32();
|
||||
LoadXFReg(dwTransferSize,dwAddress,pData);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(),0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(),0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(),0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(),0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 dwAddr = DataReadU32();
|
||||
u32 dwCount = DataReadU32();
|
||||
ExecuteDisplayList(dwAddr, dwCount);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x44:
|
||||
// zelda 4 swords calls it and checks the metrics registers after that
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
|
||||
DebugLog("Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 cmd = DataReadU32();
|
||||
LoadBPReg(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (Cmd&0x80)
|
||||
{
|
||||
// load vertices
|
||||
u16 numVertices = DataReadU16();
|
||||
tempvarray.Reset();
|
||||
VertexLoader::SetVArray(&tempvarray);
|
||||
VertexLoader& vtxLoader = g_VertexLoaders[Cmd & GX_VAT_MASK];
|
||||
vtxLoader.Setup();
|
||||
vtxLoader.PrepareRun();
|
||||
int vsize = vtxLoader.GetVertexSize();
|
||||
vtxLoader.RunVertices(numVertices);
|
||||
|
||||
// add vertices
|
||||
int primitive = (Cmd & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT;
|
||||
VertexManager::AddVertices(primitive, numVertices, &tempvarray);
|
||||
}
|
||||
else
|
||||
{
|
||||
SCPFifoStruct &fifo = *g_VideoInitialize.pCPFifo;
|
||||
|
||||
char szTmp[256];
|
||||
// sprintf(szTmp, "Illegal command %02x (at %08x)",Cmd,g_pDataReader->GetPtr());
|
||||
sprintf(szTmp, "Illegal command %02x\n"
|
||||
"CPBase: 0x%08x\n"
|
||||
"CPEnd: 0x%08x\n"
|
||||
"CPHiWatermark: 0x%08x\n"
|
||||
"CPLoWatermark: 0x%08x\n"
|
||||
"CPReadWriteDistance: 0x%08x\n"
|
||||
"CPWritePointer: 0x%08x\n"
|
||||
"CPReadPointer: 0x%08x\n"
|
||||
"CPBreakpoint: 0x%08x\n"
|
||||
"bFF_GPReadEnable: %s\n"
|
||||
"bFF_BPEnable: %s\n"
|
||||
"bFF_GPLinkEnable: %s\n"
|
||||
"bFF_Breakpoint: %s\n"
|
||||
,Cmd, fifo.CPBase, fifo.CPEnd, fifo.CPHiWatermark, fifo.CPLoWatermark, fifo.CPReadWriteDistance
|
||||
,fifo.CPWritePointer, fifo.CPReadPointer, fifo.CPBreakpoint, fifo.bFF_GPReadEnable ? "true" : "false"
|
||||
,fifo.bFF_BPEnable ? "true" : "false" ,fifo.bFF_GPLinkEnable ? "true" : "false"
|
||||
,fifo.bFF_Breakpoint ? "true" : "false");
|
||||
|
||||
g_VideoInitialize.pLog(szTmp, TRUE);
|
||||
MessageBox(0,szTmp,"GFX ERROR",0);
|
||||
// _assert_msg_(0,szTmp,"");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Init()
|
||||
{
|
||||
g_pVideoData = FAKE_GetFifoStartPtr();
|
||||
tempvarray.Create(65536*3, 1, 8, 3, 2, 8);
|
||||
}
|
||||
|
||||
|
||||
void OpcodeDecoder_Shutdown()
|
||||
{
|
||||
//VirtualFree((LPVOID)buffer,0,MEM_RELEASE);
|
||||
tempvarray.Destroy();
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Run()
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
while (FifoCommandRunnable())
|
||||
{
|
||||
Decode();
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,451 +1,451 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
#include "VertexManager.h"
|
||||
#include "Render.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "D3DPostprocess.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "TextureCache.h"
|
||||
#include "Utils.h"
|
||||
#include "EmuWindow.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
float Renderer::m_x,Renderer::m_y,Renderer::m_width, Renderer::m_height, Renderer::xScale,Renderer::yScale;
|
||||
std::vector<LPDIRECT3DBASETEXTURE9> Renderer::m_Textures;
|
||||
DWORD Renderer::m_RenderStates[MaxRenderStates];
|
||||
DWORD Renderer::m_TextureStageStates[MaxTextureStages][MaxTextureTypes];
|
||||
DWORD Renderer::m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
|
||||
DWORD Renderer::m_FVF;
|
||||
|
||||
#define NUMWNDRES 6
|
||||
extern int g_Res[NUMWNDRES][2];
|
||||
|
||||
|
||||
struct Message
|
||||
{
|
||||
Message(const std::string &msg, u32 dw) : message( msg ), dwTimeStamp( dw )
|
||||
{
|
||||
}
|
||||
|
||||
std::string message;
|
||||
u32 dwTimeStamp;
|
||||
};
|
||||
static std::list<Message> s_listMsgs;
|
||||
|
||||
|
||||
void Renderer::Init(SVideoInitialize &_VideoInitialize)
|
||||
{
|
||||
EmuWindow::SetSize(g_Res[g_Config.iWindowedRes][0], g_Res[g_Config.iWindowedRes][1]);
|
||||
|
||||
D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
D3D::dev->GetViewport(&vp);
|
||||
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_width = (float)vp.Width;
|
||||
m_height = (float)vp.Height;
|
||||
xScale = 640.0f / (float)vp.Width;
|
||||
yScale = 480.0f / (float)vp.Height;
|
||||
|
||||
D3D::font.Init();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Renderer::Shutdown(void)
|
||||
{
|
||||
D3D::font.Shutdown();
|
||||
D3D::EndFrame();
|
||||
D3D::Close();
|
||||
}
|
||||
|
||||
void Renderer::Initialize(void)
|
||||
{
|
||||
m_FVF = 0;
|
||||
|
||||
m_Textures.reserve( MaxTextureStages );
|
||||
for ( int i = 0; i < MaxTextureStages; i++ )
|
||||
{
|
||||
m_Textures.push_back( NULL );
|
||||
}
|
||||
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
D3D::dev->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 16);
|
||||
}
|
||||
ReinitView();
|
||||
|
||||
Postprocess::Initialize();
|
||||
Postprocess::BeginFrame();
|
||||
D3D::BeginFrame(true, 0);
|
||||
VertexManager::BeginFrame();
|
||||
}
|
||||
|
||||
void Renderer::AddMessage(const std::string &message, u32 ms)
|
||||
{
|
||||
s_listMsgs.push_back(Message(message, timeGetTime()+ms));
|
||||
}
|
||||
|
||||
void Renderer::ProcessMessages()
|
||||
{
|
||||
if (s_listMsgs.size() > 0) {
|
||||
int left = 25, top = 15;
|
||||
std::list<Message>::iterator it = s_listMsgs.begin();
|
||||
|
||||
while( it != s_listMsgs.end() )
|
||||
{
|
||||
int time_left = (int)(it->dwTimeStamp - timeGetTime());
|
||||
int alpha = 255;
|
||||
|
||||
if(time_left<1024)
|
||||
{
|
||||
alpha=time_left>>2;
|
||||
if(time_left<0) alpha=0;
|
||||
}
|
||||
|
||||
alpha <<= 24;
|
||||
|
||||
RenderText(it->message, left+1, top+1, 0x000000|alpha);
|
||||
RenderText(it->message, left, top, 0xffff30|alpha);
|
||||
top += 15;
|
||||
|
||||
if (time_left <= 0)
|
||||
it = s_listMsgs.erase(it);
|
||||
else ++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const std::string &text, int left, int top, u32 color)
|
||||
{
|
||||
D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text.c_str(), false);
|
||||
}
|
||||
|
||||
void dumpMatrix(D3DXMATRIX &mtx)
|
||||
{
|
||||
for (int y=0; y<4; y++)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::ReinitView()
|
||||
{
|
||||
D3DXMATRIX mtx;
|
||||
D3DXMatrixIdentity(&mtx);
|
||||
D3D::dev->SetTransform(D3DTS_VIEW,&mtx);
|
||||
D3D::dev->SetTransform(D3DTS_WORLD,&mtx);
|
||||
|
||||
float width = (float)D3D::GetDisplayWidth();
|
||||
float height = (float)D3D::GetDisplayHeight();
|
||||
|
||||
xScale = width/640.0f;
|
||||
yScale = height/480.0f;
|
||||
|
||||
RECT rc = {
|
||||
(LONG)(m_x*xScale), (LONG)(m_y*yScale), (LONG)(m_width*xScale), (LONG)(m_height*yScale)
|
||||
};
|
||||
}
|
||||
|
||||
void Renderer::SwapBuffers(void)
|
||||
{
|
||||
// center window again
|
||||
if (EmuWindow::GetParentWnd())
|
||||
{
|
||||
RECT rcWindow;
|
||||
GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow);
|
||||
|
||||
int width = rcWindow.right - rcWindow.left;
|
||||
int height = rcWindow.bottom - rcWindow.top;
|
||||
|
||||
::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE);
|
||||
// nBackbufferWidth = width;
|
||||
// nBackbufferHeight = height;
|
||||
}
|
||||
|
||||
//Finish up the current frame, print some stats
|
||||
Postprocess::FinalizeFrame();
|
||||
if (g_Config.bOverlayStats)
|
||||
{
|
||||
char st[2048];
|
||||
char *p = st;
|
||||
p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated);
|
||||
p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive);
|
||||
p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated);
|
||||
p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive);
|
||||
p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated);
|
||||
p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive);
|
||||
p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled);
|
||||
p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated);
|
||||
p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive);
|
||||
p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims);
|
||||
p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins);
|
||||
p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims);
|
||||
p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads);
|
||||
p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL);
|
||||
p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads);
|
||||
p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL);
|
||||
p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads);
|
||||
p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL);
|
||||
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
|
||||
|
||||
//end frame
|
||||
}
|
||||
|
||||
ProcessMessages();
|
||||
|
||||
#if defined(DVPROFILE)
|
||||
if( g_bWriteProfile ) {
|
||||
//g_bWriteProfile = 0;
|
||||
static int framenum = 0;
|
||||
const int UPDATE_FRAMES = 8;
|
||||
if( ++framenum >= UPDATE_FRAMES ) {
|
||||
DVProfWrite("prof.txt", UPDATE_FRAMES);
|
||||
DVProfClear();
|
||||
framenum = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
D3D::EndFrame();
|
||||
//D3D frame is now over
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//clean out old stuff from caches
|
||||
frameCount++;
|
||||
PShaderCache::Cleanup();
|
||||
VShaderCache::Cleanup();
|
||||
TextureCache::Cleanup();
|
||||
//DListCache::Cleanup();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Begin new frame
|
||||
//Set default viewport and scissor, for the clear to work correctly
|
||||
stats.ResetFrame();
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = (DWORD)m_width;
|
||||
vp.Height = (DWORD)m_height;
|
||||
vp.MinZ = 0;
|
||||
vp.MaxZ = 0;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT rc;
|
||||
rc.left = 0;
|
||||
rc.top = 0;
|
||||
rc.right = (LONG)m_width;
|
||||
rc.bottom = (LONG)m_height;
|
||||
D3D::dev->SetScissorRect(&rc);
|
||||
|
||||
u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB;
|
||||
// clearColor |= 0x003F003F;
|
||||
// D3D::BeginFrame(true,clearColor,1.0f);
|
||||
D3D::BeginFrame(false,clearColor,1.0f);
|
||||
// D3D::EnableAlphaToCoverage();
|
||||
|
||||
Postprocess::BeginFrame();
|
||||
VertexManager::BeginFrame();
|
||||
|
||||
if (g_Config.bOldCard)
|
||||
D3D::font.SetRenderStates(); //compatibility with low end cards
|
||||
}
|
||||
|
||||
void Renderer::Flush(void)
|
||||
{
|
||||
// render the rest of the vertex buffer
|
||||
//only to be used for debugging purposes
|
||||
//D3D::EndFrame();
|
||||
|
||||
//D3D::BeginFrame(false,0);
|
||||
}
|
||||
|
||||
void Renderer::SetViewport(float* _Viewport)
|
||||
{
|
||||
Viewport* pViewport = (Viewport*)_Viewport;
|
||||
D3DVIEWPORT9 vp;
|
||||
float x=(pViewport->xOrig-662)*2;
|
||||
float y=(pViewport->yOrig-582)*2; //something is wrong, but what??
|
||||
y-=16;
|
||||
|
||||
float w=pViewport->wd*2; //multiply up to real size
|
||||
float h=pViewport->ht*-2; //why is this negative? oh well..
|
||||
|
||||
if (x < 0.0f) x = 0.0f;
|
||||
if (y < 0.0f) y = 0.0f;
|
||||
if (x > 640.0f) x = 639.0f;
|
||||
if (y > 480.0f) y = 479.0f;
|
||||
if (w < 0) w=1;
|
||||
if (h < 0) h=1;
|
||||
if (x+w > 640.0f) w=640-x;
|
||||
if (y+h > 480.0f) h=480-y;
|
||||
//x=y=0;
|
||||
//if(w>0.0f) w=0.0f;
|
||||
//if(h<0.0f) h=0.0f;
|
||||
|
||||
vp.X = (DWORD)(x*xScale);
|
||||
vp.Y = (DWORD)(y*yScale);
|
||||
vp.Width = (DWORD)(w*xScale);
|
||||
vp.Height = (DWORD)(h*yScale);
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
|
||||
// char temp[256];
|
||||
// sprintf(temp,"Viewport: %i %i %i %i %f %f",vp.X,vp.Y,vp.Width,vp.Height,vp.MinZ,vp.MaxZ);
|
||||
// g_VideoInitialize.pLog(temp, FALSE);
|
||||
|
||||
D3D::dev->SetViewport(&vp);
|
||||
}
|
||||
|
||||
void Renderer::SetScissorBox(RECT &rc)
|
||||
{
|
||||
rc.left = (int)(rc.left * xScale);
|
||||
rc.top = (int)(rc.top * yScale);
|
||||
rc.right = (int)(rc.right * xScale);
|
||||
rc.bottom = (int)(rc.bottom * yScale);
|
||||
if (rc.right >= rc.left && rc.bottom >= rc.top)
|
||||
D3D::dev->SetScissorRect(&rc);
|
||||
else
|
||||
g_VideoInitialize.pLog("SCISSOR ERROR", FALSE);
|
||||
}
|
||||
|
||||
void Renderer::SetProjection(float* pMatrix, int constantIndex)
|
||||
{
|
||||
D3DXMATRIX mtx;
|
||||
if (pMatrix[6] == 0)
|
||||
{
|
||||
mtx.m[0][0] = pMatrix[0];
|
||||
mtx.m[1][0] = 0.0f;
|
||||
mtx.m[2][0] = pMatrix[1];
|
||||
mtx.m[3][0] = -0.5f/m_width;
|
||||
|
||||
mtx.m[0][1] = 0.0f;
|
||||
mtx.m[1][1] = pMatrix[2];
|
||||
mtx.m[2][1] = pMatrix[3];
|
||||
mtx.m[3][1] = +0.5f/m_height;
|
||||
|
||||
mtx.m[0][2] = 0.0f;
|
||||
mtx.m[1][2] = 0.0f;
|
||||
mtx.m[2][2] = -(1-pMatrix[4]);
|
||||
mtx.m[3][2] = pMatrix[5];
|
||||
|
||||
mtx.m[0][3] = 0.0f;
|
||||
mtx.m[1][3] = 0.0f;
|
||||
mtx.m[2][3] = -1.0f;
|
||||
mtx.m[3][3] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtx.m[0][0] = pMatrix[0];
|
||||
mtx.m[1][0] = 0.0f;
|
||||
mtx.m[2][0] = 0.0f;
|
||||
mtx.m[3][0] = pMatrix[1]-0.5f/m_width; // fix d3d pixel center
|
||||
|
||||
mtx.m[0][1] = 0.0f;
|
||||
mtx.m[1][1] = pMatrix[2];
|
||||
mtx.m[2][1] = 0.0f;
|
||||
mtx.m[3][1] = pMatrix[3]+0.5f/m_height; // fix d3d pixel center
|
||||
|
||||
mtx.m[0][2] = 0.0f;
|
||||
mtx.m[1][2] = 0.0f;
|
||||
mtx.m[2][2] = pMatrix[4];
|
||||
mtx.m[3][2] = -(-1 - pMatrix[5]);
|
||||
|
||||
mtx.m[0][3] = 0;
|
||||
mtx.m[1][3] = 0;
|
||||
mtx.m[2][3] = 0.0f;
|
||||
mtx.m[3][3] = 1.0f;
|
||||
}
|
||||
D3D::dev->SetVertexShaderConstantF(constantIndex, mtx, 4);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetTexture( DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture )
|
||||
{
|
||||
if ( m_Textures[Stage] != pTexture )
|
||||
{
|
||||
m_Textures[Stage] = pTexture;
|
||||
D3D::dev->SetTexture( Stage, pTexture );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetFVF( DWORD FVF )
|
||||
{
|
||||
if ( m_FVF != FVF )
|
||||
{
|
||||
m_FVF = FVF;
|
||||
D3D::dev->SetFVF( FVF );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value )
|
||||
{
|
||||
if ( m_RenderStates[State] != Value )
|
||||
{
|
||||
m_RenderStates[State] = Value;
|
||||
D3D::dev->SetRenderState( State, Value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value )
|
||||
{
|
||||
if ( m_TextureStageStates[Stage][Type] != Value )
|
||||
{
|
||||
m_TextureStageStates[Stage][Type] = Value;
|
||||
D3D::dev->SetTextureStageState( Stage, Type, Value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value )
|
||||
{
|
||||
if ( m_SamplerStates[Sampler][Type] != Value )
|
||||
{
|
||||
m_SamplerStates[Sampler][Type] = Value;
|
||||
D3D::dev->SetSamplerState( Sampler, Type, Value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride )
|
||||
{
|
||||
D3D::dev->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride );
|
||||
}
|
||||
|
||||
|
||||
void Renderer::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount )
|
||||
{
|
||||
D3D::dev->DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount );
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
#include "VertexManager.h"
|
||||
#include "Render.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "D3DPostprocess.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "TextureCache.h"
|
||||
#include "Utils.h"
|
||||
#include "EmuWindow.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
float Renderer::m_x,Renderer::m_y,Renderer::m_width, Renderer::m_height, Renderer::xScale,Renderer::yScale;
|
||||
std::vector<LPDIRECT3DBASETEXTURE9> Renderer::m_Textures;
|
||||
DWORD Renderer::m_RenderStates[MaxRenderStates];
|
||||
DWORD Renderer::m_TextureStageStates[MaxTextureStages][MaxTextureTypes];
|
||||
DWORD Renderer::m_SamplerStates[MaxSamplerSize][MaxSamplerTypes];
|
||||
DWORD Renderer::m_FVF;
|
||||
|
||||
#define NUMWNDRES 6
|
||||
extern int g_Res[NUMWNDRES][2];
|
||||
|
||||
|
||||
struct Message
|
||||
{
|
||||
Message(const std::string &msg, u32 dw) : message( msg ), dwTimeStamp( dw )
|
||||
{
|
||||
}
|
||||
|
||||
std::string message;
|
||||
u32 dwTimeStamp;
|
||||
};
|
||||
static std::list<Message> s_listMsgs;
|
||||
|
||||
|
||||
void Renderer::Init(SVideoInitialize &_VideoInitialize)
|
||||
{
|
||||
EmuWindow::SetSize(g_Res[g_Config.iWindowedRes][0], g_Res[g_Config.iWindowedRes][1]);
|
||||
|
||||
D3D::Create(g_Config.iAdapter, EmuWindow::GetWnd(), g_Config.bFullscreen, g_Config.iFSResolution, g_Config.iMultisampleMode);
|
||||
|
||||
D3DVIEWPORT9 vp;
|
||||
D3D::dev->GetViewport(&vp);
|
||||
|
||||
m_x = 0;
|
||||
m_y = 0;
|
||||
m_width = (float)vp.Width;
|
||||
m_height = (float)vp.Height;
|
||||
xScale = 640.0f / (float)vp.Width;
|
||||
yScale = 480.0f / (float)vp.Height;
|
||||
|
||||
D3D::font.Init();
|
||||
Initialize();
|
||||
}
|
||||
|
||||
void Renderer::Shutdown(void)
|
||||
{
|
||||
D3D::font.Shutdown();
|
||||
D3D::EndFrame();
|
||||
D3D::Close();
|
||||
}
|
||||
|
||||
void Renderer::Initialize(void)
|
||||
{
|
||||
m_FVF = 0;
|
||||
|
||||
m_Textures.reserve( MaxTextureStages );
|
||||
for ( int i = 0; i < MaxTextureStages; i++ )
|
||||
{
|
||||
m_Textures.push_back( NULL );
|
||||
}
|
||||
|
||||
for (int i=0; i<8; i++)
|
||||
{
|
||||
D3D::dev->SetSamplerState(i, D3DSAMP_MAXANISOTROPY, 16);
|
||||
}
|
||||
ReinitView();
|
||||
|
||||
Postprocess::Initialize();
|
||||
Postprocess::BeginFrame();
|
||||
D3D::BeginFrame(true, 0);
|
||||
VertexManager::BeginFrame();
|
||||
}
|
||||
|
||||
void Renderer::AddMessage(const std::string &message, u32 ms)
|
||||
{
|
||||
s_listMsgs.push_back(Message(message, timeGetTime()+ms));
|
||||
}
|
||||
|
||||
void Renderer::ProcessMessages()
|
||||
{
|
||||
if (s_listMsgs.size() > 0) {
|
||||
int left = 25, top = 15;
|
||||
std::list<Message>::iterator it = s_listMsgs.begin();
|
||||
|
||||
while( it != s_listMsgs.end() )
|
||||
{
|
||||
int time_left = (int)(it->dwTimeStamp - timeGetTime());
|
||||
int alpha = 255;
|
||||
|
||||
if(time_left<1024)
|
||||
{
|
||||
alpha=time_left>>2;
|
||||
if(time_left<0) alpha=0;
|
||||
}
|
||||
|
||||
alpha <<= 24;
|
||||
|
||||
RenderText(it->message, left+1, top+1, 0x000000|alpha);
|
||||
RenderText(it->message, left, top, 0xffff30|alpha);
|
||||
top += 15;
|
||||
|
||||
if (time_left <= 0)
|
||||
it = s_listMsgs.erase(it);
|
||||
else ++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::RenderText(const std::string &text, int left, int top, u32 color)
|
||||
{
|
||||
D3D::font.DrawTextScaled((float)left, (float)top, 20, 20, 0.0f, color, text.c_str(), false);
|
||||
}
|
||||
|
||||
void dumpMatrix(D3DXMATRIX &mtx)
|
||||
{
|
||||
for (int y=0; y<4; y++)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%4.4f %4.4f %4.4f %4.4f",mtx.m[y][0],mtx.m[y][1],mtx.m[y][2],mtx.m[y][3]);
|
||||
g_VideoInitialize.pLog(temp, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void Renderer::ReinitView()
|
||||
{
|
||||
D3DXMATRIX mtx;
|
||||
D3DXMatrixIdentity(&mtx);
|
||||
D3D::dev->SetTransform(D3DTS_VIEW,&mtx);
|
||||
D3D::dev->SetTransform(D3DTS_WORLD,&mtx);
|
||||
|
||||
float width = (float)D3D::GetDisplayWidth();
|
||||
float height = (float)D3D::GetDisplayHeight();
|
||||
|
||||
xScale = width/640.0f;
|
||||
yScale = height/480.0f;
|
||||
|
||||
RECT rc = {
|
||||
(LONG)(m_x*xScale), (LONG)(m_y*yScale), (LONG)(m_width*xScale), (LONG)(m_height*yScale)
|
||||
};
|
||||
}
|
||||
|
||||
void Renderer::SwapBuffers(void)
|
||||
{
|
||||
// center window again
|
||||
if (EmuWindow::GetParentWnd())
|
||||
{
|
||||
RECT rcWindow;
|
||||
GetWindowRect(EmuWindow::GetParentWnd(), &rcWindow);
|
||||
|
||||
int width = rcWindow.right - rcWindow.left;
|
||||
int height = rcWindow.bottom - rcWindow.top;
|
||||
|
||||
::MoveWindow(EmuWindow::GetWnd(), 0,0,width,height, FALSE);
|
||||
// nBackbufferWidth = width;
|
||||
// nBackbufferHeight = height;
|
||||
}
|
||||
|
||||
//Finish up the current frame, print some stats
|
||||
Postprocess::FinalizeFrame();
|
||||
if (g_Config.bOverlayStats)
|
||||
{
|
||||
char st[2048];
|
||||
char *p = st;
|
||||
p+=sprintf(p,"Num textures created: %i\n",stats.numTexturesCreated);
|
||||
p+=sprintf(p,"Num textures alive: %i\n",stats.numTexturesAlive);
|
||||
p+=sprintf(p,"Num pshaders created: %i\n",stats.numPixelShadersCreated);
|
||||
p+=sprintf(p,"Num pshaders alive: %i\n",stats.numPixelShadersAlive);
|
||||
p+=sprintf(p,"Num vshaders created: %i\n",stats.numVertexShadersCreated);
|
||||
p+=sprintf(p,"Num vshaders alive: %i\n",stats.numVertexShadersAlive);
|
||||
p+=sprintf(p,"Num dlists called: %i\n",stats.numDListsCalled);
|
||||
p+=sprintf(p,"Num dlists created: %i\n",stats.numDListsCreated);
|
||||
p+=sprintf(p,"Num dlists alive: %i\n",stats.numDListsAlive);
|
||||
p+=sprintf(p,"Num primitives: %i\n",stats.thisFrame.numPrims);
|
||||
p+=sprintf(p,"Num primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins);
|
||||
p+=sprintf(p,"Num primitives (DL): %i\n",stats.thisFrame.numDLPrims);
|
||||
p+=sprintf(p,"Num XF loads: %i\n",stats.thisFrame.numXFLoads);
|
||||
p+=sprintf(p,"Num XF loads (DL): %i\n",stats.thisFrame.numXFLoadsInDL);
|
||||
p+=sprintf(p,"Num CP loads: %i\n",stats.thisFrame.numCPLoads);
|
||||
p+=sprintf(p,"Num CP loads (DL): %i\n",stats.thisFrame.numCPLoadsInDL);
|
||||
p+=sprintf(p,"Num BP loads: %i\n",stats.thisFrame.numBPLoads);
|
||||
p+=sprintf(p,"Num BP loads (DL): %i\n",stats.thisFrame.numBPLoadsInDL);
|
||||
|
||||
D3D::font.DrawTextScaled(0,30,20,20,0.0f,0xFF00FFFF,st,false);
|
||||
|
||||
//end frame
|
||||
}
|
||||
|
||||
ProcessMessages();
|
||||
|
||||
#if defined(DVPROFILE)
|
||||
if( g_bWriteProfile ) {
|
||||
//g_bWriteProfile = 0;
|
||||
static int framenum = 0;
|
||||
const int UPDATE_FRAMES = 8;
|
||||
if( ++framenum >= UPDATE_FRAMES ) {
|
||||
DVProfWrite("prof.txt", UPDATE_FRAMES);
|
||||
DVProfClear();
|
||||
framenum = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
D3D::EndFrame();
|
||||
//D3D frame is now over
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//clean out old stuff from caches
|
||||
frameCount++;
|
||||
PShaderCache::Cleanup();
|
||||
VShaderCache::Cleanup();
|
||||
TextureCache::Cleanup();
|
||||
//DListCache::Cleanup();
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Begin new frame
|
||||
//Set default viewport and scissor, for the clear to work correctly
|
||||
stats.ResetFrame();
|
||||
D3DVIEWPORT9 vp;
|
||||
vp.X = 0;
|
||||
vp.Y = 0;
|
||||
vp.Width = (DWORD)m_width;
|
||||
vp.Height = (DWORD)m_height;
|
||||
vp.MinZ = 0;
|
||||
vp.MaxZ = 0;
|
||||
D3D::dev->SetViewport(&vp);
|
||||
RECT rc;
|
||||
rc.left = 0;
|
||||
rc.top = 0;
|
||||
rc.right = (LONG)m_width;
|
||||
rc.bottom = (LONG)m_height;
|
||||
D3D::dev->SetScissorRect(&rc);
|
||||
|
||||
u32 clearColor = (bpmem.clearcolorAR<<16)|bpmem.clearcolorGB;
|
||||
// clearColor |= 0x003F003F;
|
||||
// D3D::BeginFrame(true,clearColor,1.0f);
|
||||
D3D::BeginFrame(false,clearColor,1.0f);
|
||||
// D3D::EnableAlphaToCoverage();
|
||||
|
||||
Postprocess::BeginFrame();
|
||||
VertexManager::BeginFrame();
|
||||
|
||||
if (g_Config.bOldCard)
|
||||
D3D::font.SetRenderStates(); //compatibility with low end cards
|
||||
}
|
||||
|
||||
void Renderer::Flush(void)
|
||||
{
|
||||
// render the rest of the vertex buffer
|
||||
//only to be used for debugging purposes
|
||||
//D3D::EndFrame();
|
||||
|
||||
//D3D::BeginFrame(false,0);
|
||||
}
|
||||
|
||||
void Renderer::SetViewport(float* _Viewport)
|
||||
{
|
||||
Viewport* pViewport = (Viewport*)_Viewport;
|
||||
D3DVIEWPORT9 vp;
|
||||
float x=(pViewport->xOrig-662)*2;
|
||||
float y=(pViewport->yOrig-582)*2; //something is wrong, but what??
|
||||
y-=16;
|
||||
|
||||
float w=pViewport->wd*2; //multiply up to real size
|
||||
float h=pViewport->ht*-2; //why is this negative? oh well..
|
||||
|
||||
if (x < 0.0f) x = 0.0f;
|
||||
if (y < 0.0f) y = 0.0f;
|
||||
if (x > 640.0f) x = 639.0f;
|
||||
if (y > 480.0f) y = 479.0f;
|
||||
if (w < 0) w=1;
|
||||
if (h < 0) h=1;
|
||||
if (x+w > 640.0f) w=640-x;
|
||||
if (y+h > 480.0f) h=480-y;
|
||||
//x=y=0;
|
||||
//if(w>0.0f) w=0.0f;
|
||||
//if(h<0.0f) h=0.0f;
|
||||
|
||||
vp.X = (DWORD)(x*xScale);
|
||||
vp.Y = (DWORD)(y*yScale);
|
||||
vp.Width = (DWORD)(w*xScale);
|
||||
vp.Height = (DWORD)(h*yScale);
|
||||
vp.MinZ = 0.0f;
|
||||
vp.MaxZ = 1.0f;
|
||||
|
||||
// char temp[256];
|
||||
// sprintf(temp,"Viewport: %i %i %i %i %f %f",vp.X,vp.Y,vp.Width,vp.Height,vp.MinZ,vp.MaxZ);
|
||||
// g_VideoInitialize.pLog(temp, FALSE);
|
||||
|
||||
D3D::dev->SetViewport(&vp);
|
||||
}
|
||||
|
||||
void Renderer::SetScissorBox(RECT &rc)
|
||||
{
|
||||
rc.left = (int)(rc.left * xScale);
|
||||
rc.top = (int)(rc.top * yScale);
|
||||
rc.right = (int)(rc.right * xScale);
|
||||
rc.bottom = (int)(rc.bottom * yScale);
|
||||
if (rc.right >= rc.left && rc.bottom >= rc.top)
|
||||
D3D::dev->SetScissorRect(&rc);
|
||||
else
|
||||
g_VideoInitialize.pLog("SCISSOR ERROR", FALSE);
|
||||
}
|
||||
|
||||
void Renderer::SetProjection(float* pMatrix, int constantIndex)
|
||||
{
|
||||
D3DXMATRIX mtx;
|
||||
if (pMatrix[6] == 0)
|
||||
{
|
||||
mtx.m[0][0] = pMatrix[0];
|
||||
mtx.m[1][0] = 0.0f;
|
||||
mtx.m[2][0] = pMatrix[1];
|
||||
mtx.m[3][0] = -0.5f/m_width;
|
||||
|
||||
mtx.m[0][1] = 0.0f;
|
||||
mtx.m[1][1] = pMatrix[2];
|
||||
mtx.m[2][1] = pMatrix[3];
|
||||
mtx.m[3][1] = +0.5f/m_height;
|
||||
|
||||
mtx.m[0][2] = 0.0f;
|
||||
mtx.m[1][2] = 0.0f;
|
||||
mtx.m[2][2] = -(1-pMatrix[4]);
|
||||
mtx.m[3][2] = pMatrix[5];
|
||||
|
||||
mtx.m[0][3] = 0.0f;
|
||||
mtx.m[1][3] = 0.0f;
|
||||
mtx.m[2][3] = -1.0f;
|
||||
mtx.m[3][3] = 0.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtx.m[0][0] = pMatrix[0];
|
||||
mtx.m[1][0] = 0.0f;
|
||||
mtx.m[2][0] = 0.0f;
|
||||
mtx.m[3][0] = pMatrix[1]-0.5f/m_width; // fix d3d pixel center
|
||||
|
||||
mtx.m[0][1] = 0.0f;
|
||||
mtx.m[1][1] = pMatrix[2];
|
||||
mtx.m[2][1] = 0.0f;
|
||||
mtx.m[3][1] = pMatrix[3]+0.5f/m_height; // fix d3d pixel center
|
||||
|
||||
mtx.m[0][2] = 0.0f;
|
||||
mtx.m[1][2] = 0.0f;
|
||||
mtx.m[2][2] = pMatrix[4];
|
||||
mtx.m[3][2] = -(-1 - pMatrix[5]);
|
||||
|
||||
mtx.m[0][3] = 0;
|
||||
mtx.m[1][3] = 0;
|
||||
mtx.m[2][3] = 0.0f;
|
||||
mtx.m[3][3] = 1.0f;
|
||||
}
|
||||
D3D::dev->SetVertexShaderConstantF(constantIndex, mtx, 4);
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetTexture( DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture )
|
||||
{
|
||||
if ( m_Textures[Stage] != pTexture )
|
||||
{
|
||||
m_Textures[Stage] = pTexture;
|
||||
D3D::dev->SetTexture( Stage, pTexture );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetFVF( DWORD FVF )
|
||||
{
|
||||
if ( m_FVF != FVF )
|
||||
{
|
||||
m_FVF = FVF;
|
||||
D3D::dev->SetFVF( FVF );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetRenderState( D3DRENDERSTATETYPE State, DWORD Value )
|
||||
{
|
||||
if ( m_RenderStates[State] != Value )
|
||||
{
|
||||
m_RenderStates[State] = Value;
|
||||
D3D::dev->SetRenderState( State, Value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetTextureStageState( DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value )
|
||||
{
|
||||
if ( m_TextureStageStates[Stage][Type] != Value )
|
||||
{
|
||||
m_TextureStageStates[Stage][Type] = Value;
|
||||
D3D::dev->SetTextureStageState( Stage, Type, Value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::SetSamplerState( DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value )
|
||||
{
|
||||
if ( m_SamplerStates[Sampler][Type] != Value )
|
||||
{
|
||||
m_SamplerStates[Sampler][Type] = Value;
|
||||
D3D::dev->SetSamplerState( Sampler, Type, Value );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Renderer::DrawPrimitiveUP( D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void* pVertexStreamZeroData, UINT VertexStreamZeroStride )
|
||||
{
|
||||
D3D::dev->DrawPrimitiveUP( PrimitiveType, PrimitiveCount, pVertexStreamZeroData, VertexStreamZeroStride );
|
||||
}
|
||||
|
||||
|
||||
void Renderer::DrawPrimitive( D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount )
|
||||
{
|
||||
D3D::dev->DrawPrimitive( PrimitiveType, StartVertex, PrimitiveCount );
|
||||
}
|
||||
|
||||
@@ -1,218 +1,218 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "Statistics.h"
|
||||
#include "Utils.h"
|
||||
#include "Profiler.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
|
||||
|
||||
//I hope we don't get too many hash collisions :p
|
||||
//all these magic numbers are primes, it should help a bit
|
||||
tevhash GetCurrentTEV()
|
||||
{
|
||||
u32 hash = bpmem.genMode.numindstages + bpmem.genMode.numtevstages*11 + bpmem.genMode.numtexgens*8*17;
|
||||
for (int i = 0; i < (int)bpmem.genMode.numtevstages+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13);
|
||||
hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3);
|
||||
hash = _rotl(hash,9) ^ xfregs.texcoords[i].texmtxinfo.projection*451;
|
||||
}
|
||||
for (int i = 0; i < (int)bpmem.genMode.numtevstages/2+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7);
|
||||
}
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1;
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2;
|
||||
}
|
||||
hash ^= bpmem.dstalpha.enable ^ 0xc0debabe;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp0*7;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp1*13;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.logic*11;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
PShaderCache::PSCache PShaderCache::pshaders;
|
||||
VShaderCache::VSCache VShaderCache::vshaders;
|
||||
|
||||
void PShaderCache::Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PShaderCache::Shutdown()
|
||||
{
|
||||
PSCache::iterator iter = pshaders.begin();
|
||||
for (;iter!=pshaders.end();iter++)
|
||||
iter->second.Destroy();
|
||||
pshaders.clear();
|
||||
}
|
||||
|
||||
|
||||
void PShaderCache::SetShader()
|
||||
{
|
||||
if (D3D::GetShaderVersion() < 2)
|
||||
return; // we are screwed
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 lastShader = 0;
|
||||
DVSTARTPROFILE();
|
||||
|
||||
tevhash currentHash = GetCurrentTEV();
|
||||
|
||||
PSCache::iterator iter;
|
||||
iter = pshaders.find(currentHash);
|
||||
|
||||
if (iter != pshaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (!lastShader || entry.shader != lastShader)
|
||||
{
|
||||
D3D::dev->SetPixelShader(entry.shader);
|
||||
lastShader = entry.shader;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const char *code = GeneratePixelShader();
|
||||
LPDIRECT3DPIXELSHADER9 shader = D3D::CompilePShader(code, int(strlen(code)));
|
||||
if (shader)
|
||||
{
|
||||
//Make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
newentry.frameCount = frameCount;
|
||||
pshaders[currentHash] = newentry;
|
||||
}
|
||||
|
||||
D3D::dev->SetPixelShader(shader);
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
||||
}
|
||||
|
||||
void PShaderCache::Cleanup()
|
||||
{
|
||||
PSCache::iterator iter;
|
||||
iter = pshaders.begin();
|
||||
|
||||
while (iter != pshaders.end())
|
||||
{
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount < frameCount-30)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = pshaders.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::Init()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::Shutdown()
|
||||
{
|
||||
VSCache::iterator iter = vshaders.begin();
|
||||
for (; iter != vshaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::SetShader()
|
||||
{
|
||||
static LPDIRECT3DVERTEXSHADER9 shader = NULL;
|
||||
if (D3D::GetShaderVersion() < 2)
|
||||
return; // we are screwed
|
||||
|
||||
if (shader) {
|
||||
//D3D::dev->SetVertexShader(shader);
|
||||
return;
|
||||
}
|
||||
|
||||
static LPDIRECT3DVERTEXSHADER9 lastShader = 0;
|
||||
DVSTARTPROFILE();
|
||||
|
||||
tevhash currentHash = GetCurrentTEV();
|
||||
|
||||
VSCache::iterator iter;
|
||||
iter = vshaders.find(currentHash);
|
||||
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
iter->second.frameCount=frameCount;
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (!lastShader || entry.shader != lastShader)
|
||||
{
|
||||
D3D::dev->SetVertexShader(entry.shader);
|
||||
lastShader = entry.shader;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const char *code = GenerateVertexShader();
|
||||
shader = D3D::CompileVShader(code, int(strlen(code)));
|
||||
if (shader)
|
||||
{
|
||||
//Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
entry.frameCount=frameCount;
|
||||
vshaders[currentHash] = entry;
|
||||
}
|
||||
|
||||
D3D::dev->SetVertexShader(shader);
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
}
|
||||
|
||||
void VShaderCache::Cleanup()
|
||||
{
|
||||
for (VSCache::iterator iter=vshaders.begin(); iter!=vshaders.end();)
|
||||
{
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount < frameCount - 30)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = vshaders.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "Statistics.h"
|
||||
#include "Utils.h"
|
||||
#include "Profiler.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "BPMemory.h"
|
||||
#include "XFMemory.h"
|
||||
|
||||
|
||||
//I hope we don't get too many hash collisions :p
|
||||
//all these magic numbers are primes, it should help a bit
|
||||
tevhash GetCurrentTEV()
|
||||
{
|
||||
u32 hash = bpmem.genMode.numindstages + bpmem.genMode.numtevstages*11 + bpmem.genMode.numtexgens*8*17;
|
||||
for (int i = 0; i < (int)bpmem.genMode.numtevstages+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ (bpmem.combiners[i].colorC.hex*13);
|
||||
hash = _rotl(hash,7) ^ ((bpmem.combiners[i].alphaC.hex&0xFFFFFFFC)*3);
|
||||
hash = _rotl(hash,9) ^ xfregs.texcoords[i].texmtxinfo.projection*451;
|
||||
}
|
||||
for (int i = 0; i < (int)bpmem.genMode.numtevstages/2+1; i++)
|
||||
{
|
||||
hash = _rotl(hash,13) ^ (bpmem.tevorders[i].hex*7);
|
||||
}
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap1;
|
||||
hash = _rotl(hash,3) ^ bpmem.tevksel[i].swap2;
|
||||
}
|
||||
hash ^= bpmem.dstalpha.enable ^ 0xc0debabe;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp0*7;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.comp1*13;
|
||||
hash = _rotl(hash,4) ^ bpmem.alphaFunc.logic*11;
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
PShaderCache::PSCache PShaderCache::pshaders;
|
||||
VShaderCache::VSCache VShaderCache::vshaders;
|
||||
|
||||
void PShaderCache::Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
void PShaderCache::Shutdown()
|
||||
{
|
||||
PSCache::iterator iter = pshaders.begin();
|
||||
for (;iter!=pshaders.end();iter++)
|
||||
iter->second.Destroy();
|
||||
pshaders.clear();
|
||||
}
|
||||
|
||||
|
||||
void PShaderCache::SetShader()
|
||||
{
|
||||
if (D3D::GetShaderVersion() < 2)
|
||||
return; // we are screwed
|
||||
|
||||
static LPDIRECT3DPIXELSHADER9 lastShader = 0;
|
||||
DVSTARTPROFILE();
|
||||
|
||||
tevhash currentHash = GetCurrentTEV();
|
||||
|
||||
PSCache::iterator iter;
|
||||
iter = pshaders.find(currentHash);
|
||||
|
||||
if (iter != pshaders.end())
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (!lastShader || entry.shader != lastShader)
|
||||
{
|
||||
D3D::dev->SetPixelShader(entry.shader);
|
||||
lastShader = entry.shader;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const char *code = GeneratePixelShader();
|
||||
LPDIRECT3DPIXELSHADER9 shader = D3D::CompilePShader(code, int(strlen(code)));
|
||||
if (shader)
|
||||
{
|
||||
//Make an entry in the table
|
||||
PSCacheEntry newentry;
|
||||
newentry.shader = shader;
|
||||
newentry.frameCount = frameCount;
|
||||
pshaders[currentHash] = newentry;
|
||||
}
|
||||
|
||||
D3D::dev->SetPixelShader(shader);
|
||||
|
||||
INCSTAT(stats.numPixelShadersCreated);
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
||||
}
|
||||
|
||||
void PShaderCache::Cleanup()
|
||||
{
|
||||
PSCache::iterator iter;
|
||||
iter = pshaders.begin();
|
||||
|
||||
while (iter != pshaders.end())
|
||||
{
|
||||
PSCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount < frameCount-30)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = pshaders.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::Init()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::Shutdown()
|
||||
{
|
||||
VSCache::iterator iter = vshaders.begin();
|
||||
for (; iter != vshaders.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
vshaders.clear();
|
||||
}
|
||||
|
||||
|
||||
void VShaderCache::SetShader()
|
||||
{
|
||||
static LPDIRECT3DVERTEXSHADER9 shader = NULL;
|
||||
if (D3D::GetShaderVersion() < 2)
|
||||
return; // we are screwed
|
||||
|
||||
if (shader) {
|
||||
//D3D::dev->SetVertexShader(shader);
|
||||
return;
|
||||
}
|
||||
|
||||
static LPDIRECT3DVERTEXSHADER9 lastShader = 0;
|
||||
DVSTARTPROFILE();
|
||||
|
||||
tevhash currentHash = GetCurrentTEV();
|
||||
|
||||
VSCache::iterator iter;
|
||||
iter = vshaders.find(currentHash);
|
||||
|
||||
if (iter != vshaders.end())
|
||||
{
|
||||
iter->second.frameCount=frameCount;
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (!lastShader || entry.shader != lastShader)
|
||||
{
|
||||
D3D::dev->SetVertexShader(entry.shader);
|
||||
lastShader = entry.shader;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const char *code = GenerateVertexShader();
|
||||
shader = D3D::CompileVShader(code, int(strlen(code)));
|
||||
if (shader)
|
||||
{
|
||||
//Make an entry in the table
|
||||
VSCacheEntry entry;
|
||||
entry.shader = shader;
|
||||
entry.frameCount=frameCount;
|
||||
vshaders[currentHash] = entry;
|
||||
}
|
||||
|
||||
D3D::dev->SetVertexShader(shader);
|
||||
|
||||
INCSTAT(stats.numVertexShadersCreated);
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
}
|
||||
|
||||
void VShaderCache::Cleanup()
|
||||
{
|
||||
for (VSCache::iterator iter=vshaders.begin(); iter!=vshaders.end();)
|
||||
{
|
||||
VSCacheEntry &entry = iter->second;
|
||||
if (entry.frameCount < frameCount - 30)
|
||||
{
|
||||
entry.Destroy();
|
||||
iter = vshaders.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
}
|
||||
|
||||
@@ -1,251 +1,251 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
|
||||
#include "Render.h"
|
||||
|
||||
#include "TextureDecoder.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
|
||||
u8 *TextureCache::temp = NULL;
|
||||
TextureCache::TexCache TextureCache::textures;
|
||||
|
||||
extern int frameCount;
|
||||
|
||||
#define TEMP_SIZE (1024*1024*4)
|
||||
|
||||
void TextureCache::TCacheEntry::Destroy()
|
||||
{
|
||||
if (texture)
|
||||
texture->Release();
|
||||
texture = 0;
|
||||
if (!isRenderTarget) {
|
||||
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4);
|
||||
if (*ptr == hash)
|
||||
*ptr = oldpixel;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::Init()
|
||||
{
|
||||
temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE);
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
|
||||
}
|
||||
|
||||
void TextureCache::Invalidate()
|
||||
{
|
||||
TexCache::iterator iter = textures.begin();
|
||||
for (; iter != textures.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
textures.clear();
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
|
||||
}
|
||||
|
||||
void TextureCache::Shutdown()
|
||||
{
|
||||
Invalidate();
|
||||
|
||||
if (temp != NULL)
|
||||
{
|
||||
VirtualFree(temp, 0, MEM_RELEASE);
|
||||
temp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::Cleanup()
|
||||
{
|
||||
TexCache::iterator iter=textures.begin();
|
||||
|
||||
while(iter != textures.end())
|
||||
{
|
||||
if (frameCount>20+iter->second.frameCount)
|
||||
{
|
||||
if (!iter->second.isRenderTarget)
|
||||
{
|
||||
iter->second.Destroy();
|
||||
iter = textures.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
if (address == 0)
|
||||
return;
|
||||
TexCache::iterator iter = textures.find(address);
|
||||
|
||||
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
|
||||
|
||||
int palSize = TexDecoder_GetPaletteSize(format);
|
||||
u32 palhash = 0xc0debabe;
|
||||
if (palSize)
|
||||
{
|
||||
if (palSize>16)
|
||||
palSize = 16; //let's not do excessive amount of checking
|
||||
u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr);
|
||||
if (pal != 0)
|
||||
{
|
||||
for (int i=0; i<palSize; i++)
|
||||
{
|
||||
palhash = _rotl(palhash,13);
|
||||
palhash ^= pal[i];
|
||||
palhash += 31;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LPDIRECT3DTEXTURE9 lastTexture[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
if (iter != textures.end())
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
|
||||
if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
if (lastTexture[stage] == iter->second.texture)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lastTexture[stage] = iter->second.texture;
|
||||
|
||||
// D3D::dev->SetTexture(stage,iter->second.texture);
|
||||
Renderer::SetTexture( stage, iter->second.texture );
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex = entry.texture;
|
||||
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width+bs) & (~bs);
|
||||
D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||
D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt);
|
||||
D3D::dev->SetTexture(stage,tex);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{*/
|
||||
iter->second.Destroy();
|
||||
textures.erase(iter);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width+bs) & (~bs);
|
||||
PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||
D3DFORMAT d3d_fmt;
|
||||
switch (pcfmt) {
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
TCacheEntry entry;
|
||||
entry.hashoffset = 0;
|
||||
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
||||
entry.paletteHash = palhash;
|
||||
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
|
||||
((u32 *)ptr)[entry.hashoffset] = entry.hash;
|
||||
|
||||
entry.addr = address;
|
||||
entry.isRenderTarget=false;
|
||||
entry.isNonPow2 = ((width&(width-1)) || (height&(height-1)));
|
||||
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
|
||||
entry.frameCount = frameCount;
|
||||
entry.w=width;
|
||||
entry.h=height;
|
||||
entry.fmt=format;
|
||||
textures[address] = entry;
|
||||
|
||||
if (g_Config.bDumpTextures)
|
||||
{ // dump texture to file
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format);
|
||||
|
||||
D3DXSaveTextureToFile(szTemp,D3DXIFF_BMP,entry.texture,0);
|
||||
}
|
||||
|
||||
INCSTAT(stats.numTexturesCreated);
|
||||
SETSTAT(stats.numTexturesAlive, (int)textures.size());
|
||||
|
||||
//Set the texture!
|
||||
// D3D::dev->SetTexture(stage,entry.texture);
|
||||
Renderer::SetTexture( stage, entry.texture );
|
||||
|
||||
lastTexture[stage] = entry.texture;
|
||||
}
|
||||
|
||||
|
||||
void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
|
||||
{
|
||||
TexCache::iterator iter;
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
iter = textures.find(address);
|
||||
if (iter != textures.end())
|
||||
{
|
||||
if (!iter->second.isRenderTarget)
|
||||
{
|
||||
g_VideoInitialize.pLog("Using non-rendertarget texture as render target!!! WTF?", FALSE);
|
||||
//TODO: remove it and recreate it as a render target
|
||||
}
|
||||
tex = iter->second.texture;
|
||||
iter->second.frameCount=frameCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
TCacheEntry entry;
|
||||
entry.isRenderTarget=true;
|
||||
entry.hash = 0;
|
||||
entry.hashoffset = 0;
|
||||
entry.frameCount = frameCount;
|
||||
// TODO(ector): infer this size in some sensible way
|
||||
D3D::dev->CreateTexture(512,512,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
|
||||
textures[address] = entry;
|
||||
tex = entry.texture;
|
||||
}
|
||||
LPDIRECT3DSURFACE9 srcSurface,destSurface;
|
||||
tex->GetSurfaceLevel(0,&destSurface);
|
||||
srcSurface = D3D::GetBackBufferSurface();
|
||||
D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE);
|
||||
destSurface->Release();
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Statistics.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
#include "D3DTexture.h"
|
||||
|
||||
#include "Render.h"
|
||||
|
||||
#include "TextureDecoder.h"
|
||||
#include "TextureCache.h"
|
||||
|
||||
#include "Config.h"
|
||||
#include "main.h"
|
||||
|
||||
u8 *TextureCache::temp = NULL;
|
||||
TextureCache::TexCache TextureCache::textures;
|
||||
|
||||
extern int frameCount;
|
||||
|
||||
#define TEMP_SIZE (1024*1024*4)
|
||||
|
||||
void TextureCache::TCacheEntry::Destroy()
|
||||
{
|
||||
if (texture)
|
||||
texture->Release();
|
||||
texture = 0;
|
||||
if (!isRenderTarget) {
|
||||
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4);
|
||||
if (*ptr == hash)
|
||||
*ptr = oldpixel;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::Init()
|
||||
{
|
||||
temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE);
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
|
||||
}
|
||||
|
||||
void TextureCache::Invalidate()
|
||||
{
|
||||
TexCache::iterator iter = textures.begin();
|
||||
for (; iter != textures.end(); iter++)
|
||||
iter->second.Destroy();
|
||||
textures.clear();
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
|
||||
}
|
||||
|
||||
void TextureCache::Shutdown()
|
||||
{
|
||||
Invalidate();
|
||||
|
||||
if (temp != NULL)
|
||||
{
|
||||
VirtualFree(temp, 0, MEM_RELEASE);
|
||||
temp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::Cleanup()
|
||||
{
|
||||
TexCache::iterator iter=textures.begin();
|
||||
|
||||
while(iter != textures.end())
|
||||
{
|
||||
if (frameCount>20+iter->second.frameCount)
|
||||
{
|
||||
if (!iter->second.isRenderTarget)
|
||||
{
|
||||
iter->second.Destroy();
|
||||
iter = textures.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
if (address == 0)
|
||||
return;
|
||||
TexCache::iterator iter = textures.find(address);
|
||||
|
||||
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
|
||||
|
||||
int palSize = TexDecoder_GetPaletteSize(format);
|
||||
u32 palhash = 0xc0debabe;
|
||||
if (palSize)
|
||||
{
|
||||
if (palSize>16)
|
||||
palSize = 16; //let's not do excessive amount of checking
|
||||
u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr);
|
||||
if (pal != 0)
|
||||
{
|
||||
for (int i=0; i<palSize; i++)
|
||||
{
|
||||
palhash = _rotl(palhash,13);
|
||||
palhash ^= pal[i];
|
||||
palhash += 31;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static LPDIRECT3DTEXTURE9 lastTexture[8] = {0,0,0,0,0,0,0,0};
|
||||
|
||||
if (iter != textures.end())
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
|
||||
if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve
|
||||
{
|
||||
iter->second.frameCount = frameCount;
|
||||
if (lastTexture[stage] == iter->second.texture)
|
||||
{
|
||||
return;
|
||||
}
|
||||
lastTexture[stage] = iter->second.texture;
|
||||
|
||||
// D3D::dev->SetTexture(stage,iter->second.texture);
|
||||
Renderer::SetTexture( stage, iter->second.texture );
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex = entry.texture;
|
||||
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width+bs) & (~bs);
|
||||
D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||
D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt);
|
||||
D3D::dev->SetTexture(stage,tex);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{*/
|
||||
iter->second.Destroy();
|
||||
textures.erase(iter);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width+bs) & (~bs);
|
||||
PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||
D3DFORMAT d3d_fmt;
|
||||
switch (pcfmt) {
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
d3d_fmt = D3DFMT_A8R8G8B8;
|
||||
break;
|
||||
}
|
||||
|
||||
//Make an entry in the table
|
||||
TCacheEntry entry;
|
||||
entry.hashoffset = 0;
|
||||
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
||||
entry.paletteHash = palhash;
|
||||
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
|
||||
((u32 *)ptr)[entry.hashoffset] = entry.hash;
|
||||
|
||||
entry.addr = address;
|
||||
entry.isRenderTarget=false;
|
||||
entry.isNonPow2 = ((width&(width-1)) || (height&(height-1)));
|
||||
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
|
||||
entry.frameCount = frameCount;
|
||||
entry.w=width;
|
||||
entry.h=height;
|
||||
entry.fmt=format;
|
||||
textures[address] = entry;
|
||||
|
||||
if (g_Config.bDumpTextures)
|
||||
{ // dump texture to file
|
||||
static int counter = 0;
|
||||
char szTemp[MAX_PATH];
|
||||
sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format);
|
||||
|
||||
D3DXSaveTextureToFile(szTemp,D3DXIFF_BMP,entry.texture,0);
|
||||
}
|
||||
|
||||
INCSTAT(stats.numTexturesCreated);
|
||||
SETSTAT(stats.numTexturesAlive, (int)textures.size());
|
||||
|
||||
//Set the texture!
|
||||
// D3D::dev->SetTexture(stage,entry.texture);
|
||||
Renderer::SetTexture( stage, entry.texture );
|
||||
|
||||
lastTexture[stage] = entry.texture;
|
||||
}
|
||||
|
||||
|
||||
void TextureCache::CopyEFBToRenderTarget(u32 address, RECT *source)
|
||||
{
|
||||
TexCache::iterator iter;
|
||||
LPDIRECT3DTEXTURE9 tex;
|
||||
iter = textures.find(address);
|
||||
if (iter != textures.end())
|
||||
{
|
||||
if (!iter->second.isRenderTarget)
|
||||
{
|
||||
g_VideoInitialize.pLog("Using non-rendertarget texture as render target!!! WTF?", FALSE);
|
||||
//TODO: remove it and recreate it as a render target
|
||||
}
|
||||
tex = iter->second.texture;
|
||||
iter->second.frameCount=frameCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
TCacheEntry entry;
|
||||
entry.isRenderTarget=true;
|
||||
entry.hash = 0;
|
||||
entry.hashoffset = 0;
|
||||
entry.frameCount = frameCount;
|
||||
// TODO(ector): infer this size in some sensible way
|
||||
D3D::dev->CreateTexture(512,512,1,D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
|
||||
textures[address] = entry;
|
||||
tex = entry.texture;
|
||||
}
|
||||
LPDIRECT3DSURFACE9 srcSurface,destSurface;
|
||||
tex->GetSurfaceLevel(0,&destSurface);
|
||||
srcSurface = D3D::GetBackBufferSurface();
|
||||
D3D::dev->StretchRect(srcSurface,source,destSurface,0,D3DTEXF_NONE);
|
||||
destSurface->Release();
|
||||
}
|
||||
|
||||
@@ -1,372 +1,372 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <fvec.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Profiler.h"
|
||||
// #include "Globals.h"
|
||||
#include "Vec3.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "RGBAFloat.h"
|
||||
|
||||
float *CTransformEngine::m_pPosMatrix;
|
||||
float *CTransformEngine::m_pNormalMatrix;
|
||||
float *CTransformEngine::m_pTexMatrix[8];
|
||||
float *CTransformEngine::m_pTexPostMatrix[8];
|
||||
|
||||
const Light *GetLight(int i)
|
||||
{
|
||||
return (const Light *)(xfmem + XFMEM_LIGHTS) + i;
|
||||
}
|
||||
|
||||
float DoLighting(const Light *light, const LitChannel &chan, const Vec3 &pos, const Vec3 &normal)
|
||||
{
|
||||
float val;
|
||||
if (chan.attnfunc == 0 || chan.attnfunc == 2) //no attn
|
||||
{
|
||||
Vec3 ldir = (Vec3(light->dpos) - pos);
|
||||
val = ldir.normalized() * normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
float aattn = 0;
|
||||
float d;
|
||||
float mul = 1.0f;
|
||||
if (chan.attnfunc == 3)
|
||||
{
|
||||
Vec3 ldir = (Vec3(light->dpos) - pos);
|
||||
d = ldir.length();
|
||||
Vec3 ldirNorm = ldir / d; //normalize
|
||||
float l = ldirNorm * normal;
|
||||
aattn = Vec3(light->ddir) * ldirNorm;
|
||||
mul = l;
|
||||
}
|
||||
else if (chan.attnfunc == 1)
|
||||
{
|
||||
d = aattn = Vec3(light->shalfangle) * normal;
|
||||
mul = (Vec3(light->sdir) * normal > 0) ? (normal * Vec3(light->shalfangle)) : 0;
|
||||
if (mul < 0)
|
||||
mul = 0;
|
||||
}
|
||||
|
||||
float spot = (light->a2*aattn*aattn + light->a1*aattn + light->a0);
|
||||
float dist = 1.0f/(light->k2*d*d + light->k1*d + light->k0);
|
||||
if (spot<0)
|
||||
spot=0;
|
||||
|
||||
val = mul * spot * dist;
|
||||
}
|
||||
|
||||
if (val < 0 && chan.diffusefunc == 2) // clamp
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void VtxMulMtx43T(Vec3 &out, const Vec3 &in, const float pMatrix[12])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
|
||||
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
|
||||
out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11];
|
||||
}
|
||||
|
||||
void VtxMulMtx43(Vec3 &out, const Vec3 &in, const float pMatrix[12])
|
||||
{
|
||||
VtxMulMtx43T(out,in,pMatrix);
|
||||
//TODO(XK): Turns out that SSE2 computations are slower... Can anyone do
|
||||
// anything about it?
|
||||
/*
|
||||
F32vec4 a(in.x, in.y, in.z, 1), b(pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3]);
|
||||
|
||||
out.x = add_horizontal(a * b);
|
||||
|
||||
b[0] = pMatrix[4]; b[1] = pMatrix[5]; b[2] = pMatrix[6]; b[3] = pMatrix[7];
|
||||
|
||||
out.y = add_horizontal(a * b);
|
||||
|
||||
b[0] = pMatrix[8]; b[1] = pMatrix[9]; b[2] = pMatrix[10]; b[3] = pMatrix[11];
|
||||
|
||||
out.z = add_horizontal(a * b);
|
||||
*/
|
||||
}
|
||||
|
||||
void VtxMulMtx42(Vec3 &out, const Vec3 &in, const float pMatrix[8])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
|
||||
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
|
||||
}
|
||||
|
||||
void VtxMulMtx33(Vec3 &out, const Vec3 &in, const float pMatrix[9])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2];
|
||||
out.y = in.x * pMatrix[3] + in.y * pMatrix[4] + in.z * pMatrix[5];
|
||||
out.z = in.x * pMatrix[6] + in.y * pMatrix[7] + in.z * pMatrix[8];
|
||||
}
|
||||
|
||||
void CTransformEngine::TransformVertices(int _numVertices, const DecodedVArray *varray, D3DVertex *vbuffer)
|
||||
{
|
||||
if (vbuffer == 0)
|
||||
{
|
||||
MessageBox(0,"TransformVertices : vbuffer == 0","WTF",0);
|
||||
}
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
RGBAFloat lightColors[8];
|
||||
RGBAFloat lightVals[8];
|
||||
RGBAFloat chans[2];
|
||||
|
||||
u32 components = varray->GetComponents();
|
||||
|
||||
// TODO: only for active lights
|
||||
for (int i=0; i<8; i++)
|
||||
lightColors[i].convert_GC(GetLight(i)->color);
|
||||
|
||||
for (int i=0; i<_numVertices; i++)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 1: xform position and normal
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Vec3 OrigPos = varray->GetPos(i);
|
||||
|
||||
if (varray->hasPosMatIdx)
|
||||
{
|
||||
int index = varray->GetPosMtxInd(i);
|
||||
SetPosNormalMatrix(
|
||||
(float*)xfmem + (index & 63) * 4, //CHECK
|
||||
(float*)xfmem + 0x400 + 3 * (index & 31)); //CHECK
|
||||
}
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (varray->hasTexMatIdx[j])
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
int index = varray->GetTexMtxInd(j, i);
|
||||
SetTexMatrix(j, flipmem + index * 4);
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 TempPos;
|
||||
|
||||
// m_pPosMatrix can be switched out, through matrixindex vertex components
|
||||
VtxMulMtx43(TempPos, OrigPos, m_pPosMatrix);
|
||||
|
||||
Vec3 TempNormal;
|
||||
Vec3 OrigNormal;
|
||||
if (varray->hasNrm)
|
||||
{
|
||||
OrigNormal = varray->GetNormal(0, i);
|
||||
VtxMulMtx33(TempNormal, OrigNormal, m_pNormalMatrix);
|
||||
TempNormal.normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
OrigNormal.setZero();
|
||||
TempNormal.setZero();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 2: Light!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//find all used lights
|
||||
u32 lightMask =
|
||||
xfregs.colChans[0].color.GetFullLightMask() | xfregs.colChans[0].alpha.GetFullLightMask() |
|
||||
xfregs.colChans[1].color.GetFullLightMask() | xfregs.colChans[1].alpha.GetFullLightMask();
|
||||
|
||||
float r0=0,g0=0,b0=0,a0=0;
|
||||
|
||||
//go through them and compute the lit colors
|
||||
//Sum lighting for both two color channels if they're active
|
||||
for (int j = 0; j < (int)bpmem.genMode.numcolchans; j++)
|
||||
{
|
||||
RGBAFloat material;
|
||||
RGBAFloat lightSum(0,0,0,0);
|
||||
|
||||
bool hasColorJ = (components & (VertexLoader::VB_HAS_COL0 << j)) != 0;
|
||||
|
||||
//get basic material color from appropriate sources (this would compile nicely!:)
|
||||
if (xfregs.colChans[j].color.matsource == GX_SRC_REG)
|
||||
material.convertRGB_GC(xfregs.colChans[j].matColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
material.convertRGB(varray->GetColor(j, i));
|
||||
else
|
||||
material.r=material.g=material.b=1.0f;
|
||||
}
|
||||
|
||||
if (xfregs.colChans[j].alpha.matsource == GX_SRC_REG)
|
||||
material.convertA_GC(xfregs.colChans[j].matColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
material.convertA(varray->GetColor(j, i));
|
||||
else
|
||||
material.a=1.0f;
|
||||
}
|
||||
|
||||
//combine together the light values from the lights that affect the color
|
||||
if (xfregs.colChans[j].color.enablelighting)
|
||||
{
|
||||
//choose ambient source and start our lightsum accumulator with its value..
|
||||
if (xfregs.colChans[j].color.ambsource == GX_SRC_REG)
|
||||
lightSum.convertRGB_GC(xfregs.colChans[j].ambColor); //ambient
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
lightSum.convertRGB(varray->GetColor(j, i));
|
||||
else
|
||||
{
|
||||
lightSum.r=0.0f;lightSum.g=0.0f;lightSum.b=0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
//accumulate light colors
|
||||
int cmask = xfregs.colChans[j].color.GetFullLightMask();
|
||||
for (int l=0; l<8; l++)
|
||||
{
|
||||
if (cmask&1)
|
||||
{
|
||||
float val = DoLighting(GetLight(l), xfregs.colChans[j].color, TempPos, TempNormal);
|
||||
float r = lightColors[l].r * val;
|
||||
float g = lightColors[l].g * val;
|
||||
float b = lightColors[l].b * val;
|
||||
lightSum.r += r;
|
||||
lightSum.g += g;
|
||||
lightSum.b += b;
|
||||
}
|
||||
cmask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lightSum.r = lightSum.g = lightSum.b = 1.0f;
|
||||
}
|
||||
|
||||
//combine together the light values from the lights that affect alpha (should be rare)
|
||||
if (xfregs.colChans[j].alpha.enablelighting)
|
||||
{
|
||||
//choose ambient source..
|
||||
if (xfregs.colChans[j].alpha.ambsource==GX_SRC_REG)
|
||||
lightSum.convertA_GC(xfregs.colChans[j].ambColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
lightSum.convertA(varray->GetColor(j, i));
|
||||
else
|
||||
lightSum.a=0.0f;
|
||||
}
|
||||
//accumulate light alphas
|
||||
int amask = xfregs.colChans[j].alpha.GetFullLightMask();
|
||||
for (int l = 0; l < 8; l++)
|
||||
{
|
||||
if (amask&1)
|
||||
{
|
||||
float val = DoLighting(GetLight(l), xfregs.colChans[j].alpha, TempPos, TempNormal);
|
||||
float a = lightColors[l].a * val;
|
||||
lightSum.a += a;
|
||||
}
|
||||
amask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lightSum.a=1.0f;
|
||||
}
|
||||
|
||||
chans[j] = lightSum * material;
|
||||
chans[j].clamp();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 3: Generate texture coordinates!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 TempUVs[8];
|
||||
for (int j = 0; j < xfregs.numTexGens; j++)
|
||||
{
|
||||
Vec3 t;
|
||||
|
||||
switch (xfregs.texcoords[j].texmtxinfo.sourcerow) {
|
||||
case XF_SRCGEOM_INROW: t = OrigPos; break; //HACK WTFF???
|
||||
case XF_SRCNORMAL_INROW: t = OrigNormal; break;
|
||||
case XF_SRCCOLORS_INROW: break; //set uvs to something?
|
||||
case XF_SRCBINORMAL_T_INROW: t=Vec3(0,0,0);break;
|
||||
case XF_SRCBINORMAL_B_INROW: t=Vec3(0,0,0);break;
|
||||
default:
|
||||
{
|
||||
int c = xfregs.texcoords[j].texmtxinfo.sourcerow - XF_SRCTEX0_INROW;
|
||||
bool hasTCC = (components & (VertexLoader::VB_HAS_UV0 << c)) != 0;
|
||||
if (c >= 0 && c <= 7 && hasTCC)
|
||||
{
|
||||
const DecUV &uv = varray->GetUV(c, i);
|
||||
t = Vec3(uv.u, uv.v, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 out,out2;
|
||||
switch (xfregs.texcoords[j].texmtxinfo.texgentype)
|
||||
{
|
||||
case XF_TEXGEN_COLOR_STRGBC0:
|
||||
out = Vec3(chans[0].r*255, chans[0].g*255, 1)/255.0f;
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC1:
|
||||
out = Vec3(chans[1].r*255, chans[1].g*255, 1)/255.0f; //FIX: take color1 instead
|
||||
break;
|
||||
case XF_TEXGEN_REGULAR:
|
||||
if (xfregs.texcoords[j].texmtxinfo.projection)
|
||||
VtxMulMtx43(out, t, m_pTexMatrix[j]);
|
||||
else
|
||||
VtxMulMtx42(out, t, m_pTexMatrix[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (xfregs.texcoords[j].postmtxinfo.normalize)
|
||||
out.normalize();
|
||||
|
||||
int postMatrix = xfregs.texcoords[j].postmtxinfo.index;
|
||||
float *pmtx = ((float*)xfmem) + 0x500 + postMatrix * 4; //CHECK
|
||||
//multiply with postmatrix
|
||||
VtxMulMtx43(TempUVs[j], out, pmtx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 4: Output the vertex!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
for (int j = 0; j < 2; j++)
|
||||
chans[j].convertToD3DColor(vbuffer[i].colors[j]);
|
||||
|
||||
vbuffer[i].pos = TempPos;
|
||||
vbuffer[i].normal = TempNormal;
|
||||
for (int j = 0; j < (int)bpmem.genMode.numtexgens; j++)
|
||||
{
|
||||
vbuffer[i].uv[j].u = TempUVs[j].x;
|
||||
vbuffer[i].uv[j].v = TempUVs[j].y;
|
||||
vbuffer[i].uv[j].w = TempUVs[j].z;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <fvec.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Profiler.h"
|
||||
// #include "Globals.h"
|
||||
#include "Vec3.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader.h"
|
||||
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include "RGBAFloat.h"
|
||||
|
||||
float *CTransformEngine::m_pPosMatrix;
|
||||
float *CTransformEngine::m_pNormalMatrix;
|
||||
float *CTransformEngine::m_pTexMatrix[8];
|
||||
float *CTransformEngine::m_pTexPostMatrix[8];
|
||||
|
||||
const Light *GetLight(int i)
|
||||
{
|
||||
return (const Light *)(xfmem + XFMEM_LIGHTS) + i;
|
||||
}
|
||||
|
||||
float DoLighting(const Light *light, const LitChannel &chan, const Vec3 &pos, const Vec3 &normal)
|
||||
{
|
||||
float val;
|
||||
if (chan.attnfunc == 0 || chan.attnfunc == 2) //no attn
|
||||
{
|
||||
Vec3 ldir = (Vec3(light->dpos) - pos);
|
||||
val = ldir.normalized() * normal;
|
||||
}
|
||||
else
|
||||
{
|
||||
float aattn = 0;
|
||||
float d;
|
||||
float mul = 1.0f;
|
||||
if (chan.attnfunc == 3)
|
||||
{
|
||||
Vec3 ldir = (Vec3(light->dpos) - pos);
|
||||
d = ldir.length();
|
||||
Vec3 ldirNorm = ldir / d; //normalize
|
||||
float l = ldirNorm * normal;
|
||||
aattn = Vec3(light->ddir) * ldirNorm;
|
||||
mul = l;
|
||||
}
|
||||
else if (chan.attnfunc == 1)
|
||||
{
|
||||
d = aattn = Vec3(light->shalfangle) * normal;
|
||||
mul = (Vec3(light->sdir) * normal > 0) ? (normal * Vec3(light->shalfangle)) : 0;
|
||||
if (mul < 0)
|
||||
mul = 0;
|
||||
}
|
||||
|
||||
float spot = (light->a2*aattn*aattn + light->a1*aattn + light->a0);
|
||||
float dist = 1.0f/(light->k2*d*d + light->k1*d + light->k0);
|
||||
if (spot<0)
|
||||
spot=0;
|
||||
|
||||
val = mul * spot * dist;
|
||||
}
|
||||
|
||||
if (val < 0 && chan.diffusefunc == 2) // clamp
|
||||
val = 0;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
void VtxMulMtx43T(Vec3 &out, const Vec3 &in, const float pMatrix[12])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
|
||||
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
|
||||
out.z = in.x * pMatrix[8] + in.y * pMatrix[9] + in.z * pMatrix[10] + 1 * pMatrix[11];
|
||||
}
|
||||
|
||||
void VtxMulMtx43(Vec3 &out, const Vec3 &in, const float pMatrix[12])
|
||||
{
|
||||
VtxMulMtx43T(out,in,pMatrix);
|
||||
//TODO(XK): Turns out that SSE2 computations are slower... Can anyone do
|
||||
// anything about it?
|
||||
/*
|
||||
F32vec4 a(in.x, in.y, in.z, 1), b(pMatrix[0], pMatrix[1], pMatrix[2], pMatrix[3]);
|
||||
|
||||
out.x = add_horizontal(a * b);
|
||||
|
||||
b[0] = pMatrix[4]; b[1] = pMatrix[5]; b[2] = pMatrix[6]; b[3] = pMatrix[7];
|
||||
|
||||
out.y = add_horizontal(a * b);
|
||||
|
||||
b[0] = pMatrix[8]; b[1] = pMatrix[9]; b[2] = pMatrix[10]; b[3] = pMatrix[11];
|
||||
|
||||
out.z = add_horizontal(a * b);
|
||||
*/
|
||||
}
|
||||
|
||||
void VtxMulMtx42(Vec3 &out, const Vec3 &in, const float pMatrix[8])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2] + 1 * pMatrix[3];
|
||||
out.y = in.x * pMatrix[4] + in.y * pMatrix[5] + in.z * pMatrix[6] + 1 * pMatrix[7];
|
||||
}
|
||||
|
||||
void VtxMulMtx33(Vec3 &out, const Vec3 &in, const float pMatrix[9])
|
||||
{
|
||||
out.x = in.x * pMatrix[0] + in.y * pMatrix[1] + in.z * pMatrix[2];
|
||||
out.y = in.x * pMatrix[3] + in.y * pMatrix[4] + in.z * pMatrix[5];
|
||||
out.z = in.x * pMatrix[6] + in.y * pMatrix[7] + in.z * pMatrix[8];
|
||||
}
|
||||
|
||||
void CTransformEngine::TransformVertices(int _numVertices, const DecodedVArray *varray, D3DVertex *vbuffer)
|
||||
{
|
||||
if (vbuffer == 0)
|
||||
{
|
||||
MessageBox(0,"TransformVertices : vbuffer == 0","WTF",0);
|
||||
}
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
RGBAFloat lightColors[8];
|
||||
RGBAFloat lightVals[8];
|
||||
RGBAFloat chans[2];
|
||||
|
||||
u32 components = varray->GetComponents();
|
||||
|
||||
// TODO: only for active lights
|
||||
for (int i=0; i<8; i++)
|
||||
lightColors[i].convert_GC(GetLight(i)->color);
|
||||
|
||||
for (int i=0; i<_numVertices; i++)
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 1: xform position and normal
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Vec3 OrigPos = varray->GetPos(i);
|
||||
|
||||
if (varray->hasPosMatIdx)
|
||||
{
|
||||
int index = varray->GetPosMtxInd(i);
|
||||
SetPosNormalMatrix(
|
||||
(float*)xfmem + (index & 63) * 4, //CHECK
|
||||
(float*)xfmem + 0x400 + 3 * (index & 31)); //CHECK
|
||||
}
|
||||
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (varray->hasTexMatIdx[j])
|
||||
{
|
||||
float *flipmem = (float *)xfmem;
|
||||
int index = varray->GetTexMtxInd(j, i);
|
||||
SetTexMatrix(j, flipmem + index * 4);
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 TempPos;
|
||||
|
||||
// m_pPosMatrix can be switched out, through matrixindex vertex components
|
||||
VtxMulMtx43(TempPos, OrigPos, m_pPosMatrix);
|
||||
|
||||
Vec3 TempNormal;
|
||||
Vec3 OrigNormal;
|
||||
if (varray->hasNrm)
|
||||
{
|
||||
OrigNormal = varray->GetNormal(0, i);
|
||||
VtxMulMtx33(TempNormal, OrigNormal, m_pNormalMatrix);
|
||||
TempNormal.normalize();
|
||||
}
|
||||
else
|
||||
{
|
||||
OrigNormal.setZero();
|
||||
TempNormal.setZero();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 2: Light!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//find all used lights
|
||||
u32 lightMask =
|
||||
xfregs.colChans[0].color.GetFullLightMask() | xfregs.colChans[0].alpha.GetFullLightMask() |
|
||||
xfregs.colChans[1].color.GetFullLightMask() | xfregs.colChans[1].alpha.GetFullLightMask();
|
||||
|
||||
float r0=0,g0=0,b0=0,a0=0;
|
||||
|
||||
//go through them and compute the lit colors
|
||||
//Sum lighting for both two color channels if they're active
|
||||
for (int j = 0; j < (int)bpmem.genMode.numcolchans; j++)
|
||||
{
|
||||
RGBAFloat material;
|
||||
RGBAFloat lightSum(0,0,0,0);
|
||||
|
||||
bool hasColorJ = (components & (VertexLoader::VB_HAS_COL0 << j)) != 0;
|
||||
|
||||
//get basic material color from appropriate sources (this would compile nicely!:)
|
||||
if (xfregs.colChans[j].color.matsource == GX_SRC_REG)
|
||||
material.convertRGB_GC(xfregs.colChans[j].matColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
material.convertRGB(varray->GetColor(j, i));
|
||||
else
|
||||
material.r=material.g=material.b=1.0f;
|
||||
}
|
||||
|
||||
if (xfregs.colChans[j].alpha.matsource == GX_SRC_REG)
|
||||
material.convertA_GC(xfregs.colChans[j].matColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
material.convertA(varray->GetColor(j, i));
|
||||
else
|
||||
material.a=1.0f;
|
||||
}
|
||||
|
||||
//combine together the light values from the lights that affect the color
|
||||
if (xfregs.colChans[j].color.enablelighting)
|
||||
{
|
||||
//choose ambient source and start our lightsum accumulator with its value..
|
||||
if (xfregs.colChans[j].color.ambsource == GX_SRC_REG)
|
||||
lightSum.convertRGB_GC(xfregs.colChans[j].ambColor); //ambient
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
lightSum.convertRGB(varray->GetColor(j, i));
|
||||
else
|
||||
{
|
||||
lightSum.r=0.0f;lightSum.g=0.0f;lightSum.b=0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
//accumulate light colors
|
||||
int cmask = xfregs.colChans[j].color.GetFullLightMask();
|
||||
for (int l=0; l<8; l++)
|
||||
{
|
||||
if (cmask&1)
|
||||
{
|
||||
float val = DoLighting(GetLight(l), xfregs.colChans[j].color, TempPos, TempNormal);
|
||||
float r = lightColors[l].r * val;
|
||||
float g = lightColors[l].g * val;
|
||||
float b = lightColors[l].b * val;
|
||||
lightSum.r += r;
|
||||
lightSum.g += g;
|
||||
lightSum.b += b;
|
||||
}
|
||||
cmask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lightSum.r = lightSum.g = lightSum.b = 1.0f;
|
||||
}
|
||||
|
||||
//combine together the light values from the lights that affect alpha (should be rare)
|
||||
if (xfregs.colChans[j].alpha.enablelighting)
|
||||
{
|
||||
//choose ambient source..
|
||||
if (xfregs.colChans[j].alpha.ambsource==GX_SRC_REG)
|
||||
lightSum.convertA_GC(xfregs.colChans[j].ambColor);
|
||||
else
|
||||
{
|
||||
if (hasColorJ)
|
||||
lightSum.convertA(varray->GetColor(j, i));
|
||||
else
|
||||
lightSum.a=0.0f;
|
||||
}
|
||||
//accumulate light alphas
|
||||
int amask = xfregs.colChans[j].alpha.GetFullLightMask();
|
||||
for (int l = 0; l < 8; l++)
|
||||
{
|
||||
if (amask&1)
|
||||
{
|
||||
float val = DoLighting(GetLight(l), xfregs.colChans[j].alpha, TempPos, TempNormal);
|
||||
float a = lightColors[l].a * val;
|
||||
lightSum.a += a;
|
||||
}
|
||||
amask >>= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
lightSum.a=1.0f;
|
||||
}
|
||||
|
||||
chans[j] = lightSum * material;
|
||||
chans[j].clamp();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 3: Generate texture coordinates!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
Vec3 TempUVs[8];
|
||||
for (int j = 0; j < xfregs.numTexGens; j++)
|
||||
{
|
||||
Vec3 t;
|
||||
|
||||
switch (xfregs.texcoords[j].texmtxinfo.sourcerow) {
|
||||
case XF_SRCGEOM_INROW: t = OrigPos; break; //HACK WTFF???
|
||||
case XF_SRCNORMAL_INROW: t = OrigNormal; break;
|
||||
case XF_SRCCOLORS_INROW: break; //set uvs to something?
|
||||
case XF_SRCBINORMAL_T_INROW: t=Vec3(0,0,0);break;
|
||||
case XF_SRCBINORMAL_B_INROW: t=Vec3(0,0,0);break;
|
||||
default:
|
||||
{
|
||||
int c = xfregs.texcoords[j].texmtxinfo.sourcerow - XF_SRCTEX0_INROW;
|
||||
bool hasTCC = (components & (VertexLoader::VB_HAS_UV0 << c)) != 0;
|
||||
if (c >= 0 && c <= 7 && hasTCC)
|
||||
{
|
||||
const DecUV &uv = varray->GetUV(c, i);
|
||||
t = Vec3(uv.u, uv.v, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vec3 out,out2;
|
||||
switch (xfregs.texcoords[j].texmtxinfo.texgentype)
|
||||
{
|
||||
case XF_TEXGEN_COLOR_STRGBC0:
|
||||
out = Vec3(chans[0].r*255, chans[0].g*255, 1)/255.0f;
|
||||
break;
|
||||
case XF_TEXGEN_COLOR_STRGBC1:
|
||||
out = Vec3(chans[1].r*255, chans[1].g*255, 1)/255.0f; //FIX: take color1 instead
|
||||
break;
|
||||
case XF_TEXGEN_REGULAR:
|
||||
if (xfregs.texcoords[j].texmtxinfo.projection)
|
||||
VtxMulMtx43(out, t, m_pTexMatrix[j]);
|
||||
else
|
||||
VtxMulMtx42(out, t, m_pTexMatrix[j]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (xfregs.texcoords[j].postmtxinfo.normalize)
|
||||
out.normalize();
|
||||
|
||||
int postMatrix = xfregs.texcoords[j].postmtxinfo.index;
|
||||
float *pmtx = ((float*)xfmem) + 0x500 + postMatrix * 4; //CHECK
|
||||
//multiply with postmatrix
|
||||
VtxMulMtx43(TempUVs[j], out, pmtx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//Step 4: Output the vertex!
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
for (int j = 0; j < 2; j++)
|
||||
chans[j].convertToD3DColor(vbuffer[i].colors[j]);
|
||||
|
||||
vbuffer[i].pos = TempPos;
|
||||
vbuffer[i].normal = TempNormal;
|
||||
for (int j = 0; j < (int)bpmem.genMode.numtexgens; j++)
|
||||
{
|
||||
vbuffer[i].uv[j].u = TempUVs[j].x;
|
||||
vbuffer[i].uv[j].v = TempUVs[j].y;
|
||||
vbuffer[i].uv[j].w = TempUVs[j].z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,45 +1,45 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "W32Util/Misc.h"
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include <assert.h>
|
||||
|
||||
int frameCount;
|
||||
|
||||
// Message handler for about box.
|
||||
LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
W32Util::CenterWindow(hDlg);
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
||||
{
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "W32Util/Misc.h"
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include <assert.h>
|
||||
|
||||
int frameCount;
|
||||
|
||||
// Message handler for about box.
|
||||
LRESULT CALLBACK AboutProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM /*lParam*/)
|
||||
{
|
||||
switch (message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
W32Util::CenterWindow(hDlg);
|
||||
return TRUE;
|
||||
|
||||
case WM_COMMAND:
|
||||
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
|
||||
{
|
||||
EndDialog(hDlg, LOWORD(wParam));
|
||||
return TRUE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1,363 +1,363 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "x64Emitter.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "LookUpTables.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "XFStructs.h"
|
||||
#include "BPStructs.h"
|
||||
#include "DataReader.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
//these don't need to be saved
|
||||
float posScale;
|
||||
float tcScale[8];
|
||||
int tcElements[8];
|
||||
int tcFormat[8];
|
||||
int colElements[2];
|
||||
float tcScaleU[8];
|
||||
float tcScaleV[8];
|
||||
int tcIndex;
|
||||
int colIndex;
|
||||
u32 addr;
|
||||
|
||||
DecodedVArray *varray;
|
||||
|
||||
int ComputeVertexSize(u32 comp)
|
||||
{
|
||||
int size = 0;
|
||||
if (comp & VertexLoader::VB_HAS_POSMTXIDX)
|
||||
size += 4;
|
||||
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX0 | VertexLoader::VB_HAS_TEXMTXIDX1 | VertexLoader::VB_HAS_TEXMTXIDX2 | VertexLoader::VB_HAS_TEXMTXIDX3))
|
||||
size += 4;
|
||||
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX4 | VertexLoader::VB_HAS_TEXMTXIDX5 | VertexLoader::VB_HAS_TEXMTXIDX6 | VertexLoader::VB_HAS_TEXMTXIDX7))
|
||||
size += 4;
|
||||
if (comp & VertexLoader::VB_HAS_NRM0)
|
||||
size += 4;
|
||||
if (comp & (VertexLoader::VB_HAS_NRM1 | VertexLoader::VB_HAS_NRM2)) //combine into single check for speed
|
||||
size += 8;
|
||||
if (comp & VertexLoader::VB_HAS_COL0)
|
||||
size += 4;
|
||||
if (comp & VertexLoader::VB_HAS_COL1)
|
||||
size += 4;
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (comp & (VertexLoader::VB_HAS_UV0 << i))
|
||||
size += 8;
|
||||
return size;
|
||||
}
|
||||
|
||||
void VertexLoader::SetVArray(DecodedVArray *_varray)
|
||||
{
|
||||
varray = _varray;
|
||||
}
|
||||
|
||||
#include "VertexLoader_MtxIndex.h"
|
||||
#include "VertexLoader_Position.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
#include "VertexLoader_Color.h"
|
||||
#include "VertexLoader_TextCoord.h"
|
||||
|
||||
VertexLoader g_VertexLoaders[8];
|
||||
TVtxDesc VertexLoader::m_VtxDesc;
|
||||
bool VertexLoader::m_DescDirty = true;
|
||||
|
||||
VertexLoader::VertexLoader()
|
||||
{
|
||||
m_numPipelineStates = 0;
|
||||
m_VertexSize = 0;
|
||||
m_AttrDirty = true;
|
||||
VertexLoader_Normal::Init();
|
||||
}
|
||||
|
||||
VertexLoader::~VertexLoader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VertexLoader::Setup()
|
||||
{
|
||||
if (!m_AttrDirty && !m_DescDirty)
|
||||
return;
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
// Reset pipeline
|
||||
m_VertexSize = 0;
|
||||
m_numPipelineStates = 0;
|
||||
m_components = 0;
|
||||
|
||||
// Position Matrix Index
|
||||
if (m_VtxDesc.PosMatIdx)
|
||||
{
|
||||
m_PipelineStates[m_numPipelineStates++] = PosMtx_ReadDirect_UByte;
|
||||
m_VertexSize += 1;
|
||||
m_components |= VB_HAS_POSMTXIDX;
|
||||
}
|
||||
|
||||
// Texture matrix indices
|
||||
if (m_VtxDesc.Tex0MatIdx) {m_components|=VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex1MatIdx) {m_components|=VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex2MatIdx) {m_components|=VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex3MatIdx) {m_components|=VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex4MatIdx) {m_components|=VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex5MatIdx) {m_components|=VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex6MatIdx) {m_components|=VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex7MatIdx) {m_components|=VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
|
||||
// Position
|
||||
switch (m_VtxDesc.Position)
|
||||
{
|
||||
case NOT_PRESENT: {_assert_msg_(0,"Vertex descriptor without position!","WTF?");} break;
|
||||
case DIRECT:
|
||||
{
|
||||
int SizePro = 0;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: SizePro=1; WriteCall(Pos_ReadDirect_UByte); break;
|
||||
case FORMAT_BYTE: SizePro=1; WriteCall(Pos_ReadDirect_Byte); break;
|
||||
case FORMAT_USHORT: SizePro=2; WriteCall(Pos_ReadDirect_UShort); break;
|
||||
case FORMAT_SHORT: SizePro=2; WriteCall(Pos_ReadDirect_Short); break;
|
||||
case FORMAT_FLOAT: SizePro=4; WriteCall(Pos_ReadDirect_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
if (m_VtxAttr.PosElements == 1)
|
||||
m_VertexSize += SizePro * 3;
|
||||
else
|
||||
m_VertexSize += SizePro * 2;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
m_VertexSize+=1;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF?
|
||||
case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
case INDEX16:
|
||||
m_VertexSize+=2;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Normals
|
||||
if (m_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
VertexLoader_Normal::index3 = m_VtxAttr.NormalIndex3 ? true : false;
|
||||
unsigned int uSize = VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
if (pFunc == 0)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
MessageBox(0,"VertexLoader_Normal::GetFunction returned zero!",temp,0);
|
||||
}
|
||||
WriteCall(pFunc);
|
||||
m_VertexSize += uSize;
|
||||
int m_numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE;
|
||||
m_components |= VB_HAS_NRM0;
|
||||
if (m_numNormals == NRM_THREE)
|
||||
m_components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
||||
}
|
||||
|
||||
// Colors
|
||||
int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
||||
for (int i = 0; i < 2; i++)
|
||||
SetupColor(i,col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements);
|
||||
|
||||
// TextureCoord
|
||||
// Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually.
|
||||
// If we didn't do this, the vertex format would be read as one bit offset from where it should be, making
|
||||
// 01 become 00, and 10/11 become 01
|
||||
int tc[8] = {
|
||||
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
|
||||
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3
|
||||
};
|
||||
for (int i = 0; i < 8; i++)
|
||||
SetupTexCoord(i, tc[i],
|
||||
m_VtxAttr.texCoord[i].Format,
|
||||
m_VtxAttr.texCoord[i].Elements,
|
||||
m_VtxAttr.texCoord[i].Frac);
|
||||
}
|
||||
|
||||
void VertexLoader::SetupColor(int num, int mode, int format, int elements)
|
||||
{
|
||||
m_components |= VB_HAS_COL0 << num;
|
||||
switch (mode)
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_components &= ~(VB_HAS_COL0 << num);
|
||||
break;
|
||||
case DIRECT:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_565); break;
|
||||
case FORMAT_24B_888: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_888); break;
|
||||
case FORMAT_32B_888x: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break;
|
||||
case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break;
|
||||
case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break;
|
||||
case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break;
|
||||
case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break;
|
||||
case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=1;
|
||||
break;
|
||||
case INDEX16:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break;
|
||||
case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break;
|
||||
case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break;
|
||||
case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break;
|
||||
case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break;
|
||||
case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, int _iFrac)
|
||||
{
|
||||
m_components |= VB_HAS_UV0 << num;
|
||||
switch (mode)
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_components &= ~(VB_HAS_UV0 << num);
|
||||
break;
|
||||
case DIRECT:
|
||||
{
|
||||
int sizePro=0;
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_UByte); break;
|
||||
case FORMAT_BYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_Byte); break;
|
||||
case FORMAT_USHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_UShort); break;
|
||||
case FORMAT_SHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_Short); break;
|
||||
case FORMAT_FLOAT: sizePro = 4; WriteCall(TexCoord_ReadDirect_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize += sizePro * (elements ? 2 : 1);
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex8_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex8_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex8_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex8_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex8_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=1;
|
||||
break;
|
||||
case INDEX16:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex16_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex16_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex16_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex16_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex16_Float); break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
m_VertexSize+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexLoader::WriteCall(TPipelineFunction func)
|
||||
{
|
||||
m_PipelineStates[m_numPipelineStates++] = func;
|
||||
}
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
void VertexLoader::PrepareRun()
|
||||
{
|
||||
posScale = shiftLookup[m_VtxAttr.PosFrac];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
tcScaleU[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
|
||||
tcScaleV[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
|
||||
tcElements[i] = m_VtxAttr.texCoord[i].Elements;
|
||||
tcFormat[i] = m_VtxAttr.texCoord[i].Format;
|
||||
}
|
||||
for (int i = 0; i < 2; i++)
|
||||
colElements[i] = m_VtxAttr.color[i].Elements;
|
||||
|
||||
varray->SetComponents(m_components);
|
||||
}
|
||||
|
||||
void VertexLoader::RunVertices(int count)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
for (int v = 0; v < count; v++)
|
||||
{
|
||||
tcIndex = 0;
|
||||
colIndex = 0;
|
||||
s_texmtxread = 0;
|
||||
for (int i = 0; i < m_numPipelineStates; i++)
|
||||
{
|
||||
m_PipelineStates[i](&m_VtxAttr);
|
||||
}
|
||||
varray->Next();
|
||||
}
|
||||
/*
|
||||
This is not the bottleneck ATM, so compiling etc doesn't really help.
|
||||
At least not when all we do is compile it to a list of function calls.
|
||||
Should help more when we inline, but this requires the new vertex format.
|
||||
Maybe later, and with smarter caching.
|
||||
|
||||
if (count)
|
||||
{
|
||||
this->m_counter = count;
|
||||
((void (*)())((void*)&m_compiledCode[0]))();
|
||||
}*/
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "x64Emitter.h"
|
||||
|
||||
#include "Common.h"
|
||||
#include "LookUpTables.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexManager.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "XFStructs.h"
|
||||
#include "BPStructs.h"
|
||||
#include "DataReader.h"
|
||||
#include "DecodedVArray.h"
|
||||
|
||||
//these don't need to be saved
|
||||
float posScale;
|
||||
float tcScale[8];
|
||||
int tcElements[8];
|
||||
int tcFormat[8];
|
||||
int colElements[2];
|
||||
float tcScaleU[8];
|
||||
float tcScaleV[8];
|
||||
int tcIndex;
|
||||
int colIndex;
|
||||
u32 addr;
|
||||
|
||||
DecodedVArray *varray;
|
||||
|
||||
int ComputeVertexSize(u32 comp)
|
||||
{
|
||||
int size = 0;
|
||||
if (comp & VertexLoader::VB_HAS_POSMTXIDX)
|
||||
size += 4;
|
||||
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX0 | VertexLoader::VB_HAS_TEXMTXIDX1 | VertexLoader::VB_HAS_TEXMTXIDX2 | VertexLoader::VB_HAS_TEXMTXIDX3))
|
||||
size += 4;
|
||||
if (comp & (VertexLoader::VB_HAS_TEXMTXIDX4 | VertexLoader::VB_HAS_TEXMTXIDX5 | VertexLoader::VB_HAS_TEXMTXIDX6 | VertexLoader::VB_HAS_TEXMTXIDX7))
|
||||
size += 4;
|
||||
if (comp & VertexLoader::VB_HAS_NRM0)
|
||||
size += 4;
|
||||
if (comp & (VertexLoader::VB_HAS_NRM1 | VertexLoader::VB_HAS_NRM2)) //combine into single check for speed
|
||||
size += 8;
|
||||
if (comp & VertexLoader::VB_HAS_COL0)
|
||||
size += 4;
|
||||
if (comp & VertexLoader::VB_HAS_COL1)
|
||||
size += 4;
|
||||
for (int i = 0; i < 8; i++)
|
||||
if (comp & (VertexLoader::VB_HAS_UV0 << i))
|
||||
size += 8;
|
||||
return size;
|
||||
}
|
||||
|
||||
void VertexLoader::SetVArray(DecodedVArray *_varray)
|
||||
{
|
||||
varray = _varray;
|
||||
}
|
||||
|
||||
#include "VertexLoader_MtxIndex.h"
|
||||
#include "VertexLoader_Position.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
#include "VertexLoader_Color.h"
|
||||
#include "VertexLoader_TextCoord.h"
|
||||
|
||||
VertexLoader g_VertexLoaders[8];
|
||||
TVtxDesc VertexLoader::m_VtxDesc;
|
||||
bool VertexLoader::m_DescDirty = true;
|
||||
|
||||
VertexLoader::VertexLoader()
|
||||
{
|
||||
m_numPipelineStates = 0;
|
||||
m_VertexSize = 0;
|
||||
m_AttrDirty = true;
|
||||
VertexLoader_Normal::Init();
|
||||
}
|
||||
|
||||
VertexLoader::~VertexLoader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VertexLoader::Setup()
|
||||
{
|
||||
if (!m_AttrDirty && !m_DescDirty)
|
||||
return;
|
||||
|
||||
DVSTARTPROFILE();
|
||||
|
||||
// Reset pipeline
|
||||
m_VertexSize = 0;
|
||||
m_numPipelineStates = 0;
|
||||
m_components = 0;
|
||||
|
||||
// Position Matrix Index
|
||||
if (m_VtxDesc.PosMatIdx)
|
||||
{
|
||||
m_PipelineStates[m_numPipelineStates++] = PosMtx_ReadDirect_UByte;
|
||||
m_VertexSize += 1;
|
||||
m_components |= VB_HAS_POSMTXIDX;
|
||||
}
|
||||
|
||||
// Texture matrix indices
|
||||
if (m_VtxDesc.Tex0MatIdx) {m_components|=VB_HAS_TEXMTXIDX0; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex1MatIdx) {m_components|=VB_HAS_TEXMTXIDX1; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex2MatIdx) {m_components|=VB_HAS_TEXMTXIDX2; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex3MatIdx) {m_components|=VB_HAS_TEXMTXIDX3; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex4MatIdx) {m_components|=VB_HAS_TEXMTXIDX4; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex5MatIdx) {m_components|=VB_HAS_TEXMTXIDX5; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex6MatIdx) {m_components|=VB_HAS_TEXMTXIDX6; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
if (m_VtxDesc.Tex7MatIdx) {m_components|=VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); m_VertexSize+=1;}
|
||||
|
||||
// Position
|
||||
switch (m_VtxDesc.Position)
|
||||
{
|
||||
case NOT_PRESENT: {_assert_msg_(0,"Vertex descriptor without position!","WTF?");} break;
|
||||
case DIRECT:
|
||||
{
|
||||
int SizePro = 0;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: SizePro=1; WriteCall(Pos_ReadDirect_UByte); break;
|
||||
case FORMAT_BYTE: SizePro=1; WriteCall(Pos_ReadDirect_Byte); break;
|
||||
case FORMAT_USHORT: SizePro=2; WriteCall(Pos_ReadDirect_UShort); break;
|
||||
case FORMAT_SHORT: SizePro=2; WriteCall(Pos_ReadDirect_Short); break;
|
||||
case FORMAT_FLOAT: SizePro=4; WriteCall(Pos_ReadDirect_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
if (m_VtxAttr.PosElements == 1)
|
||||
m_VertexSize += SizePro * 3;
|
||||
else
|
||||
m_VertexSize += SizePro * 2;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
m_VertexSize+=1;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex8_UByte); break; //WTF?
|
||||
case FORMAT_BYTE: WriteCall(Pos_ReadIndex8_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(Pos_ReadIndex8_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(Pos_ReadIndex8_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex8_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
case INDEX16:
|
||||
m_VertexSize+=2;
|
||||
switch (m_VtxAttr.PosFormat)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(Pos_ReadIndex16_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(Pos_ReadIndex16_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(Pos_ReadIndex16_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(Pos_ReadIndex16_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(Pos_ReadIndex16_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Normals
|
||||
if (m_VtxDesc.Normal != NOT_PRESENT)
|
||||
{
|
||||
VertexLoader_Normal::index3 = m_VtxAttr.NormalIndex3 ? true : false;
|
||||
unsigned int uSize = VertexLoader_Normal::GetSize(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
TPipelineFunction pFunc = VertexLoader_Normal::GetFunction(m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
if (pFunc == 0)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp,"%i %i %i", m_VtxDesc.Normal, m_VtxAttr.NormalFormat, m_VtxAttr.NormalElements);
|
||||
MessageBox(0,"VertexLoader_Normal::GetFunction returned zero!",temp,0);
|
||||
}
|
||||
WriteCall(pFunc);
|
||||
m_VertexSize += uSize;
|
||||
int m_numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE;
|
||||
m_components |= VB_HAS_NRM0;
|
||||
if (m_numNormals == NRM_THREE)
|
||||
m_components |= VB_HAS_NRM1 | VB_HAS_NRM2;
|
||||
}
|
||||
|
||||
// Colors
|
||||
int col[2] = {m_VtxDesc.Color0, m_VtxDesc.Color1};
|
||||
for (int i = 0; i < 2; i++)
|
||||
SetupColor(i,col[i], m_VtxAttr.color[i].Comp, m_VtxAttr.color[i].Elements);
|
||||
|
||||
// TextureCoord
|
||||
// Since m_VtxDesc.Text7Coord is broken across a 32 bit word boundary, retrieve its value manually.
|
||||
// If we didn't do this, the vertex format would be read as one bit offset from where it should be, making
|
||||
// 01 become 00, and 10/11 become 01
|
||||
int tc[8] = {
|
||||
m_VtxDesc.Tex0Coord, m_VtxDesc.Tex1Coord, m_VtxDesc.Tex2Coord, m_VtxDesc.Tex3Coord,
|
||||
m_VtxDesc.Tex4Coord, m_VtxDesc.Tex5Coord, m_VtxDesc.Tex6Coord, (m_VtxDesc.Hex >> 31) & 3
|
||||
};
|
||||
for (int i = 0; i < 8; i++)
|
||||
SetupTexCoord(i, tc[i],
|
||||
m_VtxAttr.texCoord[i].Format,
|
||||
m_VtxAttr.texCoord[i].Elements,
|
||||
m_VtxAttr.texCoord[i].Frac);
|
||||
}
|
||||
|
||||
void VertexLoader::SetupColor(int num, int mode, int format, int elements)
|
||||
{
|
||||
m_components |= VB_HAS_COL0 << num;
|
||||
switch (mode)
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_components &= ~(VB_HAS_COL0 << num);
|
||||
break;
|
||||
case DIRECT:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_565); break;
|
||||
case FORMAT_24B_888: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_888); break;
|
||||
case FORMAT_32B_888x: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_888x); break;
|
||||
case FORMAT_16B_4444: m_VertexSize+=2; WriteCall(Color_ReadDirect_16b_4444); break;
|
||||
case FORMAT_24B_6666: m_VertexSize+=3; WriteCall(Color_ReadDirect_24b_6666); break;
|
||||
case FORMAT_32B_8888: m_VertexSize+=4; WriteCall(Color_ReadDirect_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: WriteCall(Color_ReadIndex8_16b_565); break;
|
||||
case FORMAT_24B_888: WriteCall(Color_ReadIndex8_24b_888); break;
|
||||
case FORMAT_32B_888x: WriteCall(Color_ReadIndex8_32b_888x); break;
|
||||
case FORMAT_16B_4444: WriteCall(Color_ReadIndex8_16b_4444); break;
|
||||
case FORMAT_24B_6666: WriteCall(Color_ReadIndex8_24b_6666); break;
|
||||
case FORMAT_32B_8888: WriteCall(Color_ReadIndex8_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=1;
|
||||
break;
|
||||
case INDEX16:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_16B_565: WriteCall(Color_ReadIndex16_16b_565); break;
|
||||
case FORMAT_24B_888: WriteCall(Color_ReadIndex16_24b_888); break;
|
||||
case FORMAT_32B_888x: WriteCall(Color_ReadIndex16_32b_888x); break;
|
||||
case FORMAT_16B_4444: WriteCall(Color_ReadIndex16_16b_4444); break;
|
||||
case FORMAT_24B_6666: WriteCall(Color_ReadIndex16_24b_6666); break;
|
||||
case FORMAT_32B_8888: WriteCall(Color_ReadIndex16_32b_8888); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexLoader::SetupTexCoord(int num, int mode, int format, int elements, int _iFrac)
|
||||
{
|
||||
m_components |= VB_HAS_UV0 << num;
|
||||
switch (mode)
|
||||
{
|
||||
case NOT_PRESENT:
|
||||
m_components &= ~(VB_HAS_UV0 << num);
|
||||
break;
|
||||
case DIRECT:
|
||||
{
|
||||
int sizePro=0;
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_UByte); break;
|
||||
case FORMAT_BYTE: sizePro = 1; WriteCall(TexCoord_ReadDirect_Byte); break;
|
||||
case FORMAT_USHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_UShort); break;
|
||||
case FORMAT_SHORT: sizePro = 2; WriteCall(TexCoord_ReadDirect_Short); break;
|
||||
case FORMAT_FLOAT: sizePro = 4; WriteCall(TexCoord_ReadDirect_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize += sizePro * (elements ? 2 : 1);
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex8_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex8_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex8_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex8_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex8_Float); break;
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
m_VertexSize+=1;
|
||||
break;
|
||||
case INDEX16:
|
||||
switch (format)
|
||||
{
|
||||
case FORMAT_UBYTE: WriteCall(TexCoord_ReadIndex16_UByte); break;
|
||||
case FORMAT_BYTE: WriteCall(TexCoord_ReadIndex16_Byte); break;
|
||||
case FORMAT_USHORT: WriteCall(TexCoord_ReadIndex16_UShort); break;
|
||||
case FORMAT_SHORT: WriteCall(TexCoord_ReadIndex16_Short); break;
|
||||
case FORMAT_FLOAT: WriteCall(TexCoord_ReadIndex16_Float); break;
|
||||
default: _assert_(0);
|
||||
}
|
||||
m_VertexSize+=2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexLoader::WriteCall(TPipelineFunction func)
|
||||
{
|
||||
m_PipelineStates[m_numPipelineStates++] = func;
|
||||
}
|
||||
|
||||
using namespace Gen;
|
||||
|
||||
void VertexLoader::PrepareRun()
|
||||
{
|
||||
posScale = shiftLookup[m_VtxAttr.PosFrac];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
tcScaleU[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
|
||||
tcScaleV[i] = shiftLookup[m_VtxAttr.texCoord[i].Frac];
|
||||
tcElements[i] = m_VtxAttr.texCoord[i].Elements;
|
||||
tcFormat[i] = m_VtxAttr.texCoord[i].Format;
|
||||
}
|
||||
for (int i = 0; i < 2; i++)
|
||||
colElements[i] = m_VtxAttr.color[i].Elements;
|
||||
|
||||
varray->SetComponents(m_components);
|
||||
}
|
||||
|
||||
void VertexLoader::RunVertices(int count)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
for (int v = 0; v < count; v++)
|
||||
{
|
||||
tcIndex = 0;
|
||||
colIndex = 0;
|
||||
s_texmtxread = 0;
|
||||
for (int i = 0; i < m_numPipelineStates; i++)
|
||||
{
|
||||
m_PipelineStates[i](&m_VtxAttr);
|
||||
}
|
||||
varray->Next();
|
||||
}
|
||||
/*
|
||||
This is not the bottleneck ATM, so compiling etc doesn't really help.
|
||||
At least not when all we do is compile it to a list of function calls.
|
||||
Should help more when we inline, but this requires the new vertex format.
|
||||
Maybe later, and with smarter caching.
|
||||
|
||||
if (count)
|
||||
{
|
||||
this->m_counter = count;
|
||||
((void (*)())((void*)&m_compiledCode[0]))();
|
||||
}*/
|
||||
}
|
||||
@@ -1,488 +1,488 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "main.h"
|
||||
#include "Utils.h"
|
||||
#include "DecodedVArray.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
|
||||
u8 VertexLoader_Normal::m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
TPipelineFunction VertexLoader_Normal::m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
|
||||
bool VertexLoader_Normal::index3;
|
||||
// __________________________________________________________________________________________________
|
||||
// Init
|
||||
//
|
||||
void VertexLoader_Normal::Init(void)
|
||||
{
|
||||
// size table
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = 3;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = 3;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = 6;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = 6;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = 12;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = 9;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = 9;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = 18;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = 18;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = 36;
|
||||
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = 3;
|
||||
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = 6;
|
||||
|
||||
// function table
|
||||
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = Normal_DirectByte; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = Normal_DirectByte;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = Normal_DirectShort; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = Normal_DirectShort;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = Normal_DirectFloat;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = Normal_DirectByte3; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = Normal_DirectByte3;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = Normal_DirectShort3; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = Normal_DirectShort3;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = Normal_DirectFloat3;
|
||||
|
||||
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = Normal_Index8_Byte; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = Normal_Index8_Byte;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = Normal_Index8_Short; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = Normal_Index8_Short;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = Normal_Index8_Float;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index8_Byte3; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = Normal_Index8_Byte3;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = Normal_Index8_Short3; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = Normal_Index8_Short3;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index8_Float3;
|
||||
|
||||
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = Normal_Index16_Byte; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = Normal_Index16_Byte;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = Normal_Index16_Short; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = Normal_Index16_Short;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = Normal_Index16_Float;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index16_Byte3; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = Normal_Index16_Byte3;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = Normal_Index16_Short3; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = Normal_Index16_Short3;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index16_Float3;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// GetSize
|
||||
//
|
||||
unsigned int
|
||||
VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
return m_sizeTable[_type][_format][_elements];
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// GetFunction
|
||||
//
|
||||
TPipelineFunction
|
||||
VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
TPipelineFunction pFunc = m_funcTable[_type][_format][_elements];
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Direct ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectByte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectByte(const void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectShort
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectShort(const void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectFloat
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectFloat(const void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, DataReadF32());
|
||||
varray->SetNormalY(0, DataReadF32());
|
||||
varray->SetNormalZ(0, DataReadF32());
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectByte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectByte3(const void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectShort3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectShort3(const void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectFloat3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectFloat3(const void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, DataReadF32());
|
||||
varray->SetNormalY(i, DataReadF32());
|
||||
varray->SetNormalZ(i, DataReadF32());
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Index8 ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Byte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Byte(const void* _p)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Short
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Short(const void* _p)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Float(const void* _p)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Byte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Byte3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Short3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Short3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Float3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Index16 ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Byte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Byte(const void* _p)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Short
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Short(const void* _p)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Float(const void* _p)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Byte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Byte3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Short3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Short3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Float3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Float3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "main.h"
|
||||
#include "Utils.h"
|
||||
#include "DecodedVArray.h"
|
||||
#include "VertexLoader.h"
|
||||
#include "VertexLoader_Normal.h"
|
||||
|
||||
u8 VertexLoader_Normal::m_sizeTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
TPipelineFunction VertexLoader_Normal::m_funcTable[NUM_NRM_TYPE][NUM_NRM_FORMAT][NUM_NRM_ELEMENTS];
|
||||
|
||||
bool VertexLoader_Normal::index3;
|
||||
// __________________________________________________________________________________________________
|
||||
// Init
|
||||
//
|
||||
void VertexLoader_Normal::Init(void)
|
||||
{
|
||||
// size table
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = 3;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = 3;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = 6;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = 6;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = 12;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = 9;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = 9;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = 18;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = 18;
|
||||
m_sizeTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = 36;
|
||||
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = 1;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = 3;
|
||||
m_sizeTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = 3;
|
||||
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = 2;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = 6;
|
||||
m_sizeTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = 6;
|
||||
|
||||
// function table
|
||||
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT] = Normal_DirectByte; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT] = Normal_DirectByte;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT] = Normal_DirectShort; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT] = Normal_DirectShort;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT] = Normal_DirectFloat;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_UBYTE] [NRM_NBT3] = Normal_DirectByte3; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_BYTE] [NRM_NBT3] = Normal_DirectByte3;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_USHORT][NRM_NBT3] = Normal_DirectShort3; //HACK
|
||||
m_funcTable[NRM_DIRECT][FORMAT_SHORT] [NRM_NBT3] = Normal_DirectShort3;
|
||||
m_funcTable[NRM_DIRECT][FORMAT_FLOAT] [NRM_NBT3] = Normal_DirectFloat3;
|
||||
|
||||
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT] = Normal_Index8_Byte; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT] = Normal_Index8_Byte;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT] = Normal_Index8_Short; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT] = Normal_Index8_Short;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT] = Normal_Index8_Float;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index8_Byte3; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_BYTE] [NRM_NBT3] = Normal_Index8_Byte3;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_USHORT][NRM_NBT3] = Normal_Index8_Short3; //HACK
|
||||
m_funcTable[NRM_INDEX8][FORMAT_SHORT] [NRM_NBT3] = Normal_Index8_Short3;
|
||||
m_funcTable[NRM_INDEX8][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index8_Float3;
|
||||
|
||||
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT] = Normal_Index16_Byte; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT] = Normal_Index16_Byte;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT] = Normal_Index16_Short; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT] = Normal_Index16_Short;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT] = Normal_Index16_Float;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_UBYTE] [NRM_NBT3] = Normal_Index16_Byte3; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_BYTE] [NRM_NBT3] = Normal_Index16_Byte3;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_USHORT][NRM_NBT3] = Normal_Index16_Short3; //HACK
|
||||
m_funcTable[NRM_INDEX16][FORMAT_SHORT] [NRM_NBT3] = Normal_Index16_Short3;
|
||||
m_funcTable[NRM_INDEX16][FORMAT_FLOAT] [NRM_NBT3] = Normal_Index16_Float3;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// GetSize
|
||||
//
|
||||
unsigned int
|
||||
VertexLoader_Normal::GetSize(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
return m_sizeTable[_type][_format][_elements];
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// GetFunction
|
||||
//
|
||||
TPipelineFunction
|
||||
VertexLoader_Normal::GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements)
|
||||
{
|
||||
TPipelineFunction pFunc = m_funcTable[_type][_format][_elements];
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Direct ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectByte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectByte(const void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectShort
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectShort(const void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectFloat
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectFloat(const void* _p)
|
||||
{
|
||||
varray->SetNormalX(0, DataReadF32());
|
||||
varray->SetNormalY(0, DataReadF32());
|
||||
varray->SetNormalZ(0, DataReadF32());
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectByte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectByte3(const void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)DataReadU8()+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectShort3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectShort3(const void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)DataReadU16()+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_DirectFloat3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_DirectFloat3(const void* _p)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
varray->SetNormalX(i, DataReadF32());
|
||||
varray->SetNormalY(i, DataReadF32());
|
||||
varray->SetNormalZ(i, DataReadF32());
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Index8 ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Byte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Byte(const void* _p)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Short
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Short(const void* _p)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Float(const void* _p)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Byte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Byte3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Short3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Short3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index8_Float3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// --- Index16 ---
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Byte
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Byte(const void* _p)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(0, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Short
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Short(const void* _p)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(0, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(0, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index8_Float
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Float(const void* _p)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]);
|
||||
|
||||
varray->SetNormalX(0, Memory_Read_Float(iAddress));
|
||||
varray->SetNormalY(0, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(0, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Byte3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Byte3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed char)Memory_Read_U8(iAddress )+0.5f) / 127.5f);
|
||||
varray->SetNormalY(i, ((float)(signed char)Memory_Read_U8(iAddress+1)+0.5f) / 127.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed char)Memory_Read_U8(iAddress+2)+0.5f) / 127.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Short3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Short3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i;
|
||||
|
||||
varray->SetNormalX(i, ((float)(signed short)Memory_Read_U16(iAddress )+0.5f) / 32767.5f);
|
||||
varray->SetNormalY(i, ((float)(signed short)Memory_Read_U16(iAddress+2)+0.5f) / 32767.5f);
|
||||
varray->SetNormalZ(i, ((float)(signed short)Memory_Read_U16(iAddress+4)+0.5f) / 32767.5f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Normal_Index16_Float3
|
||||
//
|
||||
void LOADERDECL
|
||||
VertexLoader_Normal::Normal_Index16_Float3(const void* _p)
|
||||
{
|
||||
if (index3)
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
u32 iAddress = arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i;
|
||||
|
||||
varray->SetNormalX(i, Memory_Read_Float(iAddress ));
|
||||
varray->SetNormalY(i, Memory_Read_Float(iAddress+4));
|
||||
varray->SetNormalZ(i, Memory_Read_Float(iAddress+8));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,234 +1,234 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexManager.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
|
||||
namespace VertexManager
|
||||
{
|
||||
|
||||
static IndexGenerator indexGen;
|
||||
static Collection collection;
|
||||
|
||||
static LPDIRECT3DVERTEXDECLARATION9 vDecl;
|
||||
|
||||
static D3DVertex *fakeVBuffer;
|
||||
static u16 *fakeIBuffer;
|
||||
|
||||
#define MAXVBUFFERSIZE 65536*3
|
||||
#define MAXIBUFFERSIZE 65536*3
|
||||
|
||||
const D3DVERTEXELEMENT9 decl[] =
|
||||
{
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
|
||||
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
|
||||
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
|
||||
{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 },
|
||||
{ 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
|
||||
{ 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
|
||||
{ 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
|
||||
{ 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 },
|
||||
{ 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 },
|
||||
{ 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 },
|
||||
{ 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 },
|
||||
{ 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
|
||||
bool Init()
|
||||
{
|
||||
collection = C_NOTHING;
|
||||
fakeVBuffer = new D3DVertex[65536];
|
||||
fakeIBuffer = new u16[65536];
|
||||
CreateDeviceObjects();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
delete [] fakeVBuffer;
|
||||
delete [] fakeIBuffer;
|
||||
}
|
||||
|
||||
void CreateDeviceObjects()
|
||||
{
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = D3D::dev->CreateVertexDeclaration(decl, &vDecl)))
|
||||
{
|
||||
MessageBox(0,"Failed to create vertex declaration","sdfsd",0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void BeginFrame()
|
||||
{
|
||||
D3D::dev->SetVertexDeclaration(vDecl);
|
||||
//D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex));
|
||||
}
|
||||
|
||||
void DestroyDeviceObjects()
|
||||
{
|
||||
if (vDecl)
|
||||
vDecl->Release();
|
||||
vDecl = 0;
|
||||
}
|
||||
|
||||
|
||||
void AddIndices(int _primitive, int _numVertices)
|
||||
{
|
||||
switch(_primitive) {
|
||||
case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return;
|
||||
case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return;
|
||||
case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return;
|
||||
case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return;
|
||||
}
|
||||
}
|
||||
|
||||
const Collection collectionTypeLUT[8] =
|
||||
{
|
||||
C_TRIANGLES,//quads
|
||||
C_NOTHING, //nothing
|
||||
C_TRIANGLES,//triangles
|
||||
C_TRIANGLES,//strip
|
||||
C_TRIANGLES,//fan
|
||||
C_LINES, //lines
|
||||
C_LINES, //linestrip
|
||||
C_POINTS //guess :P
|
||||
};
|
||||
|
||||
D3DVertex *vbufferwrite;
|
||||
|
||||
void AddVertices(int _primitive, int _numVertices, const DecodedVArray *varray)
|
||||
{
|
||||
if (_numVertices <= 0) //This check is pretty stupid...
|
||||
return;
|
||||
|
||||
Collection type = collectionTypeLUT[_primitive];
|
||||
if (type == C_NOTHING)
|
||||
return;
|
||||
|
||||
DVSTARTPROFILE();
|
||||
_assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF");
|
||||
|
||||
if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise?
|
||||
Flush();
|
||||
|
||||
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
|
||||
|
||||
if (collection != type)
|
||||
{
|
||||
//We are NOT collecting the right type.
|
||||
Flush();
|
||||
collection = type;
|
||||
u16 *ptr = 0;
|
||||
|
||||
if (type != C_POINTS)
|
||||
{
|
||||
ptr = fakeIBuffer;
|
||||
indexGen.Start((unsigned short*)ptr);
|
||||
AddIndices(_primitive,_numVertices);
|
||||
}
|
||||
|
||||
vbufferwrite = fakeVBuffer;
|
||||
|
||||
if (_numVertices >= MAXVBUFFERSIZE)
|
||||
MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK);
|
||||
|
||||
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite);
|
||||
}
|
||||
else //We are collecting the right type, keep going
|
||||
{
|
||||
_assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF");
|
||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||
//Success, keep adding to unlocked buffer
|
||||
int last = indexGen.GetNumVerts();
|
||||
AddIndices(_primitive, _numVertices);
|
||||
|
||||
if (_numVertices >= MAXVBUFFERSIZE)
|
||||
MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK);
|
||||
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite + last);
|
||||
}
|
||||
}
|
||||
|
||||
const D3DPRIMITIVETYPE pts[3] =
|
||||
{
|
||||
D3DPT_POINTLIST, //DUMMY
|
||||
D3DPT_TRIANGLELIST,
|
||||
D3DPT_LINELIST,
|
||||
};
|
||||
|
||||
void Flush()
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
if (collection != C_NOTHING)
|
||||
{
|
||||
ActivateTextures();
|
||||
|
||||
int numVertices = indexGen.GetNumVerts();
|
||||
if (numVertices != 0)
|
||||
{
|
||||
PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
|
||||
VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
|
||||
if (collection != C_POINTS)
|
||||
{
|
||||
int numPrimitives = indexGen.GetNumPrims();
|
||||
D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection],
|
||||
0,
|
||||
numVertices,
|
||||
numPrimitives,
|
||||
fakeIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
fakeVBuffer,
|
||||
sizeof(D3DVertex));
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::dev->SetIndices(0);
|
||||
|
||||
// D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST,
|
||||
// numVertices,
|
||||
// fakeVBuffer,
|
||||
// sizeof(D3DVertex));
|
||||
Renderer::DrawPrimitiveUP( D3DPT_POINTLIST, numVertices, fakeVBuffer, sizeof(D3DVertex) );
|
||||
}
|
||||
}
|
||||
collection = C_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "D3DBase.h"
|
||||
|
||||
#include "Statistics.h"
|
||||
#include "Profiler.h"
|
||||
#include "VertexManager.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "IndexGenerator.h"
|
||||
#include "BPStructs.h"
|
||||
#include "XFStructs.h"
|
||||
#include "ShaderManager.h"
|
||||
#include "Utils.h"
|
||||
|
||||
using namespace D3D;
|
||||
|
||||
|
||||
namespace VertexManager
|
||||
{
|
||||
|
||||
static IndexGenerator indexGen;
|
||||
static Collection collection;
|
||||
|
||||
static LPDIRECT3DVERTEXDECLARATION9 vDecl;
|
||||
|
||||
static D3DVertex *fakeVBuffer;
|
||||
static u16 *fakeIBuffer;
|
||||
|
||||
#define MAXVBUFFERSIZE 65536*3
|
||||
#define MAXIBUFFERSIZE 65536*3
|
||||
|
||||
const D3DVERTEXELEMENT9 decl[] =
|
||||
{
|
||||
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
|
||||
{ 0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 },
|
||||
{ 0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
|
||||
{ 0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1 },
|
||||
{ 0, 32+12*0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
|
||||
{ 0, 32+12*1, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
|
||||
{ 0, 32+12*2, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2 },
|
||||
{ 0, 32+12*3, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3 },
|
||||
{ 0, 32+12*4, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4 },
|
||||
{ 0, 32+12*5, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 5 },
|
||||
{ 0, 32+12*6, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6 },
|
||||
{ 0, 32+12*7, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7 },
|
||||
D3DDECL_END()
|
||||
};
|
||||
|
||||
|
||||
bool Init()
|
||||
{
|
||||
collection = C_NOTHING;
|
||||
fakeVBuffer = new D3DVertex[65536];
|
||||
fakeIBuffer = new u16[65536];
|
||||
CreateDeviceObjects();
|
||||
return true;
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
DestroyDeviceObjects();
|
||||
delete [] fakeVBuffer;
|
||||
delete [] fakeIBuffer;
|
||||
}
|
||||
|
||||
void CreateDeviceObjects()
|
||||
{
|
||||
HRESULT hr;
|
||||
if (FAILED(hr = D3D::dev->CreateVertexDeclaration(decl, &vDecl)))
|
||||
{
|
||||
MessageBox(0,"Failed to create vertex declaration","sdfsd",0);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void BeginFrame()
|
||||
{
|
||||
D3D::dev->SetVertexDeclaration(vDecl);
|
||||
//D3D::dev->SetStreamSource(0,vBuffer,0,sizeof(D3DVertex));
|
||||
}
|
||||
|
||||
void DestroyDeviceObjects()
|
||||
{
|
||||
if (vDecl)
|
||||
vDecl->Release();
|
||||
vDecl = 0;
|
||||
}
|
||||
|
||||
|
||||
void AddIndices(int _primitive, int _numVertices)
|
||||
{
|
||||
switch(_primitive) {
|
||||
case GX_DRAW_QUADS: indexGen.AddQuads(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLES: indexGen.AddList(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLE_STRIP: indexGen.AddStrip(_numVertices); return;
|
||||
case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return;
|
||||
case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return;
|
||||
case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return;
|
||||
case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return;
|
||||
}
|
||||
}
|
||||
|
||||
const Collection collectionTypeLUT[8] =
|
||||
{
|
||||
C_TRIANGLES,//quads
|
||||
C_NOTHING, //nothing
|
||||
C_TRIANGLES,//triangles
|
||||
C_TRIANGLES,//strip
|
||||
C_TRIANGLES,//fan
|
||||
C_LINES, //lines
|
||||
C_LINES, //linestrip
|
||||
C_POINTS //guess :P
|
||||
};
|
||||
|
||||
D3DVertex *vbufferwrite;
|
||||
|
||||
void AddVertices(int _primitive, int _numVertices, const DecodedVArray *varray)
|
||||
{
|
||||
if (_numVertices <= 0) //This check is pretty stupid...
|
||||
return;
|
||||
|
||||
Collection type = collectionTypeLUT[_primitive];
|
||||
if (type == C_NOTHING)
|
||||
return;
|
||||
|
||||
DVSTARTPROFILE();
|
||||
_assert_msg_(type != C_NOTHING, "type == C_NOTHING!!", "WTF");
|
||||
|
||||
if (indexGen.GetNumVerts() > 1000) // TODO(ector): Raise?
|
||||
Flush();
|
||||
|
||||
ADDSTAT(stats.thisFrame.numPrims, _numVertices);
|
||||
|
||||
if (collection != type)
|
||||
{
|
||||
//We are NOT collecting the right type.
|
||||
Flush();
|
||||
collection = type;
|
||||
u16 *ptr = 0;
|
||||
|
||||
if (type != C_POINTS)
|
||||
{
|
||||
ptr = fakeIBuffer;
|
||||
indexGen.Start((unsigned short*)ptr);
|
||||
AddIndices(_primitive,_numVertices);
|
||||
}
|
||||
|
||||
vbufferwrite = fakeVBuffer;
|
||||
|
||||
if (_numVertices >= MAXVBUFFERSIZE)
|
||||
MessageBox(NULL, "To much vertices for the buffer", "Video.DLL", MB_OK);
|
||||
|
||||
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite);
|
||||
}
|
||||
else //We are collecting the right type, keep going
|
||||
{
|
||||
_assert_msg_(vbufferwrite!=0, "collecting: vbufferwrite == 0!","WTF");
|
||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||
//Success, keep adding to unlocked buffer
|
||||
int last = indexGen.GetNumVerts();
|
||||
AddIndices(_primitive, _numVertices);
|
||||
|
||||
if (_numVertices >= MAXVBUFFERSIZE)
|
||||
MessageBox(NULL, "Too many vertices for the buffer", "Video.DLL", MB_OK);
|
||||
CTransformEngine::TransformVertices(_numVertices, varray, vbufferwrite + last);
|
||||
}
|
||||
}
|
||||
|
||||
const D3DPRIMITIVETYPE pts[3] =
|
||||
{
|
||||
D3DPT_POINTLIST, //DUMMY
|
||||
D3DPT_TRIANGLELIST,
|
||||
D3DPT_LINELIST,
|
||||
};
|
||||
|
||||
void Flush()
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
if (collection != C_NOTHING)
|
||||
{
|
||||
ActivateTextures();
|
||||
|
||||
int numVertices = indexGen.GetNumVerts();
|
||||
if (numVertices != 0)
|
||||
{
|
||||
PShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
|
||||
VShaderCache::SetShader(); // TODO(ector): only do this if shader has changed
|
||||
if (collection != C_POINTS)
|
||||
{
|
||||
int numPrimitives = indexGen.GetNumPrims();
|
||||
D3D::dev->DrawIndexedPrimitiveUP(pts[(int)collection],
|
||||
0,
|
||||
numVertices,
|
||||
numPrimitives,
|
||||
fakeIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
fakeVBuffer,
|
||||
sizeof(D3DVertex));
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::dev->SetIndices(0);
|
||||
|
||||
// D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST,
|
||||
// numVertices,
|
||||
// fakeVBuffer,
|
||||
// sizeof(D3DVertex));
|
||||
Renderer::DrawPrimitiveUP( D3DPT_POINTLIST, numVertices, fakeVBuffer, sizeof(D3DVertex) );
|
||||
}
|
||||
}
|
||||
collection = C_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -1,142 +1,142 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "D3DShader.h"
|
||||
#include "VertexShader.h"
|
||||
#include "BPStructs.h"
|
||||
|
||||
static const char *genericVS = "// Generic Vertex Shader\
|
||||
\n\
|
||||
struct VS_INPUT {\n\
|
||||
float4 pos : POSITION;\n\
|
||||
float3 normal : NORMAL;\n\
|
||||
float4 colors[2] : COLOR0;\n\
|
||||
float3 uv[8] : TEXCOORD0;\n\
|
||||
};\n\
|
||||
\n\
|
||||
struct VS_OUTPUT {\n\
|
||||
float4 pos : POSITION;\n\
|
||||
float4 colors[2] : COLOR0;\n\
|
||||
//numtexgen\n\
|
||||
float4 uv[5] : TEXCOORD0;\n\
|
||||
};\n\
|
||||
\n\
|
||||
uniform matrix matWorldViewProj : register(c0);\n\
|
||||
\n\
|
||||
VS_OUTPUT main(const VS_INPUT input)\n\
|
||||
{\n\
|
||||
VS_OUTPUT output;\n\
|
||||
\n\
|
||||
output.pos = mul(matWorldViewProj, input.pos);\n\
|
||||
// texgen\n\
|
||||
for (int i=0; i<5; i++)\n\
|
||||
output.uv[i] = float4(input.uv[i].xyz,1);\n\
|
||||
\n\
|
||||
for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n\
|
||||
return output;\n\
|
||||
}\0";
|
||||
|
||||
const char *GenerateVertexShader() {
|
||||
return genericVS;
|
||||
}
|
||||
/*
|
||||
|
||||
char text2[65536];
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
void WriteTexgen(char *&p, int n);
|
||||
|
||||
const char *GenerateVertexShader()
|
||||
{
|
||||
int numColors = 2;
|
||||
int numUV = 8;
|
||||
int numTexgen = bpmem.genMode.numtexgens;
|
||||
int numNormals = 3;
|
||||
bool fogEnable = false;
|
||||
bool hasNormal = true;
|
||||
|
||||
char *p = text2;
|
||||
WRITE(p,"//Vertex Shader\n");
|
||||
WRITE(p,"//%i uv->%i texgens, %i colors\n",numUV,numTexgen,numColors);
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"struct VS_INPUT {\n");
|
||||
WRITE(p," float4 pos : POSITION;\n");
|
||||
WRITE(p," float3 normal : NORMAL;\n");
|
||||
if (numColors)
|
||||
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
|
||||
if (numUV)
|
||||
WRITE(p," float3 uv[%i] : TEXCOORD0;\n",numUV);
|
||||
WRITE(p,"};\n");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"struct VS_OUTPUT {\n");
|
||||
WRITE(p," float4 pos : POSITION;\n");
|
||||
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
|
||||
if (numTexgen)
|
||||
WRITE(p," float4 uv[%i] : TEXCOORD0;\n",numTexgen);
|
||||
if (fogEnable)
|
||||
WRITE(p," float fog : FOG;\n",numTexgen);
|
||||
WRITE(p,"};\n");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"uniform matrix matWorldViewProj : register(c0);\n");
|
||||
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"VS_OUTPUT main(const VS_INPUT input)\n");
|
||||
WRITE(p,"{\n");
|
||||
WRITE(p," VS_OUTPUT output;");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p," output.pos = mul(matWorldViewProj, input.pos);\n");
|
||||
|
||||
for (int i = 0; i < (int)bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
//build the equation for this stage
|
||||
WriteTexgen(p,i);
|
||||
}
|
||||
|
||||
WRITE(p," for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n");
|
||||
//WRITE(p," output.fog = 0.0f;");
|
||||
WRITE(p,"return output;\n");
|
||||
WRITE(p,"}\n");
|
||||
WRITE(p,"\0");
|
||||
|
||||
// MessageBox(0,text2,0,0);
|
||||
return text2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* xform->vertexshader ideas
|
||||
|
||||
*//*
|
||||
|
||||
void WriteTexgen(char *&p, int n)
|
||||
{
|
||||
WRITE(p," output.uv[%i] = float4(input.uv[%i].xy,0,input.uv[%i].z);\n",n,n,n);
|
||||
}
|
||||
|
||||
|
||||
void WriteLight(int color, int component)
|
||||
{
|
||||
|
||||
} */
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "D3DShader.h"
|
||||
#include "VertexShader.h"
|
||||
#include "BPStructs.h"
|
||||
|
||||
static const char *genericVS = "// Generic Vertex Shader\
|
||||
\n\
|
||||
struct VS_INPUT {\n\
|
||||
float4 pos : POSITION;\n\
|
||||
float3 normal : NORMAL;\n\
|
||||
float4 colors[2] : COLOR0;\n\
|
||||
float3 uv[8] : TEXCOORD0;\n\
|
||||
};\n\
|
||||
\n\
|
||||
struct VS_OUTPUT {\n\
|
||||
float4 pos : POSITION;\n\
|
||||
float4 colors[2] : COLOR0;\n\
|
||||
//numtexgen\n\
|
||||
float4 uv[5] : TEXCOORD0;\n\
|
||||
};\n\
|
||||
\n\
|
||||
uniform matrix matWorldViewProj : register(c0);\n\
|
||||
\n\
|
||||
VS_OUTPUT main(const VS_INPUT input)\n\
|
||||
{\n\
|
||||
VS_OUTPUT output;\n\
|
||||
\n\
|
||||
output.pos = mul(matWorldViewProj, input.pos);\n\
|
||||
// texgen\n\
|
||||
for (int i=0; i<5; i++)\n\
|
||||
output.uv[i] = float4(input.uv[i].xyz,1);\n\
|
||||
\n\
|
||||
for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n\
|
||||
return output;\n\
|
||||
}\0";
|
||||
|
||||
const char *GenerateVertexShader() {
|
||||
return genericVS;
|
||||
}
|
||||
/*
|
||||
|
||||
char text2[65536];
|
||||
#define WRITE p+=sprintf
|
||||
|
||||
void WriteTexgen(char *&p, int n);
|
||||
|
||||
const char *GenerateVertexShader()
|
||||
{
|
||||
int numColors = 2;
|
||||
int numUV = 8;
|
||||
int numTexgen = bpmem.genMode.numtexgens;
|
||||
int numNormals = 3;
|
||||
bool fogEnable = false;
|
||||
bool hasNormal = true;
|
||||
|
||||
char *p = text2;
|
||||
WRITE(p,"//Vertex Shader\n");
|
||||
WRITE(p,"//%i uv->%i texgens, %i colors\n",numUV,numTexgen,numColors);
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"struct VS_INPUT {\n");
|
||||
WRITE(p," float4 pos : POSITION;\n");
|
||||
WRITE(p," float3 normal : NORMAL;\n");
|
||||
if (numColors)
|
||||
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
|
||||
if (numUV)
|
||||
WRITE(p," float3 uv[%i] : TEXCOORD0;\n",numUV);
|
||||
WRITE(p,"};\n");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"struct VS_OUTPUT {\n");
|
||||
WRITE(p," float4 pos : POSITION;\n");
|
||||
WRITE(p," float4 colors[%i] : COLOR0;\n",numColors);
|
||||
if (numTexgen)
|
||||
WRITE(p," float4 uv[%i] : TEXCOORD0;\n",numTexgen);
|
||||
if (fogEnable)
|
||||
WRITE(p," float fog : FOG;\n",numTexgen);
|
||||
WRITE(p,"};\n");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"uniform matrix matWorldViewProj : register(c0);\n");
|
||||
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p,"VS_OUTPUT main(const VS_INPUT input)\n");
|
||||
WRITE(p,"{\n");
|
||||
WRITE(p," VS_OUTPUT output;");
|
||||
WRITE(p,"\n");
|
||||
|
||||
WRITE(p," output.pos = mul(matWorldViewProj, input.pos);\n");
|
||||
|
||||
for (int i = 0; i < (int)bpmem.genMode.numtexgens; i++)
|
||||
{
|
||||
//build the equation for this stage
|
||||
WriteTexgen(p,i);
|
||||
}
|
||||
|
||||
WRITE(p," for (int i=0; i<2; i++)\n output.colors[i] = input.colors[i];\n");
|
||||
//WRITE(p," output.fog = 0.0f;");
|
||||
WRITE(p,"return output;\n");
|
||||
WRITE(p,"}\n");
|
||||
WRITE(p,"\0");
|
||||
|
||||
// MessageBox(0,text2,0,0);
|
||||
return text2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* xform->vertexshader ideas
|
||||
|
||||
*//*
|
||||
|
||||
void WriteTexgen(char *&p, int n)
|
||||
{
|
||||
WRITE(p," output.uv[%i] = float4(input.uv[%i].xy,0,input.uv[%i].z);\n",n,n,n);
|
||||
}
|
||||
|
||||
|
||||
void WriteLight(int color, int component)
|
||||
{
|
||||
|
||||
} */
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include "DialogManager.h"
|
||||
|
||||
typedef std::vector <HWND> WindowList;
|
||||
WindowList dialogs;
|
||||
|
||||
void DialogManager::AddDlg(HWND hDialog)
|
||||
{
|
||||
dialogs.push_back(hDialog);
|
||||
}
|
||||
|
||||
bool DialogManager::IsDialogMessage(LPMSG message)
|
||||
{
|
||||
WindowList::iterator iter;
|
||||
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
|
||||
{
|
||||
if (::IsDialogMessage(*iter,message))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DialogManager::EnableAll(BOOL enable)
|
||||
{
|
||||
WindowList::iterator iter;
|
||||
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
|
||||
EnableWindow(*iter,enable);
|
||||
}
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include "DialogManager.h"
|
||||
|
||||
typedef std::vector <HWND> WindowList;
|
||||
WindowList dialogs;
|
||||
|
||||
void DialogManager::AddDlg(HWND hDialog)
|
||||
{
|
||||
dialogs.push_back(hDialog);
|
||||
}
|
||||
|
||||
bool DialogManager::IsDialogMessage(LPMSG message)
|
||||
{
|
||||
WindowList::iterator iter;
|
||||
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
|
||||
{
|
||||
if (::IsDialogMessage(*iter,message))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DialogManager::EnableAll(BOOL enable)
|
||||
{
|
||||
WindowList::iterator iter;
|
||||
for (iter=dialogs.begin(); iter!=dialogs.end(); iter++)
|
||||
EnableWindow(*iter,enable);
|
||||
}
|
||||
|
||||
@@ -1,148 +1,148 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "File.h"
|
||||
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
|
||||
File::File()
|
||||
{
|
||||
fileHandle = INVALID_HANDLE_VALUE;
|
||||
isOpen=false;
|
||||
}
|
||||
|
||||
File::~File()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool File::Open(const TCHAR *filename, eFileMode _mode)
|
||||
{
|
||||
mode = _mode;
|
||||
//it's time to open the file
|
||||
fileHandle = CreateFile(filename,
|
||||
mode==FILE_READ ? GENERIC_READ : GENERIC_WRITE, //open mode
|
||||
mode == FILE_READ ? FILE_SHARE_READ : NULL, //sharemode
|
||||
NULL, //security
|
||||
mode==FILE_READ ? OPEN_EXISTING : CREATE_ALWAYS, //create mode
|
||||
FILE_ATTRIBUTE_NORMAL, //atrributes
|
||||
NULL); //template
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
isOpen=false;
|
||||
else
|
||||
isOpen=true;
|
||||
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
|
||||
void File::Close()
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
//close the file and reset variables
|
||||
CloseHandle(fileHandle);
|
||||
fileHandle=INVALID_HANDLE_VALUE;
|
||||
isOpen=false;
|
||||
}
|
||||
}
|
||||
|
||||
int File::GetSize()
|
||||
{
|
||||
if (!isOpen) //of course
|
||||
return 0;
|
||||
else
|
||||
return GetFileSize(fileHandle,0);
|
||||
}
|
||||
|
||||
int File::Write(void *data, int size) //let's do some writing
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
DWORD written;
|
||||
WriteFile(fileHandle, data, size, &written,0);
|
||||
return written; //we return the number of bytes that actually got written
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int File::Read(void *data, int size)
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
DWORD wasRead;
|
||||
ReadFile(fileHandle, data, size, &wasRead,0);
|
||||
return wasRead; //we return the number of bytes that actually was read
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int File::WR(void *data, int size)
|
||||
{
|
||||
if (mode==FILE_READ)
|
||||
return Read(data,size);
|
||||
else
|
||||
return Write(data,size);
|
||||
}
|
||||
bool File::MagicCookie(int cookie)
|
||||
{
|
||||
if (mode==FILE_READ)
|
||||
{
|
||||
if (ReadInt()!=cookie)
|
||||
{
|
||||
char mojs[5],temp[256];
|
||||
mojs[4]=0;
|
||||
*(int*)mojs=cookie;
|
||||
sprintf(temp,"W32Util::File: Magic Cookie %s is bad!",mojs);
|
||||
MessageBox(0,temp,"Error reading file",MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else if (mode==FILE_WRITE)
|
||||
{
|
||||
WriteInt(cookie);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int File::ReadInt()
|
||||
{
|
||||
int temp;
|
||||
if (Read(&temp, sizeof(int)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void File::WriteInt(int i)
|
||||
{
|
||||
Write(&i,sizeof(int));
|
||||
}
|
||||
|
||||
char File::ReadChar()
|
||||
{
|
||||
char temp;
|
||||
if (Read(&temp, sizeof(char)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void File::WriteChar(char i)
|
||||
{
|
||||
Write(&i,sizeof(char));
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "File.h"
|
||||
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
|
||||
File::File()
|
||||
{
|
||||
fileHandle = INVALID_HANDLE_VALUE;
|
||||
isOpen=false;
|
||||
}
|
||||
|
||||
File::~File()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool File::Open(const TCHAR *filename, eFileMode _mode)
|
||||
{
|
||||
mode = _mode;
|
||||
//it's time to open the file
|
||||
fileHandle = CreateFile(filename,
|
||||
mode==FILE_READ ? GENERIC_READ : GENERIC_WRITE, //open mode
|
||||
mode == FILE_READ ? FILE_SHARE_READ : NULL, //sharemode
|
||||
NULL, //security
|
||||
mode==FILE_READ ? OPEN_EXISTING : CREATE_ALWAYS, //create mode
|
||||
FILE_ATTRIBUTE_NORMAL, //atrributes
|
||||
NULL); //template
|
||||
|
||||
if (fileHandle == INVALID_HANDLE_VALUE)
|
||||
isOpen=false;
|
||||
else
|
||||
isOpen=true;
|
||||
|
||||
return isOpen;
|
||||
}
|
||||
|
||||
|
||||
void File::Close()
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
//close the file and reset variables
|
||||
CloseHandle(fileHandle);
|
||||
fileHandle=INVALID_HANDLE_VALUE;
|
||||
isOpen=false;
|
||||
}
|
||||
}
|
||||
|
||||
int File::GetSize()
|
||||
{
|
||||
if (!isOpen) //of course
|
||||
return 0;
|
||||
else
|
||||
return GetFileSize(fileHandle,0);
|
||||
}
|
||||
|
||||
int File::Write(void *data, int size) //let's do some writing
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
DWORD written;
|
||||
WriteFile(fileHandle, data, size, &written,0);
|
||||
return written; //we return the number of bytes that actually got written
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int File::Read(void *data, int size)
|
||||
{
|
||||
if (isOpen)
|
||||
{
|
||||
DWORD wasRead;
|
||||
ReadFile(fileHandle, data, size, &wasRead,0);
|
||||
return wasRead; //we return the number of bytes that actually was read
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int File::WR(void *data, int size)
|
||||
{
|
||||
if (mode==FILE_READ)
|
||||
return Read(data,size);
|
||||
else
|
||||
return Write(data,size);
|
||||
}
|
||||
bool File::MagicCookie(int cookie)
|
||||
{
|
||||
if (mode==FILE_READ)
|
||||
{
|
||||
if (ReadInt()!=cookie)
|
||||
{
|
||||
char mojs[5],temp[256];
|
||||
mojs[4]=0;
|
||||
*(int*)mojs=cookie;
|
||||
sprintf(temp,"W32Util::File: Magic Cookie %s is bad!",mojs);
|
||||
MessageBox(0,temp,"Error reading file",MB_ICONERROR);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else if (mode==FILE_WRITE)
|
||||
{
|
||||
WriteInt(cookie);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int File::ReadInt()
|
||||
{
|
||||
int temp;
|
||||
if (Read(&temp, sizeof(int)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void File::WriteInt(int i)
|
||||
{
|
||||
Write(&i,sizeof(int));
|
||||
}
|
||||
|
||||
char File::ReadChar()
|
||||
{
|
||||
char temp;
|
||||
if (Read(&temp, sizeof(char)))
|
||||
return temp;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void File::WriteChar(char i)
|
||||
{
|
||||
Write(&i,sizeof(char));
|
||||
}
|
||||
}
|
||||
@@ -1,102 +1,102 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Misc.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
//shamelessly taken from http://www.catch22.org.uk/tuts/tips.asp
|
||||
void CenterWindow(HWND hwnd)
|
||||
{
|
||||
HWND hwndParent;
|
||||
RECT rect, rectP;
|
||||
int width, height;
|
||||
int screenwidth, screenheight;
|
||||
int x, y;
|
||||
|
||||
//make the window relative to its parent
|
||||
hwndParent = GetParent(hwnd);
|
||||
if (!hwndParent)
|
||||
return;
|
||||
|
||||
GetWindowRect(hwnd, &rect);
|
||||
GetWindowRect(hwndParent, &rectP);
|
||||
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
|
||||
x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
|
||||
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
|
||||
|
||||
screenwidth = GetSystemMetrics(SM_CXSCREEN);
|
||||
screenheight = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
//make sure that the dialog box never moves outside of
|
||||
//the screen
|
||||
if(x < 0) x = 0;
|
||||
if(y < 0) y = 0;
|
||||
if(x + width > screenwidth) x = screenwidth - width;
|
||||
if(y + height > screenheight) y = screenheight - height;
|
||||
|
||||
MoveWindow(hwnd, x, y, width, height, FALSE);
|
||||
}
|
||||
|
||||
HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h)
|
||||
{
|
||||
BITMAPINFO *bitmap_header;
|
||||
static char bitmapbuffer[sizeof(BITMAPINFO)+16];
|
||||
memset(bitmapbuffer,0,sizeof(BITMAPINFO)+16);
|
||||
bitmap_header=(BITMAPINFO *)bitmapbuffer;
|
||||
bitmap_header->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmap_header->bmiHeader.biPlanes = 1;
|
||||
bitmap_header->bmiHeader.biBitCount = 32;
|
||||
bitmap_header->bmiHeader.biCompression = BI_RGB;
|
||||
bitmap_header->bmiHeader.biWidth = w;
|
||||
bitmap_header->bmiHeader.biHeight = -h;
|
||||
|
||||
((unsigned long *)bitmap_header->bmiColors)[0] = 0x00FF0000;
|
||||
((unsigned long *)bitmap_header->bmiColors)[1] = 0x0000FF00;
|
||||
((unsigned long *)bitmap_header->bmiColors)[2] = 0x000000FF;
|
||||
|
||||
HDC dc = GetDC(someHwnd);
|
||||
HBITMAP bitmap = CreateDIBitmap(dc,&bitmap_header->bmiHeader,CBM_INIT,image,bitmap_header,DIB_RGB_COLORS);
|
||||
ReleaseDC(someHwnd,dc);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void NiceSizeFormat(size_t size, char *out)
|
||||
{
|
||||
char *sizes[] = {"b","KB","MB","GB","TB","PB","EB"};
|
||||
int s = 0;
|
||||
int frac = 0;
|
||||
while (size>1024)
|
||||
{
|
||||
s++;
|
||||
frac = (int)size & 1023;
|
||||
size /= 1024;
|
||||
}
|
||||
float f = (float)size + ((float)frac / 1024.0f);
|
||||
sprintf(out,"%3.1f %s",f,sizes[s]);
|
||||
}
|
||||
BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text)
|
||||
{
|
||||
OpenClipboard(hwnd);
|
||||
EmptyClipboard();
|
||||
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1) * sizeof(TCHAR));
|
||||
if (hglbCopy == NULL)
|
||||
{
|
||||
CloseClipboard();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Lock the handle and copy the text to the buffer.
|
||||
|
||||
TCHAR *lptstrCopy = (TCHAR *)GlobalLock(hglbCopy);
|
||||
strcpy(lptstrCopy, text);
|
||||
lptstrCopy[strlen(text)] = (TCHAR) 0; // null character
|
||||
GlobalUnlock(hglbCopy);
|
||||
SetClipboardData(CF_TEXT,hglbCopy);
|
||||
CloseClipboard();
|
||||
return TRUE;
|
||||
}
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Misc.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
//shamelessly taken from http://www.catch22.org.uk/tuts/tips.asp
|
||||
void CenterWindow(HWND hwnd)
|
||||
{
|
||||
HWND hwndParent;
|
||||
RECT rect, rectP;
|
||||
int width, height;
|
||||
int screenwidth, screenheight;
|
||||
int x, y;
|
||||
|
||||
//make the window relative to its parent
|
||||
hwndParent = GetParent(hwnd);
|
||||
if (!hwndParent)
|
||||
return;
|
||||
|
||||
GetWindowRect(hwnd, &rect);
|
||||
GetWindowRect(hwndParent, &rectP);
|
||||
|
||||
width = rect.right - rect.left;
|
||||
height = rect.bottom - rect.top;
|
||||
|
||||
x = ((rectP.right-rectP.left) - width) / 2 + rectP.left;
|
||||
y = ((rectP.bottom-rectP.top) - height) / 2 + rectP.top;
|
||||
|
||||
screenwidth = GetSystemMetrics(SM_CXSCREEN);
|
||||
screenheight = GetSystemMetrics(SM_CYSCREEN);
|
||||
|
||||
//make sure that the dialog box never moves outside of
|
||||
//the screen
|
||||
if(x < 0) x = 0;
|
||||
if(y < 0) y = 0;
|
||||
if(x + width > screenwidth) x = screenwidth - width;
|
||||
if(y + height > screenheight) y = screenheight - height;
|
||||
|
||||
MoveWindow(hwnd, x, y, width, height, FALSE);
|
||||
}
|
||||
|
||||
HBITMAP CreateBitmapFromARGB(HWND someHwnd, DWORD *image, int w, int h)
|
||||
{
|
||||
BITMAPINFO *bitmap_header;
|
||||
static char bitmapbuffer[sizeof(BITMAPINFO)+16];
|
||||
memset(bitmapbuffer,0,sizeof(BITMAPINFO)+16);
|
||||
bitmap_header=(BITMAPINFO *)bitmapbuffer;
|
||||
bitmap_header->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bitmap_header->bmiHeader.biPlanes = 1;
|
||||
bitmap_header->bmiHeader.biBitCount = 32;
|
||||
bitmap_header->bmiHeader.biCompression = BI_RGB;
|
||||
bitmap_header->bmiHeader.biWidth = w;
|
||||
bitmap_header->bmiHeader.biHeight = -h;
|
||||
|
||||
((unsigned long *)bitmap_header->bmiColors)[0] = 0x00FF0000;
|
||||
((unsigned long *)bitmap_header->bmiColors)[1] = 0x0000FF00;
|
||||
((unsigned long *)bitmap_header->bmiColors)[2] = 0x000000FF;
|
||||
|
||||
HDC dc = GetDC(someHwnd);
|
||||
HBITMAP bitmap = CreateDIBitmap(dc,&bitmap_header->bmiHeader,CBM_INIT,image,bitmap_header,DIB_RGB_COLORS);
|
||||
ReleaseDC(someHwnd,dc);
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
void NiceSizeFormat(size_t size, char *out)
|
||||
{
|
||||
char *sizes[] = {"b","KB","MB","GB","TB","PB","EB"};
|
||||
int s = 0;
|
||||
int frac = 0;
|
||||
while (size>1024)
|
||||
{
|
||||
s++;
|
||||
frac = (int)size & 1023;
|
||||
size /= 1024;
|
||||
}
|
||||
float f = (float)size + ((float)frac / 1024.0f);
|
||||
sprintf(out,"%3.1f %s",f,sizes[s]);
|
||||
}
|
||||
BOOL CopyTextToClipboard(HWND hwnd, TCHAR *text)
|
||||
{
|
||||
OpenClipboard(hwnd);
|
||||
EmptyClipboard();
|
||||
HANDLE hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(text) + 1) * sizeof(TCHAR));
|
||||
if (hglbCopy == NULL)
|
||||
{
|
||||
CloseClipboard();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Lock the handle and copy the text to the buffer.
|
||||
|
||||
TCHAR *lptstrCopy = (TCHAR *)GlobalLock(hglbCopy);
|
||||
strcpy(lptstrCopy, text);
|
||||
lptstrCopy[strlen(text)] = (TCHAR) 0; // null character
|
||||
GlobalUnlock(hglbCopy);
|
||||
SetClipboardData(CF_TEXT,hglbCopy);
|
||||
CloseClipboard();
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1,225 +1,225 @@
|
||||
#include "Misc.h"
|
||||
#include "PropertySheet.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
bool centered;
|
||||
|
||||
PropSheet::PropSheet()
|
||||
{
|
||||
watermark = 0;
|
||||
header = 0;
|
||||
icon = 0;
|
||||
}
|
||||
|
||||
int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg) {
|
||||
case PSCB_PRECREATE:
|
||||
{
|
||||
if (uMsg == PSCB_PRECREATE)
|
||||
{
|
||||
/*
|
||||
if (lParam)
|
||||
{
|
||||
DLGTEMPLATE *pDlgTemplate;
|
||||
DLGTEMPLATEEX *pDlgTemplateEx;
|
||||
|
||||
pDlgTemplateEx = (DLGTEMPLATEEX *)lParam;
|
||||
if (pDlgTemplateEx->signature == 0xFFFF)
|
||||
{
|
||||
// pDlgTemplateEx points to an extended
|
||||
// dialog template structure.
|
||||
|
||||
//pDlgTemplate->style |= DS_SETFONT;
|
||||
u8 *tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX);
|
||||
u16 *tmp = (u16*)tmp1;
|
||||
tmp++; //skip menu
|
||||
tmp++; //skip dlg class
|
||||
//Crash();
|
||||
//Here we should bash in Segoe UI
|
||||
//It turns out to be way complicated though
|
||||
//Not worth it
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a standard dialog template
|
||||
// structure.
|
||||
pDlgTemplate = (DLGTEMPLATE *)lParam;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case PSCB_INITIALIZED:
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PropSheet::Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage, bool floating, bool wizard)
|
||||
{
|
||||
HPROPSHEETPAGE *pages = new HPROPSHEETPAGE[list.size()];
|
||||
PROPSHEETPAGE page;
|
||||
//common settings
|
||||
memset((void*)&page,0,sizeof(PROPSHEETPAGE));
|
||||
page.dwSize = sizeof(PROPSHEETPAGE);
|
||||
page.hInstance = hInstance;
|
||||
|
||||
int i=0;
|
||||
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++)
|
||||
{
|
||||
if (wizard)
|
||||
{
|
||||
if (i == 0 || i == list.size()-1)
|
||||
page.dwFlags = PSP_HIDEHEADER;
|
||||
else
|
||||
page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
page.dwFlags = PSP_USETITLE;
|
||||
}
|
||||
page.pszTemplate = iter->resource;
|
||||
page.pfnDlgProc = Tab::TabDlgProc;
|
||||
page.pszTitle = iter->title;
|
||||
page.pszHeaderTitle = wizard?iter->title:0;
|
||||
page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0;
|
||||
page.lParam = (LPARAM)iter->tab;
|
||||
pages[i] = CreatePropertySheetPage(&page);
|
||||
}
|
||||
|
||||
PROPSHEETHEADER sheet;
|
||||
memset(&sheet,0,sizeof(sheet));
|
||||
sheet.dwSize = sizeof(PROPSHEETHEADER);
|
||||
sheet.hInstance = hInstance;
|
||||
sheet.hwndParent = hParent;
|
||||
sheet.pszbmWatermark = watermark;
|
||||
sheet.pszbmHeader = header;
|
||||
|
||||
if (icon)
|
||||
sheet.hIcon = icon;
|
||||
|
||||
if (wizard)
|
||||
sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0);
|
||||
else
|
||||
sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
|
||||
|
||||
sheet.dwFlags |= PSH_NOCONTEXTHELP;
|
||||
|
||||
if (floating)
|
||||
sheet.dwFlags |= PSH_MODELESS;
|
||||
//else
|
||||
// sheet.dwFlags |= PSH_NOAPPLYNOW;
|
||||
|
||||
if (icon)
|
||||
sheet.dwFlags |= PSH_USEHICON;
|
||||
|
||||
sheet.pszCaption = title.c_str();
|
||||
sheet.nPages = (UINT)list.size();
|
||||
sheet.phpage = pages;
|
||||
sheet.nStartPage = startpage;
|
||||
sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback;
|
||||
|
||||
NONCLIENTMETRICS ncm = {0};
|
||||
ncm.cbSize = sizeof(ncm);
|
||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
|
||||
hDialogFont = CreateFontIndirect(&ncm.lfMessageFont);
|
||||
|
||||
if (wizard)
|
||||
{
|
||||
|
||||
//Create the intro/end title font
|
||||
LOGFONT TitleLogFont = ncm.lfMessageFont;
|
||||
TitleLogFont.lfWeight = FW_BOLD;
|
||||
lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold"));
|
||||
//StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold"));
|
||||
|
||||
HDC hdc = GetDC(NULL); //gets the screen DC
|
||||
int FontSize = 12;
|
||||
TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72;
|
||||
hTitleFont = CreateFontIndirect(&TitleLogFont);
|
||||
ReleaseDC(NULL, hdc);
|
||||
}
|
||||
else
|
||||
hTitleFont = 0;
|
||||
|
||||
centered=false;
|
||||
PropertySheet(&sheet);
|
||||
if (!floating)
|
||||
{
|
||||
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++)
|
||||
{
|
||||
delete iter->tab;
|
||||
}
|
||||
DeleteObject(hTitleFont);
|
||||
}
|
||||
DeleteObject(hDialogFont);
|
||||
delete [] pages;
|
||||
}
|
||||
void PropSheet::Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle)
|
||||
{
|
||||
tab->sheet = this;
|
||||
list.push_back(Page(tab,resource,title,subtitle));
|
||||
}
|
||||
|
||||
|
||||
void WizExteriorPage::Init(HWND hDlg)
|
||||
{
|
||||
HWND hwndControl = GetDlgItem(hDlg, captionID);
|
||||
//SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE);
|
||||
SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0);
|
||||
}
|
||||
|
||||
INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
Tab *tab = (Tab *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
|
||||
switch(message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
if (!centered) //HACK
|
||||
{
|
||||
CenterWindow(GetParent(hDlg));
|
||||
centered=true;
|
||||
}
|
||||
LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam;
|
||||
tab = (Tab *)l;
|
||||
SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l);
|
||||
tab->Init(hDlg);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
tab->Command(hDlg,wParam);
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam;
|
||||
HWND sheet = lppsn->hdr.hwndFrom;
|
||||
switch(lppsn->hdr.code) {
|
||||
case PSN_APPLY:
|
||||
tab->Apply(hDlg);
|
||||
break;
|
||||
case PSN_SETACTIVE:
|
||||
PropSheet_SetWizButtons(GetParent(hDlg),
|
||||
(tab->HasPrev()?PSWIZB_BACK:0) |
|
||||
(tab->HasNext()?PSWIZB_NEXT:0) |
|
||||
(tab->HasFinish()?PSWIZB_FINISH:0));
|
||||
break;
|
||||
case PSN_WIZNEXT:
|
||||
tab->Apply(hDlg); //maybe not always good
|
||||
break;
|
||||
case PSN_WIZBACK:
|
||||
case PSN_RESET: //cancel
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#include "Misc.h"
|
||||
#include "PropertySheet.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
bool centered;
|
||||
|
||||
PropSheet::PropSheet()
|
||||
{
|
||||
watermark = 0;
|
||||
header = 0;
|
||||
icon = 0;
|
||||
}
|
||||
|
||||
int CALLBACK PropSheet::Callback(HWND hwndDlg, UINT uMsg, LPARAM lParam)
|
||||
{
|
||||
switch (uMsg) {
|
||||
case PSCB_PRECREATE:
|
||||
{
|
||||
if (uMsg == PSCB_PRECREATE)
|
||||
{
|
||||
/*
|
||||
if (lParam)
|
||||
{
|
||||
DLGTEMPLATE *pDlgTemplate;
|
||||
DLGTEMPLATEEX *pDlgTemplateEx;
|
||||
|
||||
pDlgTemplateEx = (DLGTEMPLATEEX *)lParam;
|
||||
if (pDlgTemplateEx->signature == 0xFFFF)
|
||||
{
|
||||
// pDlgTemplateEx points to an extended
|
||||
// dialog template structure.
|
||||
|
||||
//pDlgTemplate->style |= DS_SETFONT;
|
||||
u8 *tmp1 = (u8*)&pDlgTemplateEx + sizeof(DLGTEMPLATEEX);
|
||||
u16 *tmp = (u16*)tmp1;
|
||||
tmp++; //skip menu
|
||||
tmp++; //skip dlg class
|
||||
//Crash();
|
||||
//Here we should bash in Segoe UI
|
||||
//It turns out to be way complicated though
|
||||
//Not worth it
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is a standard dialog template
|
||||
// structure.
|
||||
pDlgTemplate = (DLGTEMPLATE *)lParam;
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case PSCB_INITIALIZED:
|
||||
{
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PropSheet::Show(HINSTANCE hInstance, HWND hParent, std::string title, int startpage, bool floating, bool wizard)
|
||||
{
|
||||
HPROPSHEETPAGE *pages = new HPROPSHEETPAGE[list.size()];
|
||||
PROPSHEETPAGE page;
|
||||
//common settings
|
||||
memset((void*)&page,0,sizeof(PROPSHEETPAGE));
|
||||
page.dwSize = sizeof(PROPSHEETPAGE);
|
||||
page.hInstance = hInstance;
|
||||
|
||||
int i=0;
|
||||
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++, i++)
|
||||
{
|
||||
if (wizard)
|
||||
{
|
||||
if (i == 0 || i == list.size()-1)
|
||||
page.dwFlags = PSP_HIDEHEADER;
|
||||
else
|
||||
page.dwFlags = PSP_USEHEADERTITLE|PSP_USEHEADERSUBTITLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
page.dwFlags = PSP_USETITLE;
|
||||
}
|
||||
page.pszTemplate = iter->resource;
|
||||
page.pfnDlgProc = Tab::TabDlgProc;
|
||||
page.pszTitle = iter->title;
|
||||
page.pszHeaderTitle = wizard?iter->title:0;
|
||||
page.pszHeaderSubTitle = wizard?iter->hdrSubTitle:0;
|
||||
page.lParam = (LPARAM)iter->tab;
|
||||
pages[i] = CreatePropertySheetPage(&page);
|
||||
}
|
||||
|
||||
PROPSHEETHEADER sheet;
|
||||
memset(&sheet,0,sizeof(sheet));
|
||||
sheet.dwSize = sizeof(PROPSHEETHEADER);
|
||||
sheet.hInstance = hInstance;
|
||||
sheet.hwndParent = hParent;
|
||||
sheet.pszbmWatermark = watermark;
|
||||
sheet.pszbmHeader = header;
|
||||
|
||||
if (icon)
|
||||
sheet.hIcon = icon;
|
||||
|
||||
if (wizard)
|
||||
sheet.dwFlags = PSH_USECALLBACK | PSH_WIZARD97 | (watermark?PSH_WATERMARK:0) | (header?PSH_HEADER:0);
|
||||
else
|
||||
sheet.dwFlags = PSH_USECALLBACK | PSH_PROPTITLE;
|
||||
|
||||
sheet.dwFlags |= PSH_NOCONTEXTHELP;
|
||||
|
||||
if (floating)
|
||||
sheet.dwFlags |= PSH_MODELESS;
|
||||
//else
|
||||
// sheet.dwFlags |= PSH_NOAPPLYNOW;
|
||||
|
||||
if (icon)
|
||||
sheet.dwFlags |= PSH_USEHICON;
|
||||
|
||||
sheet.pszCaption = title.c_str();
|
||||
sheet.nPages = (UINT)list.size();
|
||||
sheet.phpage = pages;
|
||||
sheet.nStartPage = startpage;
|
||||
sheet.pfnCallback = (PFNPROPSHEETCALLBACK)Callback;
|
||||
|
||||
NONCLIENTMETRICS ncm = {0};
|
||||
ncm.cbSize = sizeof(ncm);
|
||||
SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
|
||||
hDialogFont = CreateFontIndirect(&ncm.lfMessageFont);
|
||||
|
||||
if (wizard)
|
||||
{
|
||||
|
||||
//Create the intro/end title font
|
||||
LOGFONT TitleLogFont = ncm.lfMessageFont;
|
||||
TitleLogFont.lfWeight = FW_BOLD;
|
||||
lstrcpy(TitleLogFont.lfFaceName, TEXT("Verdana Bold"));
|
||||
//StringCchCopy(TitleLogFont.lfFaceName, 32, TEXT("Verdana Bold"));
|
||||
|
||||
HDC hdc = GetDC(NULL); //gets the screen DC
|
||||
int FontSize = 12;
|
||||
TitleLogFont.lfHeight = 0 - GetDeviceCaps(hdc, LOGPIXELSY) * FontSize / 72;
|
||||
hTitleFont = CreateFontIndirect(&TitleLogFont);
|
||||
ReleaseDC(NULL, hdc);
|
||||
}
|
||||
else
|
||||
hTitleFont = 0;
|
||||
|
||||
centered=false;
|
||||
PropertySheet(&sheet);
|
||||
if (!floating)
|
||||
{
|
||||
for (DlgList::iterator iter = list.begin(); iter != list.end(); iter++)
|
||||
{
|
||||
delete iter->tab;
|
||||
}
|
||||
DeleteObject(hTitleFont);
|
||||
}
|
||||
DeleteObject(hDialogFont);
|
||||
delete [] pages;
|
||||
}
|
||||
void PropSheet::Add(Tab *tab, LPCTSTR resource, LPCTSTR title, LPCTSTR subtitle)
|
||||
{
|
||||
tab->sheet = this;
|
||||
list.push_back(Page(tab,resource,title,subtitle));
|
||||
}
|
||||
|
||||
|
||||
void WizExteriorPage::Init(HWND hDlg)
|
||||
{
|
||||
HWND hwndControl = GetDlgItem(hDlg, captionID);
|
||||
//SetWindowFont(hwndControl, sheet->GetTitleFont(), TRUE);
|
||||
SendMessage(hwndControl,WM_SETFONT,(WPARAM)sheet->GetTitleFont(),0);
|
||||
}
|
||||
|
||||
INT_PTR Tab::TabDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
Tab *tab = (Tab *)GetWindowLongPtr(hDlg, GWLP_USERDATA);
|
||||
switch(message)
|
||||
{
|
||||
case WM_INITDIALOG:
|
||||
{
|
||||
if (!centered) //HACK
|
||||
{
|
||||
CenterWindow(GetParent(hDlg));
|
||||
centered=true;
|
||||
}
|
||||
LPARAM l = ((LPPROPSHEETPAGE)lParam)->lParam;
|
||||
tab = (Tab *)l;
|
||||
SetWindowLongPtr(hDlg, GWLP_USERDATA, (DWORD_PTR)l);
|
||||
tab->Init(hDlg);
|
||||
}
|
||||
break;
|
||||
|
||||
case WM_COMMAND:
|
||||
tab->Command(hDlg,wParam);
|
||||
break;
|
||||
case WM_NOTIFY:
|
||||
{
|
||||
LPPSHNOTIFY lppsn = (LPPSHNOTIFY) lParam;
|
||||
HWND sheet = lppsn->hdr.hwndFrom;
|
||||
switch(lppsn->hdr.code) {
|
||||
case PSN_APPLY:
|
||||
tab->Apply(hDlg);
|
||||
break;
|
||||
case PSN_SETACTIVE:
|
||||
PropSheet_SetWizButtons(GetParent(hDlg),
|
||||
(tab->HasPrev()?PSWIZB_BACK:0) |
|
||||
(tab->HasNext()?PSWIZB_NEXT:0) |
|
||||
(tab->HasFinish()?PSWIZB_FINISH:0));
|
||||
break;
|
||||
case PSN_WIZNEXT:
|
||||
tab->Apply(hDlg); //maybe not always good
|
||||
break;
|
||||
case PSN_WIZBACK:
|
||||
case PSN_RESET: //cancel
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1,124 +1,124 @@
|
||||
#include <shlobj.h>
|
||||
#include <xstring>
|
||||
#include <string>
|
||||
#include "ShellUtil.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
std::string BrowseForFolder(HWND parent, char *title)
|
||||
{
|
||||
BROWSEINFO info;
|
||||
memset(&info,0,sizeof(info));
|
||||
info.hwndOwner = parent;
|
||||
info.lpszTitle = title;
|
||||
info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
|
||||
|
||||
//info.pszDisplayName
|
||||
LPCITEMIDLIST idList = SHBrowseForFolder(&info);
|
||||
|
||||
char temp[MAX_PATH];
|
||||
SHGetPathFromIDList(idList, temp);
|
||||
if (strlen(temp))
|
||||
{
|
||||
return temp;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// function WinBrowseForFileName
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension,
|
||||
std::string& _strFileName)
|
||||
{
|
||||
char szFile [MAX_PATH+1];
|
||||
char szFileTitle [MAX_PATH+1];
|
||||
|
||||
strcpy (szFile,"");
|
||||
strcpy (szFileTitle,"");
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
||||
ZeroMemory (&ofn,sizeof (ofn));
|
||||
|
||||
ofn.lStructSize = sizeof (OPENFILENAME);
|
||||
ofn.lpstrInitialDir = _pInitialFolder;
|
||||
ofn.lpstrFilter = _pFilter;
|
||||
ofn.nMaxFile = sizeof (szFile);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.lpstrFileTitle = szFileTitle;
|
||||
ofn.nMaxFileTitle = sizeof (szFileTitle);
|
||||
ofn.lpstrDefExt = _pExtension;
|
||||
ofn.hwndOwner = _hParent;
|
||||
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY;
|
||||
|
||||
if (_strFileName.size () != 0)
|
||||
ofn.lpstrFile = (char *)_strFileName.c_str();
|
||||
|
||||
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
|
||||
{
|
||||
_strFileName = ofn.lpstrFile;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension)
|
||||
{
|
||||
char szFile [MAX_PATH+1+2048*2];
|
||||
char szFileTitle [MAX_PATH+1];
|
||||
|
||||
strcpy (szFile,"");
|
||||
strcpy (szFileTitle,"");
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
||||
ZeroMemory (&ofn,sizeof (ofn));
|
||||
|
||||
ofn.lStructSize = sizeof (OPENFILENAME);
|
||||
ofn.lpstrInitialDir = _pInitialFolder;
|
||||
ofn.lpstrFilter = _pFilter;
|
||||
ofn.nMaxFile = sizeof (szFile);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.lpstrFileTitle = szFileTitle;
|
||||
ofn.nMaxFileTitle = sizeof (szFileTitle);
|
||||
ofn.lpstrDefExt = _pExtension;
|
||||
ofn.hwndOwner = _hParent;
|
||||
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT ;
|
||||
|
||||
std::vector<std::string> files;
|
||||
|
||||
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
|
||||
{
|
||||
std::string directory = ofn.lpstrFile;
|
||||
char *temp = ofn.lpstrFile;
|
||||
char *oldtemp = temp;
|
||||
temp+=strlen(temp)+1;
|
||||
if (*temp==0)
|
||||
{
|
||||
//we only got one file
|
||||
files.push_back(std::string(oldtemp));
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*temp)
|
||||
{
|
||||
files.push_back(directory+"\\"+std::string(temp));
|
||||
temp+=strlen(temp)+1;
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
else
|
||||
return std::vector<std::string>(); // empty vector;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include <shlobj.h>
|
||||
#include <xstring>
|
||||
#include <string>
|
||||
#include "ShellUtil.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
std::string BrowseForFolder(HWND parent, char *title)
|
||||
{
|
||||
BROWSEINFO info;
|
||||
memset(&info,0,sizeof(info));
|
||||
info.hwndOwner = parent;
|
||||
info.lpszTitle = title;
|
||||
info.ulFlags = BIF_EDITBOX | BIF_RETURNONLYFSDIRS;
|
||||
|
||||
//info.pszDisplayName
|
||||
LPCITEMIDLIST idList = SHBrowseForFolder(&info);
|
||||
|
||||
char temp[MAX_PATH];
|
||||
SHGetPathFromIDList(idList, temp);
|
||||
if (strlen(temp))
|
||||
{
|
||||
return temp;
|
||||
}
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
// function WinBrowseForFileName
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
bool BrowseForFileName (bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension,
|
||||
std::string& _strFileName)
|
||||
{
|
||||
char szFile [MAX_PATH+1];
|
||||
char szFileTitle [MAX_PATH+1];
|
||||
|
||||
strcpy (szFile,"");
|
||||
strcpy (szFileTitle,"");
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
||||
ZeroMemory (&ofn,sizeof (ofn));
|
||||
|
||||
ofn.lStructSize = sizeof (OPENFILENAME);
|
||||
ofn.lpstrInitialDir = _pInitialFolder;
|
||||
ofn.lpstrFilter = _pFilter;
|
||||
ofn.nMaxFile = sizeof (szFile);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.lpstrFileTitle = szFileTitle;
|
||||
ofn.nMaxFileTitle = sizeof (szFileTitle);
|
||||
ofn.lpstrDefExt = _pExtension;
|
||||
ofn.hwndOwner = _hParent;
|
||||
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY;
|
||||
|
||||
if (_strFileName.size () != 0)
|
||||
ofn.lpstrFile = (char *)_strFileName.c_str();
|
||||
|
||||
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
|
||||
{
|
||||
_strFileName = ofn.lpstrFile;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> BrowseForFileNameMultiSelect(bool _bLoad, HWND _hParent, const char *_pTitle,
|
||||
const char *_pInitialFolder,const char *_pFilter,const char *_pExtension)
|
||||
{
|
||||
char szFile [MAX_PATH+1+2048*2];
|
||||
char szFileTitle [MAX_PATH+1];
|
||||
|
||||
strcpy (szFile,"");
|
||||
strcpy (szFileTitle,"");
|
||||
|
||||
OPENFILENAME ofn;
|
||||
|
||||
ZeroMemory (&ofn,sizeof (ofn));
|
||||
|
||||
ofn.lStructSize = sizeof (OPENFILENAME);
|
||||
ofn.lpstrInitialDir = _pInitialFolder;
|
||||
ofn.lpstrFilter = _pFilter;
|
||||
ofn.nMaxFile = sizeof (szFile);
|
||||
ofn.lpstrFile = szFile;
|
||||
ofn.lpstrFileTitle = szFileTitle;
|
||||
ofn.nMaxFileTitle = sizeof (szFileTitle);
|
||||
ofn.lpstrDefExt = _pExtension;
|
||||
ofn.hwndOwner = _hParent;
|
||||
ofn.Flags = OFN_NOCHANGEDIR | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ALLOWMULTISELECT ;
|
||||
|
||||
std::vector<std::string> files;
|
||||
|
||||
if (((_bLoad)?GetOpenFileName (&ofn):GetSaveFileName (&ofn)))
|
||||
{
|
||||
std::string directory = ofn.lpstrFile;
|
||||
char *temp = ofn.lpstrFile;
|
||||
char *oldtemp = temp;
|
||||
temp+=strlen(temp)+1;
|
||||
if (*temp==0)
|
||||
{
|
||||
//we only got one file
|
||||
files.push_back(std::string(oldtemp));
|
||||
}
|
||||
else
|
||||
{
|
||||
while (*temp)
|
||||
{
|
||||
files.push_back(directory+"\\"+std::string(temp));
|
||||
temp+=strlen(temp)+1;
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
else
|
||||
return std::vector<std::string>(); // empty vector;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,94 +1,94 @@
|
||||
#include <commctrl.h>
|
||||
|
||||
#include "TabControl.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
// __________________________________________________________________________________________________
|
||||
// constructor
|
||||
//
|
||||
TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) :
|
||||
m_hInstance(_hInstance),
|
||||
m_hTabCtrl(_hTabCtrl),
|
||||
m_numDialogs(0)
|
||||
{
|
||||
for (int i=0; i<MAX_WIN_DIALOGS; i++)
|
||||
m_WinDialogs[i] = NULL;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// destructor
|
||||
//
|
||||
TabControl::~TabControl(void)
|
||||
{}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// AddItem
|
||||
//
|
||||
HWND TabControl::AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc)
|
||||
{
|
||||
TCITEM tcItem;
|
||||
|
||||
ZeroMemory (&tcItem,sizeof (tcItem));
|
||||
|
||||
tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
|
||||
tcItem.dwState = 0;
|
||||
tcItem.pszText = _szText;
|
||||
tcItem.cchTextMax = sizeof (_szText);
|
||||
tcItem.iImage = -1;
|
||||
|
||||
int nResult = TabCtrl_InsertItem (m_hTabCtrl,TabCtrl_GetItemCount (m_hTabCtrl),&tcItem);
|
||||
|
||||
|
||||
HWND hDialog = CreateDialog(m_hInstance,(LPCSTR)_iResource,m_hTabCtrl,_lpDialogFunc);
|
||||
RECT rectInnerWindow = {0,0,0,0};
|
||||
|
||||
GetWindowRect (m_hTabCtrl,&rectInnerWindow);
|
||||
|
||||
TabCtrl_AdjustRect (m_hTabCtrl,FALSE,&rectInnerWindow);
|
||||
|
||||
POINT pntPosition = {rectInnerWindow.left,rectInnerWindow.top};
|
||||
ScreenToClient(m_hTabCtrl, &pntPosition);
|
||||
|
||||
SetWindowPos(hDialog, 0,
|
||||
pntPosition.x, pntPosition.y,
|
||||
rectInnerWindow.right - rectInnerWindow.left,rectInnerWindow.bottom - rectInnerWindow.top,0);
|
||||
ShowWindow(hDialog,SW_NORMAL);
|
||||
|
||||
m_WinDialogs[m_numDialogs] = hDialog;
|
||||
m_numDialogs++;
|
||||
|
||||
SelectDialog (0);
|
||||
|
||||
return hDialog;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// SelectDialog
|
||||
//
|
||||
void TabControl::SelectDialog (int _nDialogId)
|
||||
{
|
||||
for (int i = 0 ; i < m_numDialogs ; i ++)
|
||||
if (m_WinDialogs[i] != NULL)
|
||||
ShowWindow(m_WinDialogs[i],i == _nDialogId ? SW_NORMAL : SW_HIDE);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// MessageHandler
|
||||
//
|
||||
void TabControl::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (message == WM_NOTIFY)
|
||||
{
|
||||
NMHDR* pNotifyMessage = NULL;
|
||||
pNotifyMessage = (LPNMHDR)lParam;
|
||||
if (pNotifyMessage->hwndFrom == m_hTabCtrl)
|
||||
{
|
||||
int iPage = TabCtrl_GetCurSel (m_hTabCtrl);
|
||||
SelectDialog (iPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <commctrl.h>
|
||||
|
||||
#include "TabControl.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
// __________________________________________________________________________________________________
|
||||
// constructor
|
||||
//
|
||||
TabControl::TabControl(HINSTANCE _hInstance, HWND _hTabCtrl,DLGPROC _lpDialogFunc) :
|
||||
m_hInstance(_hInstance),
|
||||
m_hTabCtrl(_hTabCtrl),
|
||||
m_numDialogs(0)
|
||||
{
|
||||
for (int i=0; i<MAX_WIN_DIALOGS; i++)
|
||||
m_WinDialogs[i] = NULL;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// destructor
|
||||
//
|
||||
TabControl::~TabControl(void)
|
||||
{}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// AddItem
|
||||
//
|
||||
HWND TabControl::AddItem (char* _szText,int _iResource,DLGPROC _lpDialogFunc)
|
||||
{
|
||||
TCITEM tcItem;
|
||||
|
||||
ZeroMemory (&tcItem,sizeof (tcItem));
|
||||
|
||||
tcItem.mask = TCIF_TEXT | TCIF_IMAGE;
|
||||
tcItem.dwState = 0;
|
||||
tcItem.pszText = _szText;
|
||||
tcItem.cchTextMax = sizeof (_szText);
|
||||
tcItem.iImage = -1;
|
||||
|
||||
int nResult = TabCtrl_InsertItem (m_hTabCtrl,TabCtrl_GetItemCount (m_hTabCtrl),&tcItem);
|
||||
|
||||
|
||||
HWND hDialog = CreateDialog(m_hInstance,(LPCSTR)_iResource,m_hTabCtrl,_lpDialogFunc);
|
||||
RECT rectInnerWindow = {0,0,0,0};
|
||||
|
||||
GetWindowRect (m_hTabCtrl,&rectInnerWindow);
|
||||
|
||||
TabCtrl_AdjustRect (m_hTabCtrl,FALSE,&rectInnerWindow);
|
||||
|
||||
POINT pntPosition = {rectInnerWindow.left,rectInnerWindow.top};
|
||||
ScreenToClient(m_hTabCtrl, &pntPosition);
|
||||
|
||||
SetWindowPos(hDialog, 0,
|
||||
pntPosition.x, pntPosition.y,
|
||||
rectInnerWindow.right - rectInnerWindow.left,rectInnerWindow.bottom - rectInnerWindow.top,0);
|
||||
ShowWindow(hDialog,SW_NORMAL);
|
||||
|
||||
m_WinDialogs[m_numDialogs] = hDialog;
|
||||
m_numDialogs++;
|
||||
|
||||
SelectDialog (0);
|
||||
|
||||
return hDialog;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// SelectDialog
|
||||
//
|
||||
void TabControl::SelectDialog (int _nDialogId)
|
||||
{
|
||||
for (int i = 0 ; i < m_numDialogs ; i ++)
|
||||
if (m_WinDialogs[i] != NULL)
|
||||
ShowWindow(m_WinDialogs[i],i == _nDialogId ? SW_NORMAL : SW_HIDE);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// MessageHandler
|
||||
//
|
||||
void TabControl::MessageHandler(UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
if (message == WM_NOTIFY)
|
||||
{
|
||||
NMHDR* pNotifyMessage = NULL;
|
||||
pNotifyMessage = (LPNMHDR)lParam;
|
||||
if (pNotifyMessage->hwndFrom == m_hTabCtrl)
|
||||
{
|
||||
int iPage = TabCtrl_GetCurSel (m_hTabCtrl);
|
||||
SelectDialog (iPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1,82 +1,82 @@
|
||||
#include "Thread.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
// __________________________________________________________________________________________________
|
||||
// Constructor
|
||||
//
|
||||
Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg)
|
||||
{
|
||||
_handle = CreateThread (
|
||||
0, // Security attributes
|
||||
0, // Stack size
|
||||
pFun,
|
||||
pArg,
|
||||
CREATE_SUSPENDED,
|
||||
&_tid);
|
||||
}
|
||||
// __________________________________________________________________________________________________
|
||||
// Destructor
|
||||
//
|
||||
Thread::~Thread (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
{
|
||||
if (CloseHandle (_handle) == FALSE)
|
||||
{
|
||||
Terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Resume
|
||||
//
|
||||
void
|
||||
Thread::Resume (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
ResumeThread (_handle);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// WaitForDeath
|
||||
//
|
||||
void
|
||||
Thread::WaitForDeath (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
WaitForSingleObject (_handle, 100);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Terminate
|
||||
//
|
||||
void
|
||||
Thread::Terminate (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
TerminateThread (_handle, 0);
|
||||
_handle = NULL;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// SetPriority
|
||||
//
|
||||
void
|
||||
Thread::SetPriority (int _nPriority)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
SetThreadPriority(_handle, _nPriority);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Suspend
|
||||
//
|
||||
void
|
||||
Thread::Suspend (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
SuspendThread(_handle);
|
||||
}
|
||||
#include "Thread.h"
|
||||
|
||||
namespace W32Util
|
||||
{
|
||||
// __________________________________________________________________________________________________
|
||||
// Constructor
|
||||
//
|
||||
Thread::Thread ( DWORD (WINAPI * pFun) (void* arg), void* pArg)
|
||||
{
|
||||
_handle = CreateThread (
|
||||
0, // Security attributes
|
||||
0, // Stack size
|
||||
pFun,
|
||||
pArg,
|
||||
CREATE_SUSPENDED,
|
||||
&_tid);
|
||||
}
|
||||
// __________________________________________________________________________________________________
|
||||
// Destructor
|
||||
//
|
||||
Thread::~Thread (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
{
|
||||
if (CloseHandle (_handle) == FALSE)
|
||||
{
|
||||
Terminate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Resume
|
||||
//
|
||||
void
|
||||
Thread::Resume (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
ResumeThread (_handle);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// WaitForDeath
|
||||
//
|
||||
void
|
||||
Thread::WaitForDeath (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
WaitForSingleObject (_handle, 100);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Terminate
|
||||
//
|
||||
void
|
||||
Thread::Terminate (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
TerminateThread (_handle, 0);
|
||||
_handle = NULL;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// SetPriority
|
||||
//
|
||||
void
|
||||
Thread::SetPriority (int _nPriority)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
SetThreadPriority(_handle, _nPriority);
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Suspend
|
||||
//
|
||||
void
|
||||
Thread::Suspend (void)
|
||||
{
|
||||
if (_handle != NULL)
|
||||
SuspendThread(_handle);
|
||||
}
|
||||
}
|
||||
@@ -1,136 +1,136 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Profiler.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Render.h"
|
||||
#include "main.h"
|
||||
#include "VertexManager.h"
|
||||
#include "Utils.h"
|
||||
|
||||
// LoadXFReg 0x10
|
||||
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
u32 address = baseAddress;
|
||||
for (int i = 0; i < (int)transferSize; i++)
|
||||
{
|
||||
address = baseAddress + i;
|
||||
|
||||
// Setup a Matrix
|
||||
if (address < 0x1000)
|
||||
{
|
||||
u32* p1 = &xfmem[address];
|
||||
memcpy(p1, &pData[i], transferSize*4);
|
||||
i += transferSize;
|
||||
}
|
||||
else if (address < 0x2000)
|
||||
{
|
||||
u32 data = pData[i];
|
||||
switch (address)
|
||||
{
|
||||
case 0x1006:
|
||||
//SetGPMetric
|
||||
break;
|
||||
case 0x1008: //__GXXfVtxSpecs, wrote 0004
|
||||
break;
|
||||
case 0x1009: //GXSetNumChans (no)
|
||||
break;
|
||||
case 0x100a: xfregs.colChans[0].ambColor = data; break; //GXSetChanAmbientcolor
|
||||
case 0x100b: xfregs.colChans[1].ambColor = data; break; //GXSetChanAmbientcolor
|
||||
case 0x100c: xfregs.colChans[0].matColor = data; break; //GXSetChanMatcolor (rgba)
|
||||
case 0x100d: xfregs.colChans[1].matColor = data; break; //GXSetChanMatcolor (rgba)
|
||||
|
||||
case 0x100e: xfregs.colChans[0].color.hex = data; break; //color0
|
||||
case 0x100f: xfregs.colChans[1].color.hex = data; break; //color1
|
||||
case 0x1010: xfregs.colChans[0].alpha.hex = data; break; //alpha0
|
||||
case 0x1011: xfregs.colChans[1].alpha.hex = data; break; //alpha1
|
||||
|
||||
case 0x1018:
|
||||
break;
|
||||
|
||||
case 0x101a:
|
||||
VertexManager::Flush();
|
||||
memcpy(xfregs.rawViewport, &pData[i], sizeof(xfregs.rawViewport));
|
||||
XFUpdateVP();
|
||||
i += 6;
|
||||
break;
|
||||
|
||||
case 0x1020:
|
||||
VertexManager::Flush();
|
||||
memcpy(xfregs.rawProjection, &pData[i], sizeof(xfregs.rawProjection));
|
||||
XFUpdatePJ();
|
||||
i += 7;
|
||||
return;
|
||||
|
||||
case 0x103f:
|
||||
xfregs.numTexGens = data;
|
||||
break;
|
||||
|
||||
case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break;
|
||||
case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break;
|
||||
case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break;
|
||||
case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break;
|
||||
case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break;
|
||||
case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break;
|
||||
case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break;
|
||||
case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break;
|
||||
|
||||
case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break;
|
||||
case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break;
|
||||
case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break;
|
||||
case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break;
|
||||
case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break;
|
||||
case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break;
|
||||
case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break;
|
||||
case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (address>=0x4000)
|
||||
{
|
||||
// MessageBox(NULL, "1", "1", MB_OK);
|
||||
//4010 __GXSetGenMode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check docs for this sucker...
|
||||
void LoadIndexedXF(u32 val, int array)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
int index = val >> 16;
|
||||
int address = val & 0xFFF; //check mask
|
||||
int size = ((val >> 12) & 0xF)+1;
|
||||
//load stuff from array to address in xf mem
|
||||
for (int i = 0; i < size; i++)
|
||||
xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4);
|
||||
}
|
||||
|
||||
void XFUpdateVP()
|
||||
{
|
||||
Renderer::SetViewport(xfregs.rawViewport);
|
||||
}
|
||||
|
||||
void XFUpdatePJ()
|
||||
{
|
||||
Renderer::SetProjection(xfregs.rawProjection, 0);
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "Profiler.h"
|
||||
#include "XFStructs.h"
|
||||
#include "Render.h"
|
||||
#include "main.h"
|
||||
#include "VertexManager.h"
|
||||
#include "Utils.h"
|
||||
|
||||
// LoadXFReg 0x10
|
||||
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
u32 address = baseAddress;
|
||||
for (int i = 0; i < (int)transferSize; i++)
|
||||
{
|
||||
address = baseAddress + i;
|
||||
|
||||
// Setup a Matrix
|
||||
if (address < 0x1000)
|
||||
{
|
||||
u32* p1 = &xfmem[address];
|
||||
memcpy(p1, &pData[i], transferSize*4);
|
||||
i += transferSize;
|
||||
}
|
||||
else if (address < 0x2000)
|
||||
{
|
||||
u32 data = pData[i];
|
||||
switch (address)
|
||||
{
|
||||
case 0x1006:
|
||||
//SetGPMetric
|
||||
break;
|
||||
case 0x1008: //__GXXfVtxSpecs, wrote 0004
|
||||
break;
|
||||
case 0x1009: //GXSetNumChans (no)
|
||||
break;
|
||||
case 0x100a: xfregs.colChans[0].ambColor = data; break; //GXSetChanAmbientcolor
|
||||
case 0x100b: xfregs.colChans[1].ambColor = data; break; //GXSetChanAmbientcolor
|
||||
case 0x100c: xfregs.colChans[0].matColor = data; break; //GXSetChanMatcolor (rgba)
|
||||
case 0x100d: xfregs.colChans[1].matColor = data; break; //GXSetChanMatcolor (rgba)
|
||||
|
||||
case 0x100e: xfregs.colChans[0].color.hex = data; break; //color0
|
||||
case 0x100f: xfregs.colChans[1].color.hex = data; break; //color1
|
||||
case 0x1010: xfregs.colChans[0].alpha.hex = data; break; //alpha0
|
||||
case 0x1011: xfregs.colChans[1].alpha.hex = data; break; //alpha1
|
||||
|
||||
case 0x1018:
|
||||
break;
|
||||
|
||||
case 0x101a:
|
||||
VertexManager::Flush();
|
||||
memcpy(xfregs.rawViewport, &pData[i], sizeof(xfregs.rawViewport));
|
||||
XFUpdateVP();
|
||||
i += 6;
|
||||
break;
|
||||
|
||||
case 0x1020:
|
||||
VertexManager::Flush();
|
||||
memcpy(xfregs.rawProjection, &pData[i], sizeof(xfregs.rawProjection));
|
||||
XFUpdatePJ();
|
||||
i += 7;
|
||||
return;
|
||||
|
||||
case 0x103f:
|
||||
xfregs.numTexGens = data;
|
||||
break;
|
||||
|
||||
case 0x1040: xfregs.texcoords[0].texmtxinfo.hex = data; break;
|
||||
case 0x1041: xfregs.texcoords[1].texmtxinfo.hex = data; break;
|
||||
case 0x1042: xfregs.texcoords[2].texmtxinfo.hex = data; break;
|
||||
case 0x1043: xfregs.texcoords[3].texmtxinfo.hex = data; break;
|
||||
case 0x1044: xfregs.texcoords[4].texmtxinfo.hex = data; break;
|
||||
case 0x1045: xfregs.texcoords[5].texmtxinfo.hex = data; break;
|
||||
case 0x1046: xfregs.texcoords[6].texmtxinfo.hex = data; break;
|
||||
case 0x1047: xfregs.texcoords[7].texmtxinfo.hex = data; break;
|
||||
|
||||
case 0x1050: xfregs.texcoords[0].postmtxinfo.hex = data; break;
|
||||
case 0x1051: xfregs.texcoords[1].postmtxinfo.hex = data; break;
|
||||
case 0x1052: xfregs.texcoords[2].postmtxinfo.hex = data; break;
|
||||
case 0x1053: xfregs.texcoords[3].postmtxinfo.hex = data; break;
|
||||
case 0x1054: xfregs.texcoords[4].postmtxinfo.hex = data; break;
|
||||
case 0x1055: xfregs.texcoords[5].postmtxinfo.hex = data; break;
|
||||
case 0x1056: xfregs.texcoords[6].postmtxinfo.hex = data; break;
|
||||
case 0x1057: xfregs.texcoords[7].postmtxinfo.hex = data; break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (address>=0x4000)
|
||||
{
|
||||
// MessageBox(NULL, "1", "1", MB_OK);
|
||||
//4010 __GXSetGenMode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check docs for this sucker...
|
||||
void LoadIndexedXF(u32 val, int array)
|
||||
{
|
||||
DVSTARTPROFILE();
|
||||
|
||||
int index = val >> 16;
|
||||
int address = val & 0xFFF; //check mask
|
||||
int size = ((val >> 12) & 0xF)+1;
|
||||
//load stuff from array to address in xf mem
|
||||
for (int i = 0; i < size; i++)
|
||||
xfmem[address + i] = Memory_Read_U32(arraybases[array] + arraystrides[array]*index + i*4);
|
||||
}
|
||||
|
||||
void XFUpdateVP()
|
||||
{
|
||||
Renderer::SetViewport(xfregs.rawViewport);
|
||||
}
|
||||
|
||||
void XFUpdatePJ()
|
||||
{
|
||||
Renderer::SetProjection(xfregs.rawProjection, 0);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,322 +1,322 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "svnrev.h"
|
||||
#include "resource.h"
|
||||
#include "main.h"
|
||||
#include "Config.h"
|
||||
#include "Fifo.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "BPStructs.h"
|
||||
#include "VertexManager.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "DlgSettings.h"
|
||||
#include "D3DPostprocess.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "W32Util/Misc.h"
|
||||
#include "EmuWindow.h"
|
||||
#include "VideoState.h"
|
||||
#include "XFBConvert.h"
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
HINSTANCE g_hInstance = NULL;
|
||||
SVideoInitialize g_VideoInitialize;
|
||||
int initCount = 0;
|
||||
|
||||
|
||||
void DllDebugger(HWND _hParent, bool Show)
|
||||
{
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Callback_PeekMessages()
|
||||
{
|
||||
//TODO: peek message
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
char temp[512];
|
||||
sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text);
|
||||
SetWindowText( EmuWindow::GetWnd(), temp);
|
||||
}
|
||||
|
||||
|
||||
bool Init()
|
||||
{
|
||||
g_Config.Load();
|
||||
|
||||
if (initCount == 0)
|
||||
{
|
||||
// create the window
|
||||
if ( !g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin
|
||||
{
|
||||
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Loading - Please wait.");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Loading - Please wait.");
|
||||
}
|
||||
|
||||
if ( g_VideoInitialize.pWindowHandle == NULL )
|
||||
{
|
||||
MessageBox(GetActiveWindow(), "An error has occurred while trying to create the window.", "Fatal Error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
EmuWindow::Show();
|
||||
g_VideoInitialize.pPeekMessages = Callback_PeekMessages;
|
||||
g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay;
|
||||
|
||||
if (FAILED(D3D::Init()))
|
||||
{
|
||||
MessageBox(GetActiveWindow(), "Unable to initialize Direct3D. Please make sure that you have DirectX 9.0c correctly installed.", "Fatal Error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
InitLUTs();
|
||||
InitXFBConvTables();
|
||||
}
|
||||
initCount++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
initCount--;
|
||||
if (initCount==0)
|
||||
{
|
||||
D3D::Shutdown();
|
||||
EmuWindow::Close();
|
||||
}
|
||||
}
|
||||
|
||||
// ====================================================================================
|
||||
|
||||
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
|
||||
#ifdef DEBUGFAST
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin DebugFast (DX9)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin (DX9)");
|
||||
#else
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin Debug (DX9)");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void DllAbout(HWND _hParent)
|
||||
{
|
||||
DialogBox(g_hInstance,(LPCSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc);
|
||||
}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
if (Init())
|
||||
{
|
||||
DlgSettings_Show(g_hInstance,_hParent);
|
||||
DeInit();
|
||||
}
|
||||
}
|
||||
|
||||
void Video_Initialize(SVideoInitialize* _pVideoInitialize)
|
||||
{
|
||||
if (_pVideoInitialize == NULL)
|
||||
return;
|
||||
|
||||
frameCount = 0;
|
||||
g_VideoInitialize = *_pVideoInitialize;
|
||||
Init();
|
||||
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
|
||||
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
|
||||
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
|
||||
|
||||
Renderer::AddMessage("Dolphin Direct3D9 Video Plugin.",5000);
|
||||
|
||||
}
|
||||
|
||||
void Video_DoState(unsigned char **ptr, int mode) {
|
||||
// Clear all caches
|
||||
TextureCache::Invalidate();
|
||||
|
||||
PointerWrap p(ptr, mode);
|
||||
VideoCommon_DoState(p);
|
||||
//PanicAlert("Saving/Loading state from DirectX9");
|
||||
}
|
||||
|
||||
|
||||
void Video_EnterLoop()
|
||||
{
|
||||
Fifo_EnterLoop(g_VideoInitialize);
|
||||
}
|
||||
|
||||
void Video_Prepare(void)
|
||||
{
|
||||
Renderer::Init(g_VideoInitialize);
|
||||
|
||||
TextureCache::Init();
|
||||
|
||||
BPInit();
|
||||
VertexManager::Init();
|
||||
Fifo_Init();
|
||||
OpcodeDecoder_Init();
|
||||
}
|
||||
|
||||
void Video_Shutdown(void)
|
||||
{
|
||||
Fifo_Shutdown();
|
||||
VertexManager::Shutdown();
|
||||
TextureCache::Shutdown();
|
||||
Renderer::Shutdown();
|
||||
OpcodeDecoder_Shutdown();
|
||||
DeInit();
|
||||
}
|
||||
|
||||
void Video_Stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Video_UpdateXFB(u8* /*_pXFB*/, u32 /*_dwWidth*/, u32 /*_dwHeight*/, s32 /*_dwYOffset*/)
|
||||
{
|
||||
/*
|
||||
ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight);
|
||||
|
||||
// blubb
|
||||
static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
|
||||
|
||||
D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
|
||||
D3D::dev->SetTexture(0, pTexture);
|
||||
|
||||
D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF);
|
||||
|
||||
D3D::EndFrame();
|
||||
D3D::BeginFrame();*/
|
||||
}
|
||||
|
||||
|
||||
void DebugLog(const char* _fmt, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
char Msg[512];
|
||||
va_list ap;
|
||||
|
||||
va_start( ap, _fmt );
|
||||
vsprintf( Msg, _fmt, ap );
|
||||
va_end( ap );
|
||||
|
||||
g_VideoInitialize.pLog(Msg, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __Log(int log, const char *format, ...)
|
||||
{
|
||||
// char temp[512];
|
||||
//va_list args;
|
||||
//va_start(args, format);
|
||||
//CharArrayFromFormatV(temp, 512, format, args);
|
||||
//va_end(args);
|
||||
|
||||
DebugLog(format); //"%s", temp);
|
||||
}
|
||||
|
||||
|
||||
HRESULT ScreenShot(TCHAR *File)
|
||||
{
|
||||
if (D3D::dev == NULL)
|
||||
return S_FALSE;
|
||||
|
||||
D3DDISPLAYMODE DisplayMode;
|
||||
if (FAILED(D3D::dev->GetDisplayMode(0, &DisplayMode)))
|
||||
return S_FALSE;
|
||||
|
||||
LPDIRECT3DSURFACE9 surf;
|
||||
if (FAILED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL)))
|
||||
return S_FALSE;
|
||||
|
||||
if (FAILED(D3D::dev->GetFrontBufferData(0, surf)))
|
||||
{
|
||||
surf->Release();
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
RECT rect;
|
||||
::GetWindowRect(EmuWindow::GetWnd(), &rect);
|
||||
if (FAILED(D3DXSaveSurfaceToFile(File, D3DXIFF_JPG, surf, NULL, &rect)))
|
||||
{
|
||||
surf->Release();
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
surf->Release();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL Video_Screenshot(TCHAR* _szFilename)
|
||||
{
|
||||
if (ScreenShot(_szFilename) == S_OK)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||
{
|
||||
Renderer::AddMessage(pstr,milliseconds);
|
||||
}
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <tchar.h>
|
||||
#include <windows.h>
|
||||
#include <d3dx9.h>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "svnrev.h"
|
||||
#include "resource.h"
|
||||
#include "main.h"
|
||||
#include "Config.h"
|
||||
#include "Fifo.h"
|
||||
#include "OpcodeDecoding.h"
|
||||
#include "TextureCache.h"
|
||||
#include "BPStructs.h"
|
||||
#include "VertexManager.h"
|
||||
#include "TransformEngine.h"
|
||||
#include "DlgSettings.h"
|
||||
#include "D3DPostprocess.h"
|
||||
#include "D3DTexture.h"
|
||||
#include "D3DUtil.h"
|
||||
#include "W32Util/Misc.h"
|
||||
#include "EmuWindow.h"
|
||||
#include "VideoState.h"
|
||||
#include "XFBConvert.h"
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
HINSTANCE g_hInstance = NULL;
|
||||
SVideoInitialize g_VideoInitialize;
|
||||
int initCount = 0;
|
||||
|
||||
|
||||
void DllDebugger(HWND _hParent, bool Show)
|
||||
{
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
|
||||
BOOL APIENTRY DllMain( HINSTANCE hinstDLL, // DLL module handle
|
||||
DWORD dwReason, // reason called
|
||||
LPVOID lpvReserved) // reserved
|
||||
{
|
||||
switch (dwReason)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
break;
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_hInstance = hinstDLL;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL Callback_PeekMessages()
|
||||
{
|
||||
//TODO: peek message
|
||||
MSG msg;
|
||||
while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
|
||||
{
|
||||
if (msg.message == WM_QUIT)
|
||||
return FALSE;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void UpdateFPSDisplay(const char *text)
|
||||
{
|
||||
char temp[512];
|
||||
sprintf_s(temp, 512, "SVN R%i: DX9: %s", SVN_REV, text);
|
||||
SetWindowText( EmuWindow::GetWnd(), temp);
|
||||
}
|
||||
|
||||
|
||||
bool Init()
|
||||
{
|
||||
g_Config.Load();
|
||||
|
||||
if (initCount == 0)
|
||||
{
|
||||
// create the window
|
||||
if ( !g_Config.renderToMainframe || g_VideoInitialize.pWindowHandle == NULL ) // ignore parent for this plugin
|
||||
{
|
||||
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create(NULL, g_hInstance, "Loading - Please wait.");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_VideoInitialize.pWindowHandle = (void*)EmuWindow::Create((HWND)g_VideoInitialize.pWindowHandle, g_hInstance, "Loading - Please wait.");
|
||||
}
|
||||
|
||||
if ( g_VideoInitialize.pWindowHandle == NULL )
|
||||
{
|
||||
MessageBox(GetActiveWindow(), "An error has occurred while trying to create the window.", "Fatal Error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
|
||||
EmuWindow::Show();
|
||||
g_VideoInitialize.pPeekMessages = Callback_PeekMessages;
|
||||
g_VideoInitialize.pUpdateFPSDisplay = UpdateFPSDisplay;
|
||||
|
||||
if (FAILED(D3D::Init()))
|
||||
{
|
||||
MessageBox(GetActiveWindow(), "Unable to initialize Direct3D. Please make sure that you have DirectX 9.0c correctly installed.", "Fatal Error", MB_OK);
|
||||
return false;
|
||||
}
|
||||
InitLUTs();
|
||||
InitXFBConvTables();
|
||||
}
|
||||
initCount++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
initCount--;
|
||||
if (initCount==0)
|
||||
{
|
||||
D3D::Shutdown();
|
||||
EmuWindow::Close();
|
||||
}
|
||||
}
|
||||
|
||||
// ====================================================================================
|
||||
|
||||
void GetDllInfo (PLUGIN_INFO* _PluginInfo)
|
||||
{
|
||||
_PluginInfo->Version = 0x0100;
|
||||
_PluginInfo->Type = PLUGIN_TYPE_VIDEO;
|
||||
#ifdef DEBUGFAST
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin DebugFast (DX9)");
|
||||
#else
|
||||
#ifndef _DEBUG
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin (DX9)");
|
||||
#else
|
||||
sprintf_s(_PluginInfo->Name, 100, "Dolphin Video Plugin Debug (DX9)");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void DllAbout(HWND _hParent)
|
||||
{
|
||||
DialogBox(g_hInstance,(LPCSTR)IDD_ABOUT,_hParent,(DLGPROC)AboutProc);
|
||||
}
|
||||
|
||||
void DllConfig(HWND _hParent)
|
||||
{
|
||||
if (Init())
|
||||
{
|
||||
DlgSettings_Show(g_hInstance,_hParent);
|
||||
DeInit();
|
||||
}
|
||||
}
|
||||
|
||||
void Video_Initialize(SVideoInitialize* _pVideoInitialize)
|
||||
{
|
||||
if (_pVideoInitialize == NULL)
|
||||
return;
|
||||
|
||||
frameCount = 0;
|
||||
g_VideoInitialize = *_pVideoInitialize;
|
||||
Init();
|
||||
_pVideoInitialize->pPeekMessages = g_VideoInitialize.pPeekMessages;
|
||||
_pVideoInitialize->pUpdateFPSDisplay = g_VideoInitialize.pUpdateFPSDisplay;
|
||||
_pVideoInitialize->pWindowHandle = g_VideoInitialize.pWindowHandle;
|
||||
|
||||
Renderer::AddMessage("Dolphin Direct3D9 Video Plugin.",5000);
|
||||
|
||||
}
|
||||
|
||||
void Video_DoState(unsigned char **ptr, int mode) {
|
||||
// Clear all caches
|
||||
TextureCache::Invalidate();
|
||||
|
||||
PointerWrap p(ptr, mode);
|
||||
VideoCommon_DoState(p);
|
||||
//PanicAlert("Saving/Loading state from DirectX9");
|
||||
}
|
||||
|
||||
|
||||
void Video_EnterLoop()
|
||||
{
|
||||
Fifo_EnterLoop(g_VideoInitialize);
|
||||
}
|
||||
|
||||
void Video_Prepare(void)
|
||||
{
|
||||
Renderer::Init(g_VideoInitialize);
|
||||
|
||||
TextureCache::Init();
|
||||
|
||||
BPInit();
|
||||
VertexManager::Init();
|
||||
Fifo_Init();
|
||||
OpcodeDecoder_Init();
|
||||
}
|
||||
|
||||
void Video_Shutdown(void)
|
||||
{
|
||||
Fifo_Shutdown();
|
||||
VertexManager::Shutdown();
|
||||
TextureCache::Shutdown();
|
||||
Renderer::Shutdown();
|
||||
OpcodeDecoder_Shutdown();
|
||||
DeInit();
|
||||
}
|
||||
|
||||
void Video_Stop(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Video_UpdateXFB(u8* /*_pXFB*/, u32 /*_dwWidth*/, u32 /*_dwHeight*/, s32 /*_dwYOffset*/)
|
||||
{
|
||||
/*
|
||||
ConvertXFB(tempBuffer, _pXFB, _dwWidth, _dwHeight);
|
||||
|
||||
// blubb
|
||||
static LPDIRECT3DTEXTURE9 pTexture = D3D::CreateTexture2D((BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
|
||||
|
||||
D3D::ReplaceTexture2D(pTexture, (BYTE*)tempBuffer, _dwWidth, _dwHeight, _dwWidth, D3DFMT_A8R8G8B8);
|
||||
D3D::dev->SetTexture(0, pTexture);
|
||||
|
||||
D3D::quad2d(0,0,(float)Postprocess::GetWidth(),(float)Postprocess::GetHeight(), 0xFFFFFFFF);
|
||||
|
||||
D3D::EndFrame();
|
||||
D3D::BeginFrame();*/
|
||||
}
|
||||
|
||||
|
||||
void DebugLog(const char* _fmt, ...)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
char Msg[512];
|
||||
va_list ap;
|
||||
|
||||
va_start( ap, _fmt );
|
||||
vsprintf( Msg, _fmt, ap );
|
||||
va_end( ap );
|
||||
|
||||
g_VideoInitialize.pLog(Msg, FALSE);
|
||||
#endif
|
||||
}
|
||||
|
||||
void __Log(int log, const char *format, ...)
|
||||
{
|
||||
// char temp[512];
|
||||
//va_list args;
|
||||
//va_start(args, format);
|
||||
//CharArrayFromFormatV(temp, 512, format, args);
|
||||
//va_end(args);
|
||||
|
||||
DebugLog(format); //"%s", temp);
|
||||
}
|
||||
|
||||
|
||||
HRESULT ScreenShot(TCHAR *File)
|
||||
{
|
||||
if (D3D::dev == NULL)
|
||||
return S_FALSE;
|
||||
|
||||
D3DDISPLAYMODE DisplayMode;
|
||||
if (FAILED(D3D::dev->GetDisplayMode(0, &DisplayMode)))
|
||||
return S_FALSE;
|
||||
|
||||
LPDIRECT3DSURFACE9 surf;
|
||||
if (FAILED(D3D::dev->CreateOffscreenPlainSurface(DisplayMode.Width, DisplayMode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surf, NULL)))
|
||||
return S_FALSE;
|
||||
|
||||
if (FAILED(D3D::dev->GetFrontBufferData(0, surf)))
|
||||
{
|
||||
surf->Release();
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
RECT rect;
|
||||
::GetWindowRect(EmuWindow::GetWnd(), &rect);
|
||||
if (FAILED(D3DXSaveSurfaceToFile(File, D3DXIFF_JPG, surf, NULL, &rect)))
|
||||
{
|
||||
surf->Release();
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
surf->Release();
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
BOOL Video_Screenshot(TCHAR* _szFilename)
|
||||
{
|
||||
if (ScreenShot(_szFilename) == S_OK)
|
||||
return TRUE;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Video_AddMessage(const char* pstr, u32 milliseconds)
|
||||
{
|
||||
Renderer::AddMessage(pstr,milliseconds);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// 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, version 2.0.
|
||||
|
||||
// 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 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
||||
Reference in New Issue
Block a user