2016-11-26 11:48:21 -05:00
|
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
|
|
#define INITGUID
|
|
|
|
//#define FULLHEXDUMP
|
|
|
|
|
|
|
|
#include <windows.h>
|
|
|
|
#include <ddraw.h>
|
|
|
|
#include "dxwnd.h"
|
|
|
|
#include "dxhook.h"
|
|
|
|
#include "ddrawi.h"
|
|
|
|
#include "dxwcore.hpp"
|
|
|
|
#include "stdio.h"
|
|
|
|
#include "hddraw.h"
|
|
|
|
#include "dxhelper.h"
|
|
|
|
#include "syslibs.h"
|
|
|
|
|
|
|
|
#define MAXBACKBUFFERS 4
|
|
|
|
|
|
|
|
extern void SetPixFmt(LPDDSURFACEDESC2);
|
|
|
|
extern void GetPixFmt(LPDDSURFACEDESC2);
|
2017-02-21 11:50:21 -05:00
|
|
|
extern CHAR *LogSurfaceAttributes(LPDDSURFACEDESC2, char *, int);
|
2016-11-26 11:48:21 -05:00
|
|
|
extern void DumpPixFmt(LPDDSURFACEDESC2);
|
|
|
|
extern void DescribeSurface(LPDIRECTDRAWSURFACE, int, char *, int);
|
|
|
|
extern void HookDDSurface(LPDIRECTDRAWSURFACE *, int, BOOL);
|
|
|
|
extern void RegisterPixelFormat(int, LPDIRECTDRAWSURFACE);
|
|
|
|
extern void SetVSyncDelays(int, LPDIRECTDRAW);
|
|
|
|
extern char *DumpPixelFormat(LPDDSURFACEDESC2);
|
|
|
|
extern void FixSurfaceCaps(LPDDSURFACEDESC2, int);
|
|
|
|
extern SetPalette_Type pSetPaletteMethod(int);
|
|
|
|
extern ReleaseS_Type pReleaseSMethod(int);
|
|
|
|
extern CreatePalette_Type pCreatePaletteMethod(int);
|
|
|
|
extern GetGDISurface_Type pGetGDISurfaceMethod(int);
|
|
|
|
|
|
|
|
extern int iBakBufferVersion;
|
|
|
|
extern LPDIRECTDRAWSURFACE lpDDSEmu_Prim;
|
|
|
|
extern LPDIRECTDRAWSURFACE lpDDSEmu_Back;
|
|
|
|
extern LPDIRECTDRAWSURFACE lpDDZBuffer;
|
|
|
|
extern DDSURFACEDESC2 DDSD_Prim;
|
|
|
|
extern LPDIRECTDRAWPALETTE lpDDP;
|
|
|
|
extern LPDIRECTDRAWCLIPPER lpddC;
|
|
|
|
extern LPDIRECTDRAW lpPrimaryDD;
|
|
|
|
extern int iDDPExtraRefCounter;
|
|
|
|
extern DWORD dwBackBufferCaps;
|
|
|
|
extern BOOL bFlippedDC;
|
|
|
|
extern PALETTEENTRY DefaultSystemPalette[];
|
|
|
|
extern GetGDISurface_Type pGetGDISurface1, pGetGDISurface2, pGetGDISurface3, pGetGDISurface4, pGetGDISurface7;
|
|
|
|
extern GetAttachedSurface_Type pGetAttachedSurface1, pGetAttachedSurface2, pGetAttachedSurface3, pGetAttachedSurface4, pGetAttachedSurface7;
|
|
|
|
extern CreateSurface1_Type pCreateSurface1, pCreateSurface2, pCreateSurface3, pCreateSurface4, pCreateSurface7;
|
|
|
|
extern ReleaseS_Type pReleaseS1, pReleaseS2, pReleaseS3, pReleaseS4, pReleaseS7;
|
|
|
|
extern GetPixelFormat_Type pGetPixelFormat1, pGetPixelFormat2, pGetPixelFormat3, pGetPixelFormat4, pGetPixelFormat7;
|
|
|
|
|
|
|
|
void InitDSScreenParameters(int dxversion, LPDIRECTDRAWSURFACE lpdds)
|
|
|
|
{
|
|
|
|
HRESULT res;
|
|
|
|
DDPIXELFORMAT p;
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
GetPixelFormat_Type pGetPixelFormat;
|
|
|
|
switch(dxversion){
|
|
|
|
case 1: pGetPixelFormat=pGetPixelFormat1; break;
|
|
|
|
case 2: pGetPixelFormat=pGetPixelFormat2; break;
|
|
|
|
case 3: pGetPixelFormat=pGetPixelFormat3; break;
|
|
|
|
case 4: pGetPixelFormat=pGetPixelFormat4; break;
|
|
|
|
case 7: pGetPixelFormat=pGetPixelFormat7; break;
|
|
|
|
}
|
|
|
|
//OutTrace("dxversion=%d pGetPixelFormat=%x\n", dxversion, pGetPixelFormat);
|
|
|
|
p.dwSize=sizeof(DDPIXELFORMAT);
|
|
|
|
if(res=(*pGetPixelFormat)(lpdds, &p)){
|
|
|
|
OutTraceE("GetPixelFormat: ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ddsd.ddpfPixelFormat = p;
|
|
|
|
OutTraceDW("InitDSScreenParameters: version=%d Actual %s\n", dxversion, DumpPixelFormat(&ddsd));
|
|
|
|
dxw.ActualPixelFormat = p;
|
|
|
|
SetBltTransformations(dxversion);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ClearSurfaceDesc(void *ddsd, int dxversion)
|
|
|
|
{
|
|
|
|
int size;
|
|
|
|
size = (dxversion < 4) ? sizeof(DDSURFACEDESC) : sizeof(DDSURFACEDESC2);
|
|
|
|
memset(ddsd, 0, size); // Clean all
|
|
|
|
((LPDDSURFACEDESC)ddsd)->dwSize = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void BuildRealSurfaces(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, int dxversion)
|
|
|
|
{
|
|
|
|
HRESULT res;
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: lpdd=%x pCreateSurface=%x version=%d\n", lpdd, pCreateSurface, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(lpDDSEmu_Prim==NULL){
|
|
|
|
ClearSurfaceDesc((void *)&ddsd, dxversion);
|
|
|
|
ddsd.dwFlags = DDSD_CAPS;
|
|
|
|
// try DDSCAPS_SYSTEMMEMORY first, then suppress it if not supported
|
|
|
|
// no, DDSCAPS_SYSTEMMEMORY cause screen flickering while moving the window (and other troubles?)
|
|
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: %s\n", LogSurfaceAttributes(&ddsd, "[EmuPrim]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0);
|
|
|
|
if(res==DDERR_PRIMARYSURFACEALREADYEXISTS){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: ASSERT DDSEmu_Prim already exists\n");
|
2016-11-26 11:48:21 -05:00
|
|
|
if(dxw.Windowize){
|
|
|
|
// in Windowize mode, the desktop properties are untouched, then the current primary surface can be recycled
|
|
|
|
res=(*pGetGDISurfaceMethod(dxversion))(lpdd, &lpDDSEmu_Prim);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// in non-Windowized mode, the primary surface must be released and rebuilt with the proper properties
|
|
|
|
res=(*pGetGDISurfaceMethod(dxversion))(lpdd, &lpDDSEmu_Prim);
|
|
|
|
if (lpDDSEmu_Prim) while((*pReleaseSMethod(dxversion))(lpDDSEmu_Prim));
|
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Prim, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildRealSurfaces: CreateSurface ERROR on DDSEmu_Prim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return;
|
|
|
|
}
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: created new DDSEmu_Prim=%x\n",lpDDSEmu_Prim);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(lpDDSEmu_Prim, dxversion, "DDSEmu_Prim", __LINE__);
|
|
|
|
InitDSScreenParameters(dxversion, lpDDSEmu_Prim);
|
|
|
|
dxwss.PopSurface(lpDDSEmu_Prim);
|
|
|
|
|
|
|
|
if (dxw.dwFlags3 & FORCECLIPPER){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: FORCE SetClipper on primary hwnd=%x lpdds=%x\n", dxw.GethWnd(), lpDDSEmu_Prim);
|
2016-11-26 11:48:21 -05:00
|
|
|
res=lpdd->CreateClipper(0, &lpddC, NULL);
|
2016-12-16 11:48:42 -05:00
|
|
|
if (res) OutTraceE("BuildRealSurfaces: CreateClipper ERROR res=%x(%s)\n", res, ExplainDDError(res));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=lpddC->SetHWnd(0, dxw.GethWnd());
|
2016-12-16 11:48:42 -05:00
|
|
|
if (res) OutTraceE("BuildRealSurfaces: SetHWnd ERROR res=%x(%s)\n", res, ExplainDDError(res));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=lpDDSEmu_Prim->SetClipper(lpddC);
|
2016-12-16 11:48:42 -05:00
|
|
|
if (res) OutTraceE("BuildRealSurfaces: SetClipper ERROR res=%x(%s)\n", res, ExplainDDError(res));
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
// can't hook lpDDSEmu_Prim as generic, since the Flip method is unimplemented for a PRIMARY surface!
|
|
|
|
// better avoid it or hook just useful methods.
|
|
|
|
//if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Prim, dxw.dwDDVersion);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(lpDDSEmu_Back==NULL){
|
|
|
|
ClearSurfaceDesc((void *)&ddsd, dxversion);
|
|
|
|
ddsd.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT;
|
|
|
|
ddsd.ddsCaps.dwCaps = dwBackBufferCaps;
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth();
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight();
|
|
|
|
if(dxw.dwFlags4 & BILINEAR2XFILTER){
|
|
|
|
// double backbuffer size
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth() << 1;
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight() << 1;
|
|
|
|
}
|
|
|
|
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: %s\n", LogSurfaceAttributes(&ddsd, "[EmuBack]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Back, 0);
|
|
|
|
if(res) {
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: %s\n", LogSurfaceAttributes(&ddsd, "[EmuBack]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, &lpDDSEmu_Back, 0);
|
|
|
|
}
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildRealSurfaces: CreateSurface ERROR on DDSEmuBack : res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return;
|
|
|
|
}
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildRealSurfaces: created new DDSEmu_Back=%x\n", lpDDSEmu_Back);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(lpDDSEmu_Back, dxversion, "DDSEmu_Back", __LINE__);
|
|
|
|
dxwss.PopSurface(lpDDSEmu_Back);
|
|
|
|
//if (dxw.dwTFlags & OUTPROXYTRACE) HookDDSurfaceGeneric(&lpDDSEmu_Back, dxversion);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void RestoreDDrawSurfaces()
|
|
|
|
{
|
|
|
|
// if it's a ddraw game ....
|
|
|
|
if(lpPrimaryDD){
|
|
|
|
OutTraceDW("RestoreDDrawSurfaces: rebuilding surfaces for dd session %x\n", lpPrimaryDD);
|
|
|
|
ReleaseS_Type pReleaseS;
|
|
|
|
CreateSurface_Type pCreateSurface;
|
|
|
|
switch(iBakBufferVersion){
|
|
|
|
case 1: pCreateSurface=(CreateSurface_Type)pCreateSurface1; pReleaseS=pReleaseS1; break;
|
|
|
|
case 2: pCreateSurface=(CreateSurface_Type)pCreateSurface2; pReleaseS=pReleaseS2; break;
|
|
|
|
case 3: pCreateSurface=(CreateSurface_Type)pCreateSurface3; pReleaseS=pReleaseS3; break;
|
|
|
|
case 4: pCreateSurface=(CreateSurface_Type)pCreateSurface4; pReleaseS=pReleaseS4; break;
|
|
|
|
case 7: pCreateSurface=(CreateSurface_Type)pCreateSurface7; pReleaseS=pReleaseS7; break;
|
|
|
|
}
|
|
|
|
if(lpDDSEmu_Back) while((*pReleaseS)(lpDDSEmu_Back)); lpDDSEmu_Back=0;
|
|
|
|
if(lpDDSEmu_Prim) while((*pReleaseS)(lpDDSEmu_Prim)); lpDDSEmu_Prim=0;
|
|
|
|
BuildRealSurfaces(lpPrimaryDD, pCreateSurface, iBakBufferVersion);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildPrimaryEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryEmu: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
// emulated primary surface
|
|
|
|
memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize);
|
|
|
|
|
|
|
|
// handle the surface attributes before the ddsd.dwFlags gets updated:
|
|
|
|
// if a surface desc is NOT specified, build one
|
|
|
|
if(!(ddsd.dwFlags & DDSD_PIXELFORMAT)) SetPixFmt((LPDDSURFACEDESC2)&ddsd);
|
|
|
|
// then save it
|
|
|
|
dxw.VirtualPixelFormat = ddsd.ddpfPixelFormat;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryEmu: DDSD_PIXELFORMAT color=%d flags=%x\n", dxw.VirtualPixelFormat.dwRGBBitCount, dxw.VirtualPixelFormat.dwFlags);
|
2016-11-26 11:48:21 -05:00
|
|
|
ddsd.dwFlags &= ~(DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE);
|
|
|
|
ddsd.dwFlags |= (DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT);
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
|
|
|
|
// DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces
|
|
|
|
ddsd.ddsCaps.dwCaps |= (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
|
|
|
|
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
|
|
|
|
if(dxw.dwFlags6 & NOSYSMEMPRIMARY) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
|
|
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth();
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight();
|
|
|
|
|
|
|
|
// create Primary surface
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildPrimaryEmu: %s\n", LogSurfaceAttributes(&ddsd, "[Primary]" , __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryEmu: CreateSurface ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
iBakBufferVersion=dxversion; // v2.03.01
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryEmu: created PRIMARY DDSPrim=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__);
|
|
|
|
HookDDSurface(lplpdds, dxversion, TRUE);
|
|
|
|
// "Hoyle Casino Empire" opens a primary surface and NOT a backbuffer ....
|
|
|
|
|
|
|
|
// build a default System palette and apply it to primary surface
|
|
|
|
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
|
|
|
|
(dxw.dwFlags6 & SYNCPALETTE)){
|
|
|
|
if(lpDDP == NULL){
|
|
|
|
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
|
2016-12-16 11:48:42 -05:00
|
|
|
if(res) OutTrace("BuildPrimaryEmu: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
// this must be done after hooking - who knows why?
|
|
|
|
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
|
|
|
|
if(res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryEmu: SetPalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
else iDDPExtraRefCounter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set a global capability value for surfaces that have to blit to primary
|
|
|
|
// DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces
|
|
|
|
// DDSCAPS_SYSTEMMEMORY makes operations faster, but it is not always good...
|
|
|
|
dwBackBufferCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
|
|
|
|
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
|
|
|
|
// this is important to avoid that certain D3D operations will abort - see "Forsaken" problem
|
|
|
|
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) dwBackBufferCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
|
|
|
|
|
|
if(dxw.dwFlags6 & SHAREDDC) bFlippedDC = TRUE;
|
|
|
|
|
|
|
|
if(dxw.dwFlags5 & GDIMODE) return DD_OK;
|
|
|
|
|
|
|
|
BuildRealSurfaces(lpdd, pCreateSurface, dxversion);
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildPrimaryFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
// emulated primary surface
|
|
|
|
memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize);
|
|
|
|
|
|
|
|
// handle the surface attributes before the ddsd.dwFlags gets updated:
|
|
|
|
// if a surface desc is NOT specified, build one
|
|
|
|
if(!(ddsd.dwFlags & DDSD_PIXELFORMAT)) SetPixFmt((LPDDSURFACEDESC2)&ddsd);
|
|
|
|
// then save it
|
|
|
|
dxw.VirtualPixelFormat = ddsd.ddpfPixelFormat;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryFlippable: DDSD_PIXELFORMAT color=%d flags=%x\n", dxw.VirtualPixelFormat.dwRGBBitCount, dxw.VirtualPixelFormat.dwFlags);
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// dwFlags
|
|
|
|
ddsd.dwFlags &= ~(DDSD_REFRESHRATE);
|
|
|
|
ddsd.dwFlags |= (DDSD_CAPS|DDSD_WIDTH|DDSD_HEIGHT|DDSD_PIXELFORMAT|DDSD_BACKBUFFERCOUNT);
|
2017-03-25 10:00:24 -04:00
|
|
|
// DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces
|
|
|
|
ddsd.ddsCaps.dwCaps |= (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// dwBackBufferCount: set to at least 1
|
|
|
|
if(!(lpddsd->dwFlags & DDSD_BACKBUFFERCOUNT) || (lpddsd->dwBackBufferCount == 0)) ddsd.dwBackBufferCount = 1;
|
|
|
|
|
|
|
|
// dwCaps
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM|DDSCAPS_FRONTBUFFER);
|
|
|
|
ddsd.ddsCaps.dwCaps |= (DDSCAPS_COMPLEX|DDSCAPS_FLIP|DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
|
|
|
|
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
|
|
|
|
if(dxw.dwFlags6 & NOSYSMEMPRIMARY) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
|
|
|
|
|
|
// dwWidth & dwHeight
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth();
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight();
|
|
|
|
|
|
|
|
// create Primary surface
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildPrimaryFlippable: %s\n", LogSurfaceAttributes(&ddsd, "[Primary]" , __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryFlippable: CreateSurface ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
iBakBufferVersion=dxversion; // v2.03.01
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryFlippable: created PRIMARY DDSPrim=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__);
|
|
|
|
HookDDSurface(lplpdds, dxversion, TRUE);
|
|
|
|
// "Hoyle Casino Empire" opens a primary surface and NOT a backbuffer ....
|
|
|
|
|
|
|
|
// build a default System palette and apply it to primary surface
|
|
|
|
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
|
|
|
|
(dxw.dwFlags6 & SYNCPALETTE)){
|
|
|
|
if(lpDDP == NULL){
|
|
|
|
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
|
2016-12-16 11:48:42 -05:00
|
|
|
if(res) OutTrace("BuildPrimaryFlippable: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
// this must be done after hooking - who knows why?
|
|
|
|
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
|
|
|
|
if(res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryFlippable: SetPalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
else iDDPExtraRefCounter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// set a global capability value for surfaces that have to blit to primary
|
|
|
|
dwBackBufferCaps = (DDSCAPS_OFFSCREENPLAIN|DDSCAPS_SYSTEMMEMORY);
|
|
|
|
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
|
|
|
|
// this is important to avoid that certain D3D operations will abort - see "Forsaken" problem
|
|
|
|
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) dwBackBufferCaps = DDSCAPS_OFFSCREENPLAIN;
|
|
|
|
|
|
|
|
if(dxw.dwFlags6 & SHAREDDC) bFlippedDC = TRUE;
|
|
|
|
|
|
|
|
if(dxw.dwFlags5 & GDIMODE) return DD_OK;
|
|
|
|
|
|
|
|
BuildRealSurfaces(lpdd, pCreateSurface, dxversion);
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildPrimaryFullscreen(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryFullscreen: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
// genuine primary surface
|
|
|
|
memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize);
|
|
|
|
|
|
|
|
// create Primary surface
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildPrimaryFullscreen: %s\n", LogSurfaceAttributes(&ddsd, "[Primary]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res){
|
|
|
|
if (res==DDERR_PRIMARYSURFACEALREADYEXISTS){
|
|
|
|
LPDIRECTDRAWSURFACE lpPrim;
|
|
|
|
GetGDISurface_Type pGetGDISurface;
|
2017-01-30 11:49:56 -05:00
|
|
|
pGetGDISurface = pGetGDISurfaceMethod(dxversion);
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryFullscreen: CreateSurface DDERR_PRIMARYSURFACEALREADYEXISTS workaround\n");
|
2016-11-26 11:48:21 -05:00
|
|
|
(*pGetGDISurface)(lpPrimaryDD, &lpPrim);
|
|
|
|
while ((*pReleaseSMethod(dxversion))(lpPrim));
|
|
|
|
res = (*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryFullscreen: CreateSurface ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryFullscreen: created PRIMARY DDSPrim=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__);
|
|
|
|
|
|
|
|
iBakBufferVersion=dxversion;
|
|
|
|
HookDDSurface(lplpdds, dxversion, TRUE);
|
|
|
|
if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor();
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildPrimaryDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryDir: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
// genuine primary surface
|
|
|
|
memcpy((void *)&ddsd, lpddsd, lpddsd->dwSize);
|
|
|
|
// v2.03.98 - when going to fullscreen mode and no emulation do not alter the capability masks, or in other words ...
|
|
|
|
// if doing emulation or in window mode, fix the capability masks (De Morgan docet)
|
|
|
|
ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE|DDSD_PIXELFORMAT);
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_FLIP|DDSCAPS_COMPLEX);
|
|
|
|
// v2.02.93: don't move primary / backbuf surfaces on systemmemory when 3DDEVICE is requested
|
|
|
|
// this impact also on capabilities for temporary surfaces for AERO optimized handling
|
2017-01-27 11:49:51 -05:00
|
|
|
// v2.04.08: this seems not always true, so it can be bypassed by ALLOWSYSMEMON3DDEV, just in case.
|
|
|
|
// should be tested with "Tomb Raider 3" in no emulation mode
|
|
|
|
if(!(dxw.dwFlags8 & ALLOWSYSMEMON3DDEV)){
|
|
|
|
if ((lpddsd->dwFlags & DDSD_CAPS) && (lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
|
|
}
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// create Primary surface
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildPrimaryDir: %s\n", LogSurfaceAttributes(&ddsd, "[Primary]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res){
|
|
|
|
if (res==DDERR_PRIMARYSURFACEALREADYEXISTS){
|
|
|
|
LPDIRECTDRAWSURFACE lpPrim;
|
|
|
|
GetGDISurface_Type pGetGDISurface;
|
2017-01-30 11:49:56 -05:00
|
|
|
pGetGDISurface = pGetGDISurfaceMethod(dxversion);
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryDir: CreateSurface DDERR_PRIMARYSURFACEALREADYEXISTS workaround\n");
|
2016-11-26 11:48:21 -05:00
|
|
|
(*pGetGDISurface)(lpPrimaryDD, &lpPrim);
|
|
|
|
while ((*pReleaseSMethod(dxversion))(lpPrim));
|
|
|
|
res = (*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
}
|
|
|
|
/* fall through */
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryDir: CreateSurface ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryDir: created PRIMARY DDSPrim=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim", __LINE__);
|
|
|
|
|
|
|
|
if(dxw.dwFlags1 & EMULATEBUFFER){
|
|
|
|
lpDDSEmu_Prim = *lplpdds;
|
|
|
|
dxwss.PopSurface(lpDDSEmu_Prim);
|
|
|
|
|
|
|
|
ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
|
|
|
|
// warning: can't create zero sized backbuffer surface !!!!
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth();
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight();
|
|
|
|
ddsd.ddsCaps.dwCaps = 0;
|
|
|
|
if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildPrimaryDir: %s\n", LogSurfaceAttributes(&ddsd, "[Dir FixBuf]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildPrimaryDir: CreateSurface ERROR on DDSPrim res=%x(%s) at %d\n",res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
return res;
|
|
|
|
}
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildPrimaryDir: created FIX DDSPrim=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSPrim(2)", __LINE__);
|
|
|
|
}
|
|
|
|
|
|
|
|
iBakBufferVersion=dxversion; // v2.03.37
|
|
|
|
HookDDSurface(lplpdds, dxversion, TRUE);
|
|
|
|
if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor();
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildBackBufferEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferEmu: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
// create BackBuffer surface
|
|
|
|
memcpy(&ddsd, lpddsd, lpddsd->dwSize);
|
|
|
|
ddsd.dwFlags &= ~(DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE);
|
|
|
|
ddsd.dwFlags |= (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT);
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_BACKBUFFER|DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
|
|
|
|
|
|
|
|
// v2.03.75: if a surface desc is NOT specified, build one. This will allow ZBUF attach.
|
|
|
|
if(!(lpddsd->dwFlags & DDSD_PIXELFORMAT)) SetPixFmt((LPDDSURFACEDESC2)&ddsd);
|
|
|
|
|
|
|
|
// DDSCAPS_OFFSCREENPLAIN seems required to support the palette in memory surfaces
|
|
|
|
ddsd.ddsCaps.dwCaps |= (DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN);
|
2017-01-27 11:49:51 -05:00
|
|
|
// necessary: Martian Gotic crashes otherwise
|
|
|
|
// v2.04.08: this seems no longer true in some cases, so ALLOWSYSMEMON3DDEV will bypass it.
|
|
|
|
// Should be tested with "Martian Gotic" and "Dominant Species" SW mode in emulation modes
|
|
|
|
if(!(dxw.dwFlags8 & ALLOWSYSMEMON3DDEV)){
|
|
|
|
if((ddsd.dwFlags & DDSD_CAPS) && (ddsd.ddsCaps.dwCaps & DDSCAPS_3DDEVICE))
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
|
|
}
|
2016-11-26 11:48:21 -05:00
|
|
|
// on WinXP Fifa 99 doesn't like DDSCAPS_SYSTEMMEMORY cap, so better to leave a way to unset it....
|
|
|
|
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth();
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight();
|
|
|
|
GetPixFmt(&ddsd);
|
|
|
|
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildBackBufferEmu: %s\n", LogSurfaceAttributes(&ddsd, "[Backbuf]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildBackBufferEmu: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferEmu: created BACK DDSBack=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
|
|
|
|
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
|
|
|
|
iBakBufferVersion=dxversion; // v2.02.31
|
|
|
|
|
|
|
|
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
|
|
|
|
(dxw.dwFlags6 & SYNCPALETTE)){
|
|
|
|
if(lpDDP == NULL){
|
|
|
|
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
|
2016-12-16 11:48:42 -05:00
|
|
|
if(res) OutTrace("BuildBackBufferEmu: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
// this must be done after hooking - who knows why?
|
|
|
|
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
|
|
|
|
if(res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildBackBufferEmu: SetPalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
else iDDPExtraRefCounter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// V2.1.85/V2.2.34: tricky !!!!
|
|
|
|
// When a real backbuffer is created, it has a reference to its frontbuffer.
|
|
|
|
// some games (Monopoly 3D) may depend on this setting - i.e. they could close
|
|
|
|
// the exceeding references - so this is better be replicated adding an initial
|
|
|
|
// reference to the zero count. But you don't have to do this if the backbuffer
|
|
|
|
// is created independently by the primary surface.
|
|
|
|
(*lplpdds)->AddRef(); // should it be repeated BBCount times????
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildBackBufferFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
//MessageBox(NULL, "BuildBackBufferFlippable", "DxWnd", MB_OK);
|
|
|
|
|
|
|
|
// create BackBuffer surface
|
|
|
|
memcpy(&ddsd, lpddsd, lpddsd->dwSize);
|
|
|
|
|
|
|
|
ddsd.dwFlags &= ~(DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE);
|
|
|
|
ddsd.dwFlags |= (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH|DDSD_PIXELFORMAT);
|
|
|
|
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_FRONTBUFFER|DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
|
|
|
|
ddsd.ddsCaps.dwCaps |= (DDSCAPS_SYSTEMMEMORY|DDSCAPS_OFFSCREENPLAIN);
|
|
|
|
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth();
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight();
|
|
|
|
GetPixFmt(&ddsd);
|
|
|
|
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildBackBufferFlippable: %s\n", LogSurfaceAttributes(&ddsd, "[Backbuf]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildBackBufferFlippable: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(res==DDERR_INVALIDPIXELFORMAT) DumpPixFmt(&ddsd);
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferFlippable: created BACK DDSBack=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
|
|
|
|
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
|
|
|
|
iBakBufferVersion=dxversion; // v2.02.31
|
|
|
|
|
|
|
|
if((ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8) &&
|
|
|
|
(dxw.dwFlags6 & SYNCPALETTE)){
|
|
|
|
if(lpDDP == NULL){
|
|
|
|
res=(*pCreatePaletteMethod(dxversion))(lpdd, DDPCAPS_8BIT|DDPCAPS_ALLOW256, DefaultSystemPalette, &lpDDP, NULL);
|
2016-12-16 11:48:42 -05:00
|
|
|
if(res) OutTrace("BuildBackBufferFlippable: CreatePalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
// this must be done after hooking - who knows why?
|
|
|
|
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
|
|
|
|
if(res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildBackBufferFlippable: SetPalette ERROR err=%x at %d\n", res, __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
else iDDPExtraRefCounter++;
|
|
|
|
}
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT AttachBackBufferFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
HRESULT res;
|
|
|
|
LPDIRECTDRAWSURFACE lpDDSPrim;
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("AttachBackBufferFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// retrieve the attached backbuffer surface and hook it
|
|
|
|
|
|
|
|
if(lpddsd->dwBackBufferCount == 0) return DD_OK; // nothing to retrieve
|
|
|
|
|
|
|
|
GetAttachedSurface_Type pGetAttachedSurface;
|
|
|
|
DDSCAPS2 caps;
|
|
|
|
switch(dxversion){
|
|
|
|
case 1: pGetAttachedSurface = pGetAttachedSurface1; break;
|
|
|
|
case 2: pGetAttachedSurface = pGetAttachedSurface2; break;
|
|
|
|
case 3: pGetAttachedSurface = pGetAttachedSurface3; break;
|
|
|
|
case 4: pGetAttachedSurface = pGetAttachedSurface4; break;
|
|
|
|
case 7: pGetAttachedSurface = pGetAttachedSurface7; break;
|
|
|
|
}
|
|
|
|
memset(&caps, 0, sizeof(caps));
|
|
|
|
caps.dwCaps = DDSCAPS_BACKBUFFER;
|
|
|
|
lpDDSPrim = dxwss.GetPrimarySurface();
|
|
|
|
res = (*pGetAttachedSurface)(lpDDSPrim, (LPDDSCAPS)&caps, lplpdds);
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("AttachBackBufferFlippable: GetAttachedSurface ERROR on DDSPrim res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("AttachBackBufferFlippable: retrieved BACK DDSBack=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
|
|
|
|
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
|
|
|
|
iBakBufferVersion=dxversion; // v2.02.31
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildBackBufferFullscreen(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferFullscreen: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT AttachBackBufferFullscreen(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("AttachBackBufferFullscreen: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildBackBufferDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferDir: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
// create BackBuffer surface
|
|
|
|
// ClearSurfaceDesc((void *)&ddsd, dxversion);
|
|
|
|
memcpy(&ddsd, lpddsd, lpddsd->dwSize);
|
|
|
|
if(dxw.IsEmulated || dxw.Windowize){
|
|
|
|
ddsd.dwFlags &= ~(DDSD_WIDTH|DDSD_HEIGHT|DDSD_BACKBUFFERCOUNT|DDSD_REFRESHRATE|DDSD_PIXELFORMAT);
|
|
|
|
ddsd.dwFlags |= (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH);
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_PRIMARYSURFACE|DDSCAPS_FLIP|DDSCAPS_COMPLEX);
|
|
|
|
// v2.02.93: don't move primary / backbuf surfaces on systemmemory when 3DDEVICE is requested
|
2017-01-27 11:49:51 -05:00
|
|
|
// v2.04.08: possibly no longer true ... to test with "Tomb Raider 3" non emulated modes
|
|
|
|
if(dxw.dwFlags8 & ALLOWSYSMEMON3DDEV){
|
2016-11-26 11:48:21 -05:00
|
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
|
|
|
|
}
|
2017-01-27 11:49:51 -05:00
|
|
|
else {
|
|
|
|
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) {
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
if (dxversion >= 4) ddsd.ddsCaps.dwCaps |= DDSCAPS_OFFSCREENPLAIN;
|
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_VIDEOMEMORY|DDSCAPS_LOCALVIDMEM);
|
|
|
|
}
|
|
|
|
}
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
if(dxw.dwFlags6 & NOSYSMEMBACKBUF) ddsd.ddsCaps.dwCaps &= ~DDSCAPS_SYSTEMMEMORY;
|
|
|
|
ddsd.dwWidth = dxw.GetScreenWidth();
|
|
|
|
ddsd.dwHeight = dxw.GetScreenHeight();
|
|
|
|
|
|
|
|
if (dxw.dwFlags2 & BACKBUFATTACH) {
|
|
|
|
LPDIRECTDRAWSURFACE lpPrim;
|
|
|
|
DDSURFACEDESC2 prim;
|
|
|
|
GetGDISurface_Type pGetGDISurface;
|
2017-01-30 11:49:56 -05:00
|
|
|
pGetGDISurface = pGetGDISurfaceMethod(dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
(*pGetGDISurface)(lpPrimaryDD, &lpPrim);
|
|
|
|
memset(&prim, 0, sizeof(DDSURFACEDESC2));
|
|
|
|
prim.dwSize = (dxversion >= 4) ? sizeof(DDSURFACEDESC2) : sizeof(DDSURFACEDESC);
|
|
|
|
res=lpPrim->GetSurfaceDesc((DDSURFACEDESC *)&prim);
|
|
|
|
(*pReleaseSMethod(dxversion))(lpPrim);
|
|
|
|
ddsd.dwWidth = prim.dwWidth;
|
|
|
|
ddsd.dwHeight = prim.dwHeight;
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferDir: BMX FIX res=%x(%s) wxh=(%dx%d)\n", res, ExplainDDError(res),ddsd.dwWidth, ddsd.dwHeight);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildBackBufferDir: %s\n", LogSurfaceAttributes(&ddsd, "[Backbuf]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
if(res) {
|
|
|
|
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res==DDERR_OUTOFVIDEOMEMORY)){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferDir: CreateSurface DDERR_OUTOFVIDEOMEMORY ERROR at %d, retry in SYSTEMMEMORY\n", __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, 0);
|
|
|
|
}
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildBackBufferDir: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildBackBufferDir: created BACK DDSBack=%x\n", *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
if(IsDebug) DescribeSurface(*lplpdds, dxversion, "DDSBack", __LINE__);
|
|
|
|
HookDDSurface(lplpdds, dxversion, FALSE); // added !!!
|
|
|
|
iBakBufferVersion=dxversion; // v2.02.31
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildGenericEmu(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericEmu: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy over ....
|
|
|
|
FixSurfaceCaps(&ddsd, dxversion);
|
|
|
|
// It looks that DDSCAPS_SYSTEMMEMORY surfaces can perfectly be DDSCAPS_3DDEVICE as well.
|
|
|
|
// For "Risk II" it is necessary that both the primary surface and the offscreen surfaces are generated
|
|
|
|
// with the same type, so that assuming an identical lPitch and memcopy-ing from one buffer to the
|
|
|
|
// other is a legitimate operation.
|
|
|
|
|
|
|
|
if(dxw.dwFlags6 & POWER2WIDTH){ // v2.03.28: POWER2WIDTH to fix "Midtown Madness" in surface emulation mode
|
|
|
|
if(((ddsd.dwFlags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) == (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) &&
|
|
|
|
(ddsd.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
|
|
|
|
){
|
|
|
|
DWORD dwWidth;
|
|
|
|
dwWidth = ((ddsd.dwWidth + 3) >> 2) << 2;
|
2016-12-16 11:48:42 -05:00
|
|
|
if(dwWidth != ddsd.dwWidth) OutTraceDW("BuildGenericEmu: POWER2WIDTH fix surface width %d->%d\n", ddsd.dwWidth, dwWidth);
|
2016-11-26 11:48:21 -05:00
|
|
|
ddsd.dwWidth = dwWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
|
2017-01-15 11:49:23 -05:00
|
|
|
// v2.04.05: error condition found & fixed on certain platforms for "Dominant Species" only (so far).
|
2017-01-17 11:49:27 -05:00
|
|
|
if (((res == DDERR_UNSUPPORTED) || (res == DDERR_UNSUPPORTEDMODE)) &&
|
|
|
|
(ddsd.ddsCaps.dwCaps & DDSCAPS_TEXTURE)){
|
2017-01-15 11:49:23 -05:00
|
|
|
OutTraceDW("BuildGenericEmu: CreateSurface ERROR res=%x(%s) at %d, TEXTURE->OFFSCREENPLAIN retry\n", res, ExplainDDError(res), __LINE__);
|
2017-01-17 11:49:27 -05:00
|
|
|
ddsd.ddsCaps.dwCaps &= ~(DDSCAPS_TEXTURE|DDSCAPS_ALLOCONLOAD);
|
|
|
|
ddsd.ddsCaps.dwCaps |= (DDSCAPS_OFFSCREENPLAIN);
|
2017-01-15 11:49:23 -05:00
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
|
2017-01-17 11:49:27 -05:00
|
|
|
}
|
2016-11-26 11:48:21 -05:00
|
|
|
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res!=DD_OK)){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericEmu: CreateSurface ERROR res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
|
|
|
|
}
|
|
|
|
if (res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildGenericEmu: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericEmu: CREATED lpddsd=%x version=%d %s\n",
|
2017-02-21 11:50:21 -05:00
|
|
|
*lplpdds, dxversion, LogSurfaceAttributes(&ddsd, "[Emu Generic]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// v2.02.66: if 8BPP paletized surface and a primary palette exixts, apply.
|
|
|
|
// fixes "Virtua Fighter PC" palette bug
|
|
|
|
if(lpDDP && (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)){
|
|
|
|
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
|
|
|
|
if(res)
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildGenericEmu: SetPalette ERROR lpdds=%x res=%x(%s) at %d\n", *lplpdds, res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
else {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericEmu: applied palette lpddp=%x to lpdds=%x\n", lpDDP, *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
iDDPExtraRefCounter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// diagnostic hooks ....
|
|
|
|
HookDDSurface(lplpdds, dxversion, FALSE);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildGenericFlippable(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericFlippable: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2016-11-26 11:48:21 -05:00
|
|
|
memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy over ....
|
|
|
|
FixSurfaceCaps(&ddsd, dxversion);
|
|
|
|
|
|
|
|
if(dxw.dwFlags6 & POWER2WIDTH){ // v2.03.28: POWER2WIDTH to fix "Midtown Madness" in surface emulation mode
|
|
|
|
if(((ddsd.dwFlags & (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) == (DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH)) &&
|
|
|
|
(ddsd.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN)
|
|
|
|
){
|
|
|
|
DWORD dwWidth;
|
|
|
|
dwWidth = ((ddsd.dwWidth + 3) >> 2) << 2;
|
2016-12-16 11:48:42 -05:00
|
|
|
if(dwWidth != ddsd.dwWidth) OutTraceDW("BuildGenericFlippable: POWER2WIDTH fix surface width %d->%d\n", ddsd.dwWidth, dwWidth);
|
2016-11-26 11:48:21 -05:00
|
|
|
ddsd.dwWidth = dwWidth;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
|
|
|
|
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && (res!=DD_OK)){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericFlippable: CreateSurface ERROR res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
ddsd.ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
|
|
ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
res=(*pCreateSurface)(lpdd, &ddsd, lplpdds, pu);
|
|
|
|
}
|
|
|
|
if (res) {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildGenericFlippable: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericFlippable: CREATED lpddsd=%x version=%d %s\n",
|
2017-02-21 11:50:21 -05:00
|
|
|
*lplpdds, dxversion, LogSurfaceAttributes(&ddsd, "[Emu Generic]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// v2.02.66: if 8BPP paletized surface and a primary palette exixts, apply.
|
|
|
|
// fixes "Virtua Fighter PC" palette bug
|
|
|
|
if(lpDDP && (ddsd.ddpfPixelFormat.dwFlags & DDPF_PALETTEINDEXED8)){
|
|
|
|
res=(*pSetPaletteMethod(dxversion))(*lplpdds, lpDDP);
|
|
|
|
if(res)
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildGenericFlippable: SetPalette ERROR on lpdds=%x res=%x(%s) at %d\n", *lplpdds, res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
else {
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericFlippable: applied palette lpddp=%x to lpdds=%x\n", lpDDP, *lplpdds);
|
2016-11-26 11:48:21 -05:00
|
|
|
iDDPExtraRefCounter++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// diagnostic hooks ....
|
|
|
|
HookDDSurface(lplpdds, dxversion, FALSE);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static HRESULT BuildGenericDir(LPDIRECTDRAW lpdd, CreateSurface_Type pCreateSurface, LPDDSURFACEDESC2 lpddsd, int dxversion, LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
HRESULT res;
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericDir: lpdd=%x pCreateSurface=%x lpddsd=%x version=%d\n", lpdd, pCreateSurface, lpddsd, dxversion);
|
2017-02-21 11:50:21 -05:00
|
|
|
OutTraceDW("BuildGenericDir: %s\n", LogSurfaceAttributes(lpddsd, "[Dir Generic]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0);
|
|
|
|
if(res){
|
|
|
|
// v2.02.60: Ref. game Incoming GOG release, post by Marek, error DDERR_UNSUPPORTED while trying to create ZBUFFER surface
|
|
|
|
if ((dxw.dwFlags1 & SWITCHVIDEOMEMORY) && ((res==DDERR_OUTOFVIDEOMEMORY)||(res==DDERR_UNSUPPORTED))){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericDir: CreateSurface ERROR res=%x(%s) at %d, retry\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
lpddsd->ddsCaps.dwCaps &= ~DDSCAPS_VIDEOMEMORY;
|
|
|
|
lpddsd->ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
|
|
|
|
res = (*pCreateSurface)(lpdd, lpddsd, lplpdds, 0);
|
|
|
|
}
|
|
|
|
if(res){
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceE("BuildGenericDir: CreateSurface ERROR res=%x(%s) at %d\n", res, ExplainDDError(res), __LINE__);
|
2016-11-26 11:48:21 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-12-16 11:48:42 -05:00
|
|
|
OutTraceDW("BuildGenericDir: CREATED lpddsd=%x version=%d %s\n",
|
2017-02-21 11:50:21 -05:00
|
|
|
*lplpdds, dxversion, LogSurfaceAttributes(lpddsd, "[Dir Generic]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// hooks ....
|
|
|
|
HookDDSurface(lplpdds, dxversion, FALSE);
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT WINAPI extCreateSurface(int dxversion, CreateSurface_Type pCreateSurface, LPDIRECTDRAW lpdd, DDSURFACEDESC2 *lpddsd,
|
|
|
|
LPDIRECTDRAWSURFACE *lplpdds, void *pu)
|
|
|
|
{
|
|
|
|
HRESULT res;
|
|
|
|
DDSURFACEDESC2 ddsd;
|
|
|
|
LPDIRECTDRAWSURFACE lpDDSPrim;
|
|
|
|
LPDIRECTDRAWSURFACE lpDDSBack = NULL;
|
|
|
|
DWORD CurFlags;
|
|
|
|
int TargetSize;
|
|
|
|
typedef HRESULT (*BuildSurface_Type)(LPDIRECTDRAW, CreateSurface_Type, LPDDSURFACEDESC2, int, LPDIRECTDRAWSURFACE *, void *);
|
|
|
|
static BuildSurface_Type BuildPrimary = 0;
|
|
|
|
static BuildSurface_Type BuildBackBuffer = 0;
|
|
|
|
static BuildSurface_Type AttachBackBuffer = 0;
|
|
|
|
static BuildSurface_Type BuildGeneric = 0;
|
|
|
|
static enum {
|
|
|
|
PRIMARY_FULLSCREEN = 0,
|
|
|
|
PRIMARY_DIRECT,
|
|
|
|
PRIMARY_FLIPPABLE,
|
|
|
|
PRIMARY_EMULATED
|
|
|
|
} SurfaceMode;
|
|
|
|
|
|
|
|
OutTraceDDRAW("CreateSurface(%d): lpdd=%x %s\n",
|
2017-02-21 11:50:21 -05:00
|
|
|
dxversion, lpdd, LogSurfaceAttributes(lpddsd, "[CreateSurface]", __LINE__));
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
// v2.03.95.fx1 - deleted: some texture handling REQUIRES a proper FourCC codec.
|
|
|
|
// maybe it could be suppressed by a dedicated config. flag and on primary surfaces only?
|
|
|
|
//lpddsd->ddpfPixelFormat.dwFourCC = 0;
|
|
|
|
|
|
|
|
// if not initialized yet ....
|
|
|
|
if(BuildPrimary == 0){
|
|
|
|
char *sLabel;
|
|
|
|
SurfaceMode = PRIMARY_FULLSCREEN;
|
|
|
|
if(dxw.IsEmulated || dxw.Windowize){
|
|
|
|
SurfaceMode = (dxw.dwFlags1 & EMULATESURFACE) ?
|
|
|
|
((dxw.dwFlags6 & FLIPEMULATION) ?
|
|
|
|
PRIMARY_EMULATED :
|
|
|
|
PRIMARY_FLIPPABLE) :
|
|
|
|
PRIMARY_DIRECT;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(SurfaceMode) {
|
|
|
|
case PRIMARY_FULLSCREEN:
|
|
|
|
BuildPrimary = BuildPrimaryFullscreen;
|
|
|
|
BuildBackBuffer = BuildBackBufferFullscreen;
|
|
|
|
AttachBackBuffer = AttachBackBufferFullscreen;
|
|
|
|
BuildGeneric = BuildGenericDir;
|
|
|
|
sLabel="FULLSCR";
|
|
|
|
break;
|
|
|
|
case PRIMARY_DIRECT:
|
|
|
|
BuildPrimary = BuildPrimaryDir;
|
|
|
|
BuildBackBuffer = BuildBackBufferDir;
|
|
|
|
AttachBackBuffer = BuildBackBufferDir;
|
|
|
|
BuildGeneric = BuildGenericDir;
|
|
|
|
sLabel="DIRECT";
|
|
|
|
break;
|
|
|
|
case PRIMARY_FLIPPABLE:
|
|
|
|
BuildPrimary = BuildPrimaryFlippable;
|
|
|
|
BuildBackBuffer = BuildBackBufferFlippable;
|
|
|
|
AttachBackBuffer = AttachBackBufferFlippable;
|
|
|
|
BuildGeneric = BuildGenericFlippable;
|
|
|
|
sLabel="FLIPPABLE";
|
|
|
|
break;
|
|
|
|
case PRIMARY_EMULATED:
|
|
|
|
BuildPrimary = BuildPrimaryEmu;
|
|
|
|
BuildBackBuffer = BuildBackBufferEmu;
|
|
|
|
AttachBackBuffer = BuildBackBufferEmu;
|
|
|
|
BuildGeneric = BuildGenericEmu;
|
|
|
|
sLabel="EMULATED";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
OutTraceDW("CreateSurface: MODE INITIALIZED mode=%d(%s)\n", SurfaceMode, sLabel);
|
|
|
|
}
|
|
|
|
|
|
|
|
// check for lpddsd->dwSize value
|
|
|
|
TargetSize=(dxversion<4)?sizeof(DDSURFACEDESC):sizeof(DDSURFACEDESC2);
|
|
|
|
if(lpddsd->dwSize != TargetSize){
|
|
|
|
char sMsg[81];
|
|
|
|
sprintf_s(sMsg,80, "CreateSurface: ASSERT bad dwSize=%d dxversion=%d\n",
|
|
|
|
lpddsd->dwSize, dxversion);
|
|
|
|
OutTraceDW(sMsg);
|
|
|
|
if(IsAssertEnabled) MessageBox(0, sMsg, "CreateSurface", MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
}
|
|
|
|
|
|
|
|
//GHO workaround (needed for WarWind, Rogue Spear):
|
|
|
|
if (lpddsd->dwFlags && !(lpddsd->dwFlags & 0x1)){
|
|
|
|
OutTraceDW("CreateSurface: fixing illegal dwFlags value: %x -> %x\n",
|
|
|
|
lpddsd->dwFlags, (lpddsd->dwFlags | DDSD_CAPS));
|
|
|
|
lpddsd->dwFlags |= DDSD_CAPS;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(&ddsd, lpddsd, lpddsd->dwSize); // Copy
|
|
|
|
|
|
|
|
// v2.02.38: this is odd: in "Star Force Deluxe" there is no PRIMARY surface, but a surface with
|
|
|
|
// 0 flags and 0 capabilities serves for this purpose. Is it a side-effect of old ddraw releases?
|
|
|
|
if((dxversion == 1) && ((ddsd.dwFlags & ~DDSD_BACKBUFFERCOUNT) == 0)){ // Star Force Deluxe
|
|
|
|
ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH;
|
|
|
|
ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
|
|
|
//if(dxw.VirtualPixelFormat.dwRGBBitCount == 8) ddsd.ddsCaps.dwCaps |= DDSCAPS_PALETTE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// creation of the primary surface....
|
|
|
|
if(ddsd.dwFlags & DDSD_CAPS && ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE){
|
|
|
|
dxwss.ClearSurfaceList(); // v2.03.83: "Daytona USA" would saturate the list otherwise
|
|
|
|
SetVSyncDelays(dxversion, lpdd);
|
|
|
|
GetHookInfo()->Height=(short)dxw.GetScreenHeight();
|
|
|
|
GetHookInfo()->Width=(short)dxw.GetScreenWidth();
|
|
|
|
GetHookInfo()->ColorDepth=(short)dxw.VirtualPixelFormat.dwRGBBitCount;
|
|
|
|
GetHookInfo()->DXVersion=dxversion;
|
|
|
|
lpPrimaryDD = lpdd; // v2.1.87
|
|
|
|
memcpy(&DDSD_Prim, lpddsd, sizeof(DDSD_Prim)); // v2.02.37
|
|
|
|
|
|
|
|
// beware of the different behaviour between older and newer directdraw releases...
|
|
|
|
if(dxversion >= 4){
|
|
|
|
if (lpDDSEmu_Back) while(lpDDSEmu_Back->Release());
|
|
|
|
if (lpDDSEmu_Prim) while(lpDDSEmu_Prim->Release());
|
|
|
|
if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) { // Praetorians !!!!
|
|
|
|
lpDDSBack = dxwss.GetBackBufferSurface();
|
|
|
|
if (lpDDSBack) {
|
|
|
|
if(dxw.dwFlags6 & FLIPEMULATION) while(lpDDSBack->Release());
|
|
|
|
dxwss.PopSurface(lpDDSBack);
|
|
|
|
lpDDSBack = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lpDDSEmu_Back=NULL;
|
|
|
|
lpDDSEmu_Prim=NULL;
|
|
|
|
|
|
|
|
int BBCount=0; // or 1 ??
|
|
|
|
if (ddsd.dwFlags & DDSD_BACKBUFFERCOUNT) BBCount=ddsd.dwBackBufferCount;
|
|
|
|
if ((BBCount > 0) && (iBakBufferVersion < 4)){
|
|
|
|
lpDDSBack=NULL;
|
|
|
|
OutTraceDW("CreateSurface: backbuffer cleared - BackBufferCount=%d\n", BBCount);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (BBCount > MAXBACKBUFFERS){
|
|
|
|
char sMsg[81];
|
|
|
|
sprintf_s(sMsg, 80, "CreateSurface: BackBufferCount=%d\n", BBCount);
|
|
|
|
OutTraceDW(sMsg);
|
|
|
|
if (IsAssertEnabled) MessageBox(0, sMsg, "CreateSurface", MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
// recover ...
|
|
|
|
BBCount = MAXBACKBUFFERS;
|
|
|
|
}
|
|
|
|
|
|
|
|
// build emulated primary surface, real primary and backbuffer surfaces
|
|
|
|
CurFlags=ddsd.dwFlags;
|
|
|
|
res=BuildPrimary(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, NULL);
|
|
|
|
if(res) return res;
|
|
|
|
lpDDSPrim = *lplpdds;
|
2017-03-25 09:58:54 -04:00
|
|
|
dxwss.PushPrimarySurface(lpDDSPrim, dxversion, lpddsd->ddsCaps.dwCaps);
|
2016-11-26 11:48:21 -05:00
|
|
|
RegisterPixelFormat(dxversion, lpDDSPrim);
|
|
|
|
|
|
|
|
if (BBCount){
|
2017-01-30 11:49:56 -05:00
|
|
|
DWORD dwCaps;
|
2016-11-26 11:48:21 -05:00
|
|
|
// build emulated backbuffer surface
|
|
|
|
res=AttachBackBuffer(lpdd, pCreateSurface, lpddsd, dxversion, &lpDDSBack, NULL);
|
|
|
|
if(res) return res;
|
2017-01-30 11:49:56 -05:00
|
|
|
// here we try to guess what sort of capabilities would expose a built-in backbuffer surface
|
|
|
|
dwCaps = lpddsd->ddsCaps.dwCaps;
|
|
|
|
dwCaps &= ~DDSCAPS_PRIMARYSURFACE;
|
|
|
|
dwCaps |= (DDSCAPS_BACKBUFFER|DDSCAPS_VIDEOMEMORY);
|
2017-03-25 09:58:54 -04:00
|
|
|
dxwss.PushBackBufferSurface(lpDDSBack, dxversion, dwCaps);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
if(IsTraceDDRAW){
|
|
|
|
char sInfo[256+1];
|
|
|
|
sprintf(sInfo, "CreateSurface: created DDSPrim=%x DDSBack=%x", lpDDSPrim, lpDDSBack);
|
|
|
|
if(dxw.IsEmulated) sprintf(sInfo, "%s DDSEmu_Prim=%x", sInfo, lpDDSEmu_Prim);
|
|
|
|
if(dxw.dwFlags1 & EMULATESURFACE) sprintf(sInfo, "%s DDSEmu_Back=%x", sInfo, lpDDSEmu_Back);
|
|
|
|
strcat(sInfo, "\n");
|
|
|
|
OutTrace(sInfo);
|
|
|
|
}
|
|
|
|
|
|
|
|
// rebuild the clipper area
|
|
|
|
if(dxw.dwFlags1 & CLIPCURSOR) dxw.SetClipCursor();
|
|
|
|
|
|
|
|
// v2.2.64: added extra ref needed to preserve ddraw session for later use. Is it a ddraw1 legacy?
|
|
|
|
// seems to fix problems in "Warhammer 40K Rites Of War" that uses a ddraw session after reaching 0 refcount.
|
|
|
|
// v2.2.84: avoid the extra referenced in non windowed mode since it causes the window shift reported by gsky916
|
|
|
|
// for Wind Fantasy SP.
|
|
|
|
// v2.3.59: same extra reference is needed by "Wahammer Chaos Gate" that uses ddraw interface release 2
|
|
|
|
// v2.3.72: fixed previous fix: condition is <=2, not >=2 !
|
|
|
|
// Be aware that it may perhaps become <=3, if we get the same problem elsewhere
|
|
|
|
// v2.3.96: deleted the if(Windowized) condition: AddRef is needed also in fullscreen mode.
|
|
|
|
if(dxw.dwDDVersion<=2) lpdd->AddRef();
|
|
|
|
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// a request for a separate (not complex) backbuffer to attach later on, maybe.
|
|
|
|
if ((ddsd.dwFlags & DDSD_CAPS) && (ddsd.ddsCaps.dwCaps & DDSCAPS_BACKBUFFER)){
|
|
|
|
if (lpDDSBack) {
|
|
|
|
OutTraceDW("CreateSurface: returning current DDSBack=%x\n", lpDDSBack);
|
|
|
|
*lplpdds = lpDDSBack;
|
|
|
|
return DD_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
res=BuildBackBuffer(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, NULL);
|
2017-03-25 09:58:54 -04:00
|
|
|
if(res == DD_OK) dxwss.PushBackBufferSurface(*lplpdds, dxversion, lpddsd->ddsCaps.dwCaps);
|
2016-11-26 11:48:21 -05:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
// if nothing else, it's a generic/zbuffer surface
|
2017-03-25 09:58:54 -04:00
|
|
|
// Note: should DxWnd trace a memory 3D surface that will be used as reference surface for D3D CreateDevice?
|
2016-11-26 11:48:21 -05:00
|
|
|
|
|
|
|
res=BuildGeneric(lpdd, pCreateSurface, lpddsd, dxversion, lplpdds, pu);
|
|
|
|
if(!res) {
|
|
|
|
dxwss.PopSurface(*lplpdds);
|
|
|
|
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_ZBUFFER) {
|
|
|
|
// v2.03.82: save ZBUFFER capabilities for later fix in D3D CreateDevice
|
|
|
|
OutTraceDW("CreateSurface: lpDDZBuffer=%x save ZBUFFER caps=%x(%s)\n", *lplpdds, lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
|
2016-12-16 11:48:42 -05:00
|
|
|
lpDDZBuffer = *lplpdds;
|
2017-02-15 11:50:18 -05:00
|
|
|
// save surface size expressed in bytes
|
|
|
|
extern int ZBufferSize;
|
|
|
|
ZBufferSize = lpddsd->dwWidth * lpddsd->dwHeight * (lpddsd->ddpfPixelFormat.dwZBufferBitDepth >> 3);
|
2017-03-25 09:58:54 -04:00
|
|
|
dxwss.PushZBufferSurface(*lplpdds, dxversion, lpddsd->ddsCaps.dwCaps);
|
2017-02-15 11:50:18 -05:00
|
|
|
OutTraceDW("CreateSurface: ZBufferSize=%d\n", ZBufferSize);
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
2017-03-25 09:59:46 -04:00
|
|
|
else {
|
|
|
|
if(lpddsd->ddsCaps.dwCaps & DDSCAPS_3DDEVICE) {
|
|
|
|
OutTraceDW("CreateSurface: lpDD3DRef=%x save 3DREF caps=%x(%s)\n", *lplpdds, lpddsd->ddsCaps.dwCaps, ExplainDDSCaps(lpddsd->ddsCaps.dwCaps));
|
|
|
|
dxwss.Push3DRefSurface(*lplpdds, dxversion, lpddsd->ddsCaps.dwCaps);
|
|
|
|
}
|
|
|
|
}
|
2016-11-26 11:48:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|