mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
1021 lines
32 KiB
C++
1021 lines
32 KiB
C++
/*
|
|
* sfall
|
|
* Copyright (C) 2008, 2009, 2010, 2012 The sfall team
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 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 received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifdef _DEBUG
|
|
#define D3D_DEBUG_INFO
|
|
#define DEBUGMESS(a) OutputDebugStringA(a)
|
|
#else
|
|
#define DEBUGMESS(a)
|
|
#endif
|
|
|
|
#include <d3d9.h>
|
|
#include <d3dx9.h>
|
|
#include <ddraw.h>
|
|
#include <math.h>
|
|
#include <stdio.h>
|
|
#include <vector>
|
|
|
|
#include "..\main.h"
|
|
|
|
#include "..\FalloutEngine\Fallout2.h"
|
|
#include "..\InputFuncs.h"
|
|
#include "..\Version.h"
|
|
|
|
#include "Graphics.h"
|
|
#include "LoadGameHook.h"
|
|
|
|
namespace sfall
|
|
{
|
|
|
|
typedef HRESULT (_stdcall *DDrawCreateProc)(void*, IDirectDraw**, void*);
|
|
typedef IDirect3D9* (_stdcall *D3DCreateProc)(UINT version);
|
|
|
|
#define UNUSEDFUNCTION { DEBUGMESS("Unused function called: " __FUNCTION__); return DDERR_GENERIC; }
|
|
#define SAFERELEASE(a) { if (a) { a->Release(); a = 0; } }
|
|
|
|
static DWORD ResWidth;
|
|
static DWORD ResHeight;
|
|
static DWORD GPUBlt;
|
|
|
|
static bool DeviceLost = false;
|
|
static DDSURFACEDESC surfaceDesc;
|
|
static DDSURFACEDESC movieDesc;
|
|
|
|
static DWORD palette[256];
|
|
|
|
static DWORD gWidth;
|
|
static DWORD gHeight;
|
|
|
|
static int ScrollWindowKey;
|
|
static DWORD windowLeft = 0;
|
|
static DWORD windowTop = 0;
|
|
|
|
static DWORD ShaderVersion;
|
|
|
|
static HWND window;
|
|
IDirect3D9* d3d9 = 0;
|
|
IDirect3DDevice9* d3d9Device = 0;
|
|
static IDirect3DTexture9* Tex = 0;
|
|
static IDirect3DTexture9* sTex1 = 0;
|
|
static IDirect3DTexture9* sTex2 = 0;
|
|
static IDirect3DSurface9* sSurf1 = 0;
|
|
static IDirect3DSurface9* sSurf2 = 0;
|
|
static IDirect3DSurface9* backbuffer = 0;
|
|
static IDirect3DVertexBuffer9* vBuffer;
|
|
static IDirect3DVertexBuffer9* vBuffer2;
|
|
static IDirect3DVertexBuffer9* movieBuffer;
|
|
static IDirect3DTexture9* gpuPalette;
|
|
static IDirect3DTexture9* movieTex = 0;
|
|
|
|
static ID3DXEffect* gpuBltEffect;
|
|
static const char* gpuEffect=
|
|
"texture image;\n"
|
|
"texture palette;\n"
|
|
"texture head;\n"
|
|
"sampler s0 = sampler_state { texture=<image>; MAGFILTER=POINT; MINFILTER=POINT; };\n"
|
|
"sampler s1 = sampler_state { texture=<palette>; MAGFILTER=POINT; MINFILTER=POINT; };\n"
|
|
"sampler s2 = sampler_state { texture=<head>; MAGFILTER=POINT; MINFILTER=POINT; };\n"
|
|
"float2 size;\n"
|
|
"float2 corner;\n"
|
|
"float4 P0( in float2 Tex : TEXCOORD0 ) : COLOR0 {\n"
|
|
" float3 result = tex1D(s1, tex2D(s0, Tex).a);\n"
|
|
" return float4(result.b, result.g, result.r, 1);\n"
|
|
"}\n"
|
|
"float4 P1( in float2 Tex : TEXCOORD0 ) : COLOR0 {\n"
|
|
" float backdrop = tex2D(s0, Tex).a;\n"
|
|
" float3 result;\n"
|
|
" if(abs(backdrop-(48.0/255.0))<0.001) {\n"
|
|
//" float2 size = float2(388.0/640.0, 200.0/480.0);\n"
|
|
//" float2 corner = float2(126.0/640.0, 14.0/480.0);\n"
|
|
" result = tex2D(s2, saturate((Tex-corner)/size));\n"
|
|
" } else {\n"
|
|
" result = tex1D(s1, backdrop);\n"
|
|
" result = float3(result.b, result.g, result.r);\n"
|
|
" }\n"
|
|
" return float4(result.r, result.g, result.b, 1);\n"
|
|
"}\n"
|
|
"technique T0\n"
|
|
"{\n"
|
|
" pass p0 { PixelShader = compile ps_2_0 P0(); }\n"
|
|
"}\n"
|
|
"technique T1\n"
|
|
"{\n"
|
|
" pass p1 { PixelShader = compile ps_2_0 P1(); }\n"
|
|
"}\n"
|
|
;
|
|
|
|
static D3DXHANDLE gpuBltBuf;
|
|
static D3DXHANDLE gpuBltPalette;
|
|
static D3DXHANDLE gpuBltHead;
|
|
static D3DXHANDLE gpuBltHeadSize;
|
|
static D3DXHANDLE gpuBltHeadCorner;
|
|
|
|
static float rcpres[2];
|
|
|
|
DWORD Graphics::mode;
|
|
|
|
struct sShader {
|
|
ID3DXEffect* Effect;
|
|
bool Active;
|
|
D3DXHANDLE ehTicks;
|
|
DWORD mode;
|
|
DWORD mode2;
|
|
|
|
sShader() {
|
|
Effect=0;
|
|
Active=false;
|
|
ehTicks=0;
|
|
mode=0;
|
|
mode2=0;
|
|
}
|
|
};
|
|
|
|
static std::vector<sShader> shaders;
|
|
static std::vector<IDirect3DTexture9*> shaderTextures;
|
|
|
|
#define MYVERTEXFORMAT D3DFVF_XYZRHW|D3DFVF_TEX1
|
|
struct MyVertex {
|
|
float x,y,z,w,u,v;
|
|
};
|
|
|
|
static MyVertex ShaderVertices[] = {
|
|
{-0.5, -0.5, 0, 1, 0, 0},
|
|
{-0.5, 479.5, 0, 1, 0, 1},
|
|
{639.5, -0.5, 0, 1, 1, 0},
|
|
{639.5, 479.5, 0, 1, 1, 1}
|
|
};
|
|
|
|
void GetFalloutWindowInfo(DWORD* width, DWORD* height, HWND* wnd) {
|
|
*width = gWidth;
|
|
*height = gHeight;
|
|
*wnd = window;
|
|
}
|
|
|
|
int _stdcall GetShaderVersion() {
|
|
return ShaderVersion;
|
|
}
|
|
|
|
void _stdcall SetShaderMode(DWORD d, DWORD mode) {
|
|
if (d >= shaders.size() || !shaders[d].Effect) return;
|
|
if (mode & 0x80000000) {
|
|
shaders[d].mode2 = mode ^ 0x80000000;
|
|
} else {
|
|
shaders[d].mode = mode;
|
|
}
|
|
}
|
|
|
|
int _stdcall LoadShader(const char* path) {
|
|
if ((Graphics::mode < 4) || (strstr(path, "..")) || (strstr(path, ":"))) return -1;
|
|
char buf[MAX_PATH];
|
|
sprintf(buf, "%s\\shaders\\%s", fo::var::patches, path);
|
|
for (DWORD d = 0; d < shaders.size(); d++) {
|
|
if (!shaders[d].Effect) {
|
|
if (FAILED(D3DXCreateEffectFromFile(d3d9Device, buf, 0, 0, 0, 0, &shaders[d].Effect, 0))) return -1;
|
|
else return d;
|
|
}
|
|
}
|
|
sShader shader = sShader();
|
|
if (FAILED(D3DXCreateEffectFromFile(d3d9Device, buf, 0, 0, 0, 0, &shader.Effect, 0))) return -1;
|
|
|
|
shader.Effect->SetFloatArray("rcpres", rcpres, 2);
|
|
|
|
for (int i = 1; i < 128; i++) {
|
|
const char* name;
|
|
IDirect3DTexture9* tex;
|
|
|
|
sprintf_s(buf, "texname%d", i);
|
|
if (FAILED(shader.Effect->GetString(buf, &name))) break;
|
|
sprintf_s(buf, "%s\\art\\stex\\%s", fo::var::patches, name);
|
|
if (FAILED(D3DXCreateTextureFromFileA(d3d9Device, buf, &tex))) continue;
|
|
sprintf_s(buf, "tex%d", i);
|
|
shader.Effect->SetTexture(buf, tex);
|
|
shaderTextures.push_back(tex);
|
|
}
|
|
|
|
shader.ehTicks = shader.Effect->GetParameterByName(0, "tickcount");
|
|
shaders.push_back(shader);
|
|
return shaders.size() - 1;
|
|
}
|
|
|
|
void _stdcall ActivateShader(DWORD d) {
|
|
if (d < shaders.size() && shaders[d].Effect) shaders[d].Active = true;
|
|
}
|
|
|
|
void _stdcall DeactivateShader(DWORD d) {
|
|
if (d < shaders.size()) shaders[d].Active = false;
|
|
}
|
|
|
|
int _stdcall GetShaderTexture(DWORD d, DWORD id) {
|
|
if (d >= shaders.size() || !shaders[d].Effect || id < 1 || id>128) return -1;
|
|
IDirect3DBaseTexture9* tex = 0;
|
|
char buf[8];
|
|
buf[0] = 't'; buf[1] = 'e'; buf[2] = 'x';
|
|
_itoa_s(id, &buf[3], 4, 10);
|
|
if (FAILED(shaders[d].Effect->GetTexture(buf, &tex))) return -1;
|
|
if (!tex) return -1;
|
|
tex->Release();
|
|
for (DWORD i = 0; i < shaderTextures.size(); i++) {
|
|
if (shaderTextures[i] == tex) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
void _stdcall FreeShader(DWORD d) {
|
|
if (d < shaders.size()) {
|
|
SAFERELEASE(shaders[d].Effect);
|
|
shaders[d].Active = false;
|
|
}
|
|
}
|
|
|
|
void _stdcall SetShaderInt(DWORD d, const char* param, int value) {
|
|
if (d >= shaders.size() || !shaders[d].Effect) return;
|
|
shaders[d].Effect->SetInt(param, value);
|
|
}
|
|
|
|
void _stdcall SetShaderFloat(DWORD d, const char* param, float value) {
|
|
if (d >= shaders.size() || !shaders[d].Effect) return;
|
|
shaders[d].Effect->SetFloat(param, value);
|
|
}
|
|
|
|
void _stdcall SetShaderVector(DWORD d, const char* param, float f1, float f2, float f3, float f4) {
|
|
if (d >= shaders.size() || !shaders[d].Effect) return;
|
|
shaders[d].Effect->SetFloatArray(param, &f1, 4);
|
|
}
|
|
|
|
void _stdcall SetShaderTexture(DWORD d, const char* param, DWORD value) {
|
|
if (d >= shaders.size() || !shaders[d].Effect || value >= shaderTextures.size()) return;
|
|
shaders[d].Effect->SetTexture(param, shaderTextures[value]);
|
|
}
|
|
|
|
static void ResetDevice(bool CreateNew) {
|
|
D3DPRESENT_PARAMETERS params;
|
|
ZeroMemory(¶ms, sizeof(params));
|
|
params.BackBufferCount = 1;
|
|
params.BackBufferFormat = (Graphics::mode == 5) ? D3DFMT_UNKNOWN : D3DFMT_X8R8G8B8;
|
|
params.BackBufferWidth = gWidth;
|
|
params.BackBufferHeight = gHeight;
|
|
params.EnableAutoDepthStencil = false;
|
|
params.MultiSampleQuality = 0;
|
|
params.MultiSampleType = D3DMULTISAMPLE_NONE;
|
|
params.Windowed = (Graphics::mode == 5);
|
|
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
|
params.hDeviceWindow = window;
|
|
params.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
|
|
|
|
bool software = false;
|
|
if (CreateNew) {
|
|
if (FAILED(d3d9->CreateDevice(0, D3DDEVTYPE_HAL, window, D3DCREATE_PUREDEVICE | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, ¶ms, &d3d9Device))) {
|
|
software = true;
|
|
d3d9->CreateDevice(0, D3DDEVTYPE_HAL, window, D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, ¶ms, &d3d9Device);
|
|
}
|
|
D3DCAPS9 caps;
|
|
d3d9Device->GetDeviceCaps(&caps);
|
|
ShaderVersion = ((caps.PixelShaderVersion & 0x0000ff00) >> 8) * 10 + (caps.PixelShaderVersion & 0xff);
|
|
|
|
if (GPUBlt == 2) {
|
|
if (ShaderVersion < 20) GPUBlt = 0;
|
|
}
|
|
|
|
if (GPUBlt) {
|
|
D3DXCreateEffect(d3d9Device, gpuEffect, strlen(gpuEffect), 0, 0, 0, 0, &gpuBltEffect, 0);
|
|
gpuBltBuf = gpuBltEffect->GetParameterByName(0, "image");
|
|
gpuBltPalette = gpuBltEffect->GetParameterByName(0, "palette");
|
|
gpuBltHead = gpuBltEffect->GetParameterByName(0, "head");
|
|
gpuBltHeadSize = gpuBltEffect->GetParameterByName(0, "size");
|
|
gpuBltHeadCorner = gpuBltEffect->GetParameterByName(0, "corner");
|
|
}
|
|
} else {
|
|
d3d9Device->Reset(¶ms);
|
|
if (gpuBltEffect) gpuBltEffect->OnResetDevice();
|
|
for (DWORD d = 0; d < shaders.size(); d++) {
|
|
if (shaders[d].Effect) shaders[d].Effect->OnResetDevice();
|
|
}
|
|
}
|
|
|
|
ShaderVertices[1].y = ResHeight - 0.5f;
|
|
ShaderVertices[2].x = ResWidth - 0.5f;
|
|
ShaderVertices[3].y = ResHeight - 0.5f;
|
|
ShaderVertices[3].x = ResWidth - 0.5f;
|
|
d3d9Device->CreateTexture(ResWidth, ResHeight, 1, D3DUSAGE_DYNAMIC, GPUBlt ? D3DFMT_A8 : D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &Tex, 0);
|
|
d3d9Device->CreateTexture(ResWidth, ResHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &sTex1, 0);
|
|
d3d9Device->CreateTexture(ResWidth, ResHeight, 1, D3DUSAGE_RENDERTARGET, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &sTex2, 0);
|
|
if (GPUBlt) {
|
|
d3d9Device->CreateTexture(256, 1, 1, D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT, &gpuPalette, 0);
|
|
gpuBltEffect->SetTexture(gpuBltBuf, Tex);
|
|
gpuBltEffect->SetTexture(gpuBltPalette, gpuPalette);
|
|
}
|
|
|
|
sTex1->GetSurfaceLevel(0, &sSurf1);
|
|
sTex2->GetSurfaceLevel(0, &sSurf2);
|
|
d3d9Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backbuffer);
|
|
|
|
d3d9Device->CreateVertexBuffer(4 * sizeof(MyVertex), D3DUSAGE_WRITEONLY | (software ? D3DUSAGE_SOFTWAREPROCESSING : 0), MYVERTEXFORMAT, D3DPOOL_DEFAULT, &vBuffer, 0);
|
|
byte* VertexPointer;
|
|
vBuffer->Lock(0, 0, (void**)&VertexPointer, 0);
|
|
CopyMemory(VertexPointer, ShaderVertices, sizeof(ShaderVertices));
|
|
vBuffer->Unlock();
|
|
|
|
d3d9Device->CreateVertexBuffer(4 * sizeof(MyVertex), D3DUSAGE_WRITEONLY | (software ? D3DUSAGE_SOFTWAREPROCESSING : 0), MYVERTEXFORMAT, D3DPOOL_DEFAULT, &movieBuffer, 0);
|
|
|
|
MyVertex ShaderVertices2[4] = {
|
|
ShaderVertices[0],
|
|
ShaderVertices[1],
|
|
ShaderVertices[2],
|
|
ShaderVertices[3]
|
|
};
|
|
|
|
ShaderVertices2[1].y = (float)gHeight - 0.5f;
|
|
ShaderVertices2[2].x = (float)gWidth - 0.5f;
|
|
ShaderVertices2[3].y = (float)gHeight - 0.5f;
|
|
ShaderVertices2[3].x = (float)gWidth - 0.5f;
|
|
|
|
d3d9Device->CreateVertexBuffer(4 * sizeof(MyVertex), D3DUSAGE_WRITEONLY | (software ? D3DUSAGE_SOFTWAREPROCESSING : 0), MYVERTEXFORMAT, D3DPOOL_DEFAULT, &vBuffer2, 0);
|
|
vBuffer2->Lock(0, 0, (void**)&VertexPointer, 0);
|
|
CopyMemory(VertexPointer, ShaderVertices2, sizeof(ShaderVertices2));
|
|
vBuffer2->Unlock();
|
|
|
|
d3d9Device->SetFVF(MYVERTEXFORMAT);
|
|
d3d9Device->SetTexture(0, Tex);
|
|
d3d9Device->SetStreamSource(0, vBuffer, 0, sizeof(MyVertex));
|
|
|
|
d3d9Device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
|
d3d9Device->SetRenderState(D3DRS_ALPHATESTENABLE, false);
|
|
d3d9Device->SetRenderState(D3DRS_ZENABLE, false);
|
|
d3d9Device->SetRenderState(D3DRS_CULLMODE, 2);
|
|
}
|
|
|
|
static void Present() {
|
|
if (ScrollWindowKey != 0 && ((ScrollWindowKey > 0 && KeyDown((BYTE)ScrollWindowKey))
|
|
|| (ScrollWindowKey == -1 && (KeyDown(DIK_LCONTROL) || KeyDown(DIK_RCONTROL)))
|
|
|| (ScrollWindowKey == -2 && (KeyDown(DIK_LMENU) || KeyDown(DIK_RMENU)))
|
|
|| (ScrollWindowKey == -3 && (KeyDown(DIK_LSHIFT) || KeyDown(DIK_RSHIFT))))) {
|
|
int winx, winy;
|
|
GetMouse(&winx, &winy);
|
|
windowLeft += winx;
|
|
windowTop += winy;
|
|
RECT r, r2;
|
|
r.left = windowLeft;
|
|
r.right = windowLeft + gWidth;
|
|
r.top = windowTop;
|
|
r.bottom = windowTop + gHeight;
|
|
AdjustWindowRect(&r, WS_OVERLAPPED | WS_CAPTION | WS_BORDER, false);
|
|
r.right -= (r.left - windowLeft);
|
|
r.left = windowLeft;
|
|
r.bottom -= (r.top - windowTop);
|
|
r.top = windowTop;
|
|
if (GetWindowRect(GetShellWindow(), &r2)) {
|
|
if (r.right > r2.right) {
|
|
DWORD move = r.right - r2.right;
|
|
r.left -= move;
|
|
r.right -= move;
|
|
windowLeft -= move;
|
|
}
|
|
if (r.left < r2.left) {
|
|
DWORD move = r2.left - r.left;
|
|
r.left += move;
|
|
r.right += move;
|
|
windowLeft += move;
|
|
}
|
|
if (r.bottom > r2.bottom) {
|
|
DWORD move = r.bottom - r2.bottom;
|
|
r.top -= move;
|
|
r.bottom -= move;
|
|
windowTop -= move;
|
|
}
|
|
if (r.top < r2.top) {
|
|
DWORD move = r2.top - r.top;
|
|
r.top += move;
|
|
r.bottom += move;
|
|
windowTop += move;
|
|
}
|
|
}
|
|
MoveWindow(window, r.left, r.top, r.right - r.left, r.bottom - r.top, true);
|
|
}
|
|
|
|
if (d3d9Device->Present(0, 0, 0, 0) == D3DERR_DEVICELOST) {
|
|
d3d9Device->SetTexture(0, 0);
|
|
SAFERELEASE(Tex)
|
|
SAFERELEASE(backbuffer);
|
|
SAFERELEASE(sSurf1);
|
|
SAFERELEASE(sSurf2);
|
|
SAFERELEASE(sTex1);
|
|
SAFERELEASE(sTex2);
|
|
SAFERELEASE(vBuffer);
|
|
SAFERELEASE(vBuffer2);
|
|
SAFERELEASE(movieBuffer);
|
|
SAFERELEASE(gpuPalette);
|
|
if (gpuBltEffect) gpuBltEffect->OnLostDevice();
|
|
for (DWORD d = 0; d < shaders.size(); d++) {
|
|
if (shaders[d].Effect) shaders[d].Effect->OnLostDevice();
|
|
}
|
|
DeviceLost = true;
|
|
}
|
|
}
|
|
|
|
void RefreshGraphics() {
|
|
if (DeviceLost) return;
|
|
//Tex->UnlockRect(0);
|
|
d3d9Device->BeginScene();
|
|
//d3d9Device->SetFVF(D3DFVF_XYZRHW|D3DFVF_TEX1);
|
|
d3d9Device->SetStreamSource(0, vBuffer, 0, sizeof(MyVertex));
|
|
d3d9Device->SetRenderTarget(0, sSurf1);
|
|
if (GPUBlt&&shaders.size()) {
|
|
UINT unused;
|
|
gpuBltEffect->Begin(&unused, 0);
|
|
gpuBltEffect->BeginPass(0);
|
|
d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
|
gpuBltEffect->EndPass();
|
|
gpuBltEffect->End();
|
|
d3d9Device->StretchRect(sSurf1, 0, sSurf2, 0, D3DTEXF_NONE);
|
|
d3d9Device->SetTexture(0, sTex2);
|
|
} else {
|
|
d3d9Device->SetTexture(0, Tex);
|
|
}
|
|
for (int d = shaders.size() - 1; d >= 0; d--) {
|
|
if (!shaders[d].Effect || !shaders[d].Active) continue;
|
|
if (shaders[d].mode2 && !(shaders[d].mode2&GetCurrentLoops())) continue;
|
|
if (shaders[d].mode&GetCurrentLoops()) continue;
|
|
if (shaders[d].ehTicks) shaders[d].Effect->SetInt(shaders[d].ehTicks, GetTickCount());
|
|
UINT passes;
|
|
shaders[d].Effect->Begin(&passes, 0);
|
|
for (DWORD pass = 0; pass < passes; pass++) {
|
|
shaders[d].Effect->BeginPass(pass);
|
|
d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
|
shaders[d].Effect->EndPass();
|
|
d3d9Device->StretchRect(sSurf1, 0, sSurf2, 0, D3DTEXF_NONE);
|
|
d3d9Device->SetTexture(0, sTex2);
|
|
}
|
|
shaders[d].Effect->End();
|
|
d3d9Device->SetTexture(0, sTex2);
|
|
}
|
|
d3d9Device->SetStreamSource(0, vBuffer2, 0, sizeof(MyVertex));
|
|
d3d9Device->SetRenderTarget(0, backbuffer);
|
|
if (GPUBlt && !shaders.size()) {
|
|
UINT unused;
|
|
gpuBltEffect->Begin(&unused, 0);
|
|
gpuBltEffect->BeginPass(0);
|
|
}
|
|
d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
|
if (GPUBlt) {
|
|
gpuBltEffect->EndPass();
|
|
gpuBltEffect->End();
|
|
}
|
|
d3d9Device->EndScene();
|
|
Present();
|
|
}
|
|
|
|
void SetMovieTexture(void* tex) {
|
|
movieTex = (IDirect3DTexture9*)tex;
|
|
D3DSURFACE_DESC desc;
|
|
movieTex->GetLevelDesc(0, &desc);
|
|
float aspect = (float)desc.Width / (float)desc.Height;
|
|
float winaspect = (float)gWidth / (float)gHeight;
|
|
|
|
byte* VertexPointer;
|
|
movieBuffer->Lock(0, 0, (void**)&VertexPointer, 0);
|
|
MyVertex ShaderVertices2[4] = {
|
|
ShaderVertices[0],
|
|
ShaderVertices[1],
|
|
ShaderVertices[2],
|
|
ShaderVertices[3]
|
|
};
|
|
|
|
ShaderVertices2[1].y = (float)gHeight - 0.5f;
|
|
ShaderVertices2[2].x = (float)gWidth - 0.5f;
|
|
ShaderVertices2[3].y = (float)gHeight - 0.5f;
|
|
ShaderVertices2[3].x = (float)gWidth - 0.5f;
|
|
|
|
DWORD gap;
|
|
if (aspect > winaspect) {
|
|
aspect = (float)desc.Width / (float)gWidth;
|
|
desc.Height = (int)(desc.Height / aspect);
|
|
gap = (gHeight - desc.Height) / 2;
|
|
|
|
ShaderVertices2[0].y += gap;
|
|
ShaderVertices2[2].y += gap;
|
|
ShaderVertices2[1].y -= gap;
|
|
ShaderVertices2[3].y -= gap;
|
|
} else if (aspect < winaspect) {
|
|
aspect = (float)desc.Height / (float)gHeight;
|
|
desc.Width = (int)(desc.Width / aspect);
|
|
gap = (gWidth - desc.Width) / 2;
|
|
ShaderVertices2[0].x += gap;
|
|
ShaderVertices2[2].x -= gap;
|
|
ShaderVertices2[3].x -= gap;
|
|
ShaderVertices2[1].x += gap;
|
|
}
|
|
CopyMemory(VertexPointer, ShaderVertices2, sizeof(ShaderVertices2));
|
|
movieBuffer->Unlock();
|
|
}
|
|
|
|
void _stdcall PlayMovieFrame() {
|
|
d3d9Device->SetTexture(0, movieTex);
|
|
d3d9Device->SetStreamSource(0, movieBuffer, 0, sizeof(MyVertex));
|
|
d3d9Device->BeginScene();
|
|
d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
|
d3d9Device->EndScene();
|
|
Present();
|
|
}
|
|
|
|
void _stdcall SetHeadTex(IDirect3DTexture9* tex, int width, int height, int xoff, int yoff) {
|
|
if (tex) {
|
|
gpuBltEffect->SetTexture(gpuBltHead, tex);
|
|
float size[2];
|
|
size[0] = ((float)width)*rcpres[0];
|
|
size[1] = ((float)height)*rcpres[1];
|
|
gpuBltEffect->SetFloatArray(gpuBltHeadSize, size, 2);
|
|
size[0] = (126.0f + xoff + (388 - width) / 2)*rcpres[0];
|
|
size[1] = (14.0f + yoff + (200 - height) / 2)*rcpres[1];
|
|
gpuBltEffect->SetFloatArray(gpuBltHeadCorner, size, 2);
|
|
gpuBltEffect->SetTechnique("T1");
|
|
} else gpuBltEffect->SetTechnique("T0");
|
|
}
|
|
|
|
void graphics_OnGameLoad() {
|
|
for (DWORD d = 0; d < shaders.size(); d++) SAFERELEASE(shaders[d].Effect);
|
|
shaders.clear();
|
|
}
|
|
|
|
class FakePalette2 : IDirectDrawPalette {
|
|
private:
|
|
ULONG Refs;
|
|
public:
|
|
FakePalette2() {
|
|
Refs = 1;
|
|
}
|
|
|
|
// IUnknown methods
|
|
HRESULT _stdcall QueryInterface(REFIID, LPVOID*) {
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG _stdcall AddRef() {
|
|
return ++Refs;
|
|
}
|
|
|
|
ULONG _stdcall Release() {
|
|
if (!--Refs) {
|
|
delete this;
|
|
return 0;
|
|
} else return Refs;
|
|
}
|
|
|
|
// IDirectDrawPalette methods
|
|
HRESULT _stdcall GetCaps(LPDWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetEntries(DWORD, DWORD, DWORD, LPPALETTEENTRY) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall Initialize(LPDIRECTDRAW, DWORD, LPPALETTEENTRY) { UNUSEDFUNCTION; }
|
|
|
|
HRESULT _stdcall SetEntries(DWORD, DWORD b, DWORD c, LPPALETTEENTRY d) {
|
|
if (b + c > 256 || c == 0) return DDERR_INVALIDPARAMS;
|
|
if (GPUBlt) {
|
|
if (!gpuPalette) {
|
|
CopyMemory(&palette[b], d, c * 4);
|
|
} else {
|
|
D3DLOCKED_RECT rect;
|
|
if (!FAILED(gpuPalette->LockRect(0, &rect, 0, D3DLOCK_DISCARD))) {
|
|
CopyMemory(&palette[b], d, c * 4);
|
|
CopyMemory(rect.pBits, palette, 256 * 4);
|
|
gpuPalette->UnlockRect(0);
|
|
}
|
|
}
|
|
} else {
|
|
CopyMemory(&palette[b], d, c * 4);
|
|
for (DWORD i = b; i < b + c; i++) {
|
|
//palette[i]&=0x00ffffff;
|
|
BYTE temp = *(BYTE*)((DWORD)&palette[i] + 0);
|
|
*(BYTE*)((DWORD)&palette[i] + 0) = *(BYTE*)((DWORD)&palette[i] + 2);
|
|
*(BYTE*)((DWORD)&palette[i] + 2) = temp;
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
};
|
|
|
|
class FakeSurface2 : IDirectDrawSurface {
|
|
private:
|
|
ULONG Refs;
|
|
bool Primary;
|
|
BYTE* lockTarget;
|
|
|
|
public:
|
|
FakeSurface2(bool primary) {
|
|
Refs = 1;
|
|
Primary = primary;
|
|
lockTarget = new BYTE[ResWidth*ResHeight];
|
|
}
|
|
|
|
// IUnknown methods
|
|
HRESULT _stdcall QueryInterface(REFIID, LPVOID *) {
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG _stdcall AddRef() {
|
|
return ++Refs;
|
|
}
|
|
|
|
ULONG _stdcall Release() {
|
|
if (!--Refs) {
|
|
delete lockTarget;
|
|
delete this;
|
|
return 0;
|
|
} else return Refs;
|
|
}
|
|
|
|
// IDirectDrawSurface methods
|
|
HRESULT _stdcall AddAttachedSurface(LPDIRECTDRAWSURFACE) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall AddOverlayDirtyRect(LPRECT) { UNUSEDFUNCTION; }
|
|
|
|
HRESULT _stdcall Blt(LPRECT a, LPDIRECTDRAWSURFACE b, LPRECT c, DWORD d, LPDDBLTFX e) {
|
|
BYTE* lockTarget = ((FakeSurface2*)b)->lockTarget;
|
|
D3DLOCKED_RECT dRect;
|
|
Tex->LockRect(0, &dRect, 0, 0);
|
|
if (!GPUBlt) dRect.Pitch /= 4;
|
|
DWORD yoffset = (ResHeight - 320) / 2;
|
|
DWORD xoffset = (ResWidth - 640) / 2;
|
|
if (GPUBlt) {
|
|
char* pBits = (char*)dRect.pBits;
|
|
for (DWORD y = 0; y < 320; y++) {
|
|
CopyMemory(&pBits[(y + yoffset)*dRect.Pitch + xoffset], &lockTarget[y * 640], 640);
|
|
}
|
|
for (DWORD y = 0; y < yoffset; y++) ZeroMemory(&pBits[y*dRect.Pitch], ResWidth);
|
|
for (DWORD y = ResHeight - yoffset; y < ResHeight; y++) ZeroMemory(&pBits[y*dRect.Pitch], ResWidth);
|
|
if (ResWidth > 640) {
|
|
for (DWORD y = yoffset; y < ResHeight - yoffset; y++) {
|
|
ZeroMemory(&pBits[y*dRect.Pitch], xoffset);
|
|
ZeroMemory(&pBits[y*dRect.Pitch + (ResWidth - xoffset)], xoffset);
|
|
}
|
|
}
|
|
} else {
|
|
for (DWORD y = 0; y < 320; y++) {
|
|
for (DWORD x = 0; x < 640; x++) {
|
|
((DWORD*)dRect.pBits)[(y + yoffset)*dRect.Pitch + x + xoffset] = palette[lockTarget[y * 640 + x]];
|
|
}
|
|
}
|
|
for (DWORD x = 0; x < ResWidth; x++) {
|
|
for (DWORD y = 0; y < yoffset; y++) ((DWORD*)dRect.pBits)[(y)*dRect.Pitch + x] = 0;
|
|
for (DWORD y = ResHeight - yoffset; y < ResHeight; y++) ((DWORD*)dRect.pBits)[(y)*dRect.Pitch + x] = 0;
|
|
}
|
|
if (ResWidth > 640) {
|
|
for (DWORD y = yoffset; y < ResHeight - yoffset; y++) {
|
|
for (DWORD x = 0; x < xoffset; x++) ((DWORD*)dRect.pBits)[(y)*dRect.Pitch + x] = 0;
|
|
for (DWORD x = ResWidth - xoffset; x < ResWidth; x++) ((DWORD*)dRect.pBits)[(y)*dRect.Pitch + x] = 0;
|
|
}
|
|
}
|
|
}
|
|
Tex->UnlockRect(0);
|
|
if (!DeviceLost) {
|
|
d3d9Device->SetStreamSource(0, vBuffer2, 0, sizeof(MyVertex));
|
|
d3d9Device->SetTexture(0, Tex);
|
|
d3d9Device->BeginScene();
|
|
if (GPUBlt) {
|
|
UINT unused;
|
|
gpuBltEffect->Begin(&unused, 0);
|
|
gpuBltEffect->BeginPass(0);
|
|
}
|
|
d3d9Device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
|
|
if (GPUBlt) {
|
|
gpuBltEffect->EndPass();
|
|
gpuBltEffect->End();
|
|
}
|
|
d3d9Device->EndScene();
|
|
Present();
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT _stdcall BltBatch(LPDDBLTBATCH, DWORD, DWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall BltFast(DWORD,DWORD,LPDIRECTDRAWSURFACE, LPRECT,DWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall DeleteAttachedSurface(DWORD,LPDIRECTDRAWSURFACE) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall EnumAttachedSurfaces(LPVOID,LPDDENUMSURFACESCALLBACK) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall EnumOverlayZOrders(DWORD,LPVOID,LPDDENUMSURFACESCALLBACK) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall Flip(LPDIRECTDRAWSURFACE, DWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetAttachedSurface(LPDDSCAPS, LPDIRECTDRAWSURFACE *) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetBltStatus(DWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetCaps(LPDDSCAPS) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetClipper(LPDIRECTDRAWCLIPPER *) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetColorKey(DWORD, LPDDCOLORKEY) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetDC(HDC *) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetFlipStatus(DWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetOverlayPosition(LPLONG, LPLONG) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetPalette(LPDIRECTDRAWPALETTE *) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetPixelFormat(LPDDPIXELFORMAT) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetSurfaceDesc(LPDDSURFACEDESC) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall Initialize(LPDIRECTDRAW, LPDDSURFACEDESC) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall IsLost() { UNUSEDFUNCTION; }
|
|
|
|
HRESULT _stdcall Lock(LPRECT a, LPDDSURFACEDESC b, DWORD c, HANDLE d) {
|
|
if (!Primary) *b = movieDesc;
|
|
else *b = surfaceDesc;
|
|
b->lpSurface = lockTarget;
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT _stdcall ReleaseDC(HDC) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall Restore() { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall SetClipper(LPDIRECTDRAWCLIPPER) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall SetColorKey(DWORD, LPDDCOLORKEY) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall SetOverlayPosition(LONG, LONG) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall SetPalette(LPDIRECTDRAWPALETTE) { return DD_OK; }
|
|
|
|
HRESULT _stdcall Unlock(LPVOID) {
|
|
if (Primary&&d3d9Device) {
|
|
if (DeviceLost) {
|
|
if (d3d9Device->TestCooperativeLevel() == D3DERR_DEVICENOTRESET) {
|
|
ResetDevice(false);
|
|
DeviceLost = false;
|
|
}
|
|
}
|
|
if (!DeviceLost) {
|
|
D3DLOCKED_RECT dRect;
|
|
Tex->LockRect(0, &dRect, 0, 0);
|
|
if (!GPUBlt) dRect.Pitch /= 4;
|
|
if (GPUBlt) {
|
|
char* target = (char*)dRect.pBits;
|
|
for (DWORD y = 0; y < ResHeight; y++) CopyMemory(&target[y*dRect.Pitch], &lockTarget[y*ResWidth], ResWidth);
|
|
} else {
|
|
if (!(ResWidth % 8)) {
|
|
DWORD target = (DWORD)(&lockTarget[0]);
|
|
DWORD palette2 = (DWORD)(&palette[0]);
|
|
dRect.Pitch = (dRect.Pitch - ResWidth) * 4;
|
|
DWORD ResWidth2 = ResWidth / 8;
|
|
__asm {
|
|
mov esi, target;
|
|
mov edi, dRect.pBits;
|
|
mov ebx, palette2;
|
|
xor edx, edx;
|
|
start:
|
|
mov ecx, ResWidth2;
|
|
start2:
|
|
movzx eax, byte ptr ds : [esi];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi], eax;
|
|
movzx eax, byte ptr ds : [esi + 1];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi + 4], eax;
|
|
movzx eax, byte ptr ds : [esi + 2];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi + 8], eax;
|
|
movzx eax, byte ptr ds : [esi + 3];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi + 12], eax;
|
|
movzx eax, byte ptr ds : [esi + 4];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi + 16], eax;
|
|
movzx eax, byte ptr ds : [esi + 5];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi + 20], eax;
|
|
movzx eax, byte ptr ds : [esi + 6];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi + 24], eax;
|
|
movzx eax, byte ptr ds : [esi + 7];
|
|
mov eax, dword ptr ds : [ebx + eax * 4];
|
|
mov dword ptr ds : [edi + 28], eax;
|
|
|
|
add esi, 8;
|
|
add edi, 32;
|
|
|
|
loop start2;
|
|
inc edx;
|
|
add edi, dRect.Pitch;
|
|
cmp edx, ResHeight;
|
|
jl start;
|
|
}
|
|
} else {
|
|
DWORD pitch2, width2 = 0;
|
|
WORD pitch = (WORD)dRect.Pitch;
|
|
WORD width = (WORD)ResWidth;
|
|
DWORD* target = ((DWORD*)dRect.pBits);
|
|
for (WORD y = 0; y < ResHeight; y++) {
|
|
pitch2 = y*pitch;
|
|
width2 = y*width;
|
|
for (DWORD x = 0; x < ResWidth; x++) {
|
|
target[pitch2 + x] = palette[lockTarget[width2 + x]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Tex->UnlockRect(0);
|
|
RefreshGraphics();
|
|
}
|
|
}
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT _stdcall UpdateOverlay(LPRECT, LPDIRECTDRAWSURFACE,LPRECT,DWORD, LPDDOVERLAYFX) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall UpdateOverlayDisplay(DWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall UpdateOverlayZOrder(DWORD, LPDIRECTDRAWSURFACE) { UNUSEDFUNCTION; }
|
|
};
|
|
|
|
class FakeDirectDraw2 : IDirectDraw
|
|
{
|
|
private:
|
|
ULONG Refs;
|
|
public:
|
|
FakeDirectDraw2() {
|
|
Refs=1;
|
|
}
|
|
|
|
// IUnknown methods
|
|
HRESULT _stdcall QueryInterface(REFIID, LPVOID*) { return E_NOINTERFACE; }
|
|
ULONG _stdcall AddRef() { return ++Refs; }
|
|
|
|
ULONG _stdcall Release() {
|
|
if (!--Refs) {
|
|
for (DWORD d = 0; d < shaders.size(); d++) SAFERELEASE(shaders[d].Effect);
|
|
for (DWORD d = 0; d < shaderTextures.size(); d++) shaderTextures[d]->Release();
|
|
shaders.clear();
|
|
shaderTextures.clear();
|
|
SAFERELEASE(backbuffer);
|
|
SAFERELEASE(sSurf1);
|
|
SAFERELEASE(sSurf2);
|
|
SAFERELEASE(Tex);
|
|
SAFERELEASE(sTex1);
|
|
SAFERELEASE(sTex2);
|
|
SAFERELEASE(vBuffer);
|
|
SAFERELEASE(vBuffer2);
|
|
SAFERELEASE(d3d9Device);
|
|
SAFERELEASE(d3d9);
|
|
SAFERELEASE(gpuPalette);
|
|
SAFERELEASE(gpuBltEffect);
|
|
SAFERELEASE(movieBuffer);
|
|
SAFERELEASE(movieTex);
|
|
delete this;
|
|
return 0;
|
|
} else return Refs;
|
|
}
|
|
|
|
// IDirectDraw methods
|
|
HRESULT _stdcall Compact() { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall CreateClipper(DWORD, LPDIRECTDRAWCLIPPER*, IUnknown*) { UNUSEDFUNCTION; }
|
|
|
|
HRESULT _stdcall CreatePalette(DWORD, LPPALETTEENTRY, LPDIRECTDRAWPALETTE* c, IUnknown*) {
|
|
*c = (IDirectDrawPalette*)new FakePalette2();
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT _stdcall CreateSurface(LPDDSURFACEDESC a, LPDIRECTDRAWSURFACE * b, IUnknown * c) {
|
|
if(a->dwFlags==1&&a->ddsCaps.dwCaps==DDSCAPS_PRIMARYSURFACE) *b=(IDirectDrawSurface*)new FakeSurface2(true);
|
|
else *b=(IDirectDrawSurface*)new FakeSurface2(false);
|
|
return DD_OK;
|
|
}
|
|
HRESULT _stdcall DuplicateSurface(LPDIRECTDRAWSURFACE, LPDIRECTDRAWSURFACE *) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall EnumDisplayModes(DWORD, LPDDSURFACEDESC, LPVOID, LPDDENUMMODESCALLBACK) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall EnumSurfaces(DWORD, LPDDSURFACEDESC, LPVOID,LPDDENUMSURFACESCALLBACK) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall FlipToGDISurface() { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetCaps(LPDDCAPS, LPDDCAPS b) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetDisplayMode(LPDDSURFACEDESC) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetFourCCCodes(LPDWORD,LPDWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetGDISurface(LPDIRECTDRAWSURFACE *) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetMonitorFrequency(LPDWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetScanLine(LPDWORD) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall GetVerticalBlankStatus(LPBOOL) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall Initialize(GUID *) { UNUSEDFUNCTION; }
|
|
HRESULT _stdcall RestoreDisplayMode() { return DD_OK; }
|
|
HRESULT _stdcall SetCooperativeLevel(HWND a, DWORD b) {
|
|
window = a;
|
|
|
|
if (!d3d9Device) {
|
|
ResetDevice(true);
|
|
CoInitialize(0);
|
|
}
|
|
|
|
if (Graphics::mode == 5) {
|
|
SetWindowLong(a, GWL_STYLE, WS_OVERLAPPED | WS_CAPTION | WS_BORDER);
|
|
RECT r;
|
|
r.left = 0;
|
|
r.right = gWidth;
|
|
r.top = 0;
|
|
r.bottom = gHeight;
|
|
AdjustWindowRect(&r, WS_OVERLAPPED | WS_CAPTION | WS_BORDER, false);
|
|
r.right -= r.left;
|
|
r.left = 0;
|
|
r.bottom -= r.top;
|
|
r.top = 0;
|
|
SetWindowPos(a, HWND_NOTOPMOST, 0, 0, r.right, r.bottom, SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
|
|
}
|
|
return DD_OK;
|
|
}
|
|
HRESULT _stdcall SetDisplayMode(DWORD, DWORD, DWORD) { return DD_OK; }
|
|
HRESULT _stdcall WaitForVerticalBlank(DWORD, HANDLE) { UNUSEDFUNCTION; }
|
|
};
|
|
|
|
HRESULT _stdcall FakeDirectDrawCreate2_graphics(void*, IDirectDraw** b, void*) {
|
|
ResWidth = *(DWORD*)0x004CAD6B;
|
|
ResHeight = *(DWORD*)0x004CAD66;
|
|
|
|
if (!d3d9) {
|
|
d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
|
|
}
|
|
|
|
ZeroMemory(&surfaceDesc, sizeof(DDSURFACEDESC));
|
|
surfaceDesc.dwSize = sizeof(DDSURFACEDESC);
|
|
surfaceDesc.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH;
|
|
surfaceDesc.dwWidth = ResWidth;
|
|
surfaceDesc.dwHeight = ResHeight;
|
|
surfaceDesc.ddpfPixelFormat.dwRGBBitCount = 16;
|
|
surfaceDesc.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
|
surfaceDesc.ddpfPixelFormat.dwRBitMask = 0xf800;
|
|
surfaceDesc.ddpfPixelFormat.dwGBitMask = 0x7e0;
|
|
surfaceDesc.ddpfPixelFormat.dwBBitMask = 0x1f;
|
|
surfaceDesc.ddpfPixelFormat.dwFlags = DDPF_RGB;
|
|
surfaceDesc.ddsCaps.dwCaps = DDSCAPS_TEXTURE;
|
|
surfaceDesc.lPitch = ResWidth;
|
|
movieDesc = surfaceDesc;
|
|
movieDesc.lPitch = 640;
|
|
movieDesc.dwHeight = 320;
|
|
movieDesc.dwWidth = 640;
|
|
|
|
gWidth = GetConfigInt("Graphics", "GraphicsWidth", 0);
|
|
gHeight = GetConfigInt("Graphics", "GraphicsHeight", 0);
|
|
if (!gWidth || !gHeight) {
|
|
gWidth = ResWidth;
|
|
gHeight = ResHeight;
|
|
}
|
|
GPUBlt = GetConfigInt("Graphics", "GPUBlt", 0);
|
|
if (!GPUBlt || GPUBlt > 2) GPUBlt = 2; //Swap them around to keep compatibility with old ddraw.ini's
|
|
else if (GPUBlt == 2) GPUBlt = 0;
|
|
|
|
if (Graphics::mode == 5) {
|
|
ScrollWindowKey = GetConfigInt("Input", "WindowScrollKey", 0);
|
|
} else ScrollWindowKey = 0;
|
|
|
|
rcpres[0] = 1.0f / (float)gWidth;
|
|
rcpres[1] = 1.0f / (float)gHeight;
|
|
|
|
*b = (IDirectDraw*)new FakeDirectDraw2();
|
|
return DD_OK;
|
|
}
|
|
|
|
static double fadeMulti;
|
|
static __declspec(naked) void FadeHook() {
|
|
__asm {
|
|
pushf;
|
|
push ebx;
|
|
fild[esp];
|
|
fmul fadeMulti;
|
|
fistp[esp];
|
|
pop ebx;
|
|
popf;
|
|
call FuncOffs::fadeSystemPalette_;
|
|
retn;
|
|
}
|
|
}
|
|
|
|
void Graphics::init() {
|
|
Graphics::mode = GetConfigInt("Graphics", "Mode", 0);
|
|
if (Graphics::mode != 4 && Graphics::mode != 5) {
|
|
Graphics::mode = 0;
|
|
}
|
|
if (Graphics::mode == 4 || Graphics::mode == 5) {
|
|
dlog("Applying dx9 graphics patch.", DL_INIT);
|
|
#ifdef WIN2K
|
|
#define _DLL_NAME "d3dx9_42.dll"
|
|
#else
|
|
#define _DLL_NAME "d3dx9_43.dll"
|
|
#endif
|
|
HMODULE h = LoadLibraryEx(_DLL_NAME, 0, LOAD_LIBRARY_AS_DATAFILE);
|
|
if (!h) {
|
|
MessageBoxA(0, "You have selected graphics mode 4 or 5, but " _DLL_NAME " is missing\nSwitch back to mode 0, or install an up to date version of DirectX", "Error", 0);
|
|
ExitProcess(-1);
|
|
} else {
|
|
FreeLibrary(h);
|
|
}
|
|
SafeWrite8(0x0050FB6B, '2');
|
|
dlogr(" Done", DL_INIT);
|
|
#undef _DLL_NAME
|
|
}
|
|
fadeMulti = GetConfigInt("Graphics", "FadeMultiplier", 100);
|
|
if (fadeMulti != 100) {
|
|
dlog("Applying fade patch.", DL_INIT);
|
|
SafeWrite32(0x00493B17, ((DWORD)&FadeHook) - 0x00493B1b);
|
|
fadeMulti = ((double)fadeMulti) / 100.0;
|
|
dlogr(" Done", DL_INIT);
|
|
}
|
|
|
|
if (Graphics::mode > 3) {
|
|
LoadGameHook::onGameReset += graphics_OnGameLoad;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// This should be in global namespace
|
|
HRESULT _stdcall FakeDirectDrawCreate2(void* a, IDirectDraw** b, void* c) {
|
|
return sfall::FakeDirectDrawCreate2_graphics(a, b, c);
|
|
}
|