cxbx-shogun/src/CxbxKrnl/EmuD3D8.cpp

10436 lines
311 KiB
C++

// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->EmuD3D8.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
// *
// * All rights reserved
// *
// ******************************************************************
#define _CXBXKRNL_INTERNAL
#define _XBOXKRNL_DEFEXTRN_
// Disable overlay updates for Unreal Championship...
// TODO: Find out why a crash occurs playing the second
// intro video.
//#define UnrealChampionshipHack
// prevent name collisions
namespace xboxkrnl
{
#include <xboxkrnl/xboxkrnl.h>
};
#include "CxbxUtil.h"
#include "CxbxKrnl.h"
#include "Emu.h"
#include "EmuFS.h"
#include "EmuShared.h"
#include "DbgConsole.h"
#include "ResourceTracker.h"
#include "EmuAlloc.h"
#include "EmuXTL.h"
#include "ResCxbxDll.h"
#include <process.h>
#include <clocale>
// Global(s)
HWND g_hEmuWindow = NULL; // rendering window
XTL::LPDIRECT3DDEVICE8 g_pD3DDevice8 = NULL; // Direct3D8 Device
XTL::LPDIRECTDRAWSURFACE7 g_pDDSPrimary = NULL; // DirectDraw7 Primary Surface
XTL::LPDIRECTDRAWSURFACE7 g_pDDSOverlay7 = NULL; // DirectDraw7 Overlay Surface
XTL::LPDIRECTDRAWCLIPPER g_pDDClipper = NULL; // DirectDraw7 Clipper
DWORD g_CurrentVertexShader = 0;
DWORD g_dwCurrentPixelShader = 0;
XTL::PIXEL_SHADER *g_CurrentPixelShader = NULL;
BOOL g_bFakePixelShaderLoaded = FALSE;
BOOL g_bIsFauxFullscreen = FALSE;
BOOL g_bHackUpdateSoftwareOverlay = FALSE;
// Static Function(s)
static BOOL WINAPI EmuEnumDisplayDevices(GUID FAR *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm);
static DWORD WINAPI EmuRenderWindow(LPVOID);
static DWORD WINAPI EmuCreateDeviceProxy(LPVOID);
static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
static DWORD WINAPI EmuUpdateTickCount(LPVOID);
static inline void EmuVerifyResourceIsRegistered(XTL::X_D3DResource *pResource);
static void EmuAdjustPower2(UINT *dwWidth, UINT *dwHeight);
// Static Variable(s)
static GUID g_ddguid; // DirectDraw driver GUID
static HMONITOR g_hMonitor = NULL; // Handle to DirectDraw monitor
static XTL::LPDIRECT3D8 g_pD3D8 = NULL; // Direct3D8
static BOOL g_bSupportsYUY2 = FALSE;// Does device support YUY2 overlays?
static XTL::LPDIRECTDRAW7 g_pDD7 = NULL; // DirectDraw7
static DWORD g_dwOverlayW = 640; // Cached Overlay Width
static DWORD g_dwOverlayH = 480; // Cached Overlay Height
static DWORD g_dwOverlayP = 640; // Cached Overlay Pitch
static Xbe::Header *g_XbeHeader = NULL; // XbeHeader
static uint32 g_XbeHeaderSize = 0; // XbeHeaderSize
static XTL::D3DCAPS8 g_D3DCaps; // Direct3D8 Caps
static HBRUSH g_hBgBrush = NULL; // Background Brush
static volatile bool g_bRenderWindowActive = false;
static XBVideo g_XBVideo;
static XTL::D3DVBLANKCALLBACK g_pVBCallback = NULL; // Vertical-Blank callback routine
static XTL::D3DSWAPCALLBACK g_pSwapCallback = NULL; // Swap/Present callback routine
static XTL::D3DCALLBACK g_pCallback = NULL; // D3DDevice::InsertCallback routine
static XTL::X_D3DCALLBACKTYPE g_CallbackType; // Callback type
static DWORD g_CallbackParam; // Callback param
//static DWORD g_dwPrimPerFrame = 0; // Number of primitives within one frame
// wireframe toggle
static int g_iWireframe = 0;
// build version
extern uint32 g_BuildVersion;
// resource caching for _Register
static XTL::X_D3DResource pCache[16] = {0};
// current active index buffer
static XTL::X_D3DIndexBuffer *g_pIndexBuffer = NULL; // current active index buffer
static DWORD g_dwBaseVertexIndex = 0;// current active index buffer base index
// current active vertex stream
static XTL::X_D3DVertexBuffer *g_pVertexBuffer = NULL; // current active vertex buffer
static XTL::IDirect3DVertexBuffer8 *g_pDummyBuffer = NULL; // Dummy buffer, used to set unused stream sources with
static DWORD g_dwLastSetStream = 0; // The last stream set by D3DDevice::SetStreamSource
// current vertical blank information
static XTL::D3DVBLANKDATA g_VBData = {0};
static DWORD g_VBLastSwap = 0;
// current swap information
static XTL::D3DSWAPDATA g_SwapData = {0};
static DWORD g_SwapLast = 0;
// cached Direct3D state variable(s)
static XTL::X_D3DSurface *g_pCachedRenderTarget = NULL;
static XTL::X_D3DSurface *g_pCachedZStencilSurface = NULL;
static XTL::X_D3DSurface *g_YuvSurface = NULL;
static BOOL g_fYuvEnabled = FALSE;
static DWORD g_dwVertexShaderUsage = 0;
static DWORD g_VertexShaderSlots[136];
// cached palette pointer
static PVOID pCurrentPalette;
// cached palette size
static DWORD dwCurrentPaletteSize = -1;
static XTL::X_VERTEXSHADERCONSTANTMODE g_VertexShaderConstantMode = X_VSCM_192;
// cached Direct3D tiles
XTL::X_D3DTILE XTL::EmuD3DTileCache[0x08] = {0};
// cached active texture
XTL::X_D3DResource *XTL::EmuD3DActiveTexture[4] = {0,0,0,0};
// information passed to the create device proxy thread
struct EmuD3D8CreateDeviceProxyData
{
XTL::UINT Adapter;
XTL::D3DDEVTYPE DeviceType;
HWND hFocusWindow;
XTL::DWORD BehaviorFlags;
XTL::X_D3DPRESENT_PARAMETERS *pPresentationParameters;
XTL::IDirect3DDevice8 **ppReturnedDeviceInterface;
volatile bool bReady;
union
{
volatile HRESULT hRet;
volatile bool bCreate; // false : release
};
}
g_EmuCDPD = {0};
// Direct3D initialization (called before emulation begins)
VOID XTL::EmuD3DInit(Xbe::Header *XbeHeader, uint32 XbeHeaderSize)
{
g_EmuShared->GetXBVideo(&g_XBVideo);
if(g_XBVideo.GetFullscreen())
CxbxKrnl_hEmuParent = NULL;
// cache XbeHeader and size of XbeHeader
g_XbeHeader = XbeHeader;
g_XbeHeaderSize = XbeHeaderSize;
// create timing thread
{
DWORD dwThreadId;
HANDLE hThread = CreateThread(NULL, NULL, EmuUpdateTickCount, NULL, NULL, &dwThreadId);
// we must duplicate this handle in order to retain Suspend/Resume thread rights from a remote thread
{
HANDLE hDupHandle = NULL;
DuplicateHandle(GetCurrentProcess(), hThread, GetCurrentProcess(), &hDupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS);
CxbxKrnlRegisterThread(hDupHandle);
}
}
// create the create device proxy thread
{
DWORD dwThreadId;
CreateThread(NULL, NULL, EmuCreateDeviceProxy, NULL, NULL, &dwThreadId);
}
// create window message processing thread
{
DWORD dwThreadId;
g_bRenderWindowActive = false;
CreateThread(NULL, NULL, EmuRenderWindow, NULL, NULL, &dwThreadId);
while(!g_bRenderWindowActive)
Sleep(10);
Sleep(50);
}
// create Direct3D8 and retrieve caps
{
using namespace XTL;
// xbox Direct3DCreate8 returns "1" always, so we need our own ptr
g_pD3D8 = Direct3DCreate8(D3D_SDK_VERSION);
if(g_pD3D8 == NULL)
CxbxKrnlCleanup("Could not initialize Direct3D8!");
D3DDEVTYPE DevType = (g_XBVideo.GetDirect3DDevice() == 0) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF;
g_pD3D8->GetDeviceCaps(g_XBVideo.GetDisplayAdapter(), DevType, &g_D3DCaps);
}
SetFocus(g_hEmuWindow);
// create default device
{
XTL::X_D3DPRESENT_PARAMETERS PresParam;
ZeroMemory(&PresParam, sizeof(PresParam));
PresParam.BackBufferWidth = 640;
PresParam.BackBufferHeight = 480;
PresParam.BackBufferFormat = 6; /* X_D3DFMT_A8R8G8B8 */
PresParam.BackBufferCount = 1;
PresParam.EnableAutoDepthStencil = TRUE;
PresParam.AutoDepthStencilFormat = 0x2A; /* X_D3DFMT_D24S8 */
PresParam.SwapEffect = XTL::D3DSWAPEFFECT_DISCARD;
EmuSwapFS(); // XBox FS
XTL::EmuIDirect3D8_CreateDevice(0, XTL::D3DDEVTYPE_HAL, 0, 0x00000040, &PresParam, &g_pD3DDevice8);
EmuSwapFS(); // Win2k/XP FS
}
}
// cleanup Direct3D
VOID XTL::EmuD3DCleanup()
{
XTL::EmuDInputCleanup();
return;
}
// enumeration procedure for locating display device GUIDs
static BOOL WINAPI EmuEnumDisplayDevices(GUID FAR *lpGUID, LPSTR lpDriverDescription, LPSTR lpDriverName, LPVOID lpContext, HMONITOR hm)
{
static DWORD dwEnumCount = 0;
if(dwEnumCount++ == g_XBVideo.GetDisplayAdapter()+1)
{
g_hMonitor = hm;
dwEnumCount = 0;
if(lpGUID != 0)
{
memcpy(&g_ddguid, lpGUID, sizeof(GUID));
}
else
{
memset(&g_ddguid, 0, sizeof(GUID));
}
return FALSE;
}
return TRUE;
}
// window message processing thread
static DWORD WINAPI EmuRenderWindow(LPVOID lpVoid)
{
char AsciiTitle[50];
// register window class
{
#ifdef _DEBUG
HMODULE hCxbxDll = GetModuleHandle("CxbxKrnl.dll");
#else
HMODULE hCxbxDll = GetModuleHandle("Cxbx.dll");
#endif
LOGBRUSH logBrush = {BS_SOLID, RGB(0,0,0)};
g_hBgBrush = CreateBrushIndirect(&logBrush);
WNDCLASSEX wc =
{
sizeof(WNDCLASSEX),
CS_CLASSDC,
EmuMsgProc,
0, 0, GetModuleHandle(NULL),
LoadIcon(hCxbxDll, MAKEINTRESOURCE(IDI_CXBX)),
LoadCursor(NULL, IDC_ARROW),
(HBRUSH)(g_hBgBrush), NULL,
"CxbxRender",
NULL
};
RegisterClassEx(&wc);
}
// retrieve Xbe title (if possible)
{
char tAsciiTitle[40] = "Unknown";
uint32 CertAddr = g_XbeHeader->dwCertificateAddr - g_XbeHeader->dwBaseAddr;
if(CertAddr + 0x0C + 40 < g_XbeHeaderSize)
{
Xbe::Certificate *XbeCert = (Xbe::Certificate*)((uint32)g_XbeHeader + CertAddr);
setlocale( LC_ALL, "English" );
wcstombs(tAsciiTitle, XbeCert->wszTitleName, 40);
}
sprintf(AsciiTitle, "Cxbx : Emulating %s", tAsciiTitle);
}
// create the window
{
DWORD dwStyle = (g_XBVideo.GetFullscreen() || (CxbxKrnl_hEmuParent == 0))? WS_OVERLAPPEDWINDOW : WS_CHILD;
int nTitleHeight = GetSystemMetrics(SM_CYCAPTION);
int nBorderWidth = GetSystemMetrics(SM_CXSIZEFRAME);
int nBorderHeight = GetSystemMetrics(SM_CYSIZEFRAME);
int x = 100, y = 100, nWidth = 640, nHeight = 480;
nWidth += nBorderWidth*2;
nHeight += nBorderHeight*2 + nTitleHeight;
sscanf(g_XBVideo.GetVideoResolution(), "%d x %d", &nWidth, &nHeight);
if(g_XBVideo.GetFullscreen())
{
x = y = nWidth = nHeight = 0;
dwStyle = WS_POPUP;
}
HWND hwndParent = GetDesktopWindow();
if(!g_XBVideo.GetFullscreen())
{
hwndParent = CxbxKrnl_hEmuParent;
}
g_hEmuWindow = CreateWindow
(
"CxbxRender", AsciiTitle,
dwStyle, x, y, nWidth, nHeight,
hwndParent, NULL, GetModuleHandle(NULL), NULL
);
}
ShowWindow(g_hEmuWindow, (g_XBVideo.GetFullscreen() || (CxbxKrnl_hEmuParent == 0) ) ? SW_SHOWDEFAULT : SW_SHOWMAXIMIZED);
UpdateWindow(g_hEmuWindow);
if(!g_XBVideo.GetFullscreen() && (CxbxKrnl_hEmuParent != NULL))
{
SetFocus(CxbxKrnl_hEmuParent);
}
// initialize direct input
if(!XTL::EmuDInputInit())
CxbxKrnlCleanup("Could not initialize DirectInput!");
DbgPrintf("EmuD3D8 (0x%X): Message-Pump thread is running.\n", GetCurrentThreadId());
SetFocus(g_hEmuWindow);
DbgConsole *dbgConsole = new DbgConsole();
// message processing loop
{
MSG msg;
ZeroMemory(&msg, sizeof(msg));
bool lPrintfOn = g_bPrintfOn;
g_bRenderWindowActive = true;
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
Sleep(10);
// if we've just switched back to display off, clear buffer & display prompt
if(!g_bPrintfOn && lPrintfOn)
{
dbgConsole->Reset();
}
lPrintfOn = g_bPrintfOn;
dbgConsole->Process();
}
}
g_bRenderWindowActive = false;
delete dbgConsole;
CxbxKrnlCleanup(NULL);
}
return 0;
}
// simple helper function
void ToggleFauxFullscreen(HWND hWnd)
{
if(g_XBVideo.GetFullscreen())
return;
static LONG lRestore = 0, lRestoreEx = 0;
static RECT lRect = {0};
if(!g_bIsFauxFullscreen)
{
if(CxbxKrnl_hEmuParent != NULL)
{
SetParent(hWnd, NULL);
}
else
{
lRestore = GetWindowLong(hWnd, GWL_STYLE);
lRestoreEx = GetWindowLong(hWnd, GWL_EXSTYLE);
GetWindowRect(hWnd, &lRect);
}
SetWindowLong(hWnd, GWL_STYLE, WS_POPUP);
ShowWindow(hWnd, SW_MAXIMIZE);
SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
}
else
{
if(CxbxKrnl_hEmuParent != NULL)
{
SetParent(hWnd, CxbxKrnl_hEmuParent);
SetWindowLong(hWnd, GWL_STYLE, WS_CHILD);
ShowWindow(hWnd, SW_MAXIMIZE);
SetFocus(CxbxKrnl_hEmuParent);
}
else
{
SetWindowLong(hWnd, GWL_STYLE, lRestore);
SetWindowLong(hWnd, GWL_EXSTYLE, lRestoreEx);
ShowWindow(hWnd, SW_RESTORE);
SetWindowPos(hWnd, HWND_NOTOPMOST, lRect.left, lRect.top, lRect.right - lRect.left, lRect.bottom - lRect.top, 0);
SetFocus(hWnd);
}
}
g_bIsFauxFullscreen = !g_bIsFauxFullscreen;
}
// rendering window message procedure
static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static bool bAutoPaused = false;
switch(msg)
{
case WM_DESTROY:
{
DeleteObject(g_hBgBrush);
PostQuitMessage(0);
return 0;
}
break;
case WM_SYSKEYDOWN:
{
if(wParam == VK_RETURN)
{
ToggleFauxFullscreen(hWnd);
}
else if(wParam == VK_F4)
{
PostMessage(hWnd, WM_CLOSE, 0, 0);
}
}
break;
case WM_KEYDOWN:
{
/*! disable fullscreen if we are set to faux mode, and faux fullscreen is active */
if(wParam == VK_ESCAPE)
{
if(g_XBVideo.GetFullscreen())
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
}
else if(g_bIsFauxFullscreen)
{
ToggleFauxFullscreen(hWnd);
}
}
else if(wParam == VK_F8)
{
g_bPrintfOn = !g_bPrintfOn;
}
else if(wParam == VK_F9)
{
XTL::g_bBrkPush = TRUE;
}
else if(wParam == VK_F10)
{
ToggleFauxFullscreen(hWnd);
}
else if(wParam == VK_F11)
{
if(g_iWireframe++ == 2)
g_iWireframe = 0;
}
else if(wParam == VK_F12)
{
XTL::g_bStepPush = !XTL::g_bStepPush;
}
}
break;
case WM_SIZE:
{
switch(wParam)
{
case SIZE_RESTORED:
case SIZE_MAXIMIZED:
{
if(bAutoPaused)
{
bAutoPaused = false;
CxbxKrnlResume();
}
}
break;
case SIZE_MINIMIZED:
{
if(g_XBVideo.GetFullscreen())
CxbxKrnlCleanup(NULL);
if(!g_bEmuSuspended)
{
bAutoPaused = true;
CxbxKrnlSuspend();
}
}
break;
}
}
break;
case WM_CLOSE:
DestroyWindow(hWnd);
break;
case WM_SETFOCUS:
{
if(CxbxKrnl_hEmuParent != NULL)
{
SetFocus(CxbxKrnl_hEmuParent);
}
}
break;
case WM_SETCURSOR:
{
if(g_XBVideo.GetFullscreen() || g_bIsFauxFullscreen)
{
SetCursor(NULL);
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
// timing thread procedure
static DWORD WINAPI EmuUpdateTickCount(LPVOID)
{
// since callbacks come from here
EmuGenerateFS(CxbxKrnl_TLS, CxbxKrnl_TLSData);
DbgPrintf("EmuD3D8 (0x%X): Timing thread is running.\n", GetCurrentThreadId());
timeBeginPeriod(0);
// current vertical blank count
int curvb = 0;
while(true)
{
xboxkrnl::KeTickCount = timeGetTime();
Sleep(1);
//
// Poll input
//
{
int v;
for(v=0;v<XINPUT_SETSTATE_SLOTS;v++)
{
HANDLE hDevice = g_pXInputSetStateStatus[v].hDevice;
if(hDevice == 0)
continue;
DWORD dwLatency = g_pXInputSetStateStatus[v].dwLatency++;
if(dwLatency < XINPUT_SETSTATE_LATENCY)
continue;
g_pXInputSetStateStatus[v].dwLatency = 0;
XTL::PXINPUT_FEEDBACK pFeedback = (XTL::PXINPUT_FEEDBACK)g_pXInputSetStateStatus[v].pFeedback;
if(pFeedback == 0)
continue;
//
// Only update slot if it has not already been updated
//
if(pFeedback->Header.dwStatus != ERROR_SUCCESS)
{
if(pFeedback->Header.hEvent != 0)
{
SetEvent(pFeedback->Header.hEvent);
}
pFeedback->Header.dwStatus = ERROR_SUCCESS;
}
}
}
// trigger vblank callback
{
g_VBData.VBlank++;
// TODO: Fixme. This may not be right...
g_SwapData.SwapVBlank = 1;
if(g_pVBCallback != NULL)
{
EmuSwapFS(); // Xbox FS
g_pVBCallback(&g_VBData);
EmuSwapFS(); // Win2k/XP FS
}
g_VBData.Swap = 0;
// TODO: This can't be accurate...
g_SwapData.TimeUntilSwapVBlank = 0;
// TODO: Recalculate this for PAL version if necessary.
// Also, we should check the D3DPRESENT_INTERVAL value for accurracy.
// g_SwapData.TimeBetweenSwapVBlanks = 1/60;
g_SwapData.TimeBetweenSwapVBlanks = 0;
}
}
timeEndPeriod(0);
}
// thread dedicated to create devices
static DWORD WINAPI EmuCreateDeviceProxy(LPVOID)
{
DbgPrintf("EmuD3D8 (0x%X): CreateDevice proxy thread is running.\n", GetCurrentThreadId());
while(true)
{
// if we have been signalled, create the device with cached parameters
if(g_EmuCDPD.bReady)
{
DbgPrintf("EmuD3D8 (0x%X): CreateDevice proxy thread recieved request.\n", GetCurrentThreadId());
if(g_EmuCDPD.bCreate)
{
// only one device should be created at once
// TODO: ensure all surfaces are somehow cleaned up?
if(g_pD3DDevice8 != 0)
{
DbgPrintf("EmuD3D8 (0x%X): CreateDevice proxy thread releasing old Device.\n", GetCurrentThreadId());
g_pD3DDevice8->EndScene();
while(g_pD3DDevice8->Release() != 0);
g_pD3DDevice8 = 0;
}
if(g_EmuCDPD.pPresentationParameters->BufferSurfaces[0] != NULL)
EmuWarning("BufferSurfaces[0] : 0x%.08X", g_EmuCDPD.pPresentationParameters->BufferSurfaces[0]);
if(g_EmuCDPD.pPresentationParameters->DepthStencilSurface != NULL)
EmuWarning("DepthStencilSurface : 0x%.08X", g_EmuCDPD.pPresentationParameters->DepthStencilSurface);
// make adjustments to parameters to make sense with windows Direct3D
{
g_EmuCDPD.DeviceType =(g_XBVideo.GetDirect3DDevice() == 0) ? XTL::D3DDEVTYPE_HAL : XTL::D3DDEVTYPE_REF;
g_EmuCDPD.Adapter = g_XBVideo.GetDisplayAdapter();
g_EmuCDPD.pPresentationParameters->Windowed = !g_XBVideo.GetFullscreen();
if(g_XBVideo.GetVSync())
g_EmuCDPD.pPresentationParameters->SwapEffect = XTL::D3DSWAPEFFECT_COPY_VSYNC;
g_EmuCDPD.hFocusWindow = g_hEmuWindow;
g_EmuCDPD.pPresentationParameters->BackBufferFormat = XTL::EmuXB2PC_D3DFormat(g_EmuCDPD.pPresentationParameters->BackBufferFormat);
g_EmuCDPD.pPresentationParameters->AutoDepthStencilFormat = XTL::EmuXB2PC_D3DFormat(g_EmuCDPD.pPresentationParameters->AutoDepthStencilFormat);
if(!g_XBVideo.GetVSync() && (g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) && g_XBVideo.GetFullscreen())
g_EmuCDPD.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
else
{
if(g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE && g_XBVideo.GetFullscreen())
g_EmuCDPD.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE;
else
g_EmuCDPD.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
}
// HACK: Disable Tripple Buffering for now...
// TODO: Enumerate maximum BackBufferCount if possible.
if(g_EmuCDPD.pPresentationParameters->BackBufferCount > 1)
{
EmuWarning("Limiting BackBufferCount to 1...");
g_EmuCDPD.pPresentationParameters->BackBufferCount = 1;
}
// TODO: Support Xbox extensions if possible
if(g_EmuCDPD.pPresentationParameters->MultiSampleType != 0)
{
EmuWarning("MultiSampleType 0x%.08X is not supported!", g_EmuCDPD.pPresentationParameters->MultiSampleType);
g_EmuCDPD.pPresentationParameters->MultiSampleType = XTL::D3DMULTISAMPLE_NONE;
// TODO: Check card for multisampling abilities
// if(pPresentationParameters->MultiSampleType == 0x00001121)
// pPresentationParameters->MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
// else
// CxbxKrnlCleanup("Unknown MultiSampleType (0x%.08X)", pPresentationParameters->MultiSampleType);
}
g_EmuCDPD.pPresentationParameters->Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
// retrieve resolution from configuration
if(g_EmuCDPD.pPresentationParameters->Windowed)
{
sscanf(g_XBVideo.GetVideoResolution(), "%d x %d", &g_EmuCDPD.pPresentationParameters->BackBufferWidth, &g_EmuCDPD.pPresentationParameters->BackBufferHeight);
XTL::D3DDISPLAYMODE D3DDisplayMode;
g_pD3D8->GetAdapterDisplayMode(g_XBVideo.GetDisplayAdapter(), &D3DDisplayMode);
g_EmuCDPD.pPresentationParameters->BackBufferFormat = D3DDisplayMode.Format;
g_EmuCDPD.pPresentationParameters->FullScreen_RefreshRateInHz = 0;
}
else
{
char szBackBufferFormat[16];
sscanf(g_XBVideo.GetVideoResolution(), "%d x %d %*dbit %s (%d hz)",
&g_EmuCDPD.pPresentationParameters->BackBufferWidth,
&g_EmuCDPD.pPresentationParameters->BackBufferHeight,
szBackBufferFormat,
&g_EmuCDPD.pPresentationParameters->FullScreen_RefreshRateInHz);
if(strcmp(szBackBufferFormat, "x1r5g5b5") == 0)
g_EmuCDPD.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_X1R5G5B5;
else if(strcmp(szBackBufferFormat, "r5g6r5") == 0)
g_EmuCDPD.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_R5G6B5;
else if(strcmp(szBackBufferFormat, "x8r8g8b8") == 0)
g_EmuCDPD.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_X8R8G8B8;
else if(strcmp(szBackBufferFormat, "a8r8g8b8") == 0)
g_EmuCDPD.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_A8R8G8B8;
}
}
// detect vertex processing capabilities
if((g_D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && g_EmuCDPD.DeviceType == XTL::D3DDEVTYPE_HAL)
{
DbgPrintf("EmuD3D8 (0x%X): Using hardware vertex processing\n", GetCurrentThreadId());
g_EmuCDPD.BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
g_dwVertexShaderUsage = 0;
}
else
{
DbgPrintf("EmuD3D8 (0x%X): Using software vertex processing\n", GetCurrentThreadId());
g_EmuCDPD.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
g_dwVertexShaderUsage = D3DUSAGE_SOFTWAREPROCESSING;
}
// redirect to windows Direct3D
g_EmuCDPD.hRet = g_pD3D8->CreateDevice
(
g_EmuCDPD.Adapter,
g_EmuCDPD.DeviceType,
g_EmuCDPD.hFocusWindow,
g_EmuCDPD.BehaviorFlags,
(XTL::D3DPRESENT_PARAMETERS*)g_EmuCDPD.pPresentationParameters,
g_EmuCDPD.ppReturnedDeviceInterface
);
// report error
if(FAILED(g_EmuCDPD.hRet))
{
if(g_EmuCDPD.hRet == D3DERR_INVALIDCALL)
CxbxKrnlCleanup("IDirect3D8::CreateDevice failed (Invalid Call)");
else if(g_EmuCDPD.hRet == D3DERR_NOTAVAILABLE)
CxbxKrnlCleanup("IDirect3D8::CreateDevice failed (Not Available)");
else if(g_EmuCDPD.hRet == D3DERR_OUTOFVIDEOMEMORY)
CxbxKrnlCleanup("IDirect3D8::CreateDevice failed (Out of Video Memory)");
CxbxKrnlCleanup("IDirect3D8::CreateDevice failed (Unknown)");
}
// cache device pointer
g_pD3DDevice8 = *g_EmuCDPD.ppReturnedDeviceInterface;
// default NULL guid
ZeroMemory(&g_ddguid, sizeof(GUID));
// enumerate device guid for this monitor, for directdraw
HRESULT hRet = XTL::DirectDrawEnumerateExA(EmuEnumDisplayDevices, NULL, DDENUM_ATTACHEDSECONDARYDEVICES);
// create DirectDraw7
{
if(FAILED(hRet))
hRet = XTL::DirectDrawCreateEx(NULL, (void**)&g_pDD7, XTL::IID_IDirectDraw7, NULL);
else
hRet = XTL::DirectDrawCreateEx(&g_ddguid, (void**)&g_pDD7, XTL::IID_IDirectDraw7, NULL);
if(FAILED(hRet))
CxbxKrnlCleanup("Could not initialize DirectDraw7");
hRet = g_pDD7->SetCooperativeLevel(0, DDSCL_NORMAL);
if(FAILED(hRet))
CxbxKrnlCleanup("Could not set cooperative level");
}
// check for YUY2 overlay support TODO: accept other overlay types
{
DWORD dwCodes = 0;
DWORD *lpCodes = 0;
g_pDD7->GetFourCCCodes(&dwCodes, lpCodes);
lpCodes = (DWORD*)CxbxMalloc(dwCodes*sizeof(DWORD));
g_pDD7->GetFourCCCodes(&dwCodes, lpCodes);
g_bSupportsYUY2 = false;
for(DWORD v=0;v<dwCodes;v++)
{
if(lpCodes[v] == MAKEFOURCC('Y','U','Y','2'))
{
g_bSupportsYUY2 = true;
break;
}
}
CxbxFree(lpCodes);
if(!g_bSupportsYUY2)
EmuWarning("YUY2 overlays are not supported in hardware, could be slow!");
// Does the user want to use Hardware accelerated YUV surfaces?
if(g_bSupportsYUY2 && g_XBVideo.GetHardwareYUV())
DbgPrintf("EmuD3D8 (0x%X): Hardware accelerated YUV surfaces Enabled...\n", GetCurrentThreadId());
if(!g_XBVideo.GetHardwareYUV())
{
g_bSupportsYUY2 = false;
DbgPrintf("EmuD3D8 (0x%X): Hardware accelerated YUV surfaces Disabled...\n", GetCurrentThreadId());
}
}
// initialize primary surface
if(g_bSupportsYUY2)
{
XTL::DDSURFACEDESC2 ddsd2;
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
ddsd2.dwFlags = DDSD_CAPS;
ddsd2.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
HRESULT hRet = g_pDD7->CreateSurface(&ddsd2, &g_pDDSPrimary, 0);
if(FAILED(hRet))
CxbxKrnlCleanup("Could not create primary surface (0x%.08X)", hRet);
}
// update render target cache
g_pCachedRenderTarget = new XTL::X_D3DSurface();
g_pCachedRenderTarget->Common = 0;
g_pCachedRenderTarget->Data = X_D3DRESOURCE_DATA_FLAG_SPECIAL | X_D3DRESOURCE_DATA_FLAG_D3DREND;
g_pD3DDevice8->GetRenderTarget(&g_pCachedRenderTarget->EmuSurface8);
// update z-stencil surface cache
g_pCachedZStencilSurface = new XTL::X_D3DSurface();
g_pCachedZStencilSurface->Common = 0;
g_pCachedZStencilSurface->Data = X_D3DRESOURCE_DATA_FLAG_SPECIAL | X_D3DRESOURCE_DATA_FLAG_D3DSTEN;
g_pD3DDevice8->GetDepthStencilSurface(&g_pCachedZStencilSurface->EmuSurface8);
(void)g_pD3DDevice8->CreateVertexBuffer
(
1, 0, 0, XTL::D3DPOOL_MANAGED,
&g_pDummyBuffer
);
for(int Streams = 0; Streams < 8; Streams++)
{
g_pD3DDevice8->SetStreamSource(Streams, g_pDummyBuffer, 1);
}
// initially, show a black screen
g_pD3DDevice8->Clear(0, 0, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0xFF000000, 1.0f, 0);
g_pD3DDevice8->BeginScene();
g_pD3DDevice8->EndScene();
g_pD3DDevice8->Present(0, 0, 0, 0);
// begin scene
g_pD3DDevice8->BeginScene();
// signal completion
g_EmuCDPD.bReady = false;
}
else
{
// release direct3d
if(g_pD3DDevice8 != 0)
{
DbgPrintf("EmuD3D8 (0x%X): CreateDevice proxy thread releasing old Device.\n", GetCurrentThreadId());
g_pD3DDevice8->EndScene();
g_EmuCDPD.hRet = g_pD3DDevice8->Release();
if(g_EmuCDPD.hRet == 0)
g_pD3DDevice8 = 0;
}
if(g_bSupportsYUY2)
{
// cleanup directdraw surface
if(g_pDDSPrimary != 0)
{
g_pDDSPrimary->Release();
g_pDDSPrimary = 0;
}
}
// cleanup directdraw
if(g_pDD7 != 0)
{
g_pDD7->Release();
g_pDD7 = 0;
}
// signal completion
g_EmuCDPD.bReady = false;
}
}
Sleep(1);
}
return 0;
}
// check if a resource has been registered yet (if not, register it)
static void EmuVerifyResourceIsRegistered(XTL::X_D3DResource *pResource)
{
// 0xEEEEEEEE and 0xFFFFFFFF are somehow set in Halo :(
if(pResource->Lock != 0 && pResource->Lock != 0xEEEEEEEE && pResource->Lock != 0xFFFFFFFF)
return;
// Already "Registered" implicitly
if((IsSpecialResource(pResource->Data) && ((pResource->Data & X_D3DRESOURCE_DATA_FLAG_D3DREND) || (pResource->Data & X_D3DRESOURCE_DATA_FLAG_D3DSTEN)))
||(pResource->Data == 0xB00BBABE))
return;
int v=0;
for(v=0;v<16;v++)
{
if(pCache[v].Data == pResource->Data && pResource->Data != 0)
{
pResource->EmuResource8 = pCache[v].EmuResource8;
return;
}
}
EmuSwapFS(); // XBox FS;
XTL::EmuIDirect3DResource8_Register(pResource, 0/*(PVOID)pResource->Data*/);
EmuSwapFS(); // Win2k/XP FS
if(pResource->Lock != X_D3DRESOURCE_LOCK_FLAG_NOSIZE)
{
for(v=0;v<16;v++)
{
if(pCache[v].Data == 0)
{
pCache[v].Data = pResource->Data;
pCache[v].EmuResource8 = pResource->EmuResource8;
break;
}
if(v == 16)
CxbxKrnlCleanup("X_D3DResource cache is maxed out!");
}
}
}
// ensure a given width/height are powers of 2
static void EmuAdjustPower2(UINT *dwWidth, UINT *dwHeight)
{
UINT NewWidth=0, NewHeight=0;
int v;
for(v=0;v<32;v++)
{
int mask = 1 << v;
if(*dwWidth & mask)
NewWidth = mask;
if(*dwHeight & mask)
NewHeight = mask;
}
if(*dwWidth != NewWidth)
{
NewWidth <<= 1;
EmuWarning("Needed to resize width (%d->%d)", *dwWidth, NewWidth);
}
if(*dwHeight != NewHeight)
{
NewHeight <<= 1;
EmuWarning("Needed to resize height (%d->%d)", *dwHeight, NewHeight);
}
*dwWidth = NewWidth;
*dwHeight = NewHeight;
}
// Derived from EmuUnswizzleActiveTexture
static void EmuUnswizzleTextureStages()
{
for( int i = 0; i < 4; i++ )
{
// for current usages, we're always on stage 0
XTL::X_D3DPixelContainer *pPixelContainer = (XTL::X_D3DPixelContainer*)XTL::EmuD3DActiveTexture[i];
if(pPixelContainer == NULL || !(pPixelContainer->Common & X_D3DCOMMON_ISLOCKED))
return;
DWORD XBFormat = (pPixelContainer->Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT;
DWORD dwBPP = 0;
if(!XTL::EmuXBFormatIsSwizzled(XBFormat, &dwBPP))
return;
// remove lock
pPixelContainer->EmuTexture8->UnlockRect(0);
pPixelContainer->Common &= ~X_D3DCOMMON_ISLOCKED;
// TODO: potentially CRC to see if this surface was actually modified..
//
// unswizzle texture
//
{
XTL::IDirect3DTexture8 *pTexture = pPixelContainer->EmuTexture8;
DWORD dwLevelCount = pTexture->GetLevelCount();
for(uint32 v=0;v<dwLevelCount;v++)
{
XTL::D3DSURFACE_DESC SurfaceDesc;
HRESULT hRet = pTexture->GetLevelDesc(v, &SurfaceDesc);
if(FAILED(hRet))
continue;
//
// perform unswizzle
//
{
XTL::D3DLOCKED_RECT LockedRect;
//if(SurfaceDesc.Format != XTL::D3DFMT_A8R8G8B8)
// break;
//CxbxKrnlCleanup("Temporarily unsupported format for active texture unswizzle (0x%.08X)", SurfaceDesc.Format);
hRet = pTexture->LockRect(v, &LockedRect, NULL, NULL);
if(FAILED(hRet))
continue;
DWORD dwWidth = SurfaceDesc.Width;
DWORD dwHeight = SurfaceDesc.Height;
DWORD dwDepth = 1;
DWORD dwPitch = LockedRect.Pitch;
RECT iRect = {0,0,0,0};
POINT iPoint = {0,0};
void *pTemp = malloc(dwHeight*dwPitch);
XTL::EmuXGUnswizzleRect
(
LockedRect.pBits, dwWidth, dwHeight, dwDepth,
pTemp, dwPitch, iRect, iPoint, dwBPP
);
memcpy(LockedRect.pBits, pTemp, dwPitch*dwHeight);
pTexture->UnlockRect(0);
free(pTemp);
}
}
DbgPrintf("Texture Stage %d was unswizzled\n", i);
}
}
}
// ******************************************************************
// * func: EmuIDirect3D8_CreateDevice
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_CreateDevice
(
UINT Adapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
X_D3DPRESENT_PARAMETERS *pPresentationParameters,
IDirect3DDevice8 **ppReturnedDeviceInterface
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_CreateDevice\n"
"(\n"
" Adapter : 0x%.08X\n"
" DeviceType : 0x%.08X\n"
" hFocusWindow : 0x%.08X\n"
" BehaviorFlags : 0x%.08X\n"
" pPresentationParameters : 0x%.08X\n"
" ppReturnedDeviceInterface : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Adapter, DeviceType, hFocusWindow,
BehaviorFlags, pPresentationParameters, ppReturnedDeviceInterface);
// Print a few of the pPresentationParameters contents to the console
DbgPrintf("BackBufferWidth: = %d\n"
"BackBufferHeight: = %d\n"
"BackBufferFormat: = 0x%.08X\n"
"BackBufferCount: = 0x%.08X\n"
"SwapEffect: = 0x%.08X\n"
"EnableAutoDepthStencil: = 0x%.08X\n"
"AutoDepthStencilFormat: = 0x%.08X\n"
"Flags: = 0x%.08X\n\n",
pPresentationParameters->BackBufferWidth, pPresentationParameters->BackBufferHeight,
pPresentationParameters->BackBufferFormat, pPresentationParameters->BackBufferCount,
pPresentationParameters->SwapEffect, pPresentationParameters->EnableAutoDepthStencil,
pPresentationParameters->AutoDepthStencilFormat, pPresentationParameters->Flags );
// Cache parameters
g_EmuCDPD.Adapter = Adapter;
g_EmuCDPD.DeviceType = DeviceType;
g_EmuCDPD.hFocusWindow = hFocusWindow;
g_EmuCDPD.pPresentationParameters = pPresentationParameters;
g_EmuCDPD.ppReturnedDeviceInterface = ppReturnedDeviceInterface;
// Wait until proxy is done with an existing call (i highly doubt this situation will come up)
while(g_EmuCDPD.bReady)
Sleep(10);
// Signal proxy thread, and wait for completion
g_EmuCDPD.bReady = true;
g_EmuCDPD.bCreate = true;
// Wait until proxy is completed
while(g_EmuCDPD.bReady)
Sleep(10);
EmuSwapFS(); // XBox FS
return g_EmuCDPD.hRet;
}
// ******************************************************************
// * func: EmuIDirect3DResource8_IsBusy
// ******************************************************************
BOOL WINAPI XTL::EmuIDirect3DDevice8_IsBusy()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_IsBusy();\n",
GetCurrentThreadId());
EmuWarning("EmuIDirect3DDevice8_IsBusy ignored!");
EmuSwapFS(); // XBox FS
return FALSE;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetCreationParameters
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetCreationParameters\n"
"(\n"
" pParameters : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pParameters);
pParameters->AdapterOrdinal = D3DADAPTER_DEFAULT;
pParameters->DeviceType = D3DDEVTYPE_HAL;
pParameters->hFocusWindow = NULL;
pParameters->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3D8_CheckDeviceFormat
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_CheckDeviceFormat
(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT AdapterFormat,
DWORD Usage,
X_D3DRESOURCETYPE RType,
X_D3DFORMAT CheckFormat
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_CheckDeviceFormat\n"
"(\n"
" Adapter : 0x%.08X\n"
" DeviceType : 0x%.08X\n"
" AdapterFormat : 0x%.08X\n"
" Usage : 0x%.08X\n"
" RType : 0x%.08X\n"
" CheckFormat : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Adapter, DeviceType, AdapterFormat,
Usage, RType, CheckFormat);
if(RType > 7)
CxbxKrnlCleanup("RType > 7");
// HACK: Return true for everything? (Hunter the Reckoning)
HRESULT hRet = S_OK; /*g_pD3D8->CheckDeviceFormat
(
g_XBVideo.GetDisplayAdapter(), (g_XBVideo.GetDirect3DDevice() == 0) ? XTL::D3DDEVTYPE_HAL : XTL::D3DDEVTYPE_REF,
EmuXB2PC_D3DFormat(AdapterFormat), Usage, (D3DRESOURCETYPE)RType, EmuXB2PC_D3DFormat(CheckFormat)
);*/
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetDisplayFieldStatus
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetDisplayFieldStatus(X_D3DFIELD_STATUS *pFieldStatus)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetDisplayFieldStatus\n"
"(\n"
" pFieldStatus : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pFieldStatus);
#if 1
pFieldStatus->Field = (g_VBData.VBlank%2 == 0) ? X_D3DFIELD_ODD : X_D3DFIELD_EVEN;
pFieldStatus->VBlankCount = g_VBData.VBlank;
#else
pFieldStatus->Field = X_D3DFIELD_PROGRESSIVE;
pFieldStatus->VBlankCount = 0;
#endif
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_BeginPush
// ******************************************************************
PDWORD WINAPI XTL::EmuIDirect3DDevice8_BeginPush(DWORD Count)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BeginPush(%d);\n", GetCurrentThreadId(), Count);
DWORD *pRet = new DWORD[Count];
g_dwPrimaryPBCount = Count;
g_pPrimaryPB = pRet;
EmuSwapFS(); // XBox FS
return pRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_EndPush
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_EndPush(DWORD *pPush)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_EndPush(0x%.08X);\n", GetCurrentThreadId(), pPush);
#ifdef _DEBUG_TRACK_PB
// DbgDumpPushBuffer(g_pPrimaryPB, g_dwPrimaryPBCount*sizeof(DWORD));
#endif
EmuExecutePushBufferRaw(g_pPrimaryPB);
delete[] g_pPrimaryPB;
g_pPrimaryPB = 0;
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_BeginVisibilityTest
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_BeginVisibilityTest()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BeginVisibilityTest();\n", GetCurrentThreadId());
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_EndVisibilityTest
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_EndVisibilityTest
(
DWORD Index
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_EndVisibilityTest\n"
"(\n"
" Index : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Index);
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetBackBufferScale
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetBackBufferScale(FLOAT x, FLOAT y)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetBackBufferScale\n"
"(\n"
" x : %f\n"
" y : %f\n"
");\n",
GetCurrentThreadId(), x, y);
EmuWarning("SetBackBufferScale ignored");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVisibilityTestResult
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetVisibilityTestResult
(
DWORD Index,
UINT *pResult,
ULONGLONG *pTimeStamp
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVisibilityTestResult\n"
"(\n"
" Index : 0x%.08X\n"
" pResult : 0x%.08X\n"
" pTimeStamp : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Index, pResult, pTimeStamp);
// TODO: actually emulate this!?
if(pResult != 0)
*pResult = 640*480;
if(pTimeStamp != 0)
*pTimeStamp = 0;
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetDeviceCaps
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetDeviceCaps
(
D3DCAPS8 *pCaps
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetDeviceCaps\n"
"(\n"
" pCaps : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pCaps);
HRESULT hRet = g_pD3D8->GetDeviceCaps(g_XBVideo.GetDisplayAdapter(), (g_XBVideo.GetDirect3DDevice() == 0) ? XTL::D3DDEVTYPE_HAL : XTL::D3DDEVTYPE_REF, pCaps);
if(FAILED(hRet))
CxbxKrnlCleanup("EmuIDirect3DDevice8_GetDeviceCaps failed!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_LoadVertexShader
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_LoadVertexShader
(
DWORD Handle,
DWORD Address
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_LoadVertexShader\n"
"(\n"
" Handle : 0x%.08X\n"
" Address : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle,Address);
if(Address < 136 && VshHandleIsVertexShader(Handle))
{
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)(VshHandleGetVertexShader(Handle))->Handle;
for (DWORD i = Address; i < pVertexShader->Size; i++)
{
// TODO: This seems very fishy
g_VertexShaderSlots[i] = Handle;
}
}
EmuSwapFS(); // Xbox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SelectVertexShader
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SelectVertexShader
(
DWORD Handle,
DWORD Address
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SelectVertexShader\n"
"(\n"
" Handle : 0x%.08X\n"
" Address : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle, Address);
if(VshHandleIsVertexShader(Handle))
{
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)(((X_D3DVertexShader *)(Handle & 0x7FFFFFFF))->Handle);
g_pD3DDevice8->SetVertexShader(pVertexShader->Handle);
}
else if(Handle == NULL)
{
g_pD3DDevice8->SetVertexShader(D3DFVF_XYZ | D3DFVF_TEX0);
}
else if(Address < 136)
{
X_D3DVertexShader *pVertexShader = (X_D3DVertexShader*)g_VertexShaderSlots[Address];
if(pVertexShader != NULL)
{
g_pD3DDevice8->SetVertexShader(((VERTEX_SHADER *)((X_D3DVertexShader *)g_VertexShaderSlots[Address])->Handle)->Handle);
}
else
{
EmuWarning("g_VertexShaderSlots[%d] = 0", Address);
}
}
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3D8_GetAdapterModeCount
// ******************************************************************
UINT WINAPI XTL::EmuIDirect3D8_GetAdapterModeCount
(
UINT Adapter
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_GetAdapterModeCount\n"
"(\n"
" Adapter : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Adapter);
UINT ret = g_pD3D8->GetAdapterModeCount(g_XBVideo.GetDisplayAdapter());
D3DDISPLAYMODE Mode;
for(uint32 v=0;v<ret;v++)
{
HRESULT hRet = g_pD3D8->EnumAdapterModes(g_XBVideo.GetDisplayAdapter(), v, &Mode);
if(hRet != D3D_OK)
break;
if(Mode.Width != 640 || Mode.Height != 480)
ret--;
}
EmuSwapFS(); // XBox FS
return ret;
}
// ******************************************************************
// * func: EmuIDirect3D8_GetAdapterDisplayMode
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_GetAdapterDisplayMode
(
UINT Adapter,
X_D3DDISPLAYMODE *pMode
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_GetAdapterDisplayMode\n"
"(\n"
" Adapter : 0x%.08X\n"
" pMode : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Adapter, pMode);
// NOTE: WARNING: We should cache the "Emulated" display mode and return
// This value. We can initialize the cache with the default Xbox mode data.
HRESULT hRet = g_pD3D8->GetAdapterDisplayMode
(
g_XBVideo.GetDisplayAdapter(),
(D3DDISPLAYMODE*)pMode
);
// make adjustments to the parameters to make sense with windows direct3d
{
D3DDISPLAYMODE *pPCMode = (D3DDISPLAYMODE*)pMode;
// Convert Format (PC->Xbox)
pMode->Format = EmuPC2XB_D3DFormat(pPCMode->Format);
// TODO: Make this configurable in the future?
// D3DPRESENTFLAG_FIELD | D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
pMode->Flags = 0x000000A1;
// TODO: Retrieve from current CreateDevice settings?
pMode->Width = 640;
pMode->Height = 480;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3D8_EnumAdapterModes
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_EnumAdapterModes
(
UINT Adapter,
UINT Mode,
X_D3DDISPLAYMODE *pMode
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_EnumAdapterModes\n"
"(\n"
" Adapter : 0x%.08X\n"
" Mode : 0x%.08X\n"
" pMode : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Adapter, Mode, pMode);
HRESULT hRet;
static int ModeAdder = 0;
if(Mode == 0)
ModeAdder = 0;
D3DDISPLAYMODE PCMode;
do
{
hRet = g_pD3D8->EnumAdapterModes(g_XBVideo.GetDisplayAdapter(), Mode+ModeAdder, (D3DDISPLAYMODE*)&PCMode);
if(hRet != D3D_OK || (PCMode.Width == 640 && PCMode.Height == 480))
break;
ModeAdder++;
}
while(true);
// make adjustments to parameters to make sense with windows direct3d
if(hRet == D3D_OK)
{
//
// NOTE: WARNING: PC D3DDISPLAYMODE is different than Xbox D3DDISPLAYMODE!
//
// Convert Format (PC->Xbox)
pMode->Width = PCMode.Width;
pMode->Height = PCMode.Height;
pMode->RefreshRate = PCMode.RefreshRate;
// TODO: Make this configurable in the future?
// D3DPRESENTFLAG_FIELD | D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
pMode->Flags = 0x000000A1;
pMode->Format = EmuPC2XB_D3DFormat(PCMode.Format);
}
else
{
// hRet = S_OK;
hRet = D3DERR_INVALIDCALL;
// CxbxKrnlCleanup("EnumAdapterModes failed!");
}
EmuSwapFS(); // XBox FS
// return hRet;
return S_OK; // Hack
}
// ******************************************************************
// * func: EmuIDirect3D8_KickOffAndWaitForIdle
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3D8_KickOffAndWaitForIdle()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_KickOffAndWaitForIdle()\n", GetCurrentThreadId());
// TODO: Actually do something here?
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3D8_KickOffAndWaitForIdle2
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3D8_KickOffAndWaitForIdle2(DWORD dwDummy1, DWORD dwDummy2)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_KickOffAndWaitForIdle\n"
"(\n"
" dwDummy1 : 0x%.08X\n"
" dwDummy2 : 0x%.08X\n"
");\n",
GetCurrentThreadId(), dwDummy1, dwDummy2);
// TODO: Actually do something here?
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetGammaRamp
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetGammaRamp
(
DWORD dwFlags,
CONST X_D3DGAMMARAMP *pRamp
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetGammaRamp\n"
"(\n"
" dwFlags : 0x%.08X\n"
" pRamp : 0x%.08X\n"
");\n",
GetCurrentThreadId(), dwFlags, pRamp);
// remove D3DSGR_IMMEDIATE
DWORD dwPCFlags = dwFlags & (~0x00000002);
D3DGAMMARAMP PCRamp;
for(int v=0;v<255;v++)
{
PCRamp.red[v] = pRamp->red[v];
PCRamp.green[v] = pRamp->green[v];
PCRamp.blue[v] = pRamp->blue[v];
}
// g_pD3DDevice8->SetGammaRamp(dwPCFlags, &PCRamp);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_AddRef
// ******************************************************************
ULONG WINAPI XTL::EmuIDirect3DDevice8_AddRef()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_AddRef()\n", GetCurrentThreadId());
ULONG ret = g_pD3DDevice8->AddRef();
EmuSwapFS(); // XBox FS
return ret;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_BeginStateBlock
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_BeginStateBlock()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BeginStateBlock()\n", GetCurrentThreadId());
ULONG ret = g_pD3DDevice8->BeginStateBlock();
EmuSwapFS(); // XBox FS
return ret;
}
/*// ******************************************************************
// * func: EmuIDirect3DDevice8_BeginStateBig
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_BeginStateBig()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BeginStateBig()\n", GetCurrentThreadId());
//ULONG ret = g_pD3DDevice8->BeginStateBlock();
CxbxKrnlCleanup("BeginStateBig is not implemented");
EmuSwapFS(); // XBox FS
return ret;
}*/
// ******************************************************************
// * func: EmuIDirect3DDevice8_CaptureStateBlock
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CaptureStateBlock(DWORD Token)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CaptureStateBlock\n"
"(\n"
" Token : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Token);
ULONG ret = g_pD3DDevice8->CaptureStateBlock(Token);
EmuSwapFS(); // XBox FS
return ret;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_ApplyStateBlock
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_ApplyStateBlock(DWORD Token)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_ApplyStateBlock\n"
"(\n"
" Token : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Token);
ULONG ret = g_pD3DDevice8->ApplyStateBlock(Token);
EmuSwapFS(); // XBox FS
return ret;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_EndStateBlock
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_EndStateBlock(DWORD *pToken)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_EndStateBlock\n"
"(\n"
" pToken : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pToken);
ULONG ret = g_pD3DDevice8->EndStateBlock(pToken);
EmuSwapFS(); // XBox FS
return ret;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CopyRects
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CopyRects
(
X_D3DSurface *pSourceSurface,
CONST RECT *pSourceRectsArray,
UINT cRects,
X_D3DSurface *pDestinationSurface,
CONST POINT *pDestPointsArray
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CopyRects\n"
"(\n"
" pSourceSurface : 0x%.08X\n"
" pSourceRectsArray : 0x%.08X\n"
" cRects : 0x%.08X\n"
" pDestinationSurface : 0x%.08X\n"
" pDestPointsArray : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pSourceSurface, pSourceRectsArray, cRects,
pDestinationSurface, pDestPointsArray);
pSourceSurface->EmuSurface8->UnlockRect();
/*
static int kthx = 0;
char fileName[255];
sprintf(fileName, "C:\\Aaron\\Textures\\SourceSurface-%d.bmp", kthx++);
D3DXSaveSurfaceToFile(fileName, D3DXIFF_BMP, pSourceSurface->EmuSurface8, NULL, NULL);
//*/
HRESULT hRet = g_pD3DDevice8->CopyRects
(
pSourceSurface->EmuSurface8,
pSourceRectsArray,
cRects,
pDestinationSurface->EmuSurface8,
pDestPointsArray
);
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateImageSurface
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateImageSurface
(
UINT Width,
UINT Height,
X_D3DFORMAT Format,
X_D3DSurface **ppBackBuffer
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateImageSurface\n"
"(\n"
" Width : 0x%.08X\n"
" Height : 0x%.08X\n"
" Format : 0x%.08X\n"
" ppBackBuffer : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Width, Height, Format, ppBackBuffer);
*ppBackBuffer = new X_D3DSurface();
D3DFORMAT PCFormat = EmuXB2PC_D3DFormat(Format);
HRESULT hRet = g_pD3DDevice8->CreateImageSurface(Width, Height, PCFormat, &((*ppBackBuffer)->EmuSurface8));
if(FAILED(hRet) && Format == 0x2E)
{
EmuWarning("CreateImageSurface: D3DFMT_LIN_D24S8 -> D3DFMT_A8R8G8B8");
hRet = g_pD3DDevice8->CreateImageSurface(Width, Height, D3DFMT_A8R8G8B8, &((*ppBackBuffer)->EmuSurface8));
}
if(FAILED(hRet))
/*EmuWarning*/CxbxKrnlCleanup("CreateImageSurface failed!\nFormat = 0x%8.8X", Format);
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetGammaRamp
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetGammaRamp
(
X_D3DGAMMARAMP *pRamp
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetGammaRamp\n"
"(\n"
" pRamp : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pRamp);
D3DGAMMARAMP *pGammaRamp = (D3DGAMMARAMP *)malloc(sizeof(D3DGAMMARAMP));
g_pD3DDevice8->GetGammaRamp(pGammaRamp);
for(int v=0;v<256;v++)
{
pRamp->red[v] = (BYTE)pGammaRamp->red[v];
pRamp->green[v] = (BYTE)pGammaRamp->green[v];
pRamp->blue[v] = (BYTE)pGammaRamp->blue[v];
}
free(pGammaRamp);
EmuSwapFS(); // Xbox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetBackBuffer2
// ******************************************************************
XTL::X_D3DSurface* WINAPI XTL::EmuIDirect3DDevice8_GetBackBuffer2
(
INT BackBuffer
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetBackBuffer2\n"
"(\n"
" BackBuffer : 0x%.08X\n"
");\n",
GetCurrentThreadId(), BackBuffer);
/** unsafe, somehow
HRESULT hRet = S_OK;
X_D3DSurface *pBackBuffer = new X_D3DSurface();
if(BackBuffer == -1)
{
static IDirect3DSurface8 *pCachedPrimarySurface = 0;
if(pCachedPrimarySurface == 0)
{
// create a buffer to return
// TODO: Verify the surface is always 640x480
g_pD3DDevice8->CreateImageSurface(640, 480, D3DFMT_A8R8G8B8, &pCachedPrimarySurface);
}
pBackBuffer->EmuSurface8 = pCachedPrimarySurface;
hRet = g_pD3DDevice8->GetFrontBuffer(pBackBuffer->EmuSurface8);
if(FAILED(hRet))
{
EmuWarning("Could not retrieve primary surface, using backbuffer");
pCachedPrimarySurface = 0;
pBackBuffer->EmuSurface8->Release();
pBackBuffer->EmuSurface8 = 0;
BackBuffer = 0;
}
// Debug: Save this image temporarily
//D3DXSaveSurfaceToFile("C:\\Aaron\\Textures\\FrontBuffer.bmp", D3DXIFF_BMP, pBackBuffer->EmuSurface8, NULL, NULL);
}
if(BackBuffer != -1)
hRet = g_pD3DDevice8->GetBackBuffer(BackBuffer, D3DBACKBUFFER_TYPE_MONO, &(pBackBuffer->EmuSurface8));
//*/
static X_D3DSurface *pBackBuffer = new X_D3DSurface();
if(BackBuffer == -1)
BackBuffer = 0;
HRESULT hRet = g_pD3DDevice8->GetBackBuffer(BackBuffer, D3DBACKBUFFER_TYPE_MONO, &(pBackBuffer->EmuSurface8));
if(FAILED(hRet))
CxbxKrnlCleanup("Unable to retrieve back buffer");
// update data pointer
pBackBuffer->Data = X_D3DRESOURCE_DATA_FLAG_SPECIAL | X_D3DRESOURCE_DATA_FLAG_SURFACE;
EmuSwapFS(); // Xbox FS
return pBackBuffer;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetBackBuffer
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetBackBuffer
(
INT BackBuffer,
D3DBACKBUFFER_TYPE Type,
X_D3DSurface **ppBackBuffer
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetBackBuffer\n"
"(\n"
" BackBuffer : 0x%.08X\n"
" Type : 0x%.08X\n"
" ppBackBuffer : 0x%.08X\n"
");\n",
GetCurrentThreadId(), BackBuffer, Type, ppBackBuffer);
EmuSwapFS(); // Xbox FS
}
#endif
*ppBackBuffer = EmuIDirect3DDevice8_GetBackBuffer2(BackBuffer);
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetViewport
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetViewport
(
CONST D3DVIEWPORT8 *pViewport
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetViewport\n"
"(\n"
" pViewport : 0x%.08X (%d, %d, %d, %d, %f, %f)\n"
");\n",
GetCurrentThreadId(), pViewport, pViewport->X, pViewport->Y, pViewport->Width,
pViewport->Height, pViewport->MinZ, pViewport->MaxZ);
DWORD dwWidth = pViewport->Width;
DWORD dwHeight = pViewport->Height;
// resize to fit screen (otherwise crashes occur)
{
if(dwWidth > 640)
{
EmuWarning("Resizing Viewport->Width to 640");
((D3DVIEWPORT8*)pViewport)->Width = 640;
}
if(dwHeight > 480)
{
EmuWarning("Resizing Viewport->Height to 480");
((D3DVIEWPORT8*)pViewport)->Height = 480;
}
}
HRESULT hRet = g_pD3DDevice8->SetViewport(pViewport);
// restore originals
{
if(dwWidth > 640)
((D3DVIEWPORT8*)pViewport)->Width = dwWidth;
if(dwHeight > 480)
((D3DVIEWPORT8*)pViewport)->Height = dwHeight;
}
if(FAILED(hRet))
{
EmuWarning("Unable to set viewport!");
hRet = D3D_OK;
}
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetViewport
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetViewport
(
D3DVIEWPORT8 *pViewport
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetViewport\n"
"(\n"
" pViewport : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pViewport);
HRESULT hRet = g_pD3DDevice8->GetViewport(pViewport);
if(FAILED(hRet))
{
EmuWarning("Unable to get viewport!");
hRet = D3D_OK;
}
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetViewportOffsetAndScale
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetViewportOffsetAndScale
(
D3DXVECTOR4 *pOffset,
D3DXVECTOR4 *pScale
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetViewportOffsetAndScale\n"
"(\n"
" pOffset : 0x%.08X\n"
" pScale : 0x%.08X\n"
");\n",
GetCurrentThreadId(),pOffset,pScale);
float fScaleX = 1.0f;
float fScaleY = 1.0f;
float fScaleZ = 1.0f;
float fOffsetX = 0.5 + 1.0/32;
float fOffsetY = 0.5 + 1.0/32;
D3DVIEWPORT8 Viewport;
EmuSwapFS();
EmuIDirect3DDevice8_GetViewport(&Viewport);
EmuSwapFS();
pScale->x = 1.0f;
pScale->y = 1.0f;
pScale->z = 1.0f;
pScale->w = 1.0f;
pOffset->x = 0.0f;
pOffset->y = 0.0f;
pOffset->z = 0.0f;
pOffset->w = 0.0f;
/*
pScale->x = (float)Viewport.Width * 0.5f * fScaleX;
pScale->y = (float)Viewport.Height * -0.5f * fScaleY;
pScale->z = (Viewport.MaxZ - Viewport.MinZ) * fScaleZ;
pScale->w = 0;
pOffset->x = (float)Viewport.Width * fScaleX * 0.5f + (float)Viewport.X * fScaleX + fOffsetX;
pOffset->y = (float)Viewport.Height * fScaleY * 0.5f + (float)Viewport.Y * fScaleY + fOffsetY;
pOffset->z = Viewport.MinZ * fScaleZ;
pOffset->w = 0;
*/
EmuSwapFS(); // XBox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetShaderConstantMode
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetShaderConstantMode
(
XTL::X_VERTEXSHADERCONSTANTMODE Mode
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetShaderConstantMode\n"
"(\n"
" Mode : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Mode);
g_VertexShaderConstantMode = Mode;
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_Reset
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_Reset
(
X_D3DPRESENT_PARAMETERS *pPresentationParameters
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_Reset\n"
"(\n"
" pPresentationParameters : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPresentationParameters);
EmuWarning("Device Reset is being utterly ignored");
EmuSwapFS(); // Xbox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetRenderTarget
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetRenderTarget
(
X_D3DSurface **ppRenderTarget
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetRenderTarget\n"
"(\n"
" ppRenderTarget : 0x%.08X\n"
");\n",
GetCurrentThreadId(), ppRenderTarget);
IDirect3DSurface8 *pSurface8 = g_pCachedRenderTarget->EmuSurface8;
pSurface8->AddRef();
*ppRenderTarget = g_pCachedRenderTarget;
DbgPrintf("EmuD3D8 (0x%X): RenderTarget := 0x%.08X\n", GetCurrentThreadId(), pSurface8);
EmuSwapFS(); // Xbox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetRenderTarget2
// ******************************************************************
XTL::X_D3DSurface * WINAPI XTL::EmuIDirect3DDevice8_GetRenderTarget2()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetRenderTarget2()\n", GetCurrentThreadId());
IDirect3DSurface8 *pSurface8 = g_pCachedRenderTarget->EmuSurface8;
pSurface8->AddRef();
DbgPrintf("EmuD3D8 (0x%X): RenderTarget := 0x%.08X\n", GetCurrentThreadId(), pSurface8);
EmuSwapFS(); // Xbox FS
return g_pCachedRenderTarget;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetDepthStencilSurface
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetDepthStencilSurface
(
X_D3DSurface **ppZStencilSurface
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetDepthStencilSurface\n"
"(\n"
" ppZStencilSurface : 0x%.08X\n"
");\n",
GetCurrentThreadId(), ppZStencilSurface);
IDirect3DSurface8 *pSurface8 = g_pCachedZStencilSurface->EmuSurface8;
if(pSurface8 != 0)
pSurface8->AddRef();
*ppZStencilSurface = g_pCachedZStencilSurface;
DbgPrintf("EmuD3D8 (0x%X): DepthStencilSurface := 0x%.08X\n", GetCurrentThreadId(), pSurface8);
EmuSwapFS(); // Xbox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetDepthStencilSurface2
// ******************************************************************
XTL::X_D3DSurface * WINAPI XTL::EmuIDirect3DDevice8_GetDepthStencilSurface2()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetDepthStencilSurface2()\n", GetCurrentThreadId());
IDirect3DSurface8 *pSurface8 = g_pCachedZStencilSurface->EmuSurface8;
if(pSurface8 != 0)
pSurface8->AddRef();
DbgPrintf("EmuD3D8 (0x%X): DepthStencilSurface := 0x%.08X\n", GetCurrentThreadId(), pSurface8);
EmuSwapFS(); // Xbox FS
return g_pCachedZStencilSurface;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetTile
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetTile
(
DWORD Index,
X_D3DTILE *pTile
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetTile\n"
"(\n"
" Index : 0x%.08X\n"
" pTile : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Index, pTile);
if(pTile != NULL)
memcpy(pTile, &EmuD3DTileCache[Index], sizeof(X_D3DTILE));
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTileNoWait
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetTileNoWait
(
DWORD Index,
CONST X_D3DTILE *pTile
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTileNoWait\n"
"(\n"
" Index : 0x%.08X\n"
" pTile : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Index, pTile);
if(pTile != NULL)
memcpy(&EmuD3DTileCache[Index], pTile, sizeof(X_D3DTILE));
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateVertexShader
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateVertexShader
(
CONST DWORD *pDeclaration,
CONST DWORD *pFunction,
DWORD *pHandle,
DWORD Usage
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateVertexShader\n"
"(\n"
" pDeclaration : 0x%.08X\n"
" pFunction : 0x%.08X\n"
" pHandle : 0x%.08X\n"
" Usage : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pDeclaration, pFunction, pHandle, Usage);
// create emulated shader struct
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader*)CxbxMalloc(sizeof(X_D3DVertexShader));
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER*)CxbxMalloc(sizeof(VERTEX_SHADER));
// TODO: Intelligently fill out these fields as necessary
ZeroMemory(pD3DVertexShader, sizeof(X_D3DVertexShader));
ZeroMemory(pVertexShader, sizeof(VERTEX_SHADER));
// HACK: TODO: support this situation
if(pDeclaration == NULL)
{
*pHandle = NULL;
EmuSwapFS(); // Win2k/XP FS
return S_OK;
}
LPD3DXBUFFER pRecompiledBuffer = NULL;
DWORD *pRecompiledDeclaration;
DWORD *pRecompiledFunction = NULL;
DWORD VertexShaderSize = 0;
DWORD DeclarationSize;
DWORD Handle = 0;
HRESULT hRet = XTL::EmuRecompileVshDeclaration((DWORD*)pDeclaration,
&pRecompiledDeclaration,
&DeclarationSize,
pFunction == NULL,
&pVertexShader->VertexDynamicPatch);
if(SUCCEEDED(hRet) && pFunction)
{
boolean bUseDeclarationOnly = 0;
hRet = XTL::EmuRecompileVshFunction((DWORD*)pFunction,
&pRecompiledBuffer,
&VertexShaderSize,
g_VertexShaderConstantMode == X_VSCM_NONERESERVED,
&bUseDeclarationOnly);
if(SUCCEEDED(hRet))
{
if(!bUseDeclarationOnly)
pRecompiledFunction = (DWORD*)pRecompiledBuffer->GetBufferPointer();
else
pRecompiledFunction = NULL;
}
else
{
pRecompiledFunction = NULL;
EmuWarning("Couldn't recompile vertex shader function.\n");
hRet = D3D_OK; // Try using a fixed function vertex shader instead
}
}
//DbgPrintf("MaxVertexShaderConst = %d\n", g_D3DCaps.MaxVertexShaderConst);
if(SUCCEEDED(hRet))
{
hRet = g_pD3DDevice8->CreateVertexShader
(
pRecompiledDeclaration,
pRecompiledFunction,
&Handle,
g_dwVertexShaderUsage // TODO: HACK: Xbox has extensions!
);
if(pRecompiledBuffer)
{
pRecompiledBuffer->Release();
pRecompiledBuffer = NULL;
}
//* Fallback to dummy shader.
if(FAILED(hRet))
{
static const char dummy[] =
"vs.1.1\n"
"mov oPos, v0\n";
EmuWarning("Trying fallback:\n%s\n", dummy);
hRet = D3DXAssembleShader(dummy,
strlen(dummy),
D3DXASM_SKIPVALIDATION,
NULL,
&pRecompiledBuffer,
NULL);
hRet = g_pD3DDevice8->CreateVertexShader
(
pRecompiledDeclaration,
(DWORD*)pRecompiledBuffer->GetBufferPointer(),
&Handle,
g_dwVertexShaderUsage
);
}
//*/
}
// Save the status, to remove things later
pVertexShader->Status = hRet;
CxbxFree(pRecompiledDeclaration);
pVertexShader->pDeclaration = (DWORD*)CxbxMalloc(DeclarationSize);
memcpy(pVertexShader->pDeclaration, pDeclaration, DeclarationSize);
pVertexShader->FunctionSize = 0;
pVertexShader->pFunction = NULL;
pVertexShader->Type = X_VST_NORMAL;
pVertexShader->Size = (VertexShaderSize - sizeof(VSH_SHADER_HEADER)) / VSH_INSTRUCTION_SIZE_BYTES;
pVertexShader->DeclarationSize = DeclarationSize;
if(SUCCEEDED(hRet))
{
if(pFunction != NULL)
{
pVertexShader->pFunction = (DWORD*)CxbxMalloc(VertexShaderSize);
memcpy(pVertexShader->pFunction, pFunction, VertexShaderSize);
pVertexShader->FunctionSize = VertexShaderSize;
}
else
{
pVertexShader->pFunction = NULL;
pVertexShader->FunctionSize = 0;
}
pVertexShader->Handle = Handle;
}
else
{
pVertexShader->Handle = D3DFVF_XYZ | D3DFVF_TEX0;
}
pD3DVertexShader->Handle = (DWORD)pVertexShader;
*pHandle = ((DWORD)pD3DVertexShader) | 0x80000000;
if(FAILED(hRet))
{
#ifdef _DEBUG_TRACK_VS
if (pFunction)
{
char pFileName[30];
static int FailedShaderCount = 0;
VSH_SHADER_HEADER *pHeader = (VSH_SHADER_HEADER*)pFunction;
EmuWarning("Couldn't create vertex shader!");
sprintf(pFileName, "failed%05d.xvu", FailedShaderCount);
FILE *f = fopen(pFileName, "wb");
if(f)
{
fwrite(pFunction, sizeof(VSH_SHADER_HEADER) + pHeader->NumInst * 16, 1, f);
fclose(f);
}
FailedShaderCount++;
}
#endif // _DEBUG_TRACK_VS
//hRet = D3D_OK;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetPixelShaderConstant
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetPixelShaderConstant
(
DWORD Register,
CONST PVOID pConstantData,
DWORD ConstantCount
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetPixelShaderConstant\n"
"(\n"
" Register : 0x%.08X\n"
" pConstantData : 0x%.08X\n"
" ConstantCount : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Register, pConstantData, ConstantCount);
// TODO: This hack is necessary for Vertex Shaders on XDKs prior to 4361, but if this
// causes problems with pixel shaders, feel free to comment out the hack below.
if(g_BuildVersion <= 4361)
Register += 96;
HRESULT hRet = g_pD3DDevice8->SetPixelShaderConstant
(
Register,
pConstantData,
ConstantCount
);
if(FAILED(hRet))
{
EmuWarning("We're lying about setting a pixel shader constant!");
hRet = D3D_OK;
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexShaderConstant
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexShaderConstant
(
INT Register,
CONST PVOID pConstantData,
DWORD ConstantCount
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexShaderConstant\n"
"(\n"
" Register : 0x%.08X\n"
" pConstantData : 0x%.08X\n"
" ConstantCount : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Register, pConstantData, ConstantCount);
/*#ifdef _DEBUG_TRACK_VS_CONST
for (uint32 i = 0; i < ConstantCount; i++)
{
printf("SetVertexShaderConstant, c%d (c%d) = { %f, %f, %f, %f }\n",
Register - 96 + i, Register + i,
*((float*)pConstantData + 4 * i),
*((float*)pConstantData + 4 * i + 1),
*((float*)pConstantData + 4 * i + 2),
*((float*)pConstantData + 4 * i + 3));
}
#endif*/ // _DEBUG_TRACK_VS_CONST
// TODO: HACK: Since Xbox vertex shader constants range from -96 to 96, during conversion
// some shaders need to add 96 to use ranges 0 to 192. This fixes 3911 - 4361 games and XDK
// samples, but breaks Turok.
if(g_BuildVersion <= 4361)
Register += 96;
HRESULT hRet = g_pD3DDevice8->SetVertexShaderConstant
(
Register,
pConstantData,
ConstantCount
);
if(FAILED(hRet))
{
EmuWarning("We're lying about setting a vertex shader constant!");
hRet = D3D_OK;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexShaderConstant1
// ******************************************************************
VOID __fastcall XTL::EmuIDirect3DDevice8_SetVertexShaderConstant1
(
INT Register,
CONST PVOID pConstantData
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexShaderConstant1\n"
"(\n"
" Register : 0x%.08X\n"
" pConstantData : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Register, pConstantData);
EmuSwapFS(); // XBox FS
}
#endif
XTL::EmuIDirect3DDevice8_SetVertexShaderConstant(Register, pConstantData, 1);
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexShaderConstant4
// ******************************************************************
VOID __fastcall XTL::EmuIDirect3DDevice8_SetVertexShaderConstant4
(
INT Register,
CONST PVOID pConstantData
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexShaderConstant4\n"
"(\n"
" Register : 0x%.08X\n"
" pConstantData : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Register, pConstantData);
EmuSwapFS(); // XBox FS
}
#endif
XTL::EmuIDirect3DDevice8_SetVertexShaderConstant(Register, pConstantData, 4);
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexShaderConstantNotInline
// ******************************************************************
VOID __fastcall XTL::EmuIDirect3DDevice8_SetVertexShaderConstantNotInline
(
INT Register,
CONST PVOID pConstantData,
DWORD ConstantCount
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexShaderConstantNotInline\n"
"(\n"
" Register : 0x%.08X\n"
" pConstantData : 0x%.08X\n"
" ConstantCount : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Register, pConstantData, ConstantCount);
EmuSwapFS(); // XBox FS
}
#endif
XTL::EmuIDirect3DDevice8_SetVertexShaderConstant(Register, pConstantData, ConstantCount / 4);
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DeletePixelShader
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_DeletePixelShader
(
DWORD Handle
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_DeletePixelShader\n"
"(\n"
" Handle : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle);
if(Handle == X_PIXELSHADER_FAKE_HANDLE)
{
// Do Nothing!
}
else
{
g_pD3DDevice8->DeletePixelShader(Handle);
}
/*PIXEL_SHADER *pPixelShader = (PIXEL_SHADER*)Handle;
if (pPixelShader)
{
if(pPixelShader->Handle != X_PIXELSHADER_FAKE_HANDLE)
{
g_pD3DDevice8->DeletePixelShader(pPixelShader->Handle);
}
CxbxFree(pPixelShader);
}*/
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreatePixelShader
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreatePixelShader
(
X_D3DPIXELSHADERDEF *pPSDef,
DWORD *pHandle
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreatePixelShader\n"
"(\n"
" pPSDef : 0x%.08X\n"
" pHandle : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPSDef, pHandle);
//HRESULT hRet = E_FAIL;
DWORD* pFunction = NULL;
LPD3DXBUFFER pRecompiledBuffer = NULL;
DWORD Handle = 0;
//hRet = CreatePixelShaderFunction(pPSDef, &pRecompiledBuffer);
//if (SUCCEEDED(hRet))
//{
// pFunction = (DWORD*)pRecompiledBuffer->GetBufferPointer();
// // redirect to windows d3d
// hRet = g_pD3DDevice8->CreatePixelShader
// (
// pFunction,
// &Handle
// );
//}
//if (pRecompiledBuffer)
//{
// pRecompiledBuffer->Release();
//}
// if(FAILED(hRet))
// {
// Handle = X_PIXELSHADER_FAKE_HANDLE;
// EmuWarning("We're lying about the creation of a pixel shader!");
// hRet = D3D_OK;
// }
//PIXEL_SHADER *pPixelShader = (PIXEL_SHADER*)CxbxMalloc(sizeof(PIXEL_SHADER));
//ZeroMemory(pPixelShader, sizeof(PIXEL_SHADER));
//memcpy(&pPixelShader->PSDef, pPSDef, sizeof(X_D3DPIXELSHADERDEF));
//pPixelShader->Handle = Handle;
//pPixelShader->dwStatus = hRet;
//*pHandle = (DWORD)pPixelShader;
#if 1
pFunction = (DWORD*) pPSDef;
#endif
// Attempt to recompile PixelShader
EmuRecompilePshDef( pPSDef, NULL );
// redirect to windows d3d
HRESULT hRet = g_pD3DDevice8->CreatePixelShader
(
pFunction,
pHandle
);
if(FAILED(hRet))
{
*pHandle = X_PIXELSHADER_FAKE_HANDLE;
// This is called too frequently as Azurik creates and destroys a
// pixel shader every frame, and makes debugging harder.
// EmuWarning("We're lying about the creation of a pixel shader!");
hRet = D3D_OK;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetPixelShader
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetPixelShader
(
DWORD Handle
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetPixelShader\n"
"(\n"
" Handle : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle);
// redirect to windows d3d
HRESULT hRet = D3D_OK;
// Fake Programmable Pipeline
if(Handle == X_PIXELSHADER_FAKE_HANDLE)
{
// programmable pipeline
//*
static DWORD dwHandle = 0;
if(dwHandle == 0)
{
// simplest possible pixel shader, simply output the texture input
static const char szDiffusePixelShader[] =
"ps.1.0\n"
"tex t0\n"
"mov r0, t0\n";
LPD3DXBUFFER pShader = 0;
LPD3DXBUFFER pErrors = 0;
// assemble the shader
D3DXAssembleShader(szDiffusePixelShader, strlen(szDiffusePixelShader) - 1, 0, NULL, &pShader, &pErrors);
// create the shader device handle
hRet = g_pD3DDevice8->CreatePixelShader((DWORD*)pShader->GetBufferPointer(), &dwHandle);
g_dwCurrentPixelShader = 0;
if(FAILED(hRet))
EmuWarning("Could not create pixel shader");
}
if(!FAILED(hRet))
hRet = g_pD3DDevice8->SetPixelShader(dwHandle);
if(FAILED(hRet))
EmuWarning("Could not set pixel shader!");
//*/
g_bFakePixelShaderLoaded = TRUE;
}
// Fixed Pipeline, or Recompiled Programmable Pipeline
else if(Handle == NULL)
{
g_bFakePixelShaderLoaded = FALSE;
g_dwCurrentPixelShader = Handle;
g_pD3DDevice8->SetPixelShader(Handle);
}
if(FAILED(hRet))
{
EmuWarning("We're lying about setting a pixel shader!");
hRet = D3D_OK;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateTexture2
// ******************************************************************
XTL::X_D3DResource * WINAPI XTL::EmuIDirect3DDevice8_CreateTexture2
(
UINT Width,
UINT Height,
UINT Depth,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DRESOURCETYPE D3DResource
)
{
X_D3DTexture *pTexture = NULL;
switch(D3DResource)
{
case 3: /*D3DRTYPE_TEXTURE*/
EmuIDirect3DDevice8_CreateTexture(Width, Height, Levels, Usage, Format, D3DPOOL_MANAGED, &pTexture);
break;
case 4: /*D3DRTYPE_VOLUMETEXTURE*/
EmuIDirect3DDevice8_CreateVolumeTexture(Width, Height, Depth, Levels, Usage, Format, D3DPOOL_MANAGED, (X_D3DVolumeTexture**)&pTexture);
break;
case 5: /*D3DRTYPE_CUBETEXTURE*/
//DbgPrintf( "D3DDevice_CreateTexture2: Width = 0x%X, Height = 0x%X\n", Width, Height );
//CxbxKrnlCleanup("Cube textures temporarily not supported!");
EmuIDirect3DDevice8_CreateCubeTexture(Width, Levels, Usage, Format, D3DPOOL_DEFAULT, (X_D3DCubeTexture**) &pTexture);
break;
default:
CxbxKrnlCleanup("D3DResource = %d is not supported!", D3DResource);
}
return pTexture;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateTexture
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateTexture
(
UINT Width,
UINT Height,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
X_D3DTexture **ppTexture
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateTexture\n"
"(\n"
" Width : 0x%.08X\n"
" Height : 0x%.08X\n"
" Levels : 0x%.08X\n"
" Usage : 0x%.08X\n"
" Format : 0x%.08X\n"
" Pool : 0x%.08X\n"
" ppTexture : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Width, Height, Levels, Usage, Format, Pool, ppTexture);
// Convert Format (Xbox->PC)
D3DFORMAT PCFormat = EmuXB2PC_D3DFormat(Format);
// TODO: HACK: Devices that don't support this should somehow emulate it!
//* This is OK on my GeForce FX 5600
if(PCFormat == D3DFMT_D16)
{
EmuWarning("D3DFMT_D16 is an unsupported texture format!");
PCFormat = D3DFMT_R5G6B5;
}
//*
else if(PCFormat == D3DFMT_P8)
{
EmuWarning("D3DFMT_P8 is an unsupported texture format!");
PCFormat = D3DFMT_L8;
}
//*/
//* This is OK on my GeForce FX 5600
else if(PCFormat == D3DFMT_D24S8)
{
EmuWarning("D3DFMT_D24S8 is an unsupported texture format!");
PCFormat = D3DFMT_X8R8G8B8;
}//*/
else if(PCFormat == D3DFMT_YUY2)
{
// cache the overlay size
g_dwOverlayW = Width;
g_dwOverlayH = Height;
g_dwOverlayP = RoundUp(g_dwOverlayW, 64)*2;
}
HRESULT hRet;
if(PCFormat != D3DFMT_YUY2)
{
DWORD PCUsage = Usage & (D3DUSAGE_RENDERTARGET);
// DWORD PCUsage = Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL);
D3DPOOL PCPool = D3DPOOL_MANAGED;
// DIRTY HACK: Render targets. The D3DUSAGE_RENDERTARGET
// flag isn't always set by the XDK (if ever).
/*if( Width != 640 && Height != 480 )
{
// EmuAdjustPower2(&Width, &Height);
}
else
{
PCUsage = D3DUSAGE_RENDERTARGET;
PCPool = D3DPOOL_DEFAULT;
}*/
// EmuAdjustPower2(&Width, &Height);
*ppTexture = new X_D3DTexture();
// if(Usage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL))
if(Usage & (D3DUSAGE_RENDERTARGET))
PCPool = D3DPOOL_DEFAULT;
hRet = g_pD3DDevice8->CreateTexture
(
Width, Height, Levels,
PCUsage, // TODO: Xbox Allows a border to be drawn (maybe hack this in software ;[)
PCFormat, PCPool, &((*ppTexture)->EmuTexture8)
);
if(FAILED(hRet))
{
EmuWarning("CreateTexture Failed!");
(*ppTexture)->Data = 0xBEADBEAD;
}
else
{
D3DLOCKED_RECT LockedRect;
(*ppTexture)->EmuTexture8->LockRect(0, &LockedRect, NULL, NULL);
(*ppTexture)->Data = (DWORD)LockedRect.pBits;
(*ppTexture)->Format = Format << X_D3DFORMAT_FORMAT_SHIFT;
g_DataToTexture.insert((*ppTexture)->Data, *ppTexture);
(*ppTexture)->EmuTexture8->UnlockRect(0);
}
DbgPrintf("EmuD3D8 (0x%X): Created Texture : 0x%.08X (0x%.08X)\n", GetCurrentThreadId(), *ppTexture, (*ppTexture)->EmuTexture8);
}
else
{
DWORD dwSize = g_dwOverlayP*g_dwOverlayH;
DWORD dwPtr = (DWORD)CxbxMalloc(dwSize + sizeof(DWORD));
DWORD *pRefCount = (DWORD*)(dwPtr + dwSize);
// initialize ref count
*pRefCount = 1;
// If YUY2 is not supported in hardware, we'll actually mark this as a special fake texture (set highest bit)
*ppTexture = new X_D3DTexture();
(*ppTexture)->Data = X_D3DRESOURCE_DATA_FLAG_SPECIAL | X_D3DRESOURCE_DATA_FLAG_YUVSURF;
(*ppTexture)->Lock = dwPtr;
(*ppTexture)->Format = 0x24;
(*ppTexture)->Size = (g_dwOverlayW & X_D3DSIZE_WIDTH_MASK);
(*ppTexture)->Size |= (g_dwOverlayH << X_D3DSIZE_HEIGHT_SHIFT);
(*ppTexture)->Size |= (g_dwOverlayP << X_D3DSIZE_PITCH_SHIFT);
g_YuvSurface = (X_D3DSurface*)*ppTexture;
hRet = D3D_OK;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateVolumeTexture
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateVolumeTexture
(
UINT Width,
UINT Height,
UINT Depth,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
X_D3DVolumeTexture **ppVolumeTexture
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateVolumeTexture\n"
"(\n"
" Width : 0x%.08X\n"
" Height : 0x%.08X\n"
" Depth : 0x%.08X\n"
" Levels : 0x%.08X\n"
" Usage : 0x%.08X\n"
" Format : 0x%.08X\n"
" Pool : 0x%.08X\n"
" ppVolumeTexture : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Width, Height, Depth, Levels, Usage, Format, Pool, ppVolumeTexture);
// Convert Format (Xbox->PC)
D3DFORMAT PCFormat = EmuXB2PC_D3DFormat(Format);
// TODO: HACK: Devices that don't support this should somehow emulate it!
if(PCFormat == D3DFMT_D16)
{
EmuWarning("D3DFMT_16 is an unsupported texture format!");
PCFormat = D3DFMT_X8R8G8B8;
}
else if(PCFormat == D3DFMT_P8)
{
EmuWarning("D3DFMT_P8 is an unsupported texture format!");
PCFormat = D3DFMT_L8;
}
else if(PCFormat == D3DFMT_D24S8)
{
EmuWarning("D3DFMT_D24S8 is an unsupported texture format!");
PCFormat = D3DFMT_X8R8G8B8;
}
else if(PCFormat == D3DFMT_YUY2)
{
// cache the overlay size
g_dwOverlayW = Width;
g_dwOverlayH = Height;
g_dwOverlayP = RoundUp(g_dwOverlayW, 64)*2;
}
HRESULT hRet;
if(PCFormat != D3DFMT_YUY2)
{
EmuAdjustPower2(&Width, &Height);
*ppVolumeTexture = new X_D3DVolumeTexture();
hRet = g_pD3DDevice8->CreateVolumeTexture
(
Width, Height, Depth, Levels,
0, // TODO: Xbox Allows a border to be drawn (maybe hack this in software ;[)
PCFormat, D3DPOOL_MANAGED, &((*ppVolumeTexture)->EmuVolumeTexture8)
);
if(FAILED(hRet))
EmuWarning("CreateVolumeTexture Failed! (0x%.08X)", hRet);
DbgPrintf("EmuD3D8 (0x%X): Created Volume Texture : 0x%.08X (0x%.08X)\n", GetCurrentThreadId(), *ppVolumeTexture, (*ppVolumeTexture)->EmuVolumeTexture8);
}
else
{
DWORD dwSize = g_dwOverlayP*g_dwOverlayH;
DWORD dwPtr = (DWORD)CxbxMalloc(dwSize + sizeof(DWORD));
DWORD *pRefCount = (DWORD*)(dwPtr + dwSize);
// initialize ref count
*pRefCount = 1;
// If YUY2 is not supported in hardware, we'll actually mark this as a special fake texture (set highest bit)
(*ppVolumeTexture)->Data = X_D3DRESOURCE_DATA_FLAG_SPECIAL | X_D3DRESOURCE_DATA_FLAG_YUVSURF;
(*ppVolumeTexture)->Lock = dwPtr;
(*ppVolumeTexture)->Format = 0x24;
(*ppVolumeTexture)->Size = (g_dwOverlayW & X_D3DSIZE_WIDTH_MASK);
(*ppVolumeTexture)->Size |= (g_dwOverlayH << X_D3DSIZE_HEIGHT_SHIFT);
(*ppVolumeTexture)->Size |= (g_dwOverlayP << X_D3DSIZE_PITCH_SHIFT);
hRet = D3D_OK;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateCubeTexture
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateCubeTexture
(
UINT EdgeLength,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
X_D3DCubeTexture **ppCubeTexture
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateCubeTexture\n"
"(\n"
" EdgeLength : 0x%.08X\n"
" Levels : 0x%.08X\n"
" Usage : 0x%.08X\n"
" Format : 0x%.08X\n"
" Pool : 0x%.08X\n"
" ppCubeTexture : 0x%.08X\n"
");\n",
GetCurrentThreadId(), EdgeLength, Levels, Usage, Format, Pool, ppCubeTexture);
// Convert Format (Xbox->PC)
D3DFORMAT PCFormat = EmuXB2PC_D3DFormat(Format);
// TODO: HACK: Devices that don't support this should somehow emulate it!
if(PCFormat == D3DFMT_D16)
{
EmuWarning("D3DFMT_16 is an unsupported texture format!");
PCFormat = D3DFMT_X8R8G8B8;
}
else if(PCFormat == D3DFMT_P8)
{
EmuWarning("D3DFMT_P8 is an unsupported texture format!");
PCFormat = D3DFMT_L8;
}
else if(PCFormat == D3DFMT_D24S8)
{
EmuWarning("D3DFMT_D24S8 is an unsupported texture format!");
PCFormat = D3DFMT_X8R8G8B8;
}
else if(PCFormat == D3DFMT_YUY2)
{
CxbxKrnlCleanup("YUV not supported for cube textures");
}
*ppCubeTexture = new X_D3DCubeTexture();
HRESULT hRet = g_pD3DDevice8->CreateCubeTexture
(
EdgeLength, Levels,
0, // TODO: Xbox Allows a border to be drawn (maybe hack this in software ;[)
PCFormat, D3DPOOL_MANAGED, &((*ppCubeTexture)->EmuCubeTexture8)
);
DbgPrintf("EmuD3D8 (0x%X): Created Cube Texture : 0x%.08X (0x%.08X)\n", GetCurrentThreadId(), *ppCubeTexture, (*ppCubeTexture)->EmuCubeTexture8);
if(FAILED(hRet))
EmuWarning("CreateCubeTexture Failed!");
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateIndexBuffer
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateIndexBuffer
(
UINT Length,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
X_D3DIndexBuffer **ppIndexBuffer
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateIndexBuffer\n"
"(\n"
" Length : 0x%.08X\n"
" Usage : 0x%.08X\n"
" Format : 0x%.08X\n"
" Pool : 0x%.08X\n"
" ppIndexBuffer : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Length, Usage, Format, Pool, ppIndexBuffer);
*ppIndexBuffer = new X_D3DIndexBuffer();
HRESULT hRet = g_pD3DDevice8->CreateIndexBuffer
(
Length, NULL, D3DFMT_INDEX16, D3DPOOL_MANAGED, &((*ppIndexBuffer)->EmuIndexBuffer8)
);
DbgPrintf("EmuD3D8 (0x%X): EmuIndexBuffer8 := 0x%.08X\n", GetCurrentThreadId(), (*ppIndexBuffer)->EmuIndexBuffer8);
if(FAILED(hRet))
EmuWarning("CreateIndexBuffer Failed! (0x%.08X)", hRet);
//
// update data ptr
//
{
BYTE *pData = NULL;
(*ppIndexBuffer)->EmuIndexBuffer8->Lock(0, Length, &pData, NULL);
(*ppIndexBuffer)->Data = (DWORD)pData;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateIndexBuffer2
// ******************************************************************
XTL::X_D3DIndexBuffer * WINAPI XTL::EmuIDirect3DDevice8_CreateIndexBuffer2(UINT Length)
{
X_D3DIndexBuffer *pIndexBuffer = NULL;
EmuIDirect3DDevice8_CreateIndexBuffer
(
Length,
NULL,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&pIndexBuffer
);
return pIndexBuffer;
}
BOOL g_bBadIndexData = FALSE;
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetIndices
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetIndices
(
X_D3DIndexBuffer *pIndexData,
UINT BaseVertexIndex
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetIndices\n"
"(\n"
" pIndexData : 0x%.08X\n"
" BaseVertexIndex : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pIndexData, BaseVertexIndex);
/*
fflush(stdout);
if(pIndexData != 0)
{
static int chk = 0;
if(chk++ == 0)
{
_asm int 3
}
}
//*/
HRESULT hRet = D3D_OK;
//#if 0
if(pIndexData != NULL)
{
DbgPrintf("EmuIDirect3DDevice8_SetIndcies(): pIndexData->EmuIndexBuffer8:= 0x%.08X\n", pIndexData->EmuIndexBuffer8 );
DbgPrintf("EmuIDirect3DDevice8_SetIndcies(): pIndexData->Lock:= 0x%.08X\n", pIndexData->Lock );
}
g_dwBaseVertexIndex = BaseVertexIndex;
if(pIndexData != 0)
{
g_pIndexBuffer = pIndexData;
// HACK: Halo Hack
if(pIndexData->Lock == 0x00840863)
pIndexData->Lock = 0;
EmuVerifyResourceIsRegistered(pIndexData);
// HACK: Unreal Championship
if((pIndexData->Lock & 0xFFFF0000) == 0x00490000 || (pIndexData->Lock & 0xF0000000) != 0x00000000 ||
pIndexData->Lock == 0x10)
{
hRet = E_FAIL;
goto fail;
}
IDirect3DIndexBuffer8 *pIndexBuffer = pIndexData->EmuIndexBuffer8;
if(pIndexData->Lock != X_D3DRESOURCE_LOCK_FLAG_NOSIZE)
hRet = g_pD3DDevice8->SetIndices(pIndexBuffer, BaseVertexIndex);
}
else
{
g_pIndexBuffer = 0;
hRet = g_pD3DDevice8->SetIndices(0, BaseVertexIndex);
}
//#endif
fail:
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTexture
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetTexture
(
DWORD Stage,
X_D3DResource *pTexture
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTexture\n"
"(\n"
" Stage : 0x%.08X\n"
" pTexture : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Stage, pTexture);
IDirect3DBaseTexture8 *pBaseTexture8 = NULL;
EmuD3DActiveTexture[Stage] = pTexture;
if(pTexture != NULL)
{
EmuVerifyResourceIsRegistered(pTexture);
if(IsSpecialResource(pTexture->Data) && (pTexture->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
//
// NOTE: TODO: This is almost a hack! :)
//
EmuSwapFS();
EmuIDirect3DDevice8_EnableOverlay(TRUE);
EmuIDirect3DDevice8_UpdateOverlay((X_D3DSurface*)pTexture, 0, 0, FALSE, 0);
EmuSwapFS();
}
else
{
// Remove old locks before setting
/*if(pTexture->Common & X_D3DCOMMON_ISLOCKED)
{
pTexture->EmuTexture8->UnlockRect(0);
pTexture->Common &= ~X_D3DCOMMON_ISLOCKED;
}*/
pBaseTexture8 = pTexture->EmuBaseTexture8;
// Let's be SURE that the texture is unlocked AND unswizzled before
// we set it!!!
// EmuUnswizzleTextureStages();
// pBaseTexture8 = EmuD3DActiveTexture[Stage]->EmuBaseTexture8;
#ifdef _DEBUG_DUMP_TEXTURE_SETTEXTURE
if(pTexture != NULL && (pTexture->EmuTexture8 != NULL))
{
static int dwDumpTexture = 0;
char szBuffer[256];
switch(pTexture->EmuResource8->GetType())
{
case D3DRTYPE_TEXTURE:
{
sprintf(szBuffer, _DEBUG_DUMP_TEXTURE_SETTEXTURE "SetTextureNorm - %.03d (0x%.08X).bmp", dwDumpTexture++, pTexture->EmuTexture8);
pTexture->EmuTexture8->UnlockRect(0);
D3DXSaveTextureToFile(szBuffer, D3DXIFF_BMP, pTexture->EmuTexture8, NULL);
}
break;
case D3DRTYPE_CUBETEXTURE:
{
for(int face=0;face<6;face++)
{
sprintf(szBuffer, _DEBUG_DUMP_TEXTURE_SETTEXTURE "SetTextureCube%d - %.03d (0x%.08X).bmp", face, dwDumpTexture++, pTexture->EmuTexture8);
pTexture->EmuCubeTexture8->UnlockRect((D3DCUBEMAP_FACES)face, 0);
D3DXSaveTextureToFile(szBuffer, D3DXIFF_BMP, pTexture->EmuTexture8, NULL);
}
}
break;
}
}
#endif
}
}
/*
static IDirect3DTexture8 *pDummyTexture[4] = {0, 0, 0, 0};
if(pDummyTexture[Stage] == 0)
{
if(Stage == 0)
{
if(D3DXCreateTextureFromFile(g_pD3DDevice8, "C:\\dummy1.bmp", &pDummyTexture[Stage]) != D3D_OK)
CxbxKrnlCleanup("Could not create dummy texture!");
}
else if(Stage == 1)
{
if(D3DXCreateTextureFromFile(g_pD3DDevice8, "C:\\dummy2.bmp", &pDummyTexture[Stage]) != D3D_OK)
CxbxKrnlCleanup("Could not create dummy texture!");
}
}
//*/
/*
static int dwDumpTexture = 0;
char szBuffer[256];
sprintf(szBuffer, "C:\\Aaron\\Textures\\DummyTexture - %.03d (0x%.08X).bmp", dwDumpTexture++, pDummyTexture);
pDummyTexture->UnlockRect(0);
D3DXSaveTextureToFile(szBuffer, D3DXIFF_BMP, pDummyTexture, NULL);
//*/
//HRESULT hRet = g_pD3DDevice8->SetTexture(Stage, pDummyTexture[Stage]);
HRESULT hRet = g_pD3DDevice8->SetTexture(Stage, (g_iWireframe == 0) ? pBaseTexture8 : 0);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SwitchTexture
// ******************************************************************
VOID __fastcall XTL::EmuIDirect3DDevice8_SwitchTexture
(
DWORD Method,
DWORD Data,
DWORD Format
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SwitchTexture\n"
"(\n"
" Method : 0x%.08X\n"
" Data : 0x%.08X\n"
" Format : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Method, Data, Format);
DWORD StageLookup[] = { 0x00081b00, 0x00081b40, 0x00081b80, 0x00081bc0 };
DWORD Stage = -1;
for(int v=0;v<4;v++)
{
if(StageLookup[v] == Method)
{
Stage = v;
}
}
if(Stage == -1)
{
EmuWarning("Unknown Method (0x%.08X)", Method);
}
else
{
//
// WARNING: TODO: Correct reference counting has not been completely verified for this code
//
X_D3DTexture *pTexture = (X_D3DTexture *)g_DataToTexture.get(Data);
EmuWarning("Switching Texture 0x%.08X (0x%.08X) @ Stage %d", pTexture, pTexture->EmuBaseTexture8, Stage);
HRESULT hRet = g_pD3DDevice8->SetTexture(Stage, pTexture->EmuBaseTexture8);
/*
if(pTexture->EmuBaseTexture8 != NULL)
{
static int dwDumpTexture = 0;
char szBuffer[255];
sprintf(szBuffer, "C:\\Aaron\\Textures\\0x%.08X-SwitchTexture%.03d.bmp", pTexture, dwDumpTexture++);
pTexture->EmuTexture8->UnlockRect(0);
D3DXSaveTextureToFile(szBuffer, D3DXIFF_BMP, pTexture->EmuBaseTexture8, NULL);
}
//*/
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetDisplayMode
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetDisplayMode
(
X_D3DDISPLAYMODE *pMode
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetDisplayMode\n"
"(\n"
" pMode : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pMode);
HRESULT hRet;
// make adjustments to parameters to make sense with windows d3d
{
D3DDISPLAYMODE *pPCMode = (D3DDISPLAYMODE*)pMode;
hRet = g_pD3DDevice8->GetDisplayMode(pPCMode);
// Convert Format (PC->Xbox)
pMode->Format = EmuPC2XB_D3DFormat(pPCMode->Format);
// TODO: Make this configurable in the future?
pMode->Flags = 0x000000A1; // D3DPRESENTFLAG_FIELD | D3DPRESENTFLAG_INTERLACED | D3DPRESENTFLAG_LOCKABLE_BACKBUFFER
// TODO: Retrieve from current CreateDevice settings?
pMode->Width = 640;
pMode->Height = 480;
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_Begin
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_Begin
(
X_D3DPRIMITIVETYPE PrimitiveType
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_Begin\n"
"(\n"
" PrimitiveType : 0x%.08X\n"
");\n",
GetCurrentThreadId(), PrimitiveType);
g_IVBPrimitiveType = PrimitiveType;
if(g_IVBTable == 0)
{
g_IVBTable = (struct XTL::_D3DIVB*)CxbxMalloc(sizeof(XTL::_D3DIVB)*1024);
}
g_IVBTblOffs = 0;
g_IVBFVF = 0;
// default values
ZeroMemory(g_IVBTable, sizeof(XTL::_D3DIVB)*1024);
if(g_pIVBVertexBuffer == 0)
{
g_pIVBVertexBuffer = (DWORD*)CxbxMalloc(sizeof(XTL::_D3DIVB)*1024);
}
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexData2f
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexData2f
(
int Register,
FLOAT a,
FLOAT b
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexData2f >>\n"
"(\n"
" Register : 0x%.08X\n"
" a : %f\n"
" b : %f\n"
");\n",
GetCurrentThreadId(), Register, a, b);
EmuSwapFS(); // XBox FS
}
#endif
return EmuIDirect3DDevice8_SetVertexData4f(Register, a, b, 0.0f, 1.0f);
}
static inline DWORD FtoDW(FLOAT f) { return *((DWORD*)&f); }
static inline FLOAT DWtoF(DWORD f) { return *((FLOAT*)&f); }
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexData2s
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexData2s
(
int Register,
SHORT a,
SHORT b
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexData2s >>\n"
"(\n"
" Register : 0x%.08X\n"
" a : %d\n"
" b : %d\n"
");\n",
GetCurrentThreadId(), Register, a, b);
EmuSwapFS(); // XBox FS
}
#endif
DWORD dwA = a, dwB = b;
return EmuIDirect3DDevice8_SetVertexData4f(Register, DWtoF(dwA), DWtoF(dwB), 0.0f, 1.0f);
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexData4f
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexData4f
(
int Register,
FLOAT a,
FLOAT b,
FLOAT c,
FLOAT d
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexData4f\n"
"(\n"
" Register : 0x%.08X\n"
" a : %f\n"
" b : %f\n"
" c : %f\n"
" d : %f\n"
");\n",
GetCurrentThreadId(), Register, a, b, c, d);
HRESULT hRet = S_OK;
switch(Register)
{
// TODO: Blend weight.
case 0: // D3DVSDE_POSITION
{
int o = g_IVBTblOffs;
g_IVBTable[o].Position.x = a;
g_IVBTable[o].Position.y = b;
g_IVBTable[o].Position.z = c;
g_IVBTable[o].Rhw = 1.0f;
g_IVBTblOffs++;
g_IVBFVF |= D3DFVF_XYZRHW;
}
break;
case 1: // D3DVSDE_BLENDWEIGHT
{
int o = g_IVBTblOffs;
g_IVBTable[o].Position.x = a;
g_IVBTable[o].Position.y = b;
g_IVBTable[o].Position.z = c;
g_IVBTable[o].Blend1 = d;
g_IVBTblOffs++;
g_IVBFVF |= D3DFVF_XYZB1;
}
break;
case 2: // D3DVSDE_NORMAL
{
int o = g_IVBTblOffs;
g_IVBTable[o].Normal.x = a;
g_IVBTable[o].Normal.y = b;
g_IVBTable[o].Normal.z = c;
g_IVBTblOffs++;
g_IVBFVF |= D3DFVF_NORMAL;
}
break;
case 3: // D3DVSDE_DIFFUSE
{
int o = g_IVBTblOffs;
DWORD ca = FtoDW(d) << 24;
DWORD cr = FtoDW(a) << 16;
DWORD cg = FtoDW(b) << 8;
DWORD cb = FtoDW(c) << 0;
g_IVBTable[o].dwDiffuse = ca | cr | cg | cb;
g_IVBFVF |= D3DFVF_DIFFUSE;
}
break;
case 4: // D3DVSDE_SPECULAR
{
int o = g_IVBTblOffs;
DWORD ca = FtoDW(d) << 24;
DWORD cr = FtoDW(a) << 16;
DWORD cg = FtoDW(b) << 8;
DWORD cb = FtoDW(c) << 0;
g_IVBTable[o].dwSpecular = ca | cr | cg | cb;
g_IVBFVF |= D3DFVF_SPECULAR;
}
break;
case 9: // D3DVSDE_TEXCOORD0
{
int o = g_IVBTblOffs;
g_IVBTable[o].TexCoord1.x = a;
g_IVBTable[o].TexCoord1.y = b;
if( (g_IVBFVF & D3DFVF_TEXCOUNT_MASK) < D3DFVF_TEX1)
{
g_IVBFVF |= D3DFVF_TEX1;
}
}
break;
case 10: // D3DVSDE_TEXCOORD1
{
int o = g_IVBTblOffs;
g_IVBTable[o].TexCoord2.x = a;
g_IVBTable[o].TexCoord2.y = b;
if( (g_IVBFVF & D3DFVF_TEXCOUNT_MASK) < D3DFVF_TEX2)
{
g_IVBFVF |= D3DFVF_TEX2;
}
}
break;
case 11: // D3DVSDE_TEXCOORD2
{
int o = g_IVBTblOffs;
g_IVBTable[o].TexCoord3.x = a;
g_IVBTable[o].TexCoord3.y = b;
if( (g_IVBFVF & D3DFVF_TEXCOUNT_MASK) < D3DFVF_TEX3)
{
g_IVBFVF |= D3DFVF_TEX3;
}
}
break;
case 12: // D3DVSDE_TEXCOORD3
{
int o = g_IVBTblOffs;
g_IVBTable[o].TexCoord4.x = a;
g_IVBTable[o].TexCoord4.y = b;
if( (g_IVBFVF & D3DFVF_TEXCOUNT_MASK) < D3DFVF_TEX4)
{
g_IVBFVF |= D3DFVF_TEX4;
}
}
break;
case 0xFFFFFFFF:
{
int o = g_IVBTblOffs;
g_IVBTable[o].Position.x = a;
g_IVBTable[o].Position.y = b;
g_IVBTable[o].Position.z = c;
g_IVBTable[o].Rhw = d;
// Copy current color to next vertex
g_IVBTable[o+1].dwDiffuse = g_IVBTable[o].dwDiffuse;
g_IVBTable[o+1].dwSpecular = g_IVBTable[o].dwSpecular;
g_IVBTblOffs++;
g_IVBFVF |= D3DFVF_XYZRHW;
}
break;
default:
CxbxKrnlCleanup("Unknown IVB Register : %d", Register);
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexData4ub
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexData4ub
(
INT Register,
BYTE a,
BYTE b,
BYTE c,
BYTE d
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexData4ub\n"
"(\n"
" Register : 0x%.08X\n"
" a : 0x%.02X\n"
" b : 0x%.02X\n"
" c : 0x%.02X\n"
" d : 0x%.02X\n"
");\n",
GetCurrentThreadId(), Register, a, b, c, d);
EmuSwapFS(); // Xbox FS
DWORD dwA = a, dwB = b, dwC = c, dwD = d;
return EmuIDirect3DDevice8_SetVertexData4f(Register, DWtoF(dwA), DWtoF(dwB), DWtoF(dwC), DWtoF(dwD));
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexData4s
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexData4s
(
INT Register,
SHORT a,
SHORT b,
SHORT c,
SHORT d
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexData4s\n"
"(\n"
" Register : 0x%.08X\n"
" a : 0x%.04X\n"
" b : 0x%.04X\n"
" c : 0x%.04X\n"
" d : 0x%.04X\n"
");\n",
GetCurrentThreadId(), Register, a, b, c, d);
EmuSwapFS(); // Xbox FS
DWORD dwA = a, dwB = b, dwC = c, dwD = d;
return EmuIDirect3DDevice8_SetVertexData4f(Register, DWtoF(dwA), DWtoF(dwB), DWtoF(dwC), DWtoF(dwD));
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexDataColor
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexDataColor
(
int Register,
D3DCOLOR Color
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexDataColor >>\n"
"(\n"
" Register : 0x%.08X\n"
" Color : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Register, Color);
EmuSwapFS(); // XBox FS
}
#endif
FLOAT a = DWtoF((Color & 0xFF000000) >> 24);
FLOAT r = DWtoF((Color & 0x00FF0000) >> 16);
FLOAT g = DWtoF((Color & 0x0000FF00) >> 8);
FLOAT b = DWtoF((Color & 0x000000FF) >> 0);
return EmuIDirect3DDevice8_SetVertexData4f(Register, r, g, b, a);
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_End
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_End()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_End();\n", GetCurrentThreadId());
if(g_IVBTblOffs != 0)
EmuFlushIVB();
// TODO: Should technically clean this up at some point..but on XP doesnt matter much
// CxbxFree(g_pIVBVertexBuffer);
// CxbxFree(g_IVBTable);
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_RunPushBuffer
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_RunPushBuffer
(
X_D3DPushBuffer *pPushBuffer,
X_D3DFixup *pFixup
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_RunPushBuffer\n"
"(\n"
" pPushBuffer : 0x%.08X\n"
" pFixup : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPushBuffer, pFixup);
XTL::EmuExecutePushBuffer(pPushBuffer, pFixup);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_Clear
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_Clear
(
DWORD Count,
CONST D3DRECT *pRects,
DWORD Flags,
D3DCOLOR Color,
float Z,
DWORD Stencil
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_Clear\n"
"(\n"
" Count : 0x%.08X\n"
" pRects : 0x%.08X\n"
" Flags : 0x%.08X\n"
" Color : 0x%.08X\n"
" Z : %f\n"
" Stencil : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Count, pRects, Flags,
Color, Z, Stencil);
// make adjustments to parameters to make sense with windows d3d
{
// TODO: D3DCLEAR_TARGET_A, *R, *G, *B don't exist on windows
DWORD newFlags = 0;
if(Flags & 0x000000f0)
newFlags |= D3DCLEAR_TARGET;
if(Flags & 0x00000001)
newFlags |= D3DCLEAR_ZBUFFER;
if(Flags & 0x00000002)
newFlags |= D3DCLEAR_STENCIL;
if(Flags & ~(0x000000f0 | 0x00000001 | 0x00000002))
EmuWarning("Unsupported Flag(s) for IDirect3DDevice8_Clear : 0x%.08X", Flags & ~(0x000000f0 | 0x00000001 | 0x00000002));
Flags = newFlags;
}
DWORD dwFillMode;
if(g_iWireframe == 0)
dwFillMode = D3DFILL_SOLID;
else if(g_iWireframe == 1)
dwFillMode = D3DFILL_WIREFRAME;
else
dwFillMode = D3DFILL_POINT;
g_pD3DDevice8->SetRenderState(D3DRS_FILLMODE, dwFillMode);
HRESULT ret = g_pD3DDevice8->Clear(Count, pRects, Flags, Color, Z, Stencil);
EmuSwapFS(); // XBox FS
return ret;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_Present
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_Present
(
CONST RECT* pSourceRect,
CONST RECT* pDestRect,
PVOID pDummy1,
PVOID pDummy2
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_Present\n"
"(\n"
" pSourceRect : 0x%.08X\n"
" pDestRect : 0x%.08X\n"
" pDummy1 : 0x%.08X\n"
" pDummy2 : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pSourceRect, pDestRect, pDummy1, pDummy2);
HRESULT hRet = S_OK;
// release back buffer lock
{
IDirect3DSurface8 *pBackBuffer;
g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
pBackBuffer->UnlockRect();
}
// TODO: Make a video option to wait for VBlank before calling Present.
// Makes syncing to 30fps easier (which is the native frame rate for Azurik
// and Halo).
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
hRet = g_pD3DDevice8->Present(pSourceRect, pDestRect, (HWND)pDummy1, (CONST RGNDATA*)pDummy2);
// Put primitives per frame in the title
/*{
char szString[64];
sprintf( szString, "Cxbx: PPF(%d)", g_dwPrimPerFrame );
SetWindowText( CxbxKrnl_hEmuParent, szString );
g_dwPrimPerFrame = 0;
}*/
// not really accurate because you definately dont always present on every vblank
g_VBData.Swap = g_VBData.VBlank;
if(g_VBData.VBlank == g_VBLastSwap + 1)
g_VBData.Flags = 1; // D3DVBLANK_SWAPDONE
else
{
g_VBData.Flags = 2; // D3DVBLANK_SWAPMISSED
g_SwapData.MissedVBlanks++;
}
// Handle Swap Callback function
{
g_SwapData.Swap++;
if(g_pSwapCallback != NULL)
{
EmuSwapFS(); // Xbox FS
g_pSwapCallback(&g_SwapData);
EmuSwapFS(); // Win2k/XP FS
}
}
g_bHackUpdateSoftwareOverlay = FALSE;
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_Swap
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_Swap
(
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_Swap\n"
"(\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Flags);
// TODO: Ensure this flag is always the same across library versions
if(Flags != 0)
EmuWarning("XTL::EmuIDirect3DDevice8_Swap: Flags != 0");
// release back buffer lock
{
IDirect3DSurface8 *pBackBuffer;
g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
if(pBackBuffer) pBackBuffer->UnlockRect();
}
// TODO: Make a video option to wait for VBlank before calling Present.
// Makes syncing to 30fps easier (which is the native frame rate for Azurik
// and Halo).
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
// g_pDD7->WaitForVerticalBlank( DDWAITVB_BLOCKEND, NULL );
HRESULT hRet = g_pD3DDevice8->Present(0, 0, 0, 0);
// Handle Swap Callback function
{
g_SwapData.Swap++;
if(g_pSwapCallback != NULL)
{
EmuSwapFS(); // Xbox FS
g_pSwapCallback(&g_SwapData);
EmuSwapFS(); // Win2k/XP FS
}
}
g_bHackUpdateSoftwareOverlay = FALSE;
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DResource8_Register
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DResource8_Register
(
X_D3DResource *pThis,
PVOID pBase
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DResource8_Register\n"
"(\n"
" pThis : 0x%.08X (->Data : 0x%.08X)\n"
" pBase : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, pThis->Data, pBase);
HRESULT hRet = S_OK;
X_D3DResource *pResource = (X_D3DResource*)pThis;
DWORD dwCommonType = pResource->Common & X_D3DCOMMON_TYPE_MASK;
// add the offset of the current texture to the base
pBase = (PVOID)((DWORD)pBase+pThis->Data);
// Determine the resource type, and initialize
switch(dwCommonType)
{
case X_D3DCOMMON_TYPE_VERTEXBUFFER:
{
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Creating VertexBuffer...\n", GetCurrentThreadId());
X_D3DVertexBuffer *pVertexBuffer = (X_D3DVertexBuffer*)pResource;
// create vertex buffer
{
DWORD dwSize = EmuCheckAllocationSize(pBase, true);
if(dwSize == -1)
{
// TODO: once this is known to be working, remove the warning
EmuWarning("Vertex buffer allocation size unknown");
dwSize = 0x2000; // temporarily assign a small buffer, which will be increased later
/*hRet = E_FAIL;
goto fail;*/
}
hRet = g_pD3DDevice8->CreateVertexBuffer
(
dwSize, 0, 0, D3DPOOL_MANAGED,
&pResource->EmuVertexBuffer8
);
if(FAILED(hRet))
{
// TODO: Hack for Crazy Taxi 3?
char szString[256];
sprintf( szString, "CreateVertexBuffer Failed!\n\nVB Size = 0x%X\n\nError: %s\nDesc: %s", dwSize,
DXGetErrorString8A(hRet), DXGetErrorDescription8A(hRet));
if( dwSize != 0 )
CxbxKrnlCleanup( szString );
else
{
EmuWarning( szString );
EmuSwapFS(); // Xbox FS
return hRet;
}
}
#ifdef _DEBUG_TRACK_VB
g_VBTrackTotal.insert(pResource->EmuVertexBuffer8);
#endif
BYTE *pData = 0;
hRet = pResource->EmuVertexBuffer8->Lock(0, 0, &pData, 0);
if(FAILED(hRet))
CxbxKrnlCleanup("VertexBuffer Lock Failed!\n\nError: %s\nDesc: %s",
DXGetErrorString8A(hRet), DXGetErrorDescription8A(hRet));
memcpy(pData, (void*)pBase, dwSize);
pResource->EmuVertexBuffer8->Unlock();
pResource->Data = (ULONG)pData;
}
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Successfully Created VertexBuffer (0x%.08X)\n", GetCurrentThreadId(), pResource->EmuVertexBuffer8);
}
break;
case X_D3DCOMMON_TYPE_INDEXBUFFER:
{
DbgPrintf("EmuIDirect3DResource8_Register :-> IndexBuffer...\n");
X_D3DIndexBuffer *pIndexBuffer = (X_D3DIndexBuffer*)pResource;
// create index buffer
{
DWORD dwSize = EmuCheckAllocationSize(pBase, true);
if(dwSize == -1 || dwSize == 0)
{
// TODO: once this is known to be working, remove the warning
EmuWarning("Index buffer allocation size unknown");
pIndexBuffer->Lock = X_D3DRESOURCE_LOCK_FLAG_NOSIZE;
break;
// Halo dwSize = 0x336;
}
HRESULT hRet = g_pD3DDevice8->CreateIndexBuffer
(
dwSize, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED,
&pIndexBuffer->EmuIndexBuffer8
);
if(FAILED(hRet))
CxbxKrnlCleanup("CreateIndexBuffer Failed!\n\nError: %s\nDesc: %s\nSize: %d",
DXGetErrorString8A(hRet), DXGetErrorDescription8A(hRet), dwSize);
BYTE *pData = 0;
hRet = pResource->EmuIndexBuffer8->Lock(0, dwSize, &pData, 0);
if(FAILED(hRet))
CxbxKrnlCleanup("IndexBuffer Lock Failed!\n\nError: %s\nDesc: %s",
DXGetErrorString8A(hRet), DXGetErrorDescription8A(hRet));
memcpy(pData, (void*)pBase, dwSize);
pResource->EmuIndexBuffer8->Unlock();
pResource->Data = (ULONG)pData;
}
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Successfully Created IndexBuffer (0x%.08X)\n", GetCurrentThreadId(), pResource->EmuIndexBuffer8);
}
break;
case X_D3DCOMMON_TYPE_PUSHBUFFER:
{
DbgPrintf("EmuIDirect3DResource8_Register :-> PushBuffer...\n");
X_D3DPushBuffer *pPushBuffer = (X_D3DPushBuffer*)pResource;
// create push buffer
{
DWORD dwSize = EmuCheckAllocationSize(pBase, true);
if(dwSize == -1)
{
// TODO: once this is known to be working, remove the warning
EmuWarning("Push buffer allocation size unknown");
pPushBuffer->Lock = X_D3DRESOURCE_LOCK_FLAG_NOSIZE;
break;
}
pResource->Data = (ULONG)pBase;
}
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Successfully Created PushBuffer (0x%.08X, 0x%.08X, 0x%.08X)\n", GetCurrentThreadId(), pResource->Data, pPushBuffer->Size, pPushBuffer->AllocationSize);
}
break;
case X_D3DCOMMON_TYPE_SURFACE:
case X_D3DCOMMON_TYPE_TEXTURE:
{
if(dwCommonType == X_D3DCOMMON_TYPE_SURFACE)
DbgPrintf("EmuIDirect3DResource8_Register :-> Surface...\n");
else
DbgPrintf("EmuIDirect3DResource8_Register :-> Texture...\n");
X_D3DPixelContainer *pPixelContainer = (X_D3DPixelContainer*)pResource;
X_D3DFORMAT X_Format = (X_D3DFORMAT)((pPixelContainer->Format & X_D3DFORMAT_FORMAT_MASK) >> X_D3DFORMAT_FORMAT_SHIFT);
D3DFORMAT Format = EmuXB2PC_D3DFormat(X_Format);
D3DFORMAT CacheFormat = (XTL::D3DFORMAT)0;
// TODO: check for dimensions
// TODO: HACK: Temporary?
if(X_Format == 0x2E)
{
/*CxbxKrnlCleanup*/EmuWarning("D3DFMT_LIN_D24S8 not yet supported!");
X_Format = 0x12;
Format = D3DFMT_A8R8G8B8;
}
if(X_Format == 0x30)
{
/*CxbxKrnlCleanup*/EmuWarning("D3DFMT_LIN_D16 not yet supported!");
X_Format = 0x11;
Format = D3DFMT_R5G6B5;
}
DWORD dwWidth, dwHeight, dwBPP, dwDepth = 1, dwPitch = 0, dwMipMapLevels = 1;
BOOL bSwizzled = FALSE, bCompressed = FALSE, dwCompressedSize = 0;
BOOL bCubemap = pPixelContainer->Format & X_D3DFORMAT_CUBEMAP;
// Interpret Width/Height/BPP
if(X_Format == 0x07 /* X_D3DFMT_X8R8G8B8 */ || X_Format == 0x06 /* X_D3DFMT_A8R8G8B8 */
|| X_Format == 0x3A /* X_D3DFMT_A8B8G8R8 */)
{
bSwizzled = TRUE;
// Swizzled 32 Bit
dwWidth = 1 << ((pPixelContainer->Format & X_D3DFORMAT_USIZE_MASK) >> X_D3DFORMAT_USIZE_SHIFT);
dwHeight = 1 << ((pPixelContainer->Format & X_D3DFORMAT_VSIZE_MASK) >> X_D3DFORMAT_VSIZE_SHIFT);
dwMipMapLevels = (pPixelContainer->Format & X_D3DFORMAT_MIPMAP_MASK) >> X_D3DFORMAT_MIPMAP_SHIFT;
dwDepth = 1;// HACK? 1 << ((pPixelContainer->Format & X_D3DFORMAT_PSIZE_MASK) >> X_D3DFORMAT_PSIZE_SHIFT);
dwPitch = dwWidth*4;
dwBPP = 4;
}
else if(X_Format == 0x05 /* X_D3DFMT_R5G6B5 */ || X_Format == 0x04 /* X_D3DFMT_A4R4G4B4 */
|| X_Format == 0x02 /* X_D3DFMT_A1R5G5B5 */ || X_Format == 0x03 /* X_D3DFMT_X1R5G5B5 */
|| X_Format == 0x28 /* X_D3DFMT_G8B8 */ )
{
bSwizzled = TRUE;
// Swizzled 16 Bit
dwWidth = 1 << ((pPixelContainer->Format & X_D3DFORMAT_USIZE_MASK) >> X_D3DFORMAT_USIZE_SHIFT);
dwHeight = 1 << ((pPixelContainer->Format & X_D3DFORMAT_VSIZE_MASK) >> X_D3DFORMAT_VSIZE_SHIFT);
dwMipMapLevels = (pPixelContainer->Format & X_D3DFORMAT_MIPMAP_MASK) >> X_D3DFORMAT_MIPMAP_SHIFT;
dwDepth = 1;// HACK? 1 << ((pPixelContainer->Format & X_D3DFORMAT_PSIZE_MASK) >> X_D3DFORMAT_PSIZE_SHIFT);
dwPitch = dwWidth*2;
dwBPP = 2;
}
else if(X_Format == 0x00 /* X_D3DFMT_L8 */ || X_Format == 0x0B /* X_D3DFMT_P8 */
|| X_Format == 0x01 /* X_D3DFMT_AL8 */ || X_Format == 0x1A /* X_D3DFMT_A8L8 */
|| X_Format == 0x19 /* X_D3DFMT_A8 */)
{
bSwizzled = TRUE;
// Swizzled 8 Bit
dwWidth = 1 << ((pPixelContainer->Format & X_D3DFORMAT_USIZE_MASK) >> X_D3DFORMAT_USIZE_SHIFT);
dwHeight = 1 << ((pPixelContainer->Format & X_D3DFORMAT_VSIZE_MASK) >> X_D3DFORMAT_VSIZE_SHIFT);
dwMipMapLevels = (pPixelContainer->Format & X_D3DFORMAT_MIPMAP_MASK) >> X_D3DFORMAT_MIPMAP_SHIFT;
dwDepth = 1;// HACK? 1 << ((pPixelContainer->Format & X_D3DFORMAT_PSIZE_MASK) >> X_D3DFORMAT_PSIZE_SHIFT);
dwPitch = dwWidth;
dwBPP = 1;
}
else if(X_Format == 0x1E /* X_D3DFMT_LIN_X8R8G8B8 */ || X_Format == 0x12 /* X_D3DFMT_LIN_A8R8G8B8 */
|| X_Format == 0x2E /* D3DFMT_LIN_D24S8 */ || X_Format == 0x3F /* X_D3DFMT_LIN_A8B8G8R8 */)
{
// Linear 32 Bit
dwWidth = (pPixelContainer->Size & X_D3DSIZE_WIDTH_MASK) + 1;
dwHeight = ((pPixelContainer->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
dwPitch = (((pPixelContainer->Size & X_D3DSIZE_PITCH_MASK) >> X_D3DSIZE_PITCH_SHIFT)+1)*64;
dwBPP = 4;
}
else if(X_Format == 0x11 /* D3DFMT_LIN_R5G6B5 */ || X_Format == 0x30 /* D3DFMT_LIN_D16 */
|| X_Format == 0x1D /* X_D3DFMT_LIN_A4R4G4B4 */ || X_Format == 0x10 /* X_D3DFMT_LIN_A1R5G5B5 */)
{
// Linear 16 Bit
dwWidth = (pPixelContainer->Size & X_D3DSIZE_WIDTH_MASK) + 1;
dwHeight = ((pPixelContainer->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
dwPitch = (((pPixelContainer->Size & X_D3DSIZE_PITCH_MASK) >> X_D3DSIZE_PITCH_SHIFT)+1)*64;
dwBPP = 2;
}
else if(X_Format == 0x0C /* D3DFMT_DXT1 */ || X_Format == 0x0E /* D3DFMT_DXT2 */ || X_Format == 0x0F /* D3DFMT_DXT3 */)
{
bCompressed = TRUE;
// Compressed
dwWidth = 1 << ((pPixelContainer->Format & X_D3DFORMAT_USIZE_MASK) >> X_D3DFORMAT_USIZE_SHIFT);
dwHeight = 1 << ((pPixelContainer->Format & X_D3DFORMAT_VSIZE_MASK) >> X_D3DFORMAT_VSIZE_SHIFT);
dwDepth = 1 << ((pPixelContainer->Format & X_D3DFORMAT_PSIZE_MASK) >> X_D3DFORMAT_PSIZE_SHIFT);
dwMipMapLevels = (pPixelContainer->Format & X_D3DFORMAT_MIPMAP_MASK) >> X_D3DFORMAT_MIPMAP_SHIFT;
// D3DFMT_DXT2...D3DFMT_DXT5 : 128bits per block/per 16 texels
dwCompressedSize = dwWidth*dwHeight;
if(X_Format == 0x0C) // D3DFMT_DXT1 : 64bits per block/per 16 texels
dwCompressedSize /= 2;
dwBPP = 1;
}
else if(X_Format == 0x24 /* D3DFMT_YUY2 */)
{
// Linear 32 Bit
dwWidth = (pPixelContainer->Size & X_D3DSIZE_WIDTH_MASK) + 1;
dwHeight = ((pPixelContainer->Size & X_D3DSIZE_HEIGHT_MASK) >> X_D3DSIZE_HEIGHT_SHIFT) + 1;
dwPitch = (((pPixelContainer->Size & X_D3DSIZE_PITCH_MASK) >> X_D3DSIZE_PITCH_SHIFT)+1)*64;
}
else
{
CxbxKrnlCleanup("0x%.08X is not a supported format!\n", X_Format);
}
if(X_Format == 0x24 /* X_D3DFMT_YUY2 */)
{
//
// cache the overlay size
//
g_dwOverlayW = dwWidth;
g_dwOverlayH = dwHeight;
g_dwOverlayP = RoundUp(g_dwOverlayW, 64)*2;
//
// create texture resource
//
DWORD dwSize = g_dwOverlayP*g_dwOverlayH;
DWORD dwPtr = (DWORD)CxbxMalloc(dwSize + sizeof(DWORD));
DWORD *pRefCount = (DWORD*)(dwPtr + dwSize);
// initialize ref count
*pRefCount = 1;
// If YUY2 is not supported in hardware, we'll actually mark this as a special fake texture (set highest bit)
pPixelContainer->Data = X_D3DRESOURCE_DATA_FLAG_SPECIAL | X_D3DRESOURCE_DATA_FLAG_YUVSURF;
pPixelContainer->Lock = dwPtr;
pPixelContainer->Format = 0x24;
pPixelContainer->Size = (g_dwOverlayW & X_D3DSIZE_WIDTH_MASK);
pPixelContainer->Size |= (g_dwOverlayH << X_D3DSIZE_HEIGHT_SHIFT);
pPixelContainer->Size |= (g_dwOverlayP << X_D3DSIZE_PITCH_SHIFT);
}
else
{
if(bSwizzled || bCompressed)
{
uint32 w = dwWidth;
uint32 h = dwHeight;
for(uint32 v=0;v<dwMipMapLevels;v++)
{
if( ((1u << v) >= w) || ((1u << v) >= h))
{
dwMipMapLevels = v + 1;
break;
}
}
}
// create the happy little texture
if(dwCommonType == X_D3DCOMMON_TYPE_SURFACE)
{
hRet = g_pD3DDevice8->CreateImageSurface(dwWidth, dwHeight, Format, &pResource->EmuSurface8);
if(FAILED(hRet))
CxbxKrnlCleanup("CreateImageSurface Failed!\n\nError: %s\nDesc: %s",
DXGetErrorString8A(hRet), DXGetErrorDescription8A(hRet));
;
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Successfully Created ImageSurface (0x%.08X, 0x%.08X)\n", GetCurrentThreadId(), pResource, pResource->EmuSurface8);
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Width : %d, Height : %d, Format : %d\n", GetCurrentThreadId(), dwWidth, dwHeight, Format);
}
else
{
// TODO: HACK: Figure out why this is necessary!
// TODO: This is necessary for DXT1 textures at least (4x4 blocks minimum)
if(dwWidth < 4)
{
EmuWarning("Expanding texture width (%d->4)", dwWidth);
dwWidth = 4;
dwMipMapLevels = 3;
}
if(dwHeight < 4)
{
EmuWarning("Expanding texture height (%d->4)", dwHeight);
dwHeight = 4;
dwMipMapLevels = 3;
}
// HACK HACK HACK HACK HACK HACK HACK HACK HACK HACK
// Since most modern graphics cards does not support
// palette based textures we need to expand it to
// ARGB texture format
if (Format == D3DFMT_P8) //Palette
{
/*EmuWarning("D3DFMT_P8 -> D3DFMT_A8R8G8B8");
CacheFormat = Format; // Save this for later
Format = D3DFMT_A8R8G8B8; */ // ARGB
// Temporarily use the LoveMhz hack
EmuWarning("D3DFMT_P8 -> D3DFMT_L8");
Format = D3DFMT_L8;
}
if(bCubemap)
{
DbgPrintf("CreateCubeTexture(%d, %d, 0, %d, D3DPOOL_MANAGED, 0x%.08X)\n", dwWidth,
dwMipMapLevels, Format, &pResource->EmuTexture8);
hRet = g_pD3DDevice8->CreateCubeTexture
(
dwWidth, dwMipMapLevels, 0, Format,
D3DPOOL_MANAGED, &pResource->EmuCubeTexture8
);
if(FAILED(hRet))
CxbxKrnlCleanup("CreateCubeTexture Failed!\n\nError: %s\nDesc: %s",
DXGetErrorString8A(hRet), DXGetErrorDescription8A(hRet));
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Successfully Created CubeTexture (0x%.08X, 0x%.08X)\n", GetCurrentThreadId(), pResource, pResource->EmuCubeTexture8);
}
else
{
// printf("CreateTexture(%d, %d, %d, 0, %d (X=0x%.08X), D3DPOOL_MANAGED, 0x%.08X)\n", dwWidth, dwHeight,
// dwMipMapLevels, Format, X_Format, &pResource->EmuTexture8);
// HACK: Quantum Redshift
/*if( dwMipMapLevels == 8 && X_Format == 0x0C )
{
printf( "Dirty Quantum Redshift hack applied!\n" );
dwMipMapLevels = 1;
}*/
hRet = g_pD3DDevice8->CreateTexture
(
dwWidth, dwHeight, dwMipMapLevels, 0, Format,
D3DPOOL_MANAGED, &pResource->EmuTexture8
);
/*if(FAILED(hRet))
{
hRet = g_pD3DDevice8->CreateTexture
(
dwWidth, dwHeight, dwMipMapLevels, 0, Format,
D3DPOOL_SYSTEMMEM, &pResource->EmuTexture8
);
}*/
if(FAILED(hRet))
CxbxKrnlCleanup("CreateTexture Failed!\n\nError: %s\nDesc: %s",
DXGetErrorString8A(hRet), DXGetErrorDescription8A(hRet));
DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Successfully Created Texture (0x%.08X, 0x%.08X)\n", GetCurrentThreadId(), pResource, pResource->EmuTexture8);
}
}
uint32 stop = bCubemap ? 6 : 1;
for(uint32 r=0;r<stop;r++)
{
// as we iterate through mipmap levels, we'll adjust the source resource offset
DWORD dwCompressedOffset = 0;
DWORD dwMipOffs = 0;
DWORD dwMipWidth = dwWidth;
DWORD dwMipHeight = dwHeight;
DWORD dwMipPitch = dwPitch;
// iterate through the number of mipmap levels
for(uint level=0;level<dwMipMapLevels;level++)
{
D3DLOCKED_RECT LockedRect;
// copy over data (deswizzle if necessary)
if(dwCommonType == X_D3DCOMMON_TYPE_SURFACE)
hRet = pResource->EmuSurface8->LockRect(&LockedRect, NULL, 0);
else
{
if(bCubemap)
{
hRet = pResource->EmuCubeTexture8->LockRect((D3DCUBEMAP_FACES)r, 0, &LockedRect, NULL, 0);
}
else
{
hRet = pResource->EmuTexture8->LockRect(level, &LockedRect, NULL, 0);
}
}
RECT iRect = {0,0,0,0};
POINT iPoint = {0,0};
BYTE *pSrc = (BYTE*)pBase;
if( pBase != NULL ) pThis->Data = (DWORD)pSrc;
if(( IsSpecialResource(pResource->Data) && (pResource->Data & X_D3DRESOURCE_DATA_FLAG_SURFACE))
||( IsSpecialResource(pBase) && ((DWORD)pBase & X_D3DRESOURCE_DATA_FLAG_SURFACE)))
{
EmuWarning("Attempt to registered to another resource's data (eww!)");
// TODO: handle this horrible situation
BYTE *pDest = (BYTE*)LockedRect.pBits;
for(DWORD v=0;v<dwMipHeight;v++)
{
memset(pDest, 0, dwMipWidth*dwBPP);
pDest += LockedRect.Pitch;
pSrc += dwMipPitch;
}
}
else
{
if(bSwizzled)
{
if((DWORD)pSrc == 0x80000000)
{
// TODO: Fix or handle this situation..?
}
else
{
if (CacheFormat == D3DFMT_P8) //Palette
{
EmuWarning("Unsupported texture format D3DFMT_P8,\nexpanding to D3DFMT_A8R8G8B8");
//#if 0
//
// create texture resource
//
//__asm int 3;
// Attempt to use correct palette sizes
DWORD dwPaletteAllocSize = (dwCurrentPaletteSize == -1) ? 256*4 : dwCurrentPaletteSize;
BYTE *pPixelData = (BYTE*)LockedRect.pBits;
DWORD dwDataSize = dwMipWidth*dwMipHeight*4;
DWORD dwPaletteSize = dwPaletteAllocSize; //256*4; // Note: This is not allways true, it can be 256- 128- 64- or 32*4
BYTE* pTextureCache = (BYTE*)CxbxMalloc(dwDataSize);
BYTE* pExpandedTexture = (BYTE*)CxbxMalloc(dwDataSize);
BYTE* pTexturePalette = (BYTE*)CxbxMalloc(dwPaletteAllocSize);
//__asm int 3;
// First we need to unswizzle the texture data
XTL::EmuXGUnswizzleRect
(
pSrc + dwMipOffs, dwMipWidth, dwMipHeight, dwDepth, LockedRect.pBits,
LockedRect.Pitch, iRect, iPoint, dwBPP
);
//__asm int 3;
// Copy the unswizzled data to a temporary buffer
memcpy(pTextureCache, pPixelData, dwDataSize);
//__asm int 3;
// Copy the currently selected palette's data to the buffer
memcpy(pTexturePalette, pCurrentPalette, dwPaletteSize);
//__asm int 3;
unsigned int w = 0;
unsigned int c = 0;
unsigned char p = 0;
for (unsigned int y = 0;y < dwDataSize/4;y++)
{
if(c == dwMipWidth)
{
w += dwMipWidth*3;
c = 0;
}
p = (unsigned char)pTextureCache[w];
pExpandedTexture[y*4+0] = pTexturePalette[p*4+0];
pExpandedTexture[y*4+1] = pTexturePalette[p*4+1];
pExpandedTexture[y*4+2] = pTexturePalette[p*4+2];
pExpandedTexture[y*4+3] = pTexturePalette[p*4+3];
w++;
c++;
}
//__asm int 3;
// Copy the expanded texture back to the buffer
memcpy(pPixelData, pExpandedTexture, dwDataSize);
// Flush unused data buffers
CxbxFree(pTexturePalette);
CxbxFree(pExpandedTexture);
CxbxFree(pTextureCache);
//#endif
}
else
{
XTL::EmuXGUnswizzleRect
(
pSrc + dwMipOffs, dwMipWidth, dwMipHeight, dwDepth, LockedRect.pBits,
LockedRect.Pitch, iRect, iPoint, dwBPP
);
}
}
}
else if(bCompressed)
{
// NOTE: compressed size is (dwWidth/2)*(dwHeight/2)/2, so each level divides by 4
memcpy(LockedRect.pBits, pSrc + dwCompressedOffset, dwCompressedSize >> (level*2));
dwCompressedOffset += (dwCompressedSize >> (level*2));
}
else
{
BYTE *pDest = (BYTE*)LockedRect.pBits;
if( pSrc )
{
if((DWORD)LockedRect.Pitch == dwMipPitch && dwMipPitch == dwMipWidth*dwBPP)
{
memcpy(pDest, pSrc + dwMipOffs, dwMipWidth*dwMipHeight*dwBPP);
}
else
{
for(DWORD v=0;v<dwMipHeight;v++)
{
memcpy(pDest, pSrc + dwMipOffs, dwMipWidth*dwBPP);
pDest += LockedRect.Pitch;
pSrc += dwMipPitch;
}
}
}
}
}
if(dwCommonType == X_D3DCOMMON_TYPE_SURFACE)
pResource->EmuSurface8->UnlockRect();
else
{
if(bCubemap)
pResource->EmuCubeTexture8->UnlockRect((D3DCUBEMAP_FACES)r, 0);
else
pResource->EmuTexture8->UnlockRect(level);
}
dwMipOffs += dwMipWidth*dwMipHeight*dwBPP;
dwMipWidth /= 2;
dwMipHeight /= 2;
dwMipPitch /= 2;
}
}
// Debug Texture Dumping
#ifdef _DEBUG_DUMP_TEXTURE_REGISTER
if(dwCommonType == X_D3DCOMMON_TYPE_SURFACE)
{
static int dwDumpSurface = 0;
char szBuffer[255];
sprintf(szBuffer, _DEBUG_DUMP_TEXTURE_REGISTER "%.03d-RegSurface%.03d.dds", X_Format, dwDumpSurface++);
D3DXSaveSurfaceToFile(szBuffer, D3DXIFF_DDS, pResource->EmuSurface8, NULL, NULL);
}
else
{
if(bCubemap)
{
static int dwDumpCube = 0;
char szBuffer[255];
for(int v=0;v<6;v++)
{
IDirect3DSurface8 *pSurface=0;
sprintf(szBuffer, _DEBUG_DUMP_TEXTURE_REGISTER "%.03d-RegCubeTex%.03d-%d.dds", X_Format, dwDumpCube++, v);
pResource->EmuCubeTexture8->GetCubeMapSurface((D3DCUBEMAP_FACES)v, 0, &pSurface);
D3DXSaveSurfaceToFile(szBuffer, D3DXIFF_DDS, pSurface, NULL, NULL);
}
}
else
{
static int dwDumpTex = 0;
char szBuffer[255];
sprintf(szBuffer, _DEBUG_DUMP_TEXTURE_REGISTER "%.03d-RegTexture%.03d.dds", X_Format, dwDumpTex++);
D3DXSaveTextureToFile(szBuffer, D3DXIFF_DDS, pResource->EmuTexture8, NULL);
}
}
#endif
}
}
break;
case X_D3DCOMMON_TYPE_PALETTE:
{
DbgPrintf("EmuIDirect3DResource8_Register :-> Palette...\n");
X_D3DPalette *pPalette = (X_D3DPalette*)pResource;
// create palette
{
DWORD dwSize = EmuCheckAllocationSize(pBase, true);
if(dwSize == -1)
{
// TODO: once this is known to be working, remove the warning
EmuWarning("Palette allocation size unknown");
pPalette->Lock = X_D3DRESOURCE_LOCK_FLAG_NOSIZE;
}
pCurrentPalette = pBase;
dwCurrentPaletteSize = dwSize;
pResource->Data = (ULONG)pBase;
}
//DbgPrintf("EmuIDirect3DResource8_Register (0x%X) : Successfully Created Palette (0x%.08X, 0x%.08X, 0x%.08X)\n", GetCurrentThreadId(), pResource->Data, pResource->Size, pResource->AllocationSize);
}
break;
case X_D3DCOMMON_TYPE_FIXUP:
{
X_D3DFixup *pFixup = (X_D3DFixup*)pResource;
CxbxKrnlCleanup("IDirect3DReosurce8::Register -> X_D3DCOMMON_TYPE_FIXUP is not yet supported\n"
"0x%.08X (pFixup->Common) \n"
"0x%.08X (pFixup->Data) \n"
"0x%.08X (pFixup->Lock) \n"
"0x%.08X (pFixup->Run) \n"
"0x%.08X (pFixup->Next) \n"
"0x%.08X (pFixup->Size) \n", pFixup->Common, pFixup->Data, pFixup->Lock, pFixup->Run, pFixup->Next, pFixup->Size);
}
default:
CxbxKrnlCleanup("IDirect3DResource8::Register -> Common Type 0x%.08X not yet supported", dwCommonType);
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DResource8_AddRef
// ******************************************************************
ULONG WINAPI XTL::EmuIDirect3DResource8_AddRef
(
X_D3DResource *pThis
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DResource8_AddRef\n"
"(\n"
" pThis : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis);
ULONG uRet = 0;
if(IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
DWORD dwPtr = (DWORD)pThis->Lock;
DWORD *pRefCount = (DWORD*)(dwPtr + g_dwOverlayP*g_dwOverlayH);
++(*pRefCount);
}
else
{
IDirect3DResource8 *pResource8 = pThis->EmuResource8;
if(pThis->Lock == 0x8000BEEF)
uRet = ++pThis->Lock;
else if(pResource8 != 0)
uRet = pResource8->AddRef();
if(!pResource8)
__asm int 3;
//EmuWarning("EmuResource is not a valid pointer!");
pThis->Common = (pThis->Common & ~X_D3DCOMMON_REFCOUNT_MASK) | ((pThis->Common & X_D3DCOMMON_REFCOUNT_MASK) + 1);
}
EmuSwapFS(); // XBox FS
return uRet;
}
// ******************************************************************
// * func: EmuIDirect3DResource8_Release
// ******************************************************************
ULONG WINAPI XTL::EmuIDirect3DResource8_Release
(
X_D3DResource *pThis
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DResource8_Release\n"
"(\n"
" pThis : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis);
ULONG uRet = 0;
// HACK: In case the clone technique fails...
if(!pThis)
{
EmuWarning("NULL texture!");
EmuSwapFS(); // Xbox FS
return 0;
}
// HACK: Clone textures generated by D3DDevice::GetTexture2
if(IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_TEXCLON))
{
EmuWarning( "Deleting clone texture (from D3DDevice::GetTexture2)...\n" );
// uRet = pThis->EmuBaseTexture8->Release();
delete pThis;
}
else if(IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
DWORD dwPtr = (DWORD)pThis->Lock;
DWORD *pRefCount = (DWORD*)(dwPtr + g_dwOverlayP*g_dwOverlayH);
if(--(*pRefCount) == 0)
{
if(g_YuvSurface == pThis)
g_YuvSurface = NULL;
// free memory associated with this special resource handle
CxbxFree((PVOID)dwPtr);
}
EmuSwapFS();
EmuIDirect3DDevice8_EnableOverlay(FALSE);
EmuSwapFS();
}
else
{
IDirect3DResource8 *pResource8 = pThis->EmuResource8;
if(pThis->Lock == 0x8000BEEF)
{
delete[] (PVOID)pThis->Data;
uRet = --pThis->Lock;
}
else if(pResource8 != 0)
{
for(int v=0;v<16;v++)
{
if(pCache[v].Data == pThis->Data && pThis->Data != 0)
{
pCache[v].Data = 0;
break;
}
}
#ifdef _DEBUG_TRACE_VB
D3DRESOURCETYPE Type = pResource8->GetType();
#endif
uRet = pResource8->Release();
if(uRet == 0)
{
DbgPrintf("EmuIDirect3DResource8_Release (0x%X): Cleaned up a Resource!\n", GetCurrentThreadId());
#ifdef _DEBUG_TRACE_VB
if(Type == D3DRTYPE_VERTEXBUFFER)
{
g_VBTrackTotal.remove(pResource8);
g_VBTrackDisable.remove(pResource8);
}
#endif
//delete pThis;
}
}
pThis->Common = (pThis->Common & ~X_D3DCOMMON_REFCOUNT_MASK) | ((pThis->Common & X_D3DCOMMON_REFCOUNT_MASK) - 1);
}
EmuSwapFS(); // XBox FS
return uRet;
}
// ******************************************************************
// * func: EmuIDirect3DResource8_IsBusy
// ******************************************************************
BOOL WINAPI XTL::EmuIDirect3DResource8_IsBusy
(
X_D3DResource *pThis
)
{
EmuSwapFS(); // Win2k/XP FS
/* too much output
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DResource8_IsBusy\n"
"(\n"
" pThis : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis);
//*/
IDirect3DResource8 *pResource8 = pThis->EmuResource8;
EmuSwapFS(); // XBox FS
return FALSE;
}
// ******************************************************************
// * func: EmuIDirect3DResource8_GetType
// ******************************************************************
XTL::X_D3DRESOURCETYPE WINAPI XTL::EmuIDirect3DResource8_GetType
(
X_D3DResource *pThis
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DResource8_GetType\n"
"(\n"
" pThis : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis);
D3DRESOURCETYPE rType;
// Check for Xbox specific resources (Azurik may need this)
DWORD dwType = pThis->Common & X_D3DCOMMON_TYPE_MASK;
switch(dwType)
{
case X_D3DCOMMON_TYPE_PUSHBUFFER:
rType = (D3DRESOURCETYPE) 8; break;
case X_D3DCOMMON_TYPE_PALETTE:
rType = (D3DRESOURCETYPE) 9; break;
case X_D3DCOMMON_TYPE_FIXUP:
rType = (D3DRESOURCETYPE) 10; break;
default:
rType = pThis->EmuResource8->GetType(); break;
}
EmuSwapFS(); // XBox FS
return (X_D3DRESOURCETYPE)rType;
}
// ******************************************************************
// * func: EmuLock2DSurface
// ******************************************************************
VOID WINAPI XTL::EmuLock2DSurface
(
X_D3DPixelContainer *pPixelContainer,
D3DCUBEMAP_FACES FaceType,
UINT Level,
D3DLOCKED_RECT *pLockedRect,
RECT *pRect,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuLock2DSurface\n"
"(\n"
" pPixelContainer : 0x%.08X\n"
" FaceType : 0x%.08X\n"
" Level : 0x%.08X\n"
" pLockedRect : 0x%.08X\n"
" pRect : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPixelContainer, FaceType, Level, pLockedRect, pRect, Flags);
EmuVerifyResourceIsRegistered(pPixelContainer);
HRESULT hRet = pPixelContainer->EmuCubeTexture8->LockRect(FaceType, Level, pLockedRect, pRect, Flags);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuLock3DSurface
// ******************************************************************
VOID WINAPI XTL::EmuLock3DSurface
(
X_D3DPixelContainer *pPixelContainer,
UINT Level,
D3DLOCKED_BOX *pLockedVolume,
D3DBOX *pBox,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuLock2DSurface\n"
"(\n"
" pPixelContainer : 0x%.08X\n"
" Level : 0x%.08X\n"
" pLockedVolume : 0x%.08X\n"
" pBox : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPixelContainer, Level, pLockedVolume, pBox, Flags);
EmuVerifyResourceIsRegistered(pPixelContainer);
HRESULT hRet = pPixelContainer->EmuVolumeTexture8->LockBox(Level, pLockedVolume, pBox, Flags);
if(FAILED(hRet))
EmuWarning("Lock3DSurface failed!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuGet2DSurfaceDesc
// ******************************************************************
VOID WINAPI XTL::EmuGet2DSurfaceDesc
(
X_D3DPixelContainer *pPixelContainer,
DWORD dwLevel,
X_D3DSURFACE_DESC *pDesc
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuGet2DSurfaceDesc\n"
"(\n"
" pPixelContainer : 0x%.08X\n"
" dwLevel : 0x%.08X\n"
" pDesc : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPixelContainer, dwLevel, pDesc);
EmuVerifyResourceIsRegistered(pPixelContainer);
D3DSURFACE_DESC SurfaceDesc;
ZeroMemory(&SurfaceDesc, sizeof(SurfaceDesc));
HRESULT hRet;
if(dwLevel == 0xFEFEFEFE)
{
DbgPrintf("EmuSurface8: = 0x%.08X\n", pPixelContainer->EmuSurface8 );
hRet = pPixelContainer->EmuSurface8->GetDesc(&SurfaceDesc);
/*
static int dwDumpSurface = 0;
char szBuffer[255];
sprintf(szBuffer, "C:\\Aaron\\Textures\\Surface%.03d.bmp", dwDumpSurface++);
D3DXSaveSurfaceToFile(szBuffer, D3DXIFF_BMP, pPixelContainer->EmuSurface8, NULL, NULL);
*/
}
else
{
DbgPrintf("EmuTexture8: = 0x%.08X\n", pPixelContainer->EmuTexture8 );
if(pPixelContainer->Data == 0xFFFF0002)
{
hRet = E_FAIL;
}
else
{
hRet = pPixelContainer->EmuTexture8->GetLevelDesc(dwLevel, &SurfaceDesc);
if(FAILED(hRet))
EmuWarning("IDirect3DTexture8::GetSurfaceDesc failed!");
}
/*
static int dwDumpTexture = 0;
char szBuffer[255];
sprintf(szBuffer, "C:\\Aaron\\Textures\\GetDescTexture%.03d.bmp", dwDumpTexture++);
D3DXSaveTextureToFile(szBuffer, D3DXIFF_BMP, pPixelContainer->EmuTexture8, NULL);
*/
}
// rearrange into xbox format (remove D3DPOOL)
if(SUCCEEDED(hRet))
{
// Convert Format (PC->Xbox)
pDesc->Format = EmuPC2XB_D3DFormat(SurfaceDesc.Format);
pDesc->Type = (X_D3DRESOURCETYPE)SurfaceDesc.Type;
if(pDesc->Type > 7)
CxbxKrnlCleanup("EmuGet2DSurfaceDesc: pDesc->Type > 7");
pDesc->Usage = SurfaceDesc.Usage;
pDesc->Size = SurfaceDesc.Size;
// TODO: Convert from Xbox to PC!!
if(SurfaceDesc.MultiSampleType == D3DMULTISAMPLE_NONE)
pDesc->MultiSampleType = (XTL::D3DMULTISAMPLE_TYPE)0x0011;
else
CxbxKrnlCleanup("EmuGet2DSurfaceDesc Unknown Multisample format! (%d)", SurfaceDesc.MultiSampleType);
pDesc->Width = SurfaceDesc.Width;
pDesc->Height = SurfaceDesc.Height;
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuGet2DSurfaceDescD
// ******************************************************************
VOID WINAPI XTL::EmuGet2DSurfaceDescD
(
X_D3DPixelContainer *pPixelContainer,
X_D3DSURFACE_DESC *pDesc
)
{
// debug trace
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuGet2DSurfaceDescD\n"
"(\n"
" pPixelContainer : 0x%.08X\n"
" pDesc : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPixelContainer, pDesc);
EmuSwapFS(); // Xbox FS
}
#endif
EmuGet2DSurfaceDesc(pPixelContainer, 0xFEFEFEFE, pDesc);
return;
}
// ******************************************************************
// * func: EmuIDirect3DSurface8_GetDesc
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DSurface8_GetDesc
(
X_D3DResource *pThis,
X_D3DSURFACE_DESC *pDesc
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DSurface8_GetDesc\n"
"(\n"
" pThis : 0x%.08X\n"
" pDesc : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, pDesc);
HRESULT hRet;
EmuVerifyResourceIsRegistered(pThis);
if(IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
pDesc->Format = EmuPC2XB_D3DFormat(D3DFMT_YUY2);
pDesc->Height = g_dwOverlayH;
pDesc->Width = g_dwOverlayW;
pDesc->MultiSampleType = (D3DMULTISAMPLE_TYPE)0;
pDesc->Size = g_dwOverlayP*g_dwOverlayH;
pDesc->Type = X_D3DRTYPE_SURFACE;
pDesc->Usage = 0;
hRet = D3D_OK;
}
else
{
IDirect3DSurface8 *pSurface8 = pThis->EmuSurface8;
D3DSURFACE_DESC SurfaceDesc;
hRet = pSurface8->GetDesc(&SurfaceDesc);
// rearrange into windows format (remove D3DPool)
{
// Convert Format (PC->Xbox)
pDesc->Format = EmuPC2XB_D3DFormat(SurfaceDesc.Format);
pDesc->Type = (X_D3DRESOURCETYPE)SurfaceDesc.Type;
if(pDesc->Type > 7)
CxbxKrnlCleanup("EmuIDirect3DSurface8_GetDesc: pDesc->Type > 7");
pDesc->Usage = SurfaceDesc.Usage;
pDesc->Size = SurfaceDesc.Size;
// TODO: Convert from Xbox to PC!!
if(SurfaceDesc.MultiSampleType == D3DMULTISAMPLE_NONE)
pDesc->MultiSampleType = (XTL::D3DMULTISAMPLE_TYPE)0x0011;
else
CxbxKrnlCleanup("EmuIDirect3DSurface8_GetDesc Unknown Multisample format! (%d)", SurfaceDesc.MultiSampleType);
pDesc->Width = SurfaceDesc.Width;
pDesc->Height = SurfaceDesc.Height;
}
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DSurface8_LockRect
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DSurface8_LockRect
(
X_D3DResource *pThis,
D3DLOCKED_RECT *pLockedRect,
CONST RECT *pRect,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DSurface8_LockRect\n"
"(\n"
" pThis : 0x%.08X\n"
" pLockedRect : 0x%.08X\n"
" pRect : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, pLockedRect, pRect, Flags);
HRESULT hRet;
// DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DSurface8_LockRect (pThis->Surface = 0x%8.8X)\n", pThis->EmuSurface8 );
if(!pThis->EmuSurface8)
{
EmuWarning("Invalid Surface!" );
__asm int 3;
EmuSwapFS();
return E_FAIL;
}
EmuVerifyResourceIsRegistered(pThis);
if(IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
pLockedRect->Pitch = g_dwOverlayP;
pLockedRect->pBits = (PVOID)pThis->Lock;
hRet = D3D_OK;
}
else
{
if(Flags & 0x40)
EmuWarning("D3DLOCK_TILED ignored!");
IDirect3DSurface8 *pSurface8 = pThis->EmuSurface8;
DWORD NewFlags = 0;
if(Flags & 0x80)
NewFlags |= D3DLOCK_READONLY;
if(Flags & !(0x80 | 0x40))
CxbxKrnlCleanup("EmuIDirect3DSurface8_LockRect: Unknown Flags! (0x%.08X)", Flags);
try
{
// Remove old lock(s)
pSurface8->UnlockRect();
hRet = pSurface8->LockRect(pLockedRect, pRect, NewFlags);
if(FAILED(hRet))
EmuWarning("LockRect Failed!");
}
catch(...)
{
EmuWarning("Invalid Surface!");
}
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DBaseTexture8_GetLevelCount
// ******************************************************************
DWORD WINAPI XTL::EmuIDirect3DBaseTexture8_GetLevelCount
(
X_D3DBaseTexture *pThis
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DBaseTexture8_GetLevelCount\n"
"(\n"
" pThis : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis);
EmuVerifyResourceIsRegistered(pThis);
IDirect3DBaseTexture8 *pBaseTexture8 = pThis->EmuBaseTexture8;
DWORD dwRet = pBaseTexture8->GetLevelCount();
EmuSwapFS(); // XBox FS
return dwRet;
}
// ******************************************************************
// * func: EmuIDirect3DTexture8_GetSurfaceLevel2
// ******************************************************************
XTL::X_D3DResource * WINAPI XTL::EmuIDirect3DTexture8_GetSurfaceLevel2
(
X_D3DTexture *pThis,
UINT Level
)
{
X_D3DSurface *pSurfaceLevel;
// In a special situation, we are actually returning a memory ptr with high bit set
if(IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
DWORD dwSize = g_dwOverlayP*g_dwOverlayH;
DWORD *pRefCount = (DWORD*)((DWORD)pThis->Lock + dwSize);
// initialize ref count
(*pRefCount)++;
return pThis;
}
EmuIDirect3DTexture8_GetSurfaceLevel(pThis, Level, &pSurfaceLevel);
return pSurfaceLevel;
}
// ******************************************************************
// * func: EmuIDirect3DTexture8_LockRect
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DTexture8_LockRect
(
X_D3DTexture *pThis,
UINT Level,
D3DLOCKED_RECT *pLockedRect,
CONST RECT *pRect,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DTexture8_LockRect\n"
"(\n"
" pThis : 0x%.08X\n"
" Level : 0x%.08X\n"
" pLockedRect : 0x%.08X\n"
" pRect : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, Level, pLockedRect, pRect, Flags);
HRESULT hRet;
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DTexture8_LockRect (pThis->Texture = 0x%8.8X)\n", pThis->EmuTexture8);
EmuVerifyResourceIsRegistered(pThis);
// check if we have an unregistered YUV2 resource
if( (pThis != 0) && IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
pLockedRect->Pitch = g_dwOverlayP;
pLockedRect->pBits = (PVOID)pThis->Lock;
hRet = D3D_OK;
}
else
{
IDirect3DTexture8 *pTexture8 = pThis->EmuTexture8;
DWORD NewFlags = 0;
if(Flags & 0x80)
NewFlags |= D3DLOCK_READONLY;
if(Flags & !(0x80 | 0x40))
CxbxKrnlCleanup("EmuIDirect3DTexture8_LockRect: Unknown Flags! (0x%.08X)", Flags);
// Remove old lock(s)
if(Level == 6 || Level == 7 || Level == 8 || Level == 9)
{
// HACK: Unreal Championship crashes when the texture level reaches 9...
EmuWarning("Unreal Championship texture hack applied!");
hRet = D3DERR_INVALIDCALL;
}
else
{
pTexture8->UnlockRect(Level);
hRet = pTexture8->LockRect(Level, pLockedRect, pRect, NewFlags);
pThis->Common |= X_D3DCOMMON_ISLOCKED;
}
}
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DTexture8_GetSurfaceLevel
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DTexture8_GetSurfaceLevel
(
X_D3DTexture *pThis,
UINT Level,
X_D3DSurface **ppSurfaceLevel
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DTexture8_GetSurfaceLevel\n"
"(\n"
" pThis : 0x%.08X\n"
" Level : 0x%.08X\n"
" ppSurfaceLevel : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, Level, ppSurfaceLevel);
HRESULT hRet;
EmuVerifyResourceIsRegistered(pThis);
// if(pThis)
// {
// if highest bit is set, this is actually a raw memory pointer (for YUY2 simulation)
if(IsSpecialResource(pThis->Data) && (pThis->Data & X_D3DRESOURCE_DATA_FLAG_YUVSURF))
{
DWORD dwSize = g_dwOverlayP*g_dwOverlayH;
DWORD *pRefCount = (DWORD*)((DWORD)pThis->Lock + dwSize);
// initialize ref count
(*pRefCount)++;
*ppSurfaceLevel = (X_D3DSurface*)pThis;
hRet = D3D_OK;
}
else
{
IDirect3DTexture8 *pTexture8 = pThis->EmuTexture8;
*ppSurfaceLevel = new X_D3DSurface();
(*ppSurfaceLevel)->Data = 0xB00BBABE;
(*ppSurfaceLevel)->Common = 0;
(*ppSurfaceLevel)->Format = 0;
(*ppSurfaceLevel)->Size = 0;
hRet = pTexture8->GetSurfaceLevel(Level, &((*ppSurfaceLevel)->EmuSurface8));
if(FAILED(hRet))
{
EmuWarning("EmuIDirect3DTexture8_GetSurfaceLevel Failed!\n");
}
else
{
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DTexture8_GetSurfaceLevel := 0x%.08X\n", GetCurrentThreadId(), (*ppSurfaceLevel)->EmuSurface8);
}
}
// }
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DVolumeTexture8_LockBox
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DVolumeTexture8_LockBox
(
X_D3DVolumeTexture *pThis,
UINT Level,
D3DLOCKED_BOX *pLockedVolume,
CONST D3DBOX *pBox,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DVolumeTexture8_LockBox\n"
"(\n"
" pThis : 0x%.08X\n"
" Level : 0x%.08X\n"
" pLockedVolume : 0x%.08X\n"
" pBox : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, Level, pLockedVolume, pBox, Flags);
EmuVerifyResourceIsRegistered(pThis);
IDirect3DVolumeTexture8 *pVolumeTexture8 = pThis->EmuVolumeTexture8;
HRESULT hRet = pVolumeTexture8->LockBox(Level, pLockedVolume, pBox, Flags);
if(FAILED(hRet))
EmuWarning("LockBox Failed!");
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DCubeTexture8_LockRect
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DCubeTexture8_LockRect
(
X_D3DCubeTexture *pThis,
D3DCUBEMAP_FACES FaceType,
UINT Level,
D3DLOCKED_RECT *pLockedBox,
CONST RECT *pRect,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DCubeTexture8_LockRect\n"
"(\n"
" pThis : 0x%.08X\n"
" FaceType : 0x%.08X\n"
" Level : 0x%.08X\n"
" pLockedBox : 0x%.08X\n"
" pRect : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, FaceType, Level, pLockedBox, pRect, Flags);
EmuVerifyResourceIsRegistered(pThis);
IDirect3DCubeTexture8 *pCubeTexture8 = pThis->EmuCubeTexture8;
HRESULT hRet = pCubeTexture8->LockRect(FaceType, Level, pLockedBox, pRect, Flags);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_Release
// ******************************************************************
ULONG WINAPI XTL::EmuIDirect3DDevice8_Release()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_Release();\n", GetCurrentThreadId());
g_pD3DDevice8->AddRef();
DWORD RefCount = g_pD3DDevice8->Release();
if (RefCount == 1)
{
// Signal proxy thread, and wait for completion
g_EmuCDPD.bReady = true;
g_EmuCDPD.bCreate = false;
while(g_EmuCDPD.bReady)
Sleep(10);
RefCount = g_EmuCDPD.hRet;
}
else
{
RefCount = g_pD3DDevice8->Release();
}
EmuSwapFS(); // XBox FS
return RefCount;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateVertexBuffer
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateVertexBuffer
(
UINT Length,
DWORD Usage,
DWORD FVF,
D3DPOOL Pool,
X_D3DVertexBuffer **ppVertexBuffer
)
{
*ppVertexBuffer = EmuIDirect3DDevice8_CreateVertexBuffer2(Length);
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreateVertexBuffer2
// ******************************************************************
XTL::X_D3DVertexBuffer* WINAPI XTL::EmuIDirect3DDevice8_CreateVertexBuffer2
(
UINT Length
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateVertexBuffer2\n"
"(\n"
" Length : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Length);
X_D3DVertexBuffer *pD3DVertexBuffer = new X_D3DVertexBuffer();
HRESULT hRet = g_pD3DDevice8->CreateVertexBuffer
(
Length,
0,
0,
D3DPOOL_MANAGED,
&pD3DVertexBuffer->EmuVertexBuffer8
);
if(FAILED(hRet))
CxbxKrnlCleanup("CreateVertexBuffer Failed!");
#ifdef _DEBUG_TRACK_VB
g_VBTrackTotal.insert(pD3DVertexBuffer->EmuVertexBuffer8);
#endif
EmuSwapFS(); // XBox FS
return pD3DVertexBuffer;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_EnableOverlay
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_EnableOverlay
(
BOOL Enable
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_EnableOverlay\n"
"(\n"
" Enable : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Enable);
if(Enable == FALSE && (g_pDDSOverlay7 != NULL))
{
g_pDDSOverlay7->UpdateOverlay(NULL, g_pDDSPrimary, NULL, DDOVER_HIDE, 0);
// cleanup overlay clipper
if(g_pDDClipper != 0)
{
g_pDDClipper->Release();
g_pDDClipper = 0;
}
// cleanup overlay surface
if(g_pDDSOverlay7 != 0)
{
g_pDDSOverlay7->Release();
g_pDDSOverlay7 = 0;
}
}
else if(Enable == TRUE && (g_pDDSOverlay7 == 0))
{
// initialize overlay surface
if(g_bSupportsYUY2)
{
XTL::DDSURFACEDESC2 ddsd2;
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
ddsd2.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT;
ddsd2.ddsCaps.dwCaps = DDSCAPS_OVERLAY;
ddsd2.dwWidth = g_dwOverlayW;
ddsd2.dwHeight = g_dwOverlayH;
ddsd2.ddpfPixelFormat.dwSize = sizeof(XTL::DDPIXELFORMAT);
ddsd2.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
ddsd2.ddpfPixelFormat.dwFourCC = MAKEFOURCC('Y','U','Y','2');
HRESULT hRet = g_pDD7->CreateSurface(&ddsd2, &g_pDDSOverlay7, NULL);
if(FAILED(hRet))
CxbxKrnlCleanup("Could not create overlay surface");
hRet = g_pDD7->CreateClipper(0, &g_pDDClipper, NULL);
if(FAILED(hRet))
CxbxKrnlCleanup("Could not create overlay clipper");
hRet = g_pDDClipper->SetHWnd(0, g_hEmuWindow);
}
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_UpdateOverlay
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_UpdateOverlay
(
X_D3DSurface *pSurface,
CONST RECT *SrcRect,
CONST RECT *DstRect,
BOOL EnableColorKey,
D3DCOLOR ColorKey
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_UpdateOverlay\n"
"(\n"
" pSurface : 0x%.08X\n"
" SrcRect : 0x%.08X\n"
" DstRect : 0x%.08X\n"
" EnableColorKey : 0x%.08X\n"
" ColorKey : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pSurface, SrcRect, DstRect, EnableColorKey, ColorKey);
#ifndef UnrealChampionshipHack
if(pSurface)
{
// manually copy data over to overlay
if(g_bSupportsYUY2)
{
DDSURFACEDESC2 ddsd2;
ZeroMemory(&ddsd2, sizeof(ddsd2));
ddsd2.dwSize = sizeof(ddsd2);
if(FAILED(g_pDDSOverlay7->Lock(NULL, &ddsd2, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT, NULL)))
EmuWarning("Unable to lock overlay surface!");
// copy data
{
char *pDest = (char*)ddsd2.lpSurface;
char *pSour = (char*)pSurface->Lock;
int w = g_dwOverlayW;
int h = g_dwOverlayH;
// TODO: sucker the game into rendering directly to the overlay (speed boost)
if( (ddsd2.lPitch == w*2) && ((int)g_dwOverlayP == w*2) )
memcpy(pDest, pSour, h*w*2);
else
{
for(int y=0;y<h;y++)
{
memcpy(pDest, pSour, w*2);
pDest += ddsd2.lPitch;
pSour += g_dwOverlayP;
}
}
}
g_pDDSOverlay7->Unlock(NULL);
}
// update overlay!
if(g_bSupportsYUY2)
{
RECT SourRect = {0, 0, g_dwOverlayW, g_dwOverlayH}, DestRect;
MONITORINFO MonitorInfo = {0};
int nTitleHeight = 0;//GetSystemMetrics(SM_CYCAPTION);
int nBorderWidth = 0;//GetSystemMetrics(SM_CXSIZEFRAME);
int nBorderHeight = 0;//GetSystemMetrics(SM_CYSIZEFRAME);
MonitorInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(g_hMonitor, &MonitorInfo);
GetWindowRect(g_hEmuWindow, &DestRect);
DestRect.left += nBorderWidth;
DestRect.right -= nBorderWidth;
DestRect.top += nTitleHeight + nBorderHeight;
DestRect.bottom -= nBorderHeight;
DestRect.left -= MonitorInfo.rcMonitor.left;
DestRect.right -= MonitorInfo.rcMonitor.left;
DestRect.top -= MonitorInfo.rcMonitor.top;
DestRect.bottom -= MonitorInfo.rcMonitor.top;
DDOVERLAYFX ddofx;
ZeroMemory(&ddofx, sizeof(ddofx));
ddofx.dwSize = sizeof(DDOVERLAYFX);
ddofx.dckDestColorkey.dwColorSpaceLowValue = 0;
ddofx.dckDestColorkey.dwColorSpaceHighValue = 0;
HRESULT hRet = g_pDDSOverlay7->UpdateOverlay(&SourRect, g_pDDSPrimary, &DestRect, /*DDOVER_KEYDESTOVERRIDE | */DDOVER_SHOW, /*&ddofx*/0);
}
else
{
// TODO: dont assume X8R8G8B8 ?
D3DLOCKED_RECT LockedRectDest;
IDirect3DSurface8 *pBackBuffer=0;
HRESULT hRet = g_pD3DDevice8->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer);
// if we obtained the backbuffer, manually translate the YUY2 into the backbuffer format
if(hRet == D3D_OK && pBackBuffer->LockRect(&LockedRectDest, NULL, NULL) == D3D_OK)
{
uint08 *pCurByte = (uint08*)pSurface->Lock;
uint08 *pDest = (uint08*)LockedRectDest.pBits;
uint32 dx=0, dy=0;
uint32 dwImageSize = g_dwOverlayP*g_dwOverlayH;
// grayscale
if(false)
{
for(uint32 y=0;y<g_dwOverlayH;y++)
{
uint32 stop = g_dwOverlayW*4;
for(uint32 x=0;x<stop;x+=4)
{
uint08 Y = *pCurByte;
pDest[x+0] = Y;
pDest[x+1] = Y;
pDest[x+2] = Y;
pDest[x+3] = 0xFF;
pCurByte+=2;
}
pDest += LockedRectDest.Pitch;
}
}
// full color conversion (YUY2->XRGB)
else
{
for(uint32 v=0;v<dwImageSize;v+=4)
{
float Y[2], U, V;
Y[0] = *pCurByte++;
U = *pCurByte++;
Y[1] = *pCurByte++;
V = *pCurByte++;
int a=0;
for(int x=0;x<2;x++)
{
float R = Y[a] + 1.402f*(V-128);
float G = Y[a] - 0.344f*(U-128) - 0.714f*(V-128);
float B = Y[a] + 1.772f*(U-128);
R = (R < 0) ? 0 : ((R > 255) ? 255 : R);
G = (G < 0) ? 0 : ((G > 255) ? 255 : G);
B = (B < 0) ? 0 : ((B > 255) ? 255 : B);
uint32 i = (dy*LockedRectDest.Pitch+(dx+x)*4);
pDest[i+0] = (uint08)B;
pDest[i+1] = (uint08)G;
pDest[i+2] = (uint08)R;
pDest[i+3] = 0xFF;
a++;
}
dx+=2;
if((dx % g_dwOverlayW) == 0)
{
dy++;
dx=0;
}
}
}
pBackBuffer->UnlockRect();
}
// Update overlay if present was not called since the last call to
// EmuIDirect3DDevice8_UpdateOverlay.
if(g_bHackUpdateSoftwareOverlay)
g_pD3DDevice8->Present(0, 0, 0, 0);
g_bHackUpdateSoftwareOverlay = TRUE;
}
}
else
{
EmuWarning("pSurface == NULL!");
}
#endif
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetOverlayUpdateStatus
// ******************************************************************
BOOL WINAPI XTL::EmuIDirect3DDevice8_GetOverlayUpdateStatus()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetOverlayUpdateStatus();\n",
GetCurrentThreadId());
EmuSwapFS(); // XBox FS
// TODO: Actually check for update status
return FALSE;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_BlockUntilVerticalBlank
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_BlockUntilVerticalBlank()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BlockUntilVerticalBlank();\n",
GetCurrentThreadId());
// segaGT tends to freeze with this on
// if(g_XBVideo.GetVSync())
// g_pDD7->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, 0);
// HACK: For many games (when used in mutithreaded code), using
// DDraw::WaitForVerticalBlank will wreak havoc on CPU usage and really
// slow things down. This is the case for various SEGA and other Japanese
// titles. On Xbox, it isn't a big deal, but for PC, I can't even
// guarantee this is a good idea. So instead, I'll be "faking"
// the vertical blank thing.
Sleep( 1000/60 );
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVerticalBlankCallback
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetVerticalBlankCallback
(
D3DVBLANKCALLBACK pCallback
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVerticalBlankCallback\n"
"(\n"
" pCallback : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pCallback);
g_pVBCallback = pCallback;
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTextureState_TexCoordIndex
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetTextureState_TexCoordIndex
(
DWORD Stage,
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTextureState_TexCoordIndex\n"
"(\n"
" Stage : 0x%.08X\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Stage, Value);
// TODO: Xbox Direct3D supports sphere mapping OpenGL style.
// BUG FIX: The lower 16 bits were causing false Unknown TexCoordIndex errors.
// Check for 0x00040000 instead.
if(Value >= 0x00040000)
CxbxKrnlCleanup("EmuIDirect3DDevice8_SetTextureState_TexCoordIndex: Unknown TexCoordIndex Value (0x%.08X)", Value);
g_pD3DDevice8->SetTextureStageState(Stage, D3DTSS_TEXCOORDINDEX, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTextureState_TwoSidedLighting
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetTextureState_TwoSidedLighting
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTextureState_TwoSidedLighting\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("TwoSidedLighting is not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_BackFillMode
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_BackFillMode
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_BackFillMode\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("BackFillMode is not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTextureState_BorderColor
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetTextureState_BorderColor
(
DWORD Stage,
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTextureState_BorderColor\n"
"(\n"
" Stage : 0x%.08X\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Stage, Value);
g_pD3DDevice8->SetTextureStageState(Stage, D3DTSS_BORDERCOLOR, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTextureState_ColorKeyColor
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetTextureState_ColorKeyColor
(
DWORD Stage,
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTextureState_ColorKeyColor\n"
"(\n"
" Stage : 0x%.08X\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Stage, Value);
EmuWarning("SetTextureState_ColorKeyColor is not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTextureState_BumpEnv
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetTextureState_BumpEnv
(
DWORD Stage,
X_D3DTEXTURESTAGESTATETYPE Type,
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTextureState_BumpEnv\n"
"(\n"
" Stage : 0x%.08X\n"
" Type : 0x%.08X\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Stage, Type, Value);
switch(Type)
{
case 22: // X_D3DTSS_BUMPENVMAT00
g_pD3DDevice8->SetTextureStageState(Stage, D3DTSS_BUMPENVMAT00, Value);
break;
case 23: // X_D3DTSS_BUMPENVMAT01
g_pD3DDevice8->SetTextureStageState(Stage, D3DTSS_BUMPENVMAT01, Value);
break;
case 24: // X_D3DTSS_BUMPENVMAT11
g_pD3DDevice8->SetTextureStageState(Stage, D3DTSS_BUMPENVMAT11, Value);
break;
case 25: // X_D3DTSS_BUMPENVMAT10
g_pD3DDevice8->SetTextureStageState(Stage, D3DTSS_BUMPENVMAT10, Value);
break;
case 26: // X_D3DTSS_BUMPENVLSCALE
g_pD3DDevice8->SetTextureStageState(Stage, D3DTSS_BUMPENVLSCALE, Value);
break;
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_FrontFace
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_FrontFace
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_FrontFace\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_FrontFace not supported!\n");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_LogicOp
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_LogicOp
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_LogicOp\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_LogicOp is not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_NormalizeNormals
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_NormalizeNormals
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_NormalizeNormals\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_NORMALIZENORMALS, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_TextureFactor
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_TextureFactor
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_TextureFactor\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_TEXTUREFACTOR, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_ZBias
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_ZBias
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_ZBias\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_ZBIAS, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_EdgeAntiAlias
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_EdgeAntiAlias
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_EdgeAntiAlias\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
// TODO: Analyze performance and compatibility (undefined behavior on PC with triangles or points)
// g_pD3DDevice8->SetRenderState(D3DRS_EDGEANTIALIAS, Value);
// EmuWarning("SetRenderState_EdgeAntiAlias not implemented!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_FillMode
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_FillMode
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_FillMode\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
DWORD dwFillMode;
if(g_iWireframe == 0)
dwFillMode = EmuXB2PC_D3DFILLMODE(Value);
else if(g_iWireframe == 1)
dwFillMode = D3DFILL_WIREFRAME;
else
dwFillMode = D3DFILL_POINT;
g_pD3DDevice8->SetRenderState(D3DRS_FILLMODE, dwFillMode);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_FogColor
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_FogColor
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_FogColor\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_FOGCOLOR, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_Dxt1NoiseEnable
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_Dxt1NoiseEnable
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_Dxt1NoiseEnable\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_Dxt1NoiseEnable not implemented!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_Simple
// ******************************************************************
VOID __fastcall XTL::EmuIDirect3DDevice8_SetRenderState_Simple
(
DWORD Method,
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_Simple\n"
"(\n"
" Method : 0x%.08X\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Method, Value);
int State = -1;
// Todo: make this faster and more elegant
for(int v=0;v<174;v++)
{
if(EmuD3DRenderStateSimpleEncoded[v] == Method)
{
State = v;
break;
}
}
if(State == -1)
EmuWarning("RenderState_Simple(0x%.08X, 0x%.08X) is unsupported!", Method, Value);
else
{
switch(State)
{
case D3DRS_COLORWRITEENABLE:
{
DWORD OrigValue = Value;
Value = 0;
if(OrigValue & (1L<<16))
Value |= D3DCOLORWRITEENABLE_RED;
if(OrigValue & (1L<<8))
Value |= D3DCOLORWRITEENABLE_GREEN;
if(OrigValue & (1L<<0))
Value |= D3DCOLORWRITEENABLE_BLUE;
if(OrigValue & (1L<<24))
Value |= D3DCOLORWRITEENABLE_ALPHA;
DbgPrintf("D3DRS_COLORWRITEENABLE := 0x%.08X\n", Value);
}
break;
case D3DRS_SHADEMODE:
Value = EmuXB2PC_D3DSHADEMODE(Value);
DbgPrintf("D3DRS_SHADEMODE := 0x%.08X\n", Value);
break;
case D3DRS_BLENDOP:
Value = EmuXB2PC_D3DBLENDOP(Value);
DbgPrintf("D3DRS_BLENDOP := 0x%.08X\n", Value);
break;
case D3DRS_SRCBLEND:
Value = EmuXB2PC_D3DBLEND(Value);
DbgPrintf("D3DRS_SRCBLEND := 0x%.08X\n", Value);
break;
case D3DRS_DESTBLEND:
Value = EmuXB2PC_D3DBLEND(Value);
DbgPrintf("D3DRS_DESTBLEND := 0x%.08X\n", Value);
break;
case D3DRS_ZFUNC:
Value = EmuXB2PC_D3DCMPFUNC(Value);
DbgPrintf("D3DRS_ZFUNC := 0x%.08X\n", Value);
break;
case D3DRS_ALPHAFUNC:
Value = EmuXB2PC_D3DCMPFUNC(Value);
DbgPrintf("D3DRS_ALPHAFUNC := 0x%.08X\n", Value);
break;
case D3DRS_ALPHATESTENABLE:
DbgPrintf("D3DRS_ALPHATESTENABLE := 0x%.08X\n", Value);
break;
case D3DRS_ALPHABLENDENABLE:
DbgPrintf("D3DRS_ALPHABLENDENABLE := 0x%.08X\n", Value);
break;
case D3DRS_ALPHAREF:
DbgPrintf("D3DRS_ALPHAREF := %lf\n", DWtoF(Value));
break;
case D3DRS_ZWRITEENABLE:
DbgPrintf("D3DRS_ZWRITEENABLE := 0x%.08X\n", Value);
break;
case D3DRS_DITHERENABLE:
DbgPrintf("D3DRS_DITHERENABLE := 0x%.08X\n", Value);
break;
case D3DRS_STENCILZFAIL:
Value = EmuXB2PC_D3DSTENCILOP(Value);
DbgPrintf("D3DRS_STENCILZFAIL := 0x%.08X\n", Value);
break;
case D3DRS_STENCILPASS:
Value = EmuXB2PC_D3DSTENCILOP(Value);
DbgPrintf("D3DRS_STENCILPASS := 0x%.08X\n", Value);
break;
case D3DRS_STENCILFUNC:
Value = EmuXB2PC_D3DCMPFUNC(Value);
DbgPrintf("D3DRS_STENCILFUNC := 0x%.08X\n", Value);
break;
case D3DRS_STENCILREF:
DbgPrintf("D3DRS_STENCILREF := 0x%.08X\n", Value);
break;
case D3DRS_STENCILMASK:
DbgPrintf("D3DRS_STENCILMASK := 0x%.08X\n", Value);
break;
case D3DRS_STENCILWRITEMASK:
DbgPrintf("D3DRS_STENCILWRITEMASK := 0x%.08X\n", Value);
break;
default:
CxbxKrnlCleanup("Unsupported RenderState (0x%.08X)", State);
break;
};
// TODO: verify these params as you add support for them!
g_pD3DDevice8->SetRenderState((D3DRENDERSTATETYPE)State, Value);
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_VertexBlend
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_VertexBlend
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_VertexBlend\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
// convert from Xbox direct3d to PC direct3d enumeration
if(Value <= 1)
Value = Value;
else if(Value == 3)
Value = 2;
else if(Value == 5)
Value = 3;
else
CxbxKrnlCleanup("Unsupported D3DVERTEXBLENDFLAGS (%d)", Value);
g_pD3DDevice8->SetRenderState(D3DRS_VERTEXBLEND, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_PSTextureModes
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_PSTextureModes
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_PSTextureModes\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
// TODO: do something..
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_CullMode
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_CullMode
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_CullMode\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
// convert from Xbox D3D to PC D3D enumeration
// TODO: XDK-Specific Tables? So far they are the same
switch(Value)
{
case 0:
Value = D3DCULL_NONE;
break;
case 0x900:
Value = D3DCULL_CW;
break;
case 0x901:
Value = D3DCULL_CCW;
break;
default:
CxbxKrnlCleanup("EmuIDirect3DDevice8_SetRenderState_CullMode: Unknown Cullmode (%d)", Value);
}
g_pD3DDevice8->SetRenderState(D3DRS_CULLMODE, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_LineWidth
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_LineWidth
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_LineWidth\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
// TODO: Convert to PC format??
// g_pD3DDevice8->SetRenderState(D3DRS_LINEPATTERN, Value);
EmuWarning("SetRenderState_LineWidth is not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_StencilFail
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_StencilFail
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_StencilFail\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_STENCILFAIL, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_OcclusionCullEnable
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_OcclusionCullEnable
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_OcclusionCullEnable\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_OcclusionCullEnable not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_StencilCullEnable
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_StencilCullEnable
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_StencilCullEnable\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_StencilCullEnable not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_RopZCmpAlwaysRead
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_RopZCmpAlwaysRead
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_RopZCmpAlwaysRead\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_RopZCmpAlwaysRead not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_RopZRead
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_RopZRead
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_RopZRead\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_RopZRead not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_DoNotCullUncompressed
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_DoNotCullUncompressed
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_DoNotCullUncompressed\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_DoNotCullUncompressed not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_ZEnable
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_ZEnable
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_ZEnable\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_ZENABLE, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_StencilEnable
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_StencilEnable
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_StencilEnable\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_STENCILENABLE, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_MultiSampleAntiAlias
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_MultiSampleAntiAlias
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_MultiSampleAntiAlias\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_MultiSampleMask
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_MultiSampleMask
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_MultiSampleMask\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
g_pD3DDevice8->SetRenderState(D3DRS_MULTISAMPLEMASK, Value);
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_MultiSampleMode
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_MultiSampleMode
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_MultiSampleMode\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_MultiSampleMode is not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_MultiSampleRenderTargetMode
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_MultiSampleRenderTargetMode
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_MultiSampleRenderTargetMode\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
EmuWarning("SetRenderState_MultiSampleRenderTargetMode is not supported!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_ShadowFunc
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_ShadowFunc
(
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_ShadowFunc\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
// this warning just gets annoying
// EmuWarning("ShadowFunc not implemented");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_YuvEnable
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_YuvEnable
(
BOOL Enable
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_YuvEnable\n"
"(\n"
" Enable : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Enable);
// HACK: Display YUV surface by using an overlay.
if(Enable != g_fYuvEnabled)
{
g_fYuvEnabled = Enable;
EmuWarning("EmuIDirect3DDevice8_SetRenderState_YuvEnable using overlay!");
EmuSwapFS();
EmuIDirect3DDevice8_EnableOverlay(g_fYuvEnabled);
EmuSwapFS();
}
if(g_fYuvEnabled)
{
EmuSwapFS();
EmuIDirect3DDevice8_UpdateOverlay(g_YuvSurface, 0, 0, FALSE, 0);
EmuSwapFS();
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetTransform
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetTransform
(
D3DTRANSFORMSTATETYPE State,
CONST D3DMATRIX *pMatrix
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetTransform\n"
"(\n"
" State : 0x%.08X\n"
" pMatrix : 0x%.08X\n"
");\n",
GetCurrentThreadId(), State, pMatrix);
/*
printf("pMatrix (%d)\n", State);
printf("{\n");
printf(" %.08f,%.08f,%.08f,%.08f\n", pMatrix->_11, pMatrix->_12, pMatrix->_13, pMatrix->_14);
printf(" %.08f,%.08f,%.08f,%.08f\n", pMatrix->_21, pMatrix->_22, pMatrix->_23, pMatrix->_24);
printf(" %.08f,%.08f,%.08f,%.08f\n", pMatrix->_31, pMatrix->_32, pMatrix->_33, pMatrix->_34);
printf(" %.08f,%.08f,%.08f,%.08f\n", pMatrix->_41, pMatrix->_42, pMatrix->_43, pMatrix->_44);
printf("}\n");
if(State == 6 && (pMatrix->_11 == 1.0f) && (pMatrix->_22 == 1.0f) && (pMatrix->_33 == 1.0f) && (pMatrix->_44 == 1.0f))
{
g_bSkipPush = TRUE;
printf("SkipPush ON\n");
}
else
{
g_bSkipPush = FALSE;
printf("SkipPush OFF\n");
}
*/
State = EmuXB2PC_D3DTS(State);
HRESULT hRet = g_pD3DDevice8->SetTransform(State, pMatrix);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetTransform
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetTransform
(
D3DTRANSFORMSTATETYPE State,
D3DMATRIX *pMatrix
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetTransform\n"
"(\n"
" State : 0x%.08X\n"
" pMatrix : 0x%.08X\n"
");\n",
GetCurrentThreadId(), State, pMatrix);
State = EmuXB2PC_D3DTS(State);
HRESULT hRet = g_pD3DDevice8->GetTransform(State, pMatrix);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DVertexBuffer8_Lock
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DVertexBuffer8_Lock
(
X_D3DVertexBuffer *ppVertexBuffer,
UINT OffsetToLock,
UINT SizeToLock,
BYTE **ppbData,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DVertexBuffer8_Lock\n"
"(\n"
" ppVertexBuffer : 0x%.08X\n"
" OffsetToLock : 0x%.08X\n"
" SizeToLock : 0x%.08X\n"
" ppbData : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), ppVertexBuffer, OffsetToLock, SizeToLock, ppbData, Flags);
IDirect3DVertexBuffer8 *pVertexBuffer8 = ppVertexBuffer->EmuVertexBuffer8;
HRESULT hRet = pVertexBuffer8->Lock(OffsetToLock, SizeToLock, ppbData, Flags);
if(FAILED(hRet))
EmuWarning("VertexBuffer Lock Failed!");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DVertexBuffer8_Lock2
// ******************************************************************
BYTE* WINAPI XTL::EmuIDirect3DVertexBuffer8_Lock2
(
X_D3DVertexBuffer *ppVertexBuffer,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DVertexBuffer8_Lock2\n"
"(\n"
" ppVertexBuffer : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), ppVertexBuffer, Flags);
IDirect3DVertexBuffer8 *pVertexBuffer8 = ppVertexBuffer->EmuVertexBuffer8;
BYTE *pbData = NULL;
HRESULT hRet = pVertexBuffer8->Lock(0, 0, &pbData, EmuXB2PC_D3DLock(Flags)); // Fixed flags check, Battlestar Galactica now displays graphics correctly
EmuSwapFS(); // XBox FS
return pbData;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetStreamSource2
// ******************************************************************
XTL::X_D3DVertexBuffer* WINAPI XTL::EmuIDirect3DDevice8_GetStreamSource2
(
UINT StreamNumber,
UINT *pStride
)
{
EmuSwapFS();
// debug trace
DbgPrintf( "EmuD3D8 (0x%.08X): EmuIDirect3DDevice8_GetStreamSource2\n"
"(\n"
" StreamNumber : 0x%.08X\n"
" pStride : 0x%.08X\n"
");\n",
GetCurrentThreadId(), StreamNumber, pStride);
EmuWarning("Not correctly implemented yet!");
X_D3DVertexBuffer* pVertexBuffer;
g_pD3DDevice8->GetStreamSource(StreamNumber, (struct XTL::IDirect3DVertexBuffer8 **)&pVertexBuffer, pStride);
EmuSwapFS();
return pVertexBuffer;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetStreamSource
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetStreamSource
(
UINT StreamNumber,
X_D3DVertexBuffer *pStreamData,
UINT Stride
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetStreamSource\n"
"(\n"
" StreamNumber : 0x%.08X\n"
" pStreamData : 0x%.08X (0x%.08X)\n"
" Stride : 0x%.08X\n"
");\n",
GetCurrentThreadId(), StreamNumber, pStreamData, (pStreamData != 0) ? pStreamData->EmuVertexBuffer8 : 0, Stride);
// Cache stream number
g_dwLastSetStream = StreamNumber;
if(StreamNumber == 0)
g_pVertexBuffer = pStreamData;
// Test for a non-zero stream source. Unreal Championship gives us
// some funky number when going ingame.
// if(StreamNumber != 0)
// {
// EmuWarning( "StreamNumber: = %d", StreamNumber );
// EmuWarning( "pStreamData: = 0x%.08X (0x%.08X)", pStreamData, (pStreamData != 0) ? pStreamData->EmuVertexBuffer8 : NULL );
//// __asm int 3;
// }
IDirect3DVertexBuffer8 *pVertexBuffer8 = NULL;
if(pStreamData != NULL)
{
EmuVerifyResourceIsRegistered(pStreamData);
pVertexBuffer8 = pStreamData->EmuVertexBuffer8;
pVertexBuffer8->Unlock();
}
#ifdef _DEBUG_TRACK_VB
if(pStreamData != NULL)
{
g_bVBSkipStream = g_VBTrackDisable.exists(pStreamData->EmuVertexBuffer8);
}
#endif
HRESULT hRet = g_pD3DDevice8->SetStreamSource(StreamNumber, pVertexBuffer8, Stride);
if(FAILED(hRet))
CxbxKrnlCleanup("SetStreamSource Failed!");
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexShader
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexShader
(
DWORD Handle
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexShader\n"
"(\n"
" Handle : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle);
HRESULT hRet = D3D_OK;
g_CurrentVertexShader = Handle;
// Store viewport offset and scale in constant registers 58 (c-38) and
// 59 (c-37) used for screen space transformation.
if(g_VertexShaderConstantMode != X_VSCM_NONERESERVED)
{
// TODO: Proper solution.
static float vScale[] = { (2.0f / 640), (-2.0f / 480), 0.0f, 0.0f };
static float vOffset[] = { -1.0f, 1.0f, 0.0f, 1.0f };
g_pD3DDevice8->SetVertexShaderConstant(58, vScale, 1);
g_pD3DDevice8->SetVertexShaderConstant(59, vOffset, 1);
}
DWORD RealHandle;
if(VshHandleIsVertexShader(Handle))
{
RealHandle = ((VERTEX_SHADER *)(VshHandleGetVertexShader(Handle))->Handle)->Handle;
}
else
{
RealHandle = Handle;
RealHandle &= ~D3DFVF_XYZ;
RealHandle &= ~D3DFVF_XYZRHW;
RealHandle &= ~D3DFVF_XYZB1;
RealHandle &= ~D3DFVF_XYZB2;
RealHandle &= ~D3DFVF_XYZB3;
RealHandle &= ~D3DFVF_XYZB4;
RealHandle &= ~D3DFVF_DIFFUSE;
RealHandle &= ~D3DFVF_NORMAL;
RealHandle &= ~D3DFVF_SPECULAR;
RealHandle &= 0x00FF;
if( RealHandle != 0 )
printf( "EmuWarning: Handle = 0x%.08X\n", RealHandle );
RealHandle = Handle;
}
hRet = g_pD3DDevice8->SetVertexShader(RealHandle);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DrawVertices
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_DrawVertices
(
X_D3DPRIMITIVETYPE PrimitiveType,
UINT StartVertex,
UINT VertexCount
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_DrawVertices\n"
"(\n"
" PrimitiveType : 0x%.08X\n"
" StartVertex : 0x%.08X\n"
" VertexCount : 0x%.08X\n"
");\n",
GetCurrentThreadId(), PrimitiveType, StartVertex, VertexCount);
EmuUpdateDeferredStates();
EmuUnswizzleTextureStages();
VertexPatchDesc VPDesc;
VPDesc.PrimitiveType = PrimitiveType;
VPDesc.dwVertexCount = VertexCount;
VPDesc.dwOffset = StartVertex;
VPDesc.pVertexStreamZeroData = 0;
VPDesc.uiVertexStreamZeroStride = 0;
VPDesc.hVertexShader = g_CurrentVertexShader;
VertexPatcher VertPatch;
bool bPatched = VertPatch.Apply(&VPDesc, NULL);
if(IsValidCurrentShader())
{
#ifdef _DEBUG_TRACK_VB
if(!g_bVBSkipStream)
{
#endif
g_pD3DDevice8->DrawPrimitive
(
EmuPrimitiveType(VPDesc.PrimitiveType),
StartVertex,
VPDesc.dwPrimitiveCount
);
g_dwPrimPerFrame += VPDesc.dwPrimitiveCount;
#ifdef _DEBUG_TRACK_VB
}
#endif
}
VertPatch.Restore();
// Execute callback procedure
if( g_CallbackType == X_D3DCALLBACK_WRITE )
{
if( g_pCallback )
{
EmuSwapFS();
g_pCallback(g_CallbackParam);
EmuSwapFS();
// TODO: Reset pointer?
}
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DrawVerticesUP
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_DrawVerticesUP
(
X_D3DPRIMITIVETYPE PrimitiveType,
UINT VertexCount,
CONST PVOID pVertexStreamZeroData,
UINT VertexStreamZeroStride
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_DrawVerticesUP\n"
"(\n"
" PrimitiveType : 0x%.08X\n"
" VertexCount : 0x%.08X\n"
" pVertexStreamZeroData : 0x%.08X\n"
" VertexStreamZeroStride : 0x%.08X\n"
");\n",
GetCurrentThreadId(), PrimitiveType, VertexCount, pVertexStreamZeroData,
VertexStreamZeroStride);
EmuUpdateDeferredStates();
EmuUnswizzleTextureStages();
/*#if 0
// HACK: Phantom Crash...
// if( (*(DWORD*)&pVertexStreamZeroData) == 0x81FC3080 || (*(DWORD*)&pVertexStreamZeroData) == 0x8191E080 )
if( ((*(DWORD*)&pVertexStreamZeroData) & 0xFF000FFF) == 0x81000080 )
{
// EmuWarning( "Invalid vertex data! (0x%.08X)", pVertexStreamZeroData );
EmuWarning( "Phantom Crash hack applied!" );
return;
}
#else
return;
#endif*/
VertexPatchDesc VPDesc;
VPDesc.PrimitiveType = PrimitiveType;
VPDesc.dwVertexCount = VertexCount;
VPDesc.dwOffset = 0;
VPDesc.pVertexStreamZeroData = pVertexStreamZeroData;
VPDesc.uiVertexStreamZeroStride = VertexStreamZeroStride;
VPDesc.hVertexShader = g_CurrentVertexShader;
VertexPatcher VertPatch;
bool bPatched = VertPatch.Apply(&VPDesc, NULL);
if (IsValidCurrentShader())
{
#ifdef _DEBUG_TRACK_VB
if(!g_bVBSkipStream)
{
#endif
g_pD3DDevice8->DrawPrimitiveUP
(
EmuPrimitiveType(VPDesc.PrimitiveType),
VPDesc.dwPrimitiveCount,
VPDesc.pVertexStreamZeroData,
VPDesc.uiVertexStreamZeroStride
);
g_dwPrimPerFrame += VPDesc.dwPrimitiveCount;
#ifdef _DEBUG_TRACK_VB
}
#endif
}
VertPatch.Restore();
// Execute callback procedure
if( g_CallbackType == X_D3DCALLBACK_WRITE )
{
if( g_pCallback )
{
EmuSwapFS();
g_pCallback(g_CallbackParam);
EmuSwapFS();
// TODO: Reset pointer?
}
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DrawIndexedVertices
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_DrawIndexedVertices
(
X_D3DPRIMITIVETYPE PrimitiveType,
UINT VertexCount,
CONST PWORD pIndexData
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_DrawIndexedVertices\n"
"(\n"
" PrimitiveType : 0x%.08X\n"
" VertexCount : 0x%.08X\n"
" pIndexData : 0x%.08X\n"
");\n",
GetCurrentThreadId(), PrimitiveType, VertexCount, pIndexData);
//#if 0
// update index buffer, if necessary
if(g_pIndexBuffer != 0 && g_pIndexBuffer->Lock == X_D3DRESOURCE_LOCK_FLAG_NOSIZE)
{
DWORD dwSize = VertexCount*2; // 16-bit indices
HRESULT hRet = g_pD3DDevice8->CreateIndexBuffer
(
dwSize, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED,
&g_pIndexBuffer->EmuIndexBuffer8
);
if(FAILED(hRet))
CxbxKrnlCleanup("CreateIndexBuffer Failed!");
BYTE *pData = 0;
hRet = g_pIndexBuffer->EmuIndexBuffer8->Lock(0, dwSize, &pData, 0);
if(FAILED(hRet))
CxbxKrnlCleanup("IndexBuffer Lock Failed!");
memcpy(pData, (void*)g_pIndexBuffer->Data, dwSize);
g_pIndexBuffer->EmuIndexBuffer8->Unlock();
g_pIndexBuffer->Data = (ULONG)pData;
hRet = g_pD3DDevice8->SetIndices(g_pIndexBuffer->EmuIndexBuffer8, g_dwBaseVertexIndex);
if(FAILED(hRet))
CxbxKrnlCleanup("SetIndices Failed!");
}
EmuUpdateDeferredStates();
EmuUnswizzleTextureStages();
if( (PrimitiveType == X_D3DPT_LINELOOP) || (PrimitiveType == X_D3DPT_QUADLIST) )
EmuWarning("Unsupported PrimitiveType! (%d)", (DWORD)PrimitiveType);
// HACK: Azurik :(
// if( ((DWORD)PrimitiveType) > 11 )
/*if( PrimitiveType != X_D3DPT_POINTLIST && PrimitiveType != X_D3DPT_LINELIST &&
PrimitiveType != X_D3DPT_LINELOOP && PrimitiveType != X_D3DPT_LINESTRIP &&
PrimitiveType != X_D3DPT_TRIANGLELIST && PrimitiveType != X_D3DPT_TRIANGLESTRIP &&
PrimitiveType != X_D3DPT_TRIANGLEFAN && PrimitiveType != X_D3DPT_QUADLIST &&
PrimitiveType != X_D3DPT_QUADSTRIP && PrimitiveType != X_D3DPT_POLYGON )
{
CxbxKrnlCleanup("Invalid Primitive type! %d (0x%X)", (int)PrimitiveType, (DWORD)PrimitiveType);
}*/
VertexPatchDesc VPDesc;
VPDesc.PrimitiveType = PrimitiveType;
VPDesc.dwVertexCount = VertexCount;
VPDesc.dwOffset = 0;
VPDesc.pVertexStreamZeroData = 0;
VPDesc.uiVertexStreamZeroStride = 0;
VPDesc.hVertexShader = g_CurrentVertexShader;
VertexPatcher VertPatch;
bool FatalError = false;
bool bPatched = VertPatch.Apply(&VPDesc, &FatalError);
#ifdef _DEBUG_TRACK_VB
if(!g_bVBSkipStream)
{
#endif
bool bActiveIB = false;
IDirect3DIndexBuffer8 *pIndexBuffer = 0;
// check if there is an active index buffer
{
UINT BaseIndex = 0;
g_pD3DDevice8->GetIndices(&pIndexBuffer, &BaseIndex);
if(pIndexBuffer != 0)
{
bActiveIB = true;
pIndexBuffer->Release();
}
}
UINT uiNumVertices = 0;
UINT uiStartIndex = 0;
// TODO: caching (if it becomes noticably slow to recreate the buffer each time)
if(!bActiveIB)
{
if(FAILED(g_pD3DDevice8->CreateIndexBuffer(VertexCount*2, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndexBuffer)))
CxbxKrnlCleanup("Cound not create index buffer! (%d bytes)", VertexCount*2);
if(pIndexBuffer == 0)
CxbxKrnlCleanup("Could not create index buffer! (%d bytes)", VertexCount*2);
BYTE *pbData = 0;
pIndexBuffer->Lock(0, 0, &pbData, 0);
if(pbData == 0)
CxbxKrnlCleanup("Could not lock index buffer!");
if(pIndexData)
memcpy(pbData, pIndexData, VertexCount*2);
pIndexBuffer->Unlock();
g_pD3DDevice8->SetIndices(pIndexBuffer, g_dwBaseVertexIndex);
uiNumVertices = VertexCount;
uiStartIndex = 0;
}
else
{
uiNumVertices = ((DWORD)pIndexData)/2 + VertexCount;
uiStartIndex = ((DWORD)pIndexData)/2;
}
if(IsValidCurrentShader() && !FatalError)
{
g_pD3DDevice8->DrawIndexedPrimitive
(
EmuPrimitiveType(VPDesc.PrimitiveType), 0, uiNumVertices, uiStartIndex, VPDesc.dwPrimitiveCount
);
g_dwPrimPerFrame += VPDesc.dwPrimitiveCount;
/*if( (PrimitiveType == X_D3DPT_LINELOOP) || (PrimitiveType == X_D3DPT_QUADLIST) )
{
g_pD3DDevice8->DrawPrimitive
(
EmuPrimitiveType(VPDesc.PrimitiveType), 0, VPDesc.dwPrimitiveCount
);
}
else
{
g_pD3DDevice8->DrawIndexedPrimitive
(
EmuPrimitiveType(VPDesc.PrimitiveType), 0, uiNumVertices, uiStartIndex, VPDesc.dwPrimitiveCount
);
} */
}
if(!bActiveIB)
{
g_pD3DDevice8->SetIndices(0, 0);
pIndexBuffer->Release();
}
#ifdef _DEBUG_TRACK_VB
}
#endif
VertPatch.Restore();
// Execute callback procedure
if( g_CallbackType == X_D3DCALLBACK_WRITE )
{
if( g_pCallback )
{
EmuSwapFS();
g_pCallback(g_CallbackParam);
EmuSwapFS();
// TODO: Reset pointer?
}
}
//#endif
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DrawIndexedVerticesUP
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_DrawIndexedVerticesUP
(
X_D3DPRIMITIVETYPE PrimitiveType,
UINT VertexCount,
CONST PVOID pIndexData,
CONST PVOID pVertexStreamZeroData,
UINT VertexStreamZeroStride
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_DrawIndexedVerticesUP\n"
"(\n"
" PrimitiveType : 0x%.08X\n"
" VertexCount : 0x%.08X\n"
" pIndexData : 0x%.08X\n"
" pVertexStreamZeroData : 0x%.08X\n"
" VertexStreamZeroStride : 0x%.08X\n"
");\n",
GetCurrentThreadId(), PrimitiveType, VertexCount, pIndexData, pVertexStreamZeroData, VertexStreamZeroStride);
// update index buffer, if necessary
if(g_pIndexBuffer != 0 && g_pIndexBuffer->Lock == X_D3DRESOURCE_LOCK_FLAG_NOSIZE)
CxbxKrnlCleanup("g_pIndexBuffer != 0");
EmuUpdateDeferredStates();
EmuUnswizzleTextureStages();
if( (PrimitiveType == X_D3DPT_LINELOOP) || (PrimitiveType == X_D3DPT_QUADLIST) )
EmuWarning("Unsupported PrimitiveType! (%d)", (DWORD)PrimitiveType);
VertexPatchDesc VPDesc;
VPDesc.PrimitiveType = PrimitiveType;
VPDesc.dwVertexCount = VertexCount;
VPDesc.dwOffset = 0;
VPDesc.pVertexStreamZeroData = pVertexStreamZeroData;
VPDesc.uiVertexStreamZeroStride = VertexStreamZeroStride;
VPDesc.hVertexShader = g_CurrentVertexShader;
VertexPatcher VertPatch;
bool bPatched = VertPatch.Apply(&VPDesc, NULL);
#ifdef _DEBUG_TRACK_VB
if(!g_bVBSkipStream)
{
#endif
if (IsValidCurrentShader())
{
g_pD3DDevice8->DrawIndexedPrimitiveUP
(
EmuPrimitiveType(VPDesc.PrimitiveType), 0, VPDesc.dwVertexCount, VPDesc.dwPrimitiveCount, pIndexData, D3DFMT_INDEX16, VPDesc.pVertexStreamZeroData, VPDesc.uiVertexStreamZeroStride
);
g_dwPrimPerFrame += VPDesc.dwPrimitiveCount;
}
#ifdef _DEBUG_TRACK_VB
}
#endif
VertPatch.Restore();
// Execute callback procedure
if( g_CallbackType == X_D3DCALLBACK_WRITE )
{
if( g_pCallback )
{
EmuSwapFS();
g_pCallback(g_CallbackParam);
EmuSwapFS();
// TODO: Reset pointer?
}
}
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetLight
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetLight
(
DWORD Index,
CONST D3DLIGHT8 *pLight
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetLight\n"
"(\n"
" Index : 0x%.08X\n"
" pLight : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Index, pLight);
HRESULT hRet = g_pD3DDevice8->SetLight(Index, pLight);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetMaterial
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetMaterial
(
CONST D3DMATERIAL8 *pMaterial
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetMaterial\n"
"(\n"
" pMaterial : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pMaterial);
HRESULT hRet = g_pD3DDevice8->SetMaterial(pMaterial);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_LightEnable
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_LightEnable
(
DWORD Index,
BOOL bEnable
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_LightEnable\n"
"(\n"
" Index : 0x%.08X\n"
" bEnable : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Index, bEnable);
HRESULT hRet = g_pD3DDevice8->LightEnable(Index, bEnable);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderTarget
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetRenderTarget
(
X_D3DSurface *pRenderTarget,
X_D3DSurface *pNewZStencil
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderTarget\n"
"(\n"
" pRenderTarget : 0x%.08X (0x%.08X)\n"
" pNewZStencil : 0x%.08X (0x%.08X)\n"
");\n",
GetCurrentThreadId(), pRenderTarget, (pRenderTarget != 0) ? pRenderTarget->EmuSurface8 : 0, pNewZStencil,
(pNewZStencil != 0) ? pNewZStencil->EmuSurface8 : 0);
IDirect3DSurface8 *pPCRenderTarget = 0;
IDirect3DSurface8 *pPCNewZStencil = 0;
if(pRenderTarget != 0)
{
if(pRenderTarget->EmuSurface8)
{
EmuVerifyResourceIsRegistered(pRenderTarget);
pPCRenderTarget = pRenderTarget->EmuSurface8;
}
else
{
pPCRenderTarget = g_pCachedRenderTarget->EmuSurface8;
}
}
if(pNewZStencil != 0)
{
if(pNewZStencil->EmuSurface8 != 0)
{
EmuVerifyResourceIsRegistered(pNewZStencil);
pPCNewZStencil = pNewZStencil->EmuSurface8;
}
else
{
pPCNewZStencil = g_pCachedZStencilSurface->EmuSurface8;
}
}
// TODO: Follow that stencil!
HRESULT hRet = g_pD3DDevice8->SetRenderTarget(pPCRenderTarget, pPCNewZStencil);
if(FAILED(hRet))
EmuWarning("SetRenderTarget Failed! (0x%.08X)", hRet);
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreatePalette
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreatePalette
(
X_D3DPALETTESIZE Size,
X_D3DPalette **ppPalette
)
{
*ppPalette = EmuIDirect3DDevice8_CreatePalette2(Size);
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_CreatePalette2
// ******************************************************************
XTL::X_D3DPalette * WINAPI XTL::EmuIDirect3DDevice8_CreatePalette2
(
X_D3DPALETTESIZE Size
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreatePalette2\n"
"(\n"
" Size : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Size);
X_D3DPalette *pPalette = new X_D3DPalette();
static int lk[4] =
{
256*sizeof(D3DCOLOR), // D3DPALETTE_256
128*sizeof(D3DCOLOR), // D3DPALETTE_128
64*sizeof(D3DCOLOR), // D3DPALETTE_64
32*sizeof(D3DCOLOR) // D3DPALETTE_32
};
pPalette->Common = 0;
pPalette->Lock = 0x8000BEEF; // emulated reference count for palettes
pPalette->Data = (DWORD)new uint08[lk[Size]];
// TODO: Should't we register the palette with a call to
// EmuIDirect3DResource8_Register? So far, it doesn't look
// like the palette registration code gets used. If not, then we
// need to cache the palette manually during any calls to
// EmuIDirect3DDevice8_SetPalette for 8-bit textures to work properly.
EmuSwapFS(); // XBox FS
return pPalette;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetPalette
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetPalette
(
DWORD Stage,
X_D3DPalette *pPalette
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetPalette\n"
"(\n"
" Stage : 0x%.08X\n"
" pPalette : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Stage, pPalette);
// g_pD3DDevice8->SetPaletteEntries(0, (PALETTEENTRY*)pPalette->Data);
// Cache palette data and size
if( pPalette )
{
if( pPalette->Data )
{
pCurrentPalette = (LPVOID) pPalette->Data;
dwCurrentPaletteSize = 256; //EmuCheckAllocationSize( (LPVOID) pPalette->Data, false );
}
}
EmuWarning("Not setting palette");
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetFlickerFilter
// ******************************************************************
void WINAPI XTL::EmuIDirect3DDevice8_SetFlickerFilter
(
DWORD Filter
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetFlickerFilter\n"
"(\n"
" Filter : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Filter);
EmuWarning("Not setting flicker filter");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetSoftDisplayFilter
// ******************************************************************
void WINAPI XTL::EmuIDirect3DDevice8_SetSoftDisplayFilter
(
BOOL Enable
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetSoftDisplayFilter\n"
"(\n"
" Enable : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Enable);
EmuWarning("Not setting soft display filter");
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DPalette8_Lock
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DPalette8_Lock
(
X_D3DPalette *pThis,
D3DCOLOR **ppColors,
DWORD Flags
)
{
HRESULT hRet = D3D_OK;
if( pThis )
*ppColors = EmuIDirect3DPalette8_Lock2(pThis, Flags);
else
{
EmuWarning( "EmuIDirect3DPalette8_Lock: pThis == NULL!" );
hRet = E_FAIL;
}
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DPalette8_Lock2
// ******************************************************************
XTL::D3DCOLOR * WINAPI XTL::EmuIDirect3DPalette8_Lock2
(
X_D3DPalette *pThis,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DPalette8_Lock\n"
"(\n"
" pThis : 0x%.08X\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Flags);
D3DCOLOR *pColors = (D3DCOLOR*)pThis->Data;
EmuSwapFS(); // XBox FS
return pColors;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVertexShaderSize
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetVertexShaderSize
(
DWORD Handle,
UINT* pSize
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVertexShaderSize\n"
"(\n"
" Handle : 0x%.08X\n"
" pSize : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle, pSize);
if(pSize && VshHandleIsVertexShader(Handle))
{
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader *)(Handle & 0x7FFFFFFF);
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)pD3DVertexShader->Handle;
*pSize = pVertexShader->Size;
}
else if(pSize)
{
*pSize = 0;
}
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DeleteVertexShader
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_DeleteVertexShader
(
DWORD Handle
)
{
EmuSwapFS();
DbgPrintf( "EmuD3D8 (0x%.08X): EmuIDirect3DDevice8_DeleteVertexShader\n"
"(\n"
" Handle : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle);
DWORD RealHandle = 0;
if(VshHandleIsVertexShader(Handle))
{
X_D3DVertexShader *pD3DVertexShader = (X_D3DVertexShader *)(Handle & 0x7FFFFFFF);
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)pD3DVertexShader->Handle;
RealHandle = pVertexShader->Handle;
CxbxFree(pVertexShader->pDeclaration);
if(pVertexShader->pFunction)
{
CxbxFree(pVertexShader->pFunction);
}
FreeVertexDynamicPatch(pVertexShader);
CxbxFree(pVertexShader);
CxbxFree(pD3DVertexShader);
}
HRESULT hRet = g_pD3DDevice8->DeleteVertexShader(RealHandle);
EmuSwapFS();
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SelectVertexShaderDirect
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_SelectVertexShaderDirect
(
X_VERTEXATTRIBUTEFORMAT *pVAF,
DWORD Address
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_SelectVertexShaderDirect\n"
"(\n"
" pVAF : 0x%.08X\n"
" Address : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pVAF,Address);
DbgPrintf("NOT YET IMPLEMENTED!\n");
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetShaderConstantMode
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetShaderConstantMode
(
DWORD *pMode
)
{
#ifdef _DEBUG_TRACE
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetShaderConstantMode\n"
"(\n"
" pMode : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pMode);
EmuSwapFS(); // Xbox FS
}
#endif
if(pMode)
{
*pMode = g_VertexShaderConstantMode;
}
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVertexShader
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetVertexShader
(
DWORD *pHandle
)
{
EmuSwapFS();
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVertexShader\n"
"(\n"
" pHandle : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pHandle);
if(pHandle)
{
(*pHandle) = g_CurrentVertexShader;
}
EmuSwapFS();
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVertexShaderConstant
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetVertexShaderConstant
(
INT Register,
void *pConstantData,
DWORD ConstantCount
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVertexShaderConstant\n"
"(\n"
" Register : 0x%.08X\n"
" pConstantData : 0x%.08X\n"
" ConstantCount : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Register, pConstantData, ConstantCount);
HRESULT hRet = g_pD3DDevice8->GetVertexShaderConstant
(
Register + 96,
pConstantData,
ConstantCount
);
EmuSwapFS(); // XBox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexShaderInputDirect
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexShaderInputDirect
(
X_VERTEXATTRIBUTEFORMAT *pVAF,
UINT StreamCount,
X_STREAMINPUT *pStreamInputs
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_SelectVertexShaderDirect\n"
"(\n"
" pVAF : 0x%.08X\n"
" StreamCount : 0x%.08X\n"
" pStreamInputs : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pVAF, StreamCount, pStreamInputs);
DbgPrintf("NOT YET IMPLEMENTED!\n");
EmuSwapFS(); // Xbox FS
return 0;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVertexShaderInput
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetVertexShaderInput
(
DWORD *pHandle,
UINT *pStreamCount,
X_STREAMINPUT *pStreamInputs
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVertexShaderInput\n"
"(\n"
" pHandle : 0x%.08X\n"
" pStreamCount : 0x%.08X\n"
" pStreamInputs : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pHandle, pStreamCount, pStreamInputs);
DbgPrintf("NOT YET IMPLEMENTED!\n");
EmuSwapFS(); // Xbox FS
return 0;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetVertexShaderInput
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetVertexShaderInput
(
DWORD Handle,
UINT StreamCount,
X_STREAMINPUT *pStreamInputs
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetVertexShaderInput\n"
"(\n"
" Handle : 0x%.08X\n"
" StreamCount : 0x%.08X\n"
" pStreamInputs : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle, StreamCount, pStreamInputs);
DbgPrintf("NOT YET IMPLEMENTED!\n");
EmuSwapFS(); // Xbox FS
return 0;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_RunVertexStateShader
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_RunVertexStateShader
(
DWORD Address,
CONST FLOAT *pData
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_RunVertexStateShader\n"
"(\n"
" Address : 0x%.08X\n"
" pData : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Address,pData);
DbgPrintf("NOT YET IMPLEMENTED!\n");
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_LoadVertexShaderProgram
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_LoadVertexShaderProgram
(
CONST DWORD *pFunction,
DWORD Address
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_LoadVertexShaderProgram\n"
"(\n"
" pFunction : 0x%.08X\n"
" Address : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pFunction,Address);
DbgPrintf("NOT YET IMPLEMENTED!\n");
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVertexShaderType
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_GetVertexShaderType
(
DWORD Handle,
DWORD *pType
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVertexShaderType\n"
"(\n"
" Handle : 0x%.08X\n"
" pType : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle, pType);
if(pType && VshHandleIsVertexShader(Handle))
{
*pType = ((VERTEX_SHADER *)(VshHandleGetVertexShader(Handle))->Handle)->Type;
}
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVertexShaderDeclaration
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetVertexShaderDeclaration
(
DWORD Handle,
PVOID pData,
DWORD *pSizeOfData
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVertexShaderDeclaration\n"
"(\n"
" Handle : 0x%.08X\n"
" pData : 0x%.08X\n"
" pSizeOfData : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle, pData, pSizeOfData);
HRESULT hRet = D3DERR_INVALIDCALL;
if(pSizeOfData && VshHandleIsVertexShader(Handle))
{
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)(VshHandleGetVertexShader(Handle))->Handle;
if(*pSizeOfData < pVertexShader->DeclarationSize || !pData)
{
*pSizeOfData = pVertexShader->DeclarationSize;
hRet = !pData ? D3D_OK : D3DERR_MOREDATA;
}
else
{
memcpy(pData, pVertexShader->pDeclaration, pVertexShader->DeclarationSize);
hRet = D3D_OK;
}
}
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetVertexShaderFunction
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetVertexShaderFunction
(
DWORD Handle,
PVOID *pData,
DWORD *pSizeOfData
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetVertexShaderFunction\n"
"(\n"
" Handle : 0x%.08X\n"
" pData : 0x%.08X\n"
" pSizeOfData : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle,pData,pSizeOfData);
HRESULT hRet = D3DERR_INVALIDCALL;
if(pSizeOfData && VshHandleIsVertexShader(Handle))
{
VERTEX_SHADER *pVertexShader = (VERTEX_SHADER *)(VshHandleGetVertexShader(Handle))->Handle;
if(*pSizeOfData < pVertexShader->FunctionSize || !pData)
{
*pSizeOfData = pVertexShader->FunctionSize;
hRet = !pData ? D3D_OK : D3DERR_MOREDATA;
}
else
{
memcpy(pData, pVertexShader->pFunction, pVertexShader->FunctionSize);
hRet = D3D_OK;
}
}
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3D8_AllocContiguousMemory
// ******************************************************************
PVOID WINAPI XTL::EmuIDirect3D8_AllocContiguousMemory
(
SIZE_T dwSize,
DWORD dwAllocAttributes
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3D8_AllocContiguousMemory\n"
"(\n"
" dwSize : 0x%.08X\n"
" dwAllocAttributes : 0x%.08X\n"
");\n",
GetCurrentThreadId(), dwSize,dwAllocAttributes);
//
// NOTE: Kludgey (but necessary) solution:
//
// Since this memory must be aligned on a page boundary, we must allocate an extra page
// so that we can return a valid page aligned pointer
//
PVOID pRet = CxbxMalloc(dwSize + 0x1000);
// align to page boundary
{
DWORD dwRet = (DWORD)pRet;
dwRet += 0x1000 - dwRet%0x1000;
g_AlignCache.insert(dwRet, pRet);
pRet = (PVOID)dwRet;
}
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_AllocContiguousMemory returned 0x%.08X\n", GetCurrentThreadId(), pRet);
EmuSwapFS(); // Xbox FS
return pRet;
}
// ******************************************************************
// * func: EmuIDirect3DTexture8_GetLevelDesc
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DTexture8_GetLevelDesc
(
UINT Level,
X_D3DSURFACE_DESC* pDesc
)
{
EmuSwapFS(); // Win2k/XP FS
// debug trace
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3DTexture8_GetLevelDesc\n"
"(\n"
" Level : 0x%.08X\n"
" pDesc : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Level,pDesc);
EmuSwapFS(); // Xbox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3D8_CheckDeviceMultiSampleType
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_CheckDeviceMultiSampleType
(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DFORMAT SurfaceFormat,
BOOL Windowed,
D3DMULTISAMPLE_TYPE MultiSampleType
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf( "EmuD3D8 (0x%X): EmuIDirect3D8_CheckDeviceMultiSampleType\n"
"(\n"
" Adapter : 0x%.08X\n"
" DeviceType : 0x%.08X\n"
" SurfaceFormat : 0x%.08X\n"
" Windowed : 0x%.08X\n"
" MultiSampleType : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Adapter, DeviceType, SurfaceFormat, Windowed, MultiSampleType);
if(Adapter != D3DADAPTER_DEFAULT)
{
EmuWarning("Adapter is not D3DADAPTER_DEFAULT, correcting!");
Adapter = D3DADAPTER_DEFAULT;
}
if(DeviceType == D3DDEVTYPE_FORCE_DWORD)
EmuWarning("DeviceType == D3DDEVTYPE_FORCE_DWORD");
// Convert SurfaceFormat (Xbox->PC)
D3DFORMAT PCSurfaceFormat = EmuXB2PC_D3DFormat(SurfaceFormat);
// TODO: HACK: Devices that don't support this should somehow emulate it!
if(PCSurfaceFormat == D3DFMT_D16)
{
EmuWarning("D3DFMT_D16 is an unsupported texture format!");
PCSurfaceFormat = D3DFMT_X8R8G8B8;
}
else if(PCSurfaceFormat == D3DFMT_P8)
{
EmuWarning("D3DFMT_P8 is an unsupported texture format!");
PCSurfaceFormat = D3DFMT_X8R8G8B8;
}
else if(PCSurfaceFormat == D3DFMT_D24S8)
{
EmuWarning("D3DFMT_D24S8 is an unsupported texture format!");
PCSurfaceFormat = D3DFMT_X8R8G8B8;
}
if(Windowed != FALSE)
Windowed = FALSE;
// TODO: Convert from Xbox to PC!!
D3DMULTISAMPLE_TYPE PCMultiSampleType = EmuXB2PC_D3DMultiSampleFormat((DWORD) MultiSampleType);
// Now call the real CheckDeviceMultiSampleType with the corrected parameters.
HRESULT hRet = g_pD3D8->CheckDeviceMultiSampleType
(
Adapter,
DeviceType,
PCSurfaceFormat,
Windowed,
PCMultiSampleType
);
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3D8_GetDeviceCaps
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_GetDeviceCaps
(
UINT Adapter,
D3DDEVTYPE DeviceType,
D3DCAPS8 *pCaps
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_GetDeviceCaps\n"
"(\n"
" Adapter : 0x%.08X\n"
" DeviceType : 0x%.08X\n"
" pCaps : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Adapter, DeviceType, pCaps);
HRESULT hRet = g_pD3D8->GetDeviceCaps(Adapter, DeviceType, pCaps);
if(FAILED(hRet))
CxbxKrnlCleanup("IDirect3D8::GetDeviceCaps failed!");
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3D8_SetPushBufferSize
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_SetPushBufferSize
(
DWORD PushBufferSize,
DWORD KickOffSize
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_SetPushBufferSize\n"
"(\n"
" PushBufferSize : 0x%.08X\n"
" KickOffSize : 0x%.08X\n"
");\n",
GetCurrentThreadId(), PushBufferSize, KickOffSize);
HRESULT hRet = D3D_OK;
// This is a Xbox extension, meaning there is no pc counterpart.
EmuSwapFS(); // XBox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_InsertFence
// ******************************************************************
DWORD WINAPI XTL::EmuIDirect3DDevice8_InsertFence()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_InsertFence()\n", GetCurrentThreadId());
// TODO: Actually implement this
DWORD dwRet = 0x8000BEEF;
EmuSwapFS(); // XBox FS
return dwRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_IsFencePending
// ******************************************************************
BOOL WINAPI XTL::EmuIDirect3DDevice8_IsFencePending
(
DWORD Fence
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_IsFencePending\n"
"(\n"
" Fence : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Fence);
// TODO: Implement
EmuSwapFS(); // XBox FS
return FALSE;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_BlockOnFence
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_BlockOnFence
(
DWORD Fence
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BlockOnFence\n"
"(\n"
" Fence : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Fence);
// TODO: Implement
EmuSwapFS(); // XBox FS
}
// ******************************************************************
// * func: EmuIDirect3DResource8_BlockUntilNotBusy
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DResource8_BlockUntilNotBusy
(
X_D3DResource *pThis
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DResource8_BlockUntilNotBusy\n"
"(\n"
" pThis : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis);
// TODO: Implement
EmuSwapFS(); // XBox FS
}
// ******************************************************************
// * func: EmuIDirect3DVertexBuffer8_GetDesc
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DVertexBuffer8_GetDesc
(
X_D3DVertexBuffer *pThis,
D3DVERTEXBUFFER_DESC *pDesc
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DVertexBuffer8_GetDesc\n"
"(\n"
" pThis : 0x%.08X\n"
" pDesc : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pThis, pDesc);
// TODO: Implement
EmuSwapFS(); // XBox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetScissors
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetScissors
(
DWORD Count,
BOOL Exclusive,
CONST D3DRECT *pRects
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetScissors\n"
"(\n"
" Count : 0x%.08X\n"
" Exclusive : 0x%.08X\n"
" pRects : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Count, Exclusive, pRects);
// TODO: Implement
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetScreenSpaceOffset
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetScreenSpaceOffset
(
FLOAT x,
FLOAT y
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetScreenSpaceOffset\n"
"(\n"
" x : %f\n"
" y : %f\n"
");\n",
GetCurrentThreadId(), x, y);
EmuWarning("EmuIDirect3DDevice8_SetScreenSpaceOffset ignored");
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetPixelShaderProgram
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetPixelShaderProgram
(
X_D3DPIXELSHADERDEF* pPSDef
)
{
EmuSwapFS(); // Win2kXP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetPixelShaderProgram\n"
"(\n"
" pPSDef : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pPSDef );
HRESULT hRet = E_FAIL;
DWORD dwHandle;
// Redirect this call to windows Direct3D
hRet = g_pD3DDevice8->CreatePixelShader
(
(DWORD*) pPSDef,
&dwHandle
);
if(FAILED(hRet))
{
dwHandle = X_PIXELSHADER_FAKE_HANDLE;
EmuWarning("We're lying about the creation of a pixel shader!");
}
// Now, redirect this to Xbox Direct3D
//EmuSwapFS();
//EmuIDirect3DDevice8_CreatePixelShader(pPSDef, &dwHandle);
//hRet = XTL::EmuIDirect3DDevice8_SetPixelShader( dwHandle );
//EmuSwapFS();
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice_CreateStateBlock
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_CreateStateBlock
(
D3DSTATEBLOCKTYPE Type,
DWORD *pToken
)
{
EmuSwapFS(); // Win2K/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_CreateStateBlock\n"
"(\n"
" Type : %f\n"
" pToken : %f\n"
");\n",
GetCurrentThreadId(), Type, pToken);
// blueshogun96 10/1/07
// I'm assuming this is the same as the PC version...
HRESULT hRet = g_pD3DDevice8->CreateStateBlock( Type, pToken );
if(FAILED(hRet))
EmuWarning("CreateStateBlock failed!\n");
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_InsertCallback
// ******************************************************************
VOID WINAPI XTL::EmuIDirect3DDevice8_InsertCallback
(
X_D3DCALLBACKTYPE Type,
X_D3DCALLBACK pCallback,
DWORD Context
)
{
EmuSwapFS(); // Win2K/XP FS
/*DbgP*/printf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_InsertCallback\n"
"(\n"
" Type : 0x%.08X\n"
" pCallback : 0x%.08X\n"
" Context : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Type, pCallback, Context);
EmuWarning("InsertCallback ignored!\n");
// TODO: Implement
g_pCallback = (D3DCALLBACK) pCallback;
g_CallbackType = Type;
g_CallbackParam = Context;
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DrawRectPatch
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_DrawRectPatch
(
UINT Handle,
CONST FLOAT *pNumSegs,
CONST D3DRECTPATCH_INFO *pRectPatchInfo
)
{
EmuSwapFS(); // Win2K/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_DrawRectPatch\n"
"(\n"
" Handle : 0x%.08X\n"
" pNumSegs : %f\n"
" pRectPatchInfo : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Handle, *pNumSegs, pRectPatchInfo);
HRESULT hRet = g_pD3DDevice8->DrawRectPatch( Handle, pNumSegs, pRectPatchInfo );
if(FAILED(hRet))
EmuWarning("DrawRectPatch failed!\n");
EmuSwapFS(); // Xbox FS
return hRet;
}
#pragma warning(disable:4244)
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetProjectionViewportMatrix
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetProjectionViewportMatrix
(
D3DXMATRIX *pProjectionViewport
)
{
EmuSwapFS(); // Win2K/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetProjectionViewportMatrix\n"
"(\n"
" pProjectionViewport : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pProjectionViewport);
// blueshogun96 1/25/10
// It's been almost 3 years, but I think this is a better
// implementation. Still probably not right, but better
// then before.
HRESULT hRet;
D3DXMATRIX Out, mtxProjection, mtxViewport;
D3DVIEWPORT8 Viewport;
// Get current viewport
hRet = g_pD3DDevice8->GetViewport(&Viewport);
if(FAILED(hRet))
EmuWarning("Unable to get viewport!\n");
// Get current projection matrix
hRet = g_pD3DDevice8->GetTransform(D3DTS_PROJECTION, &mtxProjection);
if(FAILED(hRet))
EmuWarning("Unable to get projection matrix!\n");
// Clear the destination matrix
::ZeroMemory(&Out, sizeof(D3DMATRIX));
// Create the Viewport matrix manually
// Direct3D8 doesn't give me everything I need in a viewport structure
// (one thing I REALLY HATE!) so some constants will have to be used
// instead.
float ClipWidth = 2.0f;
float ClipHeight = 2.0f;
float ClipX = -1.0f;
float ClipY = 1.0f;
float Width = DWtoF(Viewport.Width);
float Height = DWtoF(Viewport.Height);
D3DXMatrixIdentity(&mtxViewport);
mtxViewport._11 = Width / ClipWidth;
mtxViewport._22 = -(Height / ClipHeight);
mtxViewport._41 = -(ClipX * mtxViewport._11);
mtxViewport._42 = -(ClipY * mtxViewport._22);
// Multiply projection and viewport matrix together
Out = mtxProjection * mtxViewport;
*pProjectionViewport = Out;
// __asm int 3;
EmuSwapFS(); // Xbox FS
return S_OK;
}
#pragma warning(default:4244)
// ******************************************************************
// * func: EmuIDirect3DDevice8_BackFillMode
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_BackFillMode
(
DWORD Value
)
{
EmuSwapFS(); // Win2K/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BackFillMode\n"
"(\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Value);
// blueshogun96 12/4/07
// I haven't had access to Cxbx sources in a few months, great to be back :)
//
// Anyway, since standard Direct3D doesn't support the back fill mode
// operation, this function will be ignored. Things like this make me
// think even more that an OpenGL port wouldn't hurt since OpenGL supports
// nearly all of the missing features that Direct3D lacks. The Xbox's version
// of Direct3D was specifically created to take advantage of certain NVIDIA
// GPU registers and provide more OpenGL-like features IHMO.
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuD3DDevice_KickOff (D3D::CDevice::KickOff)
// ******************************************************************
VOID WINAPI XTL::EmuD3DDevice_KickOff()
{
EmuSwapFS(); // Win2K/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuD3DDevice_KickOff()\n", GetCurrentThreadId());
// TODO: Anything (kick off and NOT wait for idle)?
// NOTE: We should actually emulate IDirect3DDevice8_KickPushBuffer()
// instead of this function. When needed, use the breakpoint (int 3)
// to determine what is calling this function if it's something other
// than IDirect3DDevice8_KickPushBuffer() itself.
// __asm int 3;
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetTexture2
// ******************************************************************
XTL::X_D3DResource* WINAPI XTL::EmuIDirect3DDevice8_GetTexture2(DWORD Stage)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetTexture2\n"
"(\n"
" Stage : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Stage);
// Get the active texture from this stage
X_D3DResource* pRet = EmuD3DActiveTexture[Stage];
EmuSwapFS(); // Xbox FS
return pRet;
}
// ******************************************************************
// * func: EmuD3DDevice_SetStateVB (D3D::CDevice::SetStateVB)
// ******************************************************************
VOID WINAPI XTL::EmuD3DDevice_SetStateVB( ULONG Unknown1 )
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuD3DDevice_SetStateVB\n"
"(\n"
" Unknown1 : 0x%.08X\n"
")\n",
GetCurrentThreadId(), Unknown1);
// TODO: Anything?
__asm int 3;
EmuSwapFS();
}
// ******************************************************************
// * func: EmuD3DDevice_SetStateUP (D3D::CDevice::SetStateUP)
// ******************************************************************
VOID WINAPI XTL::EmuD3DDevice_SetStateUP()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuD3DDevice_SetStateUP()\n");
// TODO: Anything?
__asm int 3;
EmuSwapFS();
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetStipple
// ******************************************************************
void WINAPI XTL::EmuIDirect3DDevice8_SetStipple( DWORD* pPattern )
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetStipple\n"
"(\n"
" pPattern : 0x%.08X\n"
")\n",
GetCurrentThreadId(), pPattern);
// We need an OpenGL port... badly
EmuSwapFS();
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetSwapCallback
// ******************************************************************
void WINAPI XTL::EmuIDirect3DDevice8_SetSwapCallback
(
D3DSWAPCALLBACK pCallback
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetSwapCallback\n"
"(\n"
" pCallback : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pCallback);
DbgPrintf("pCallback: = 0x%.08X\n", pCallback);
g_pSwapCallback = pCallback;
EmuSwapFS(); // XBox FS
return;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_PersistDisplay
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_PersistDisplay()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_PersistDisplay()\n", GetCurrentThreadId());
HRESULT hRet = S_OK;
// TODO: If this functionality is ever really needed, an idea for
// implementation would be to save a copy of the backbuffer's contents
// and free the memory after the next call to D3DDevice::Present().
// This temporary data could also be made available to the Xbox game
// through AvGetSavedDataAddress() since D3DDevice::GetPersistedDisplay2
// just contains a call to that kernel function. So far, Unreal Champ-
// ionship is the only game that uses this functionality that I know of.
// Other Unreal Engine 2.x games might as well.
IDirect3DSurface8* pBackSurface = NULL;
if( SUCCEEDED( g_pD3DDevice8->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackSurface ) ) )
{
D3DXSaveSurfaceToFile( "persisted_surface.bmp", D3DXIFF_BMP, pBackSurface, NULL, NULL );
pBackSurface->Release();
DbgPrintf("Persisted display surface saved to persisted_surface.bmp\n");
}
else
{
EmuWarning("(Temporarily) Not persisting display. Blueshogun can fix this.");
}
if(!g_pD3DDevice8)
{
EmuWarning("Direct3D device not initialized!");
hRet = E_FAIL;
}
/*else
{
IDirect3DSurface8* pBackBuffer = NULL;
D3DLOCKED_RECT LockedRect;
D3DSURFACE_DESC BackBufferDesc;
g_pD3DDevice8->GetBackBuffer( 0, D3DBACKBUFFER_TYPE_MONO, &pBackBuffer );
pBackBuffer->GetDesc( &BackBufferDesc );
DWORD dwBytesPerPixel = ( BackBufferDesc.Format == D3DFMT_X8R8G8B8 || BackBufferDesc.Format == D3DFMT_A8R8G8B8 ) ? 4 : 2;
FILE* fp = fopen( "PersistedSurface.bin", "wb" );
if(fp)
{
void* ptr = malloc( BackBufferDesc.Width * BackBufferDesc.Height * dwBytesPerPixel );
if( SUCCEEDED( pBackBuffer->LockRect( &LockedRect, NULL, 0 ) ) )
{
CopyMemory( ptr, LockedRect.pBits, BackBufferDesc.Width * BackBufferDesc.Height * dwBytesPerPixel );
fwrite( ptr, BackBufferDesc.Width * BackBufferDesc.Height * dwBytesPerPixel, 1, fp );
pBackBuffer->UnlockRect();
}
fclose(fp);
}
}*/
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_Unknown1
// ******************************************************************
void WINAPI XTL::EmuIDirect3DDevice8_Unknown1()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_Unknown1()\n", GetCurrentThreadId());
// TODO: Find out what this actually is.
// This function was only found in Run Like Hell (5233) @ 0x11FCD0.
// So far, this function hasn't been found in any other XDKs. Since
// the only major thing going on inside of it is a call to the kernel
// function AvSendTVEncoderOption, we can probably ignore it.
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_PrimeVertexCache
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_PrimeVertexCache
(
UINT VertexCount,
WORD *pIndexData
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_PrimeVertexCache\n"
"(\n"
" VertexCount : 0x%.08X\n"
" pIndexData : 0x%.08X\n"
");\n",
GetCurrentThreadId(), VertexCount, pIndexData);
// TODO: Implement
EmuWarning("PrimeVertexCache is not supported!");
EmuSwapFS(); // Win2k/XP FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_SampleAlpha
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetRenderState_SampleAlpha
(
DWORD dwSampleAlpha
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_SampleAlpha\n"
"(\n"
" dwSampleAlpha : 0x%.08X\n"
");\n",
GetCurrentThreadId(), dwSampleAlpha);
// TODO: Implement?
EmuWarning("SampleAlpha not supported!");
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderState_Deferred
// ******************************************************************
VOID __fastcall XTL::EmuIDirect3DDevice8_SetRenderState_Deferred
(
DWORD State,
DWORD Value
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderState_Deferred\n"
"(\n"
" State : 0x%.08X\n"
" Value : 0x%.08X\n"
");\n",
GetCurrentThreadId(), State, Value);
// TODO: HACK: Technically, this function doesn't need to be emulated.
// The location of EmuD3DDeferredRenderState for 3911 isn't correct and at
// the time of writing, I don't understand how to fix it. Until then,
// I'm going to implement this in a reckless manner. When the offset for
// EmuD3DDeferredRenderState is fixed for 3911, this function should be
// obsolete!
if( State > 81 && State < 116 )
EmuD3DDeferredRenderState[State-82] = Value;
else
CxbxKrnlCleanup("Unknown Deferred RenderState! (%d)\n", State);
/*
XDK 3911 Deferred RenderState values
D3DRS_FOGENABLE = 82, // TRUE to enable fog blending
D3DRS_FOGTABLEMODE = 83, // D3DFOGMODE
D3DRS_FOGSTART = 84, // float fog start (for both vertex and pixel fog)
D3DRS_FOGEND = 85, // float fog end
D3DRS_FOGDENSITY = 86, // float fog density
D3DRS_RANGEFOGENABLE = 87, // TRUE to enable range-based fog
D3DRS_WRAP0 = 88, // D3DWRAP* flags (D3DWRAP_U, D3DWRAPCOORD_0, etc.) for 1st texture coord.
D3DRS_WRAP1 = 89, // D3DWRAP* flags (D3DWRAP_U, D3DWRAPCOORD_0, etc.) for 2nd texture coord.
D3DRS_WRAP2 = 90, // D3DWRAP* flags (D3DWRAP_U, D3DWRAPCOORD_0, etc.) for 3rd texture coord.
D3DRS_WRAP3 = 91, // D3DWRAP* flags (D3DWRAP_U, D3DWRAPCOORD_0, etc.) for 4th texture coord.
D3DRS_LIGHTING = 92, // TRUE to enable lighting
D3DRS_SPECULARENABLE = 93, // TRUE to enable specular
D3DRS_LOCALVIEWER = 94, // TRUE to enable camera-relative specular highlights
D3DRS_COLORVERTEX = 95, // TRUE to enable per-vertex color
D3DRS_BACKSPECULARMATERIALSOURCE= 96, // D3DMATERIALCOLORSOURCE (Xbox extension)
D3DRS_BACKDIFFUSEMATERIALSOURCE = 97, // D3DMATERIALCOLORSOURCE (Xbox extension)
D3DRS_BACKAMBIENTMATERIALSOURCE = 98, // D3DMATERIALCOLORSOURCE (Xbox extension)
D3DRS_BACKEMISSIVEMATERIALSOURCE= 99, // D3DMATERIALCOLORSOURCE (Xbox extension)
D3DRS_SPECULARMATERIALSOURCE = 100, // D3DMATERIALCOLORSOURCE
D3DRS_DIFFUSEMATERIALSOURCE = 101, // D3DMATERIALCOLORSOURCE
D3DRS_AMBIENTMATERIALSOURCE = 102, // D3DMATERIALCOLORSOURCE
D3DRS_EMISSIVEMATERIALSOURCE = 103, // D3DMATERIALCOLORSOURCE
D3DRS_BACKAMBIENT = 104, // D3DCOLOR (Xbox extension)
D3DRS_AMBIENT = 105, // D3DCOLOR
D3DRS_POINTSIZE = 106, // float point size
D3DRS_POINTSIZE_MIN = 107, // float point size min threshold
D3DRS_POINTSPRITEENABLE = 108, // TRUE to enable point sprites
D3DRS_POINTSCALEENABLE = 109, // TRUE to enable point size scaling
D3DRS_POINTSCALE_A = 110, // float point attenuation A value
D3DRS_POINTSCALE_B = 111, // float point attenuation B value
D3DRS_POINTSCALE_C = 112, // float point attenuation C value
D3DRS_POINTSIZE_MAX = 113, // float point size max threshold
D3DRS_PATCHEDGESTYLE = 114, // D3DPATCHEDGESTYLE
D3DRS_PATCHSEGMENTS = 115, // DWORD number of segments per edge when drawing patches
*/
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_DeleteStateBlock
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_DeleteStateBlock
(
DWORD Token
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_DeleteStateBlock\n"
"(\n"
" Token : 0x%.08X\n"
");\n",
GetCurrentThreadId(), Token);
HRESULT hRet = g_pD3DDevice8->DeleteStateBlock(Token);
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetModelView
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetModelView
(
CONST D3DMATRIX *pModelView,
CONST D3DMATRIX *pInverseModelView,
CONST D3DMATRIX *pComposite
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetModelView\n"
"(\n"
" pModelView : 0x%.08X\n"
" pInverseModelView : 0x%.08X\n"
" pComposite : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pModelView, pInverseModelView, pComposite);
// TODO: Implement
// CxbxKrnlCleanup("SetModelView not yet implemented (should be easy fix, tell blueshogun)");
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_FlushVertexCache
// ******************************************************************
void WINAPI XTL::EmuIDirect3DDevice8_FlushVertexCache()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_FlushVertexCache();\n", GetCurrentThreadId());
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_BeginPushBuffer
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_BeginPushBuffer
(
X_D3DPushBuffer *pPushBuffer
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_BeginPushBuffer\n"
"(\n"
" pPushBuffer : 0x%.08X\n"
");\n", GetCurrentThreadId(), pPushBuffer);
// TODO: Implement. Easier said than done with Direct3D, but OpenGL
// can emulate this functionality rather easily.
// CxbxKrnlCleanup("BeginPushBuffer is not yet implemented!\n"
// "This is going to be a difficult fix for Direct3D but NOT OpenGL!");
EmuWarning("BeginPushBuffer is not yet implemented!");
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_EndPushBuffer
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_EndPushBuffer()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_EndPushBuffer();\n", GetCurrentThreadId());
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuXMETAL_StartPush
// ******************************************************************
void WINAPI XTL::EmuXMETAL_StartPush(void* Unknown)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuXMETAL_StartPush\n"
"(\n"
" Unknown : 0x%.08X\n",
");\n", GetCurrentThreadId(), Unknown);
// This function is too low level to actually emulate
// Only use for debugging.
__asm int 3;
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetModelView
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetModelView(D3DXMATRIX* pModelView)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetModelView\n"
"(\n"
" pModelView : 0x%.08X\n"
");\n", GetCurrentThreadId(), pModelView);
D3DXMATRIX mtxWorld, mtxView;
// I hope this is right
g_pD3DDevice8->GetTransform( D3DTS_WORLD, &mtxWorld );
g_pD3DDevice8->GetTransform( D3DTS_VIEW, &mtxView );
*pModelView = mtxWorld * mtxView;
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetBackMaterial
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetBackMaterial(D3DMATERIAL8* pMaterial)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetBackMaterial\n"
"(\n"
" pMaterial : 0x%.08X\n"
");\n", GetCurrentThreadId(), pMaterial);
EmuWarning("SetBackMaterial is not supported!");
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3D8_GetAdapterIdentifier
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3D8_GetAdapterIdentifier
(
UINT Adapter,
DWORD Flags,
D3DADAPTER_IDENTIFIER8* pIdentifier
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3D8_GetAdapterIdentifier\n"
"(\n"
" Adapter : 0x%.08X\n"
" Flags : 0x%.08X\n"
" pIdentifier : 0x%.08X (0x%.08X)\n"
");\n", GetCurrentThreadId(), Adapter, Flags, pIdentifier, pIdentifier);
// TODO: Fill the Intentifier structure with the content of what an Xbox would return.
// It might not matter for now, but just in case.
// NOTE: Games do not crash when this function is not intercepted (at least not so far)
// so it's recommended to add this function to every XDK you possibly can as it will
// save you much hassle (at least it did for Max Payne).
HRESULT hRet = g_pD3D8->GetAdapterIdentifier( Adapter, Flags, pIdentifier );
if(FAILED(hRet))
EmuWarning("GetAdapterIdentifier failed!");
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: D3D::MakeRequestedSpace
// ******************************************************************
HRESULT WINAPI XTL::EmuD3D_MakeRequestedSpace( DWORD Unknown1, DWORD Unknown2 )
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuD3D_MakeRequestedSpace\n"
"(\n"
" Unknown1 : 0x%.08X\n"
" Unknown2 : 0x%.08X\n"
");\n", GetCurrentThreadId(), Unknown1, Unknown2);
// NOTE: This function is not meant to me emulated. Just use it to find out
// the function that is calling it, and emulate that instead!!! If necessary,
// create an XRef...
__asm int 3;
CxbxKrnlCleanup("D3D::MakeRequestedSpace not implemented (tell blueshogun)");
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: D3DDevice_MakeSpace
// ******************************************************************
void WINAPI XTL::EmuD3DDevice_MakeSpace()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf( "EmuD3D8 (0x%X): EmuD3DDevice_MakeSpace();\n", GetCurrentThreadId());
// NOTE: Like the above function, this should not be emulated. The intended
// usage is the same as above.
__asm int 3;
CxbxKrnlCleanup("D3DDevice::MakeSpace not implemented (tell blueshogun)");
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: D3D::SetCommonDebugRegisters
// ******************************************************************
void WINAPI XTL::EmuD3D_SetCommonDebugRegisters()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf( "EmuD3D8 (0x%X): EmuD3D_SetCommonDebugRegisters();\n", GetCurrentThreadId());
// NOTE: I added this because I was too lazy to deal with emulating certain render
// states that use it.
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: D3D::BlockOnTime
// ******************************************************************
void WINAPI XTL::EmuD3D_BlockOnTime( DWORD Unknown1, int Unknown2 )
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuD3D_BlockOnTime\n"
"(\n"
" Unknown1 : 0x%.08X\n"
" Unknown2 : 0x%.08X\n"
");\n", GetCurrentThreadId(), Unknown1, Unknown2);
// NOTE: This function is not meant to me emulated. Just use it to find out
// the function that is calling it, and emulate that instead!!! If necessary,
// create an XRef...
// __asm int 3;
CxbxKrnlCleanup("D3D::BlockOnTime not implemented (tell blueshogun)");
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: D3D::BlockOnResource
// ******************************************************************
void WINAPI XTL::EmuD3D_BlockOnResource( X_D3DResource* pResource )
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuD3D_BlockOnResource\n"
"(\n"
" pResource : 0x%.08X\n"
");\n", GetCurrentThreadId(), pResource);
// TODO: Implement
// NOTE: Azurik appears to call this directly from numerous points
EmuSwapFS(); // Xbox FS
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetPushBufferOffset
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetPushBufferOffset
(
DWORD *pOffset
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetPushBufferOffset\n"
"(\n"
" pOffset : 0x%.08X\n"
");\n", GetCurrentThreadId(), pOffset);
// TODO: Implement
*pOffset = 0;
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DCubeTexture8_GetCubeMapSurface
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DCubeTexture8_GetCubeMapSurface
(
X_D3DCubeTexture* pThis,
D3DCUBEMAP_FACES FaceType,
UINT Level,
X_D3DSurface** ppCubeMapSurface
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DCubeTexture8_GetCubeMapSurface\n"
"(\n"
" pThis : 0x%.08X\n"
" FaceType : 0x%.08X\n"
" Level : 0x%.08X\n"
" ppCubeMapSurface : 0x%.08X (0x%.08X)\n"
");\n", GetCurrentThreadId(), pThis, FaceType, Level, ppCubeMapSurface, *ppCubeMapSurface);
HRESULT hRet;
// Create a new surface
*ppCubeMapSurface = new X_D3DSurface;
hRet = pThis->EmuCubeTexture8->GetCubeMapSurface( FaceType, Level, &(*ppCubeMapSurface)->EmuSurface8 );
EmuSwapFS(); // Xbox FS
return hRet;
}
// ******************************************************************
// * func: EmuIDirect3DCubeTexture8_GetCubeMapSurface2
// ******************************************************************
XTL::X_D3DSurface* WINAPI XTL::EmuIDirect3DCubeTexture8_GetCubeMapSurface2
(
X_D3DCubeTexture* pThis,
D3DCUBEMAP_FACES FaceType,
UINT Level
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DCubeTexture8_GetCubeMapSurface2\n"
"(\n"
" pThis : 0x%.08X\n"
" FaceType : 0x%.08X\n"
" Level : 0x%.08X\n"
");\n", GetCurrentThreadId(), pThis, FaceType, Level);
HRESULT hRet;
// Create a new surface
X_D3DSurface* pCubeMapSurface = new X_D3DSurface;
hRet = pThis->EmuCubeTexture8->GetCubeMapSurface( FaceType, Level, &pCubeMapSurface->EmuSurface8 );
EmuSwapFS(); // Xbox FS
return pCubeMapSurface;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetPixelShader
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetPixelShader
(
DWORD Name,
DWORD* pHandle
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetPixelShader\n"
"(\n"
" Name : 0x%.08X\n"
" pHandle : 0x%.08X\n"
");\n", GetCurrentThreadId(), Name, pHandle);
// TODO: This implementation is very wrong, but better than nothing.
*pHandle = g_dwCurrentPixelShader;
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetPersistedSurface
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetPersistedSurface(X_D3DSurface **ppSurface)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetPersistedSurface\n"
"(\n"
" ppSurface : 0x%.08X\n"
");\n", GetCurrentThreadId(), ppSurface);
// Attempt to load the persisted surface from persisted_surface.bmp
*ppSurface = new X_D3DSurface;
HRESULT hr = g_pD3DDevice8->CreateImageSurface( 640, 480, D3DFMT_X8R8G8B8, &(*ppSurface)->EmuSurface8 );
if( SUCCEEDED( hr ) )
{
hr = D3DXLoadSurfaceFromFileA( (*ppSurface)->EmuSurface8, NULL, NULL, "persisted_surface.bmp",
NULL, D3DX_DEFAULT, 0, NULL );
if( SUCCEEDED( hr ) )
{
DbgPrintf( "Successfully loaded persisted_surface.bmp\n" );
}
else
{
EmuWarning( "Could not load persisted_surface.bmp!\n" );
}
}
else
{
EmuWarning( "Could not create temporary surface!" );
}
EmuSwapFS(); // Xbox FS
return S_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetPersistedSurface
// ******************************************************************
XTL::X_D3DSurface* WINAPI XTL::EmuIDirect3DDevice8_GetPersistedSurface2()
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetPersistedSurface()\n", GetCurrentThreadId());
// Attempt to load the persisted surface from persisted_surface.bmp
X_D3DSurface* pSurface = new X_D3DSurface;
HRESULT hr = g_pD3DDevice8->CreateImageSurface( 640, 480, D3DFMT_X8R8G8B8, &pSurface->EmuSurface8 );
if( SUCCEEDED( hr ) )
{
hr = D3DXLoadSurfaceFromFileA( pSurface->EmuSurface8, NULL, NULL, "persisted_surface.bmp",
NULL, D3DX_DEFAULT, 0, NULL );
if( SUCCEEDED( hr ) )
{
DbgPrintf( "Successfully loaded persisted_surface.bmp\n" );
}
else
{
EmuWarning( "Could not load persisted_surface.bmp!\n" );
}
}
else
{
EmuWarning( "Could not create temporary surface!" );
}
EmuSwapFS(); // Xbox FS
return pSurface;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_SetRenderTargetFast
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_SetRenderTargetFast
(
X_D3DSurface *pRenderTarget,
X_D3DSurface *pNewZStencil,
DWORD Flags
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_SetRenderTarget\n"
"(\n"
" pRenderTarget : 0x%.08X (0x%.08X)\n"
" pNewZStencil : 0x%.08X (0x%.08X)\n"
" Flags : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pRenderTarget, (pRenderTarget != 0) ? pRenderTarget->EmuSurface8 : 0, pNewZStencil,
(pNewZStencil != 0) ? pNewZStencil->EmuSurface8 : 0, Flags);
// Redirect to the standard version.
EmuSwapFS();
HRESULT hr = EmuIDirect3DDevice8_SetRenderTarget(pRenderTarget, pNewZStencil);
EmuSwapFS();
EmuSwapFS();
return hr;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetScissors
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetScissors
(
DWORD *pCount,
BOOL *pExclusive,
D3DRECT *pRects
)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetScissors\n"
"(\n"
" pCount : 0x%.08X\n"
" pExclusive : 0x%.08X\n"
" pRects : 0x%.08X\n"
");\n",
GetCurrentThreadId(), pCount, pExclusive, pRects);
// TODO: Save a copy of each scissor rect in case this function is called
// in conjunction with D3DDevice::SetScissors. So far, only Outrun2 uses
// this function. For now, just return the values within the current
// viewport.
D3DVIEWPORT8 vp;
g_pD3DDevice8->GetViewport( &vp );
pRects->x1 = pRects->x2 = 0;
pRects->x2 = vp.Width;
pRects->y2 = vp.Height;
pExclusive[0] = FALSE;
EmuSwapFS(); // XBox FS
return D3D_OK;
}
// ******************************************************************
// * func: EmuIDirect3DDevice8_GetBackMaterial
// ******************************************************************
HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetBackMaterial(D3DMATERIAL8* pMaterial)
{
EmuSwapFS(); // Win2k/XP FS
DbgPrintf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetBackMaterial\n"
"(\n"
" pMaterial : 0x%.08X\n"
");\n", GetCurrentThreadId(), pMaterial);
EmuWarning("GetBackMaterial is not supported!");
// TODO: HACK: This is wrong, but better than nothing, right?
if( pMaterial )
g_pD3DDevice8->GetMaterial( pMaterial );
EmuSwapFS(); // Xbox FS
return S_OK;
}