mirror of
https://github.com/jmarshall23/Hellfire.git
synced 2026-08-12 16:00:51 +02:00
2366 lines
63 KiB
C++
2366 lines
63 KiB
C++
#include "DirectDrawWrapper.h"
|
|
#include "resource.h"
|
|
|
|
#include <d3d11.h>
|
|
#include <dxgi.h>
|
|
#include <d3dcompiler.h>
|
|
#include <wincodec.h>
|
|
#include <wrl/client.h>
|
|
|
|
#include <cstdio>
|
|
|
|
#pragma comment(lib, "d3d11.lib")
|
|
#pragma comment(lib, "dxgi.lib")
|
|
#pragma comment(lib, "d3dcompiler.lib")
|
|
#pragma comment(lib, "windowscodecs.lib")
|
|
|
|
using Microsoft::WRL::ComPtr;
|
|
|
|
#ifndef SAFE_DELETE_ARRAY
|
|
#define SAFE_DELETE_ARRAY(x) do { if ((x) != NULL) { delete[] (x); (x) = NULL; } } while (0)
|
|
#endif
|
|
|
|
#ifndef SAFE_DELETE
|
|
#define SAFE_DELETE(x) do { if ((x) != NULL) { delete (x); (x) = NULL; } } while (0)
|
|
#endif
|
|
|
|
#ifndef DD_OK
|
|
#define DD_OK S_OK
|
|
#endif
|
|
|
|
static const char* g_BlitVS_HLSL = R"(
|
|
struct VS_IN
|
|
{
|
|
float3 pos : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
struct VS_OUT
|
|
{
|
|
float4 pos : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
VS_OUT main(VS_IN input)
|
|
{
|
|
VS_OUT o;
|
|
o.pos = float4(input.pos, 1.0f);
|
|
o.uv = input.uv;
|
|
return o;
|
|
}
|
|
)";
|
|
static const char* g_BlitPS_HLSL = R"(
|
|
Texture2D tex0 : register(t0);
|
|
SamplerState samp0 : register(s0);
|
|
|
|
struct PS_IN
|
|
{
|
|
float4 pos : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
};
|
|
|
|
float Luma(float3 c)
|
|
{
|
|
return dot(c, float3(0.299f, 0.587f, 0.114f));
|
|
}
|
|
|
|
float3 SoftContrast(float3 c)
|
|
{
|
|
return saturate(c * c * (3.0f - 2.0f * c));
|
|
}
|
|
|
|
float Vignette(float2 uv)
|
|
{
|
|
float2 p = uv * 2.0f - 1.0f;
|
|
float r2 = dot(p, p);
|
|
return saturate(1.0f - r2 * 0.22f);
|
|
}
|
|
|
|
float GrainRand(float2 p)
|
|
{
|
|
return frac(sin(dot(p, float2(127.1f, 311.7f))) * 43758.5453123f);
|
|
}
|
|
|
|
float GrainValue(float2 p)
|
|
{
|
|
float2 i = floor(p);
|
|
float2 f = frac(p);
|
|
|
|
float a = GrainRand(i);
|
|
float b = GrainRand(i + float2(1.0f, 0.0f));
|
|
float c = GrainRand(i + float2(0.0f, 1.0f));
|
|
float d = GrainRand(i + float2(1.0f, 1.0f));
|
|
|
|
float2 u = f * f * (3.0f - 2.0f * f);
|
|
|
|
return lerp(lerp(a, b, u.x), lerp(c, d, u.x), u.y);
|
|
}
|
|
|
|
float FilmGrain(float2 uv, float2 resolution)
|
|
{
|
|
float2 p = uv * resolution;
|
|
|
|
float g1 = GrainValue(p * 0.75f);
|
|
float g2 = GrainValue(p * 1.50f);
|
|
float g3 = GrainValue(p * 3.00f);
|
|
|
|
float grain = g1 * 0.55f + g2 * 0.30f + g3 * 0.15f;
|
|
return grain - 0.5f;
|
|
}
|
|
|
|
float3 BrightPass(float3 c, float lo, float hi)
|
|
{
|
|
float lum = Luma(c);
|
|
float mask = smoothstep(lo, hi, lum);
|
|
return c * mask;
|
|
}
|
|
|
|
float4 main(PS_IN input) : SV_Target
|
|
{
|
|
uint texWidth, texHeight;
|
|
tex0.GetDimensions(texWidth, texHeight);
|
|
|
|
float2 px = float2(1.0f / (float)texWidth, 1.0f / (float)texHeight);
|
|
float2 uv = input.uv;
|
|
|
|
// baked constants
|
|
const float sharpenStrength = 0.95f;
|
|
const float contrastStrength = 0.62f;
|
|
|
|
// denoise tuning
|
|
const float denoiseStrength = 0.22f;
|
|
const float denoiseSigma = 24.0f;
|
|
|
|
// dark-area tuning
|
|
const float darkStart = 0.42f;
|
|
const float darkEnd = 0.10f;
|
|
const float darkStrength = 0.12f;
|
|
|
|
// smart brightness tuning
|
|
const float brightnessLift = 0.20f;
|
|
const float brightnessLowMax = 0.85f;
|
|
|
|
// bloom tuning
|
|
const float bloomStrength = 0.78f;
|
|
const float bloomThresholdLo = 0.18f;
|
|
const float bloomThresholdHi = 0.96f;
|
|
|
|
// pseudo-AO tuning
|
|
const float aoStrength = 0.58f;
|
|
const float aoRadius1 = 1.5f;
|
|
const float aoRadius2 = 3.0f;
|
|
const float aoDarkBoost = 0.65f;
|
|
|
|
// 3x3 neighborhood
|
|
float3 c00 = tex0.Sample(samp0, uv + float2(-px.x, -px.y)).rgb;
|
|
float3 c10 = tex0.Sample(samp0, uv + float2( 0.0f, -px.y)).rgb;
|
|
float3 c20 = tex0.Sample(samp0, uv + float2( px.x, -px.y)).rgb;
|
|
|
|
float3 c01 = tex0.Sample(samp0, uv + float2(-px.x, 0.0f)).rgb;
|
|
float3 c11 = tex0.Sample(samp0, uv).rgb;
|
|
float3 c21 = tex0.Sample(samp0, uv + float2( px.x, 0.0f)).rgb;
|
|
|
|
float3 c02 = tex0.Sample(samp0, uv + float2(-px.x, px.y)).rgb;
|
|
float3 c12 = tex0.Sample(samp0, uv + float2( 0.0f, px.y)).rgb;
|
|
float3 c22 = tex0.Sample(samp0, uv + float2( px.x, px.y)).rgb;
|
|
|
|
// Luma values
|
|
float l00 = Luma(c00);
|
|
float l10 = Luma(c10);
|
|
float l20 = Luma(c20);
|
|
float l01 = Luma(c01);
|
|
float l11 = Luma(c11);
|
|
float l21 = Luma(c21);
|
|
float l02 = Luma(c02);
|
|
float l12 = Luma(c12);
|
|
float l22 = Luma(c22);
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Edge-aware denoise
|
|
// -------------------------------------------------------------------------
|
|
float invSigma = 1.0f / denoiseSigma;
|
|
|
|
float w00 = 1.0f / (1.0f + abs(l00 - l11) * invSigma);
|
|
float w10 = 1.0f / (1.0f + abs(l10 - l11) * invSigma);
|
|
float w20 = 1.0f / (1.0f + abs(l20 - l11) * invSigma);
|
|
float w01 = 1.0f / (1.0f + abs(l01 - l11) * invSigma);
|
|
float w21 = 1.0f / (1.0f + abs(l21 - l11) * invSigma);
|
|
float w02 = 1.0f / (1.0f + abs(l02 - l11) * invSigma);
|
|
float w12 = 1.0f / (1.0f + abs(l12 - l11) * invSigma);
|
|
float w22 = 1.0f / (1.0f + abs(l22 - l11) * invSigma);
|
|
|
|
float wCenter = 4.0f;
|
|
|
|
float3 denoised =
|
|
c00 * w00 + c10 * w10 + c20 * w20 +
|
|
c01 * w01 + c11 * wCenter + c21 * w21 +
|
|
c02 * w02 + c12 * w12 + c22 * w22;
|
|
|
|
float wSum =
|
|
w00 + w10 + w20 +
|
|
w01 + wCenter + w21 +
|
|
w02 + w12 + w22;
|
|
|
|
denoised /= max(wSum, 1e-5f);
|
|
|
|
float3 baseColor = lerp(c11, denoised, denoiseStrength);
|
|
float baseLuma = Luma(baseColor);
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Blur / sharpen pipeline
|
|
// -------------------------------------------------------------------------
|
|
float3 blur =
|
|
(c00 + 2.0f * c10 + c20 +
|
|
2.0f * c01 + 4.0f * baseColor + 2.0f * c21 +
|
|
c02 + 2.0f * c12 + c22) / 16.0f;
|
|
|
|
float lBlur =
|
|
(l00 + 2.0f * l10 + l20 +
|
|
2.0f * l01 + 4.0f * baseLuma + 2.0f * l21 +
|
|
l02 + 2.0f * l12 + l22) / 16.0f;
|
|
|
|
float detail = baseLuma - lBlur;
|
|
|
|
float edge =
|
|
abs(l10 - l12) +
|
|
abs(l01 - l21) +
|
|
0.5f * abs(l00 - l22) +
|
|
0.5f * abs(l20 - l02);
|
|
|
|
float adapt = 1.0f - saturate(edge * 4.0f);
|
|
adapt = adapt * adapt;
|
|
|
|
float amount = sharpenStrength * adapt;
|
|
|
|
float3 color = baseColor + detail.xxx * amount;
|
|
|
|
// Mild contrast boost
|
|
float3 contrasted = SoftContrast(saturate(color));
|
|
color = lerp(color, contrasted, contrastStrength);
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Pseudo AO from neighborhood enclosure / crevices
|
|
// -------------------------------------------------------------------------
|
|
{
|
|
float2 r1 = px * aoRadius1;
|
|
float2 r2 = px * aoRadius2;
|
|
|
|
float3 a0 = tex0.Sample(samp0, uv + float2(-r1.x, 0.0f)).rgb;
|
|
float3 a1 = tex0.Sample(samp0, uv + float2( r1.x, 0.0f)).rgb;
|
|
float3 a2 = tex0.Sample(samp0, uv + float2( 0.0f, -r1.y)).rgb;
|
|
float3 a3 = tex0.Sample(samp0, uv + float2( 0.0f, r1.y)).rgb;
|
|
float3 a4 = tex0.Sample(samp0, uv + float2(-r1.x, -r1.y)).rgb;
|
|
float3 a5 = tex0.Sample(samp0, uv + float2( r1.x, -r1.y)).rgb;
|
|
float3 a6 = tex0.Sample(samp0, uv + float2(-r1.x, r1.y)).rgb;
|
|
float3 a7 = tex0.Sample(samp0, uv + float2( r1.x, r1.y)).rgb;
|
|
|
|
float3 b0 = tex0.Sample(samp0, uv + float2(-r2.x, 0.0f)).rgb;
|
|
float3 b1 = tex0.Sample(samp0, uv + float2( r2.x, 0.0f)).rgb;
|
|
float3 b2 = tex0.Sample(samp0, uv + float2( 0.0f, -r2.y)).rgb;
|
|
float3 b3 = tex0.Sample(samp0, uv + float2( 0.0f, r2.y)).rgb;
|
|
|
|
float la0 = Luma(a0);
|
|
float la1 = Luma(a1);
|
|
float la2 = Luma(a2);
|
|
float la3 = Luma(a3);
|
|
float la4 = Luma(a4);
|
|
float la5 = Luma(a5);
|
|
float la6 = Luma(a6);
|
|
float la7 = Luma(a7);
|
|
|
|
float lb0 = Luma(b0);
|
|
float lb1 = Luma(b1);
|
|
float lb2 = Luma(b2);
|
|
float lb3 = Luma(b3);
|
|
|
|
float nearAvg = (la0 + la1 + la2 + la3 + la4 + la5 + la6 + la7) * (1.0f / 8.0f);
|
|
float farAvg = (lb0 + lb1 + lb2 + lb3) * 0.25f;
|
|
|
|
// if center is darker than nearby samples, treat as enclosed/occluded
|
|
float enclosedNear = saturate((nearAvg - baseLuma) * 2.4f);
|
|
float enclosedFar = saturate((farAvg - baseLuma) * 1.8f);
|
|
|
|
// strengthen inside little crevices and cracks
|
|
float creviceAO = saturate((-detail) * 7.0f);
|
|
|
|
// stronger in darker regions, weaker in highlights
|
|
float darkAO = 1.0f - smoothstep(0.18f, 0.80f, baseLuma);
|
|
|
|
float ao = enclosedNear * 0.50f +
|
|
enclosedFar * 0.25f +
|
|
creviceAO * 0.25f;
|
|
|
|
ao *= lerp(1.0f, darkAO, aoDarkBoost);
|
|
ao = saturate(ao);
|
|
ao *= ao; // softer rolloff
|
|
|
|
color *= (1.0f - ao * aoStrength);
|
|
}
|
|
|
|
// Dark-region deepening
|
|
float lum = Luma(saturate(color));
|
|
float darkMask = 1.0f - smoothstep(darkEnd, darkStart, lum);
|
|
darkMask *= darkMask;
|
|
|
|
float creviceMask = saturate((-detail) * 6.0f);
|
|
darkMask *= lerp(1.0f, creviceMask, 0.65f);
|
|
|
|
color *= (1.0f - darkMask * darkStrength);
|
|
|
|
// Slight desaturation for grimier Diablo-like look
|
|
color = lerp(color, Luma(color).xxx, 0.12f);
|
|
|
|
// Cool shadows / warm mids
|
|
{
|
|
float gradedLum = Luma(color);
|
|
float shadowMask = 1.0f - smoothstep(0.05f, 0.35f, gradedLum);
|
|
float midMask = smoothstep(0.18f, 0.55f, gradedLum) *
|
|
(1.0f - smoothstep(0.55f, 0.85f, gradedLum));
|
|
|
|
color = lerp(color, color * float3(0.92f, 0.95f, 1.04f), shadowMask * 0.18f);
|
|
color = lerp(color, color * float3(1.04f, 1.00f, 0.94f), midMask * 0.10f);
|
|
}
|
|
|
|
// Slight highlight softening so bright areas don't feel too modern/clean
|
|
{
|
|
float hl = smoothstep(0.65f, 1.0f, Luma(color));
|
|
color = lerp(color, blur, hl * 0.08f);
|
|
}
|
|
|
|
// Smart brightness lift
|
|
{
|
|
float brightLum = Luma(saturate(color));
|
|
float brightMask = 1.0f - smoothstep(0.0f, brightnessLowMax, brightLum);
|
|
brightMask = 0.35f + brightMask * 0.65f;
|
|
|
|
color *= (1.0f + brightnessLift * brightMask);
|
|
}
|
|
|
|
// -------------------------------------------------------------------------
|
|
// Advanced multi-radius bloom
|
|
// -------------------------------------------------------------------------
|
|
{
|
|
float2 off1 = px * 4.0f;
|
|
float2 off2 = px * 8.0f;
|
|
float2 off3 = px * 10.0f;
|
|
|
|
float3 bloomAccum = 0.0f.xxx;
|
|
float bloomWeight = 0.0f;
|
|
|
|
{
|
|
float3 s = BrightPass(c11, bloomThresholdLo, bloomThresholdHi);
|
|
bloomAccum += s * 1.20f;
|
|
bloomWeight += 1.20f;
|
|
}
|
|
|
|
{
|
|
float3 s0 = BrightPass(tex0.Sample(samp0, uv + float2(-off1.x, 0.0f)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s1 = BrightPass(tex0.Sample(samp0, uv + float2( off1.x, 0.0f)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s2 = BrightPass(tex0.Sample(samp0, uv + float2(0.0f, -off1.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s3 = BrightPass(tex0.Sample(samp0, uv + float2(0.0f, off1.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
|
|
bloomAccum += (s0 + s1 + s2 + s3) * 0.90f;
|
|
bloomWeight += 4.0f * 0.90f;
|
|
}
|
|
|
|
{
|
|
float3 s0 = BrightPass(tex0.Sample(samp0, uv + float2(-off1.x, -off1.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s1 = BrightPass(tex0.Sample(samp0, uv + float2( off1.x, -off1.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s2 = BrightPass(tex0.Sample(samp0, uv + float2(-off1.x, off1.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s3 = BrightPass(tex0.Sample(samp0, uv + float2( off1.x, off1.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
|
|
bloomAccum += (s0 + s1 + s2 + s3) * 0.72f;
|
|
bloomWeight += 4.0f * 0.72f;
|
|
}
|
|
|
|
{
|
|
float3 s0 = BrightPass(tex0.Sample(samp0, uv + float2(-off2.x, 0.0f)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s1 = BrightPass(tex0.Sample(samp0, uv + float2( off2.x, 0.0f)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s2 = BrightPass(tex0.Sample(samp0, uv + float2(0.0f, -off2.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s3 = BrightPass(tex0.Sample(samp0, uv + float2(0.0f, off2.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
|
|
bloomAccum += (s0 + s1 + s2 + s3) * 0.52f;
|
|
bloomWeight += 4.0f * 0.52f;
|
|
}
|
|
|
|
{
|
|
float3 s0 = BrightPass(tex0.Sample(samp0, uv + float2(-off3.x, 0.0f)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s1 = BrightPass(tex0.Sample(samp0, uv + float2( off3.x, 0.0f)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s2 = BrightPass(tex0.Sample(samp0, uv + float2(0.0f, -off3.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
float3 s3 = BrightPass(tex0.Sample(samp0, uv + float2(0.0f, off3.y)).rgb, bloomThresholdLo, bloomThresholdHi);
|
|
|
|
bloomAccum += (s0 + s1 + s2 + s3) * 0.30f;
|
|
bloomWeight += 4.0f * 0.30f;
|
|
}
|
|
|
|
float3 bloom = bloomAccum / max(bloomWeight, 1e-5f);
|
|
|
|
bloom *= float3(1.10f, 1.02f, 0.90f);
|
|
|
|
float bloomLum = Luma(bloom);
|
|
float bloomMask = smoothstep(0.02f, 0.75f, bloomLum);
|
|
bloom *= (0.65f + bloomMask * 0.35f);
|
|
|
|
color += bloom * bloomStrength;
|
|
}
|
|
|
|
// Film-style grain
|
|
{
|
|
float2 resolution = float2((float)texWidth, (float)texHeight);
|
|
float grain = FilmGrain(uv, resolution);
|
|
|
|
float lumNow = Luma(saturate(color));
|
|
float grainMask = 1.0f - smoothstep(0.35f, 0.90f, lumNow);
|
|
grainMask = 0.35f + grainMask * 0.65f;
|
|
|
|
color += grain.xxx * (0.052f * grainMask);
|
|
}
|
|
|
|
// Subtle vignette for enclosed dungeon feel
|
|
color *= Vignette(uv);
|
|
|
|
return float4(saturate(color), 1.0f);
|
|
}
|
|
)";
|
|
|
|
static bool CompileShaderSource(const char* source, const char* entry, const char* target, ID3DBlob** blobOut)
|
|
{
|
|
if (!source || !entry || !target || !blobOut)
|
|
return false;
|
|
|
|
UINT flags = D3DCOMPILE_ENABLE_STRICTNESS;
|
|
#ifdef _DEBUG
|
|
flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION;
|
|
#endif
|
|
|
|
ComPtr<ID3DBlob> shaderBlob;
|
|
ComPtr<ID3DBlob> errorBlob;
|
|
|
|
HRESULT hr = D3DCompile(
|
|
source,
|
|
strlen(source),
|
|
nullptr,
|
|
nullptr,
|
|
nullptr,
|
|
entry,
|
|
target,
|
|
flags,
|
|
0,
|
|
&shaderBlob,
|
|
&errorBlob);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
if (errorBlob)
|
|
OutputDebugStringA((const char*)errorBlob->GetBufferPointer());
|
|
return false;
|
|
}
|
|
|
|
*blobOut = shaderBlob.Detach();
|
|
return true;
|
|
}
|
|
|
|
static inline float PixelToNdcX(float x, float width)
|
|
{
|
|
return (x / width) * 2.0f - 1.0f;
|
|
}
|
|
|
|
static inline float PixelToNdcY(float y, float height)
|
|
{
|
|
return 1.0f - (y / height) * 2.0f;
|
|
}
|
|
|
|
static bool SaveBGRA8TextureToPng(
|
|
ID3D11Device* device,
|
|
ID3D11DeviceContext* context,
|
|
ID3D11Texture2D* texture,
|
|
const wchar_t* filename)
|
|
{
|
|
if (!device || !context || !texture || !filename)
|
|
return false;
|
|
|
|
D3D11_TEXTURE2D_DESC srcDesc = {};
|
|
texture->GetDesc(&srcDesc);
|
|
|
|
D3D11_TEXTURE2D_DESC stagingDesc = srcDesc;
|
|
stagingDesc.Usage = D3D11_USAGE_STAGING;
|
|
stagingDesc.BindFlags = 0;
|
|
stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
|
stagingDesc.MiscFlags = 0;
|
|
|
|
ComPtr<ID3D11Texture2D> staging;
|
|
HRESULT hr = device->CreateTexture2D(&stagingDesc, nullptr, &staging);
|
|
if (FAILED(hr))
|
|
return false;
|
|
|
|
context->CopyResource(staging.Get(), texture);
|
|
|
|
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
|
hr = context->Map(staging.Get(), 0, D3D11_MAP_READ, 0, &mapped);
|
|
if (FAILED(hr))
|
|
return false;
|
|
|
|
ComPtr<IWICImagingFactory> factory;
|
|
hr = CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER,
|
|
IID_PPV_ARGS(&factory));
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
ComPtr<IWICStream> stream;
|
|
hr = factory->CreateStream(&stream);
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
hr = stream->InitializeFromFilename(filename, GENERIC_WRITE);
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
ComPtr<IWICBitmapEncoder> encoder;
|
|
hr = factory->CreateEncoder(GUID_ContainerFormatPng, nullptr, &encoder);
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
hr = encoder->Initialize(stream.Get(), WICBitmapEncoderNoCache);
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
ComPtr<IWICBitmapFrameEncode> frame;
|
|
ComPtr<IPropertyBag2> props;
|
|
hr = encoder->CreateNewFrame(&frame, &props);
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
hr = frame->Initialize(props.Get());
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
hr = frame->SetSize(srcDesc.Width, srcDesc.Height);
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
WICPixelFormatGUID format = GUID_WICPixelFormat32bppBGRA;
|
|
hr = frame->SetPixelFormat(&format);
|
|
if (FAILED(hr))
|
|
{
|
|
context->Unmap(staging.Get(), 0);
|
|
return false;
|
|
}
|
|
|
|
hr = frame->WritePixels(
|
|
srcDesc.Height,
|
|
mapped.RowPitch,
|
|
mapped.RowPitch * srcDesc.Height,
|
|
reinterpret_cast<BYTE*>(mapped.pData));
|
|
|
|
context->Unmap(staging.Get(), 0);
|
|
|
|
if (FAILED(hr))
|
|
return false;
|
|
|
|
hr = frame->Commit();
|
|
if (FAILED(hr))
|
|
return false;
|
|
|
|
hr = encoder->Commit();
|
|
if (FAILED(hr))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*******************
|
|
**IUnknown methods**
|
|
********************/
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::QueryInterface(REFIID riid, LPVOID FAR* ppvObj)
|
|
{
|
|
debugMessage(1, "IDirectDrawWrapper::QueryInterface", "Partially Implemented");
|
|
|
|
if (ppvObj == NULL)
|
|
return E_POINTER;
|
|
|
|
*ppvObj = NULL;
|
|
|
|
if (riid == IID_IUnknown ||
|
|
riid == IID_IDirectDraw ||
|
|
riid == IID_IDirectDraw2 ||
|
|
riid == IID_IDirectDraw4 ||
|
|
riid == IID_IDirectDraw7)
|
|
{
|
|
*ppvObj = this;
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
ULONG __stdcall IDirectDrawWrapper::AddRef()
|
|
{
|
|
debugMessage(1, "IDirectDrawWrapper::AddRef", "Partially Implemented");
|
|
ReferenceCount++;
|
|
return ReferenceCount;
|
|
}
|
|
|
|
ULONG __stdcall IDirectDrawWrapper::Release()
|
|
{
|
|
debugMessage(1, "IDirectDrawWrapper::Release", "Partially Implemented");
|
|
|
|
if (ReferenceCount > 0)
|
|
ReferenceCount--;
|
|
|
|
if (ReferenceCount == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
|
|
return ReferenceCount;
|
|
}
|
|
|
|
/**********************
|
|
**IDirectDraw methods**
|
|
***********************/
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::Compact()
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::Compact", "Unsupported in DirectDraw");
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::CreateClipper(DWORD dwFlags, LPDIRECTDRAWCLIPPER FAR* lplpDDClipper, IUnknown FAR* pUnkOuter)
|
|
{
|
|
UNREFERENCED_PARAMETER(pUnkOuter);
|
|
|
|
char message[2048] = "\0";
|
|
sprintf_s(message, 2048, "Partially Supported dwFlags: %u", dwFlags);
|
|
debugMessage(1, "IDirectDrawWrapper::CreateClipper", message);
|
|
|
|
if (lplpDDClipper == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
IDirectDrawClipperWrapper* lpDDClipper = new IDirectDrawClipperWrapper();
|
|
if (lpDDClipper == NULL)
|
|
return DDERR_OUTOFMEMORY;
|
|
|
|
HRESULT hr = lpDDClipper->WrapperInitialize(dwFlags);
|
|
if (hr != DD_OK)
|
|
{
|
|
delete lpDDClipper;
|
|
return hr;
|
|
}
|
|
|
|
*lplpDDClipper = (LPDIRECTDRAWCLIPPER)lpDDClipper;
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::CreatePalette(DWORD dwFlags, LPPALETTEENTRY lpDDColorArray, LPDIRECTDRAWPALETTE FAR* lplpDDPalette, IUnknown FAR* pUnkOuter)
|
|
{
|
|
UNREFERENCED_PARAMETER(pUnkOuter);
|
|
|
|
char message[2048] = "\0";
|
|
sprintf_s(message, 2048, "Created dwFlags: %u", dwFlags);
|
|
|
|
if (lplpDDPalette == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
IDirectDrawPaletteWrapper* lpDDPalette = new IDirectDrawPaletteWrapper();
|
|
if (lpDDPalette == NULL)
|
|
return DDERR_OUTOFMEMORY;
|
|
|
|
HRESULT hr = lpDDPalette->WrapperInitialize(dwFlags, lpDDColorArray, lplpDDPalette);
|
|
if (hr != DD_OK)
|
|
{
|
|
delete lpDDPalette;
|
|
return hr;
|
|
}
|
|
|
|
*lplpDDPalette = (LPDIRECTDRAWPALETTE)lpDDPalette;
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::CreatePalette", message);
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::CreateSurface(LPDDSURFACEDESC lpDDSurfaceDesc, LPDIRECTDRAWSURFACE FAR* lplpDDSurface, IUnknown FAR* pUnkOuter)
|
|
{
|
|
UNREFERENCED_PARAMETER(pUnkOuter);
|
|
|
|
if (lpDDSurfaceDesc == NULL || lplpDDSurface == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
char message[2048] = "\0";
|
|
sprintf_s(message, 2048, "lpDDSurfaceDesc->dwFlags:: %u", lpDDSurfaceDesc->dwFlags);
|
|
|
|
if (lpAttachedSurface != NULL)
|
|
{
|
|
delete lpAttachedSurface;
|
|
lpAttachedSurface = NULL;
|
|
}
|
|
|
|
lpAttachedSurface = new IDirectDrawSurfaceWrapper(this);
|
|
if (lpAttachedSurface == NULL)
|
|
return DDERR_OUTOFMEMORY;
|
|
|
|
HRESULT hr = lpAttachedSurface->WrapperInitialize(lpDDSurfaceDesc, displayModeWidth, displayModeHeight, displayWidth, displayHeight);
|
|
if (hr != DD_OK)
|
|
return hr;
|
|
|
|
*lplpDDSurface = (LPDIRECTDRAWSURFACE)lpAttachedSurface;
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::CreateSurface", message);
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::DuplicateSurface(LPDIRECTDRAWSURFACE lpDDSurface, LPDIRECTDRAWSURFACE FAR* lplpDupDDSurface)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpDDSurface);
|
|
UNREFERENCED_PARAMETER(lplpDupDDSurface);
|
|
debugMessage(0, "DirectDrawWrapper::DuplicateSurface", "Not Implemented");
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::EnumDisplayModes(DWORD dwFlags, LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext, LPDDENUMMODESCALLBACK lpEnumModesCallback)
|
|
{
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
UNREFERENCED_PARAMETER(lpDDSurfaceDesc);
|
|
UNREFERENCED_PARAMETER(lpContext);
|
|
UNREFERENCED_PARAMETER(lpEnumModesCallback);
|
|
|
|
debugMessage(0, "IDirectDrawWrapper::EnumDisplayModes", "Not Implemented");
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::EnumSurfaces(DWORD dwFlags, LPDDSURFACEDESC lpDDSD, LPVOID lpContext, LPDDENUMSURFACESCALLBACK lpEnumSurfacesCallback)
|
|
{
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
UNREFERENCED_PARAMETER(lpDDSD);
|
|
UNREFERENCED_PARAMETER(lpContext);
|
|
UNREFERENCED_PARAMETER(lpEnumSurfacesCallback);
|
|
|
|
debugMessage(0, "IDirectDrawWrapper::EnumSurfaces", "Not Implemented");
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::FlipToGDISurface()
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::FlipToGDISurface", "Not Implemented");
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetCaps(LPDDCAPS lpDDDriverCaps, LPDDCAPS lpDDHELCaps)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::GetCaps", "Partially Implemented");
|
|
|
|
if (lpDDDriverCaps == NULL && lpDDHELCaps == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
if (lpDDDriverCaps != NULL)
|
|
{
|
|
ZeroMemory(lpDDDriverCaps, lpDDDriverCaps->dwSize);
|
|
lpDDDriverCaps->dwCaps = DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_GDI;
|
|
lpDDDriverCaps->dwVidMemTotal = 64 * 1024 * 1024;
|
|
lpDDDriverCaps->dwVidMemFree = 64 * 1024 * 1024;
|
|
}
|
|
|
|
if (lpDDHELCaps != NULL)
|
|
{
|
|
ZeroMemory(lpDDHELCaps, lpDDHELCaps->dwSize);
|
|
lpDDHELCaps->dwCaps = DDCAPS_BLT | DDCAPS_BLTCOLORFILL | DDCAPS_GDI;
|
|
lpDDHELCaps->dwVidMemTotal = 64 * 1024 * 1024;
|
|
lpDDHELCaps->dwVidMemFree = 64 * 1024 * 1024;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetDisplayMode(LPDDSURFACEDESC lpDDSurfaceDesc)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::GetDisplayMode", "Partially Implemented");
|
|
|
|
if (lpDDSurfaceDesc == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
ZeroMemory(lpDDSurfaceDesc, sizeof(DDSURFACEDESC));
|
|
lpDDSurfaceDesc->dwSize = sizeof(DDSURFACEDESC);
|
|
lpDDSurfaceDesc->dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_PIXELFORMAT | DDSD_PITCH;
|
|
lpDDSurfaceDesc->dwWidth = displayModeWidth;
|
|
lpDDSurfaceDesc->dwHeight = displayModeHeight;
|
|
lpDDSurfaceDesc->lPitch = displayModeWidth * 4;
|
|
|
|
lpDDSurfaceDesc->ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
|
lpDDSurfaceDesc->ddpfPixelFormat.dwFlags = DDPF_RGB;
|
|
lpDDSurfaceDesc->ddpfPixelFormat.dwRGBBitCount = 32;
|
|
lpDDSurfaceDesc->ddpfPixelFormat.dwRBitMask = 0x00FF0000;
|
|
lpDDSurfaceDesc->ddpfPixelFormat.dwGBitMask = 0x0000FF00;
|
|
lpDDSurfaceDesc->ddpfPixelFormat.dwBBitMask = 0x000000FF;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetFourCCCodes(LPDWORD lpNumCodes, LPDWORD lpCodes)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::GetFourCCCodes", "Partially Implemented");
|
|
|
|
if (lpNumCodes == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
if (lpCodes == NULL)
|
|
{
|
|
*lpNumCodes = 0;
|
|
}
|
|
else
|
|
{
|
|
*lpNumCodes = 0;
|
|
}
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetGDISurface(LPDIRECTDRAWSURFACE FAR* lplpGDIDDSSurface)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::GetGDISurface", "Partially Implemented");
|
|
|
|
if (lplpGDIDDSSurface == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
if (lpAttachedSurface == NULL)
|
|
return DDERR_NOTFOUND;
|
|
|
|
*lplpGDIDDSSurface = (LPDIRECTDRAWSURFACE)lpAttachedSurface;
|
|
lpAttachedSurface->AddRef();
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetMonitorFrequency(LPDWORD lpdwFrequency)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::GetMonitorFrequency", "Partially Implemented");
|
|
|
|
if (lpdwFrequency == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
*lpdwFrequency = refreshRate;
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetScanLine(LPDWORD lpdwScanLine)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::GetScanLine", "Not Implemented");
|
|
|
|
if (lpdwScanLine == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
*lpdwScanLine = 0;
|
|
return DDERR_UNSUPPORTED;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetVerticalBlankStatus(LPBOOL lpbIsInVB)
|
|
{
|
|
if (lpbIsInVB == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
*lpbIsInVB = FALSE;
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::Initialize(GUID FAR* lpGUID)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpGUID);
|
|
debugMessage(1, "IDirectDrawWrapper::Initialize", "Partially Implemented");
|
|
return DDERR_ALREADYINITIALIZED;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::RestoreDisplayMode()
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::RestoreDisplayMode", "Partially Implemented");
|
|
|
|
isWindowed = true;
|
|
displayWidth = displayWidthWindowed;
|
|
displayHeight = displayHeightWindowed;
|
|
AdjustWindow();
|
|
ReinitDevice();
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::SetCooperativeLevel(HWND in_hWnd, DWORD dwFlags)
|
|
{
|
|
char message[2048] = "\0";
|
|
sprintf_s(message, 2048, "Completed in_hWnd: 0x%p, dwFlags: %u", in_hWnd, dwFlags);
|
|
|
|
if (in_hWnd == NULL)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::SetCooperativeLevel", "Unimplemented for NULL window handle");
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
cooperativeFlags = dwFlags;
|
|
hWnd = in_hWnd;
|
|
|
|
#ifdef _WIN64
|
|
lpPrevWndFunc = (WNDPROC)GetWindowLongPtr(hWnd, GWLP_WNDPROC);
|
|
if (SetWindowLongPtr(hWnd, GWLP_WNDPROC, (LONG_PTR)WndProc) == 0)
|
|
#else
|
|
lpPrevWndFunc = (WNDPROC)GetWindowLong(hWnd, GWL_WNDPROC);
|
|
if (SetWindowLong(hWnd, GWL_WNDPROC, (LONG)WndProc) == 0)
|
|
#endif
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::SetCooperativeLevel", "Failed to overload WNDPROC");
|
|
}
|
|
|
|
AdjustWindow();
|
|
|
|
if (!CreateD3DDevice())
|
|
{
|
|
MessageBox(NULL, TEXT("Error creating Direct3D11 Device"), TEXT("Error"), MB_OK | MB_ICONERROR);
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::SetCooperativeLevel", message);
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::SetDisplayMode(DWORD dwWidth, DWORD dwHeight, DWORD dwBPP)
|
|
{
|
|
char message[2048] = "\0";
|
|
sprintf_s(message, "Complete dwWidth: %u, dwHeight: %u, dwBPP: %u", dwWidth, dwHeight, dwBPP);
|
|
|
|
displayModeWidth = dwWidth;
|
|
displayModeHeight = dwHeight;
|
|
|
|
if (!CreateSurfaceTexture())
|
|
{
|
|
MessageBox(NULL, TEXT("Error creating Direct3D11 surface texture"), TEXT("Error"), MB_OK | MB_ICONERROR);
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::SetDisplayMode", message);
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::WaitForVerticalBlank(DWORD dwFlags, HANDLE hEvent)
|
|
{
|
|
UNREFERENCED_PARAMETER(hEvent);
|
|
|
|
if (dwFlags & DDWAITVB_BLOCKBEGINEVENT)
|
|
return DDERR_UNSUPPORTED;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
/****************************
|
|
**Added in the V2 interface**
|
|
*****************************/
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetAvailableVideoMem(LPDDSCAPS2 lpDDSCaps2, LPDWORD lpdwTotal, LPDWORD lpdwFree)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpDDSCaps2);
|
|
|
|
debugMessage(0, "IDirectDrawWrapper::GetAvailableVideoMem", "Partially Implemented");
|
|
|
|
if (lpDDSCaps2 == NULL || lpdwTotal == NULL || lpdwFree == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
*lpdwTotal = 64 * 1024 * 1024;
|
|
*lpdwFree = 64 * 1024 * 1024;
|
|
return DD_OK;
|
|
}
|
|
|
|
/****************************
|
|
**Added in the V4 interface**
|
|
*****************************/
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::EvaluateMode(DWORD dwFlags, DWORD* pSecondsUntilTimeout)
|
|
{
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
debugMessage(0, "IDirectDrawWrapper::EvaluateMode", "Not Implemented");
|
|
|
|
if (pSecondsUntilTimeout == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
*pSecondsUntilTimeout = 0;
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetDeviceIdentifier(LPDDDEVICEIDENTIFIER2 lpdddi, DWORD dwFlags)
|
|
{
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
debugMessage(0, "IDirectDrawWrapper::GetDeviceIdentifier", "Partially Implemented");
|
|
|
|
if (lpdddi == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
ZeroMemory(lpdddi, sizeof(DDDEVICEIDENTIFIER2));
|
|
strcpy_s(lpdddi->szDriver, "D3D11Wrapper");
|
|
strcpy_s(lpdddi->szDescription, "DirectDraw to Direct3D11 Wrapper");
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::GetSurfaceFromDC(HDC hdc, LPDIRECTDRAWSURFACE7* lpDDS)
|
|
{
|
|
UNREFERENCED_PARAMETER(hdc);
|
|
|
|
debugMessage(0, "IDirectDrawWrapper::GetSurfaceFromDC", "Not Implemented");
|
|
|
|
if (lpDDS == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::RestoreAllSurfaces()
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::RestoreAllSurfaces", "Partially Implemented");
|
|
|
|
if (lpAttachedSurface != NULL)
|
|
lpAttachedSurface->Restore();
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::StartModeTest(LPSIZE lpModesToTest, DWORD dwNumEntries, DWORD dwFlags)
|
|
{
|
|
UNREFERENCED_PARAMETER(lpModesToTest);
|
|
UNREFERENCED_PARAMETER(dwNumEntries);
|
|
UNREFERENCED_PARAMETER(dwFlags);
|
|
|
|
debugMessage(0, "IDirectDrawWrapper::StartModeTest", "Not Implemented");
|
|
return DDERR_GENERIC;
|
|
}
|
|
|
|
HRESULT __stdcall IDirectDrawWrapper::TestCooperativeLevel()
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::TestCooperativeLevel", "Partially Implemented");
|
|
|
|
if (!d3d11Device || !swapChain)
|
|
return DDERR_GENERIC;
|
|
|
|
return DD_OK;
|
|
}
|
|
|
|
// Default constructor
|
|
IDirectDrawWrapper::IDirectDrawWrapper()
|
|
{
|
|
hWnd = NULL;
|
|
WndProc = NULL;
|
|
lpPrevWndFunc = NULL;
|
|
hModule = NULL;
|
|
|
|
cooperativeFlags = 0;
|
|
ReferenceCount = 0;
|
|
|
|
lpAttachedSurface = NULL;
|
|
|
|
inMenu = false;
|
|
curMenu = 0;
|
|
|
|
curMenuFrame = 0;
|
|
menuTextureWidth = 512;
|
|
menuTextureHeight = 512;
|
|
|
|
menuLocations[0] = 117;
|
|
menuLocations[1] = 162;
|
|
menuLocations[2] = 208;
|
|
menuLocations[3] = 253;
|
|
menuLocations[4] = 298;
|
|
|
|
menuSprites[0].left = 0;
|
|
menuSprites[0].top = 0;
|
|
menuSprites[0].right = 30;
|
|
menuSprites[0].bottom = 32;
|
|
|
|
menuSprites[1].left = menuSprites[0].right;
|
|
menuSprites[1].top = 0;
|
|
menuSprites[1].right = menuSprites[1].left + 14;
|
|
menuSprites[1].bottom = 32;
|
|
|
|
menuSprites[2].left = menuSprites[1].right;
|
|
menuSprites[2].top = 0;
|
|
menuSprites[2].right = menuSprites[2].left + 22;
|
|
menuSprites[2].bottom = 32;
|
|
|
|
menuSprites[3].left = menuSprites[2].right;
|
|
menuSprites[3].top = 0;
|
|
menuSprites[3].right = menuSprites[3].left + 21;
|
|
menuSprites[3].bottom = 32;
|
|
|
|
menuSprites[4].left = menuSprites[3].right;
|
|
menuSprites[4].top = 0;
|
|
menuSprites[4].right = menuSprites[4].left + 23;
|
|
menuSprites[4].bottom = 32;
|
|
|
|
menuSprites[5].left = menuSprites[4].right;
|
|
menuSprites[5].top = 0;
|
|
menuSprites[5].right = menuSprites[5].left + 21;
|
|
menuSprites[5].bottom = 32;
|
|
|
|
menuSprites[6].left = menuSprites[5].right;
|
|
menuSprites[6].top = 0;
|
|
menuSprites[6].right = menuSprites[6].left + 20;
|
|
menuSprites[6].bottom = 32;
|
|
|
|
menuSprites[7].left = menuSprites[6].right;
|
|
menuSprites[7].top = 0;
|
|
menuSprites[7].right = menuSprites[7].left + 21;
|
|
menuSprites[7].bottom = 32;
|
|
|
|
menuSprites[8].left = menuSprites[7].right;
|
|
menuSprites[8].top = 0;
|
|
menuSprites[8].right = menuSprites[8].left + 20;
|
|
menuSprites[8].bottom = 32;
|
|
|
|
menuSprites[9].left = menuSprites[8].right;
|
|
menuSprites[9].top = 0;
|
|
menuSprites[9].right = menuSprites[9].left + 21;
|
|
menuSprites[9].bottom = 32;
|
|
|
|
menuSprites[10].left = menuSprites[9].right;
|
|
menuSprites[10].top = 0;
|
|
menuSprites[10].right = menuSprites[10].left + 25;
|
|
menuSprites[10].bottom = 32;
|
|
|
|
menuSprites[11].left = 0;
|
|
menuSprites[11].top = 32;
|
|
menuSprites[11].right = 246;
|
|
menuSprites[11].bottom = 64;
|
|
|
|
menuSprites[12].left = 0;
|
|
menuSprites[12].top = 64;
|
|
menuSprites[12].right = 243;
|
|
menuSprites[12].bottom = 96;
|
|
|
|
menuSprites[13].left = 0;
|
|
menuSprites[13].top = 96;
|
|
menuSprites[13].right = 144;
|
|
menuSprites[13].bottom = 128;
|
|
|
|
menuSprites[14].left = 0;
|
|
menuSprites[14].top = 128;
|
|
menuSprites[14].right = 151;
|
|
menuSprites[14].bottom = 160;
|
|
|
|
menuSprites[15].left = 160;
|
|
menuSprites[15].top = 96;
|
|
menuSprites[15].right = menuSprites[15].left + 55;
|
|
menuSprites[15].bottom = 128;
|
|
|
|
menuSprites[16].left = 160;
|
|
menuSprites[16].top = 128;
|
|
menuSprites[16].right = menuSprites[15].left + 69;
|
|
menuSprites[16].bottom = 160;
|
|
|
|
menuSprites[17].left = 0;
|
|
menuSprites[17].top = 256;
|
|
menuSprites[17].right = 295;
|
|
menuSprites[17].bottom = 356;
|
|
|
|
windowedResolutions = new POINT[10];
|
|
windowedResolutionCount = 10;
|
|
windowedResolutions[0].x = 640; windowedResolutions[0].y = 480;
|
|
windowedResolutions[1].x = 800; windowedResolutions[1].y = 600;
|
|
windowedResolutions[2].x = 960; windowedResolutions[2].y = 720;
|
|
windowedResolutions[3].x = 1024; windowedResolutions[3].y = 768;
|
|
windowedResolutions[4].x = 1152; windowedResolutions[4].y = 864;
|
|
windowedResolutions[5].x = 1280; windowedResolutions[5].y = 960;
|
|
windowedResolutions[6].x = 1400; windowedResolutions[6].y = 1050;
|
|
windowedResolutions[7].x = 1440; windowedResolutions[7].y = 1080;
|
|
windowedResolutions[8].x = 1600; windowedResolutions[8].y = 1200;
|
|
windowedResolutions[9].x = 1920; windowedResolutions[9].y = 1440;
|
|
|
|
fullscreenResolutionCount = 0;
|
|
fullscreenResolutions = NULL;
|
|
fullscreenRefreshes = NULL;
|
|
|
|
displayModeWidth = 640;
|
|
displayModeHeight = 480;
|
|
|
|
displayWidthWindowed = 640;
|
|
displayHeightWindowed = 480;
|
|
displayWidthFullscreen = 640;
|
|
displayHeightFullscreen = 480;
|
|
|
|
displayWidth = 640;
|
|
displayHeight = 480;
|
|
|
|
refreshRate = 60;
|
|
isWindowed = true;
|
|
vSync = true;
|
|
|
|
menuWindowed = true;
|
|
menuvSync = true;
|
|
menuWindowedResolution = 0;
|
|
menuFullscreenResolution = 0;
|
|
|
|
lastPosition.x = 100;
|
|
lastPosition.y = 100;
|
|
|
|
ZeroMemory(&swapDesc, sizeof(swapDesc));
|
|
|
|
CoInitialize(NULL);
|
|
|
|
wchar_t curPath[MAX_PATH];
|
|
wchar_t filename[MAX_PATH];
|
|
wchar_t temp[1024];
|
|
|
|
GetCurrentDirectory(MAX_PATH, curPath);
|
|
wsprintf(filename, TEXT("%s\\hellfire_settings.ini"), curPath);
|
|
|
|
GetPrivateProfileString(TEXT("video"), TEXT("windowedResolution"), TEXT("640x480"), temp, 1024, filename);
|
|
for (int i = 0; i < 1024 && temp[i] != TEXT('\0'); i++)
|
|
{
|
|
if (temp[i] == TEXT('x') || temp[i] == TEXT('X'))
|
|
{
|
|
temp[i] = TEXT('\0');
|
|
displayWidthWindowed = _wtoi(temp);
|
|
displayHeightWindowed = _wtoi(&(temp[i + 1]));
|
|
if (displayWidthWindowed == 0 || displayHeightWindowed == 0)
|
|
{
|
|
displayWidthWindowed = 640;
|
|
displayHeightWindowed = 480;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
GetPrivateProfileString(TEXT("video"), TEXT("fullscreenResolution"), TEXT("640x480"), temp, 1024, filename);
|
|
for (int i = 0; i < 1024 && temp[i] != TEXT('\0'); i++)
|
|
{
|
|
if (temp[i] == TEXT('x') || temp[i] == TEXT('X'))
|
|
{
|
|
temp[i] = TEXT('\0');
|
|
displayWidthFullscreen = _wtoi(temp);
|
|
displayHeightFullscreen = _wtoi(&(temp[i + 1]));
|
|
if (displayWidthFullscreen == 0 || displayHeightFullscreen == 0)
|
|
{
|
|
displayWidthFullscreen = 640;
|
|
displayHeightFullscreen = 480;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
GetPrivateProfileString(TEXT("video"), TEXT("fullscreen"), TEXT("0"), temp, 1024, filename);
|
|
if (temp[0] == TEXT('1'))
|
|
isWindowed = false;
|
|
else
|
|
isWindowed = true;
|
|
|
|
if (isWindowed)
|
|
{
|
|
displayWidth = displayWidthWindowed;
|
|
displayHeight = displayHeightWindowed;
|
|
}
|
|
else
|
|
{
|
|
displayWidth = displayWidthFullscreen;
|
|
displayHeight = displayHeightFullscreen;
|
|
}
|
|
|
|
GetPrivateProfileString(TEXT("video"), TEXT("vsync"), TEXT("1"), temp, 1024, filename);
|
|
if (temp[0] == TEXT('1'))
|
|
vSync = true;
|
|
else
|
|
vSync = false;
|
|
|
|
GetPrivateProfileString(TEXT("video"), TEXT("refresh"), TEXT("60"), temp, 1024, filename);
|
|
refreshRate = _wtoi(temp);
|
|
if (refreshRate == 0)
|
|
refreshRate = 60;
|
|
|
|
AddRef();
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::IDirectDrawWrapper", "Created");
|
|
}
|
|
|
|
IDirectDrawWrapper::~IDirectDrawWrapper()
|
|
{
|
|
if (d3d11Context)
|
|
{
|
|
d3d11Context->ClearState();
|
|
d3d11Context->Flush();
|
|
}
|
|
|
|
if (lpAttachedSurface != NULL)
|
|
{
|
|
delete lpAttachedSurface;
|
|
lpAttachedSurface = NULL;
|
|
}
|
|
|
|
menuSRV.Reset();
|
|
menuTexture.Reset();
|
|
menuVertexBuffer.Reset();
|
|
|
|
surfaceSRV.Reset();
|
|
surfaceTexture.Reset();
|
|
|
|
vertexBuffer.Reset();
|
|
inputLayout.Reset();
|
|
blitVS.Reset();
|
|
blitPS.Reset();
|
|
samplerLinear.Reset();
|
|
alphaBlendState.Reset();
|
|
rasterState.Reset();
|
|
renderTargetView.Reset();
|
|
swapChain.Reset();
|
|
d3d11Context.Reset();
|
|
d3d11Device.Reset();
|
|
|
|
SAFE_DELETE_ARRAY(windowedResolutions);
|
|
windowedResolutionCount = 0;
|
|
|
|
SAFE_DELETE_ARRAY(fullscreenResolutions);
|
|
fullscreenResolutionCount = 0;
|
|
|
|
SAFE_DELETE_ARRAY(fullscreenRefreshes);
|
|
|
|
CoUninitialize();
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::~IDirectDrawWrapper", "Destroyed");
|
|
}
|
|
|
|
HRESULT IDirectDrawWrapper::WrapperInitialize(WNDPROC wp, HMODULE hMod)
|
|
{
|
|
WndProc = wp;
|
|
hModule = hMod;
|
|
|
|
ZeroMemory(&swapDesc, sizeof(swapDesc));
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::WrapperInitialize", "Initialized");
|
|
return DD_OK;
|
|
}
|
|
|
|
bool IDirectDrawWrapper::CreateRenderTarget()
|
|
{
|
|
renderTargetView.Reset();
|
|
|
|
ComPtr<ID3D11Texture2D> backBuffer;
|
|
HRESULT hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuffer.GetAddressOf());
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateRenderTarget", "GetBuffer failed");
|
|
return false;
|
|
}
|
|
|
|
hr = d3d11Device->CreateRenderTargetView(backBuffer.Get(), nullptr, &renderTargetView);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateRenderTarget", "CreateRenderTargetView failed");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IDirectDrawWrapper::CreateShaders()
|
|
{
|
|
ComPtr<ID3DBlob> vsBlob;
|
|
ComPtr<ID3DBlob> psBlob;
|
|
|
|
if (!CompileShaderSource(g_BlitVS_HLSL, "main", "vs_4_0", &vsBlob))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateShaders", "Vertex shader compile failed");
|
|
return false;
|
|
}
|
|
|
|
if (!CompileShaderSource(g_BlitPS_HLSL, "main", "ps_4_0", &psBlob))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateShaders", "Pixel shader compile failed");
|
|
return false;
|
|
}
|
|
|
|
HRESULT hr = d3d11Device->CreateVertexShader(vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), nullptr, &blitVS);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateShaders", "CreateVertexShader failed");
|
|
return false;
|
|
}
|
|
|
|
hr = d3d11Device->CreatePixelShader(psBlob->GetBufferPointer(), psBlob->GetBufferSize(), nullptr, &blitPS);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateShaders", "CreatePixelShader failed");
|
|
return false;
|
|
}
|
|
|
|
D3D11_INPUT_ELEMENT_DESC layout[] =
|
|
{
|
|
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, offsetof(TLVERTEX11, x), D3D11_INPUT_PER_VERTEX_DATA, 0 },
|
|
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(TLVERTEX11, u), D3D11_INPUT_PER_VERTEX_DATA, 0 }
|
|
};
|
|
|
|
hr = d3d11Device->CreateInputLayout(
|
|
layout,
|
|
_countof(layout),
|
|
vsBlob->GetBufferPointer(),
|
|
vsBlob->GetBufferSize(),
|
|
&inputLayout);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateShaders", "CreateInputLayout failed");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IDirectDrawWrapper::CreateMenuVertexBuffer()
|
|
{
|
|
menuVertexBuffer.Reset();
|
|
|
|
D3D11_BUFFER_DESC vbDesc = {};
|
|
vbDesc.ByteWidth = sizeof(SpriteVertex11) * 4;
|
|
vbDesc.Usage = D3D11_USAGE_DYNAMIC;
|
|
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
|
vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
|
|
HRESULT hr = d3d11Device->CreateBuffer(&vbDesc, nullptr, &menuVertexBuffer);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateMenuVertexBuffer", "CreateBuffer failed");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool IDirectDrawWrapper::CreateD3DDevice()
|
|
{
|
|
if (d3d11Context)
|
|
{
|
|
d3d11Context->ClearState();
|
|
d3d11Context->Flush();
|
|
}
|
|
|
|
menuSRV.Reset();
|
|
menuTexture.Reset();
|
|
menuVertexBuffer.Reset();
|
|
|
|
surfaceSRV.Reset();
|
|
surfaceTexture.Reset();
|
|
vertexBuffer.Reset();
|
|
|
|
inputLayout.Reset();
|
|
blitVS.Reset();
|
|
blitPS.Reset();
|
|
samplerLinear.Reset();
|
|
alphaBlendState.Reset();
|
|
rasterState.Reset();
|
|
renderTargetView.Reset();
|
|
swapChain.Reset();
|
|
d3d11Context.Reset();
|
|
d3d11Device.Reset();
|
|
|
|
SAFE_DELETE_ARRAY(fullscreenResolutions);
|
|
SAFE_DELETE_ARRAY(fullscreenRefreshes);
|
|
fullscreenResolutionCount = 0;
|
|
|
|
ComPtr<IDXGIFactory> dxgiFactory;
|
|
ComPtr<IDXGIAdapter> adapter;
|
|
ComPtr<IDXGIOutput> output;
|
|
|
|
HRESULT hr = CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)dxgiFactory.GetAddressOf());
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "CreateDXGIFactory failed");
|
|
return false;
|
|
}
|
|
|
|
hr = dxgiFactory->EnumAdapters(0, &adapter);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "EnumAdapters failed");
|
|
return false;
|
|
}
|
|
|
|
hr = adapter->EnumOutputs(0, &output);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "EnumOutputs failed");
|
|
return false;
|
|
}
|
|
|
|
UINT modeCount = 0;
|
|
hr = output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 0, &modeCount, nullptr);
|
|
if (FAILED(hr) || modeCount == 0)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "GetDisplayModeList count failed");
|
|
return false;
|
|
}
|
|
|
|
DXGI_MODE_DESC* modes = new DXGI_MODE_DESC[modeCount];
|
|
hr = output->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, 0, &modeCount, modes);
|
|
if (FAILED(hr))
|
|
{
|
|
SAFE_DELETE_ARRAY(modes);
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "GetDisplayModeList failed");
|
|
return false;
|
|
}
|
|
|
|
fullscreenResolutions = new POINT[modeCount];
|
|
fullscreenRefreshes = new UINT[modeCount];
|
|
|
|
bool modeFound = false;
|
|
for (UINT i = 0; i < modeCount; i++)
|
|
{
|
|
const DXGI_MODE_DESC& m = modes[i];
|
|
UINT refresh = 60;
|
|
if (m.RefreshRate.Denominator != 0)
|
|
refresh = m.RefreshRate.Numerator / m.RefreshRate.Denominator;
|
|
|
|
if (m.Width == (UINT)displayWidth && m.Height == (UINT)displayHeight && refresh == refreshRate)
|
|
{
|
|
modeFound = true;
|
|
menuFullscreenResolution = fullscreenResolutionCount;
|
|
}
|
|
|
|
if (m.Width < 1920 && m.Height < 1440)
|
|
{
|
|
fullscreenResolutions[fullscreenResolutionCount].x = (LONG)m.Width;
|
|
fullscreenResolutions[fullscreenResolutionCount].y = (LONG)m.Height;
|
|
fullscreenRefreshes[fullscreenResolutionCount] = refresh;
|
|
fullscreenResolutionCount++;
|
|
}
|
|
}
|
|
|
|
SAFE_DELETE_ARRAY(modes);
|
|
|
|
ZeroMemory(&swapDesc, sizeof(swapDesc));
|
|
swapDesc.BufferCount = 1;
|
|
swapDesc.BufferDesc.Width = isWindowed ? 0 : displayWidth;
|
|
swapDesc.BufferDesc.Height = isWindowed ? 0 : displayHeight;
|
|
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
swapDesc.BufferDesc.RefreshRate.Numerator = vSync ? refreshRate : 0;
|
|
swapDesc.BufferDesc.RefreshRate.Denominator = vSync ? 1 : 0;
|
|
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
swapDesc.OutputWindow = hWnd;
|
|
swapDesc.SampleDesc.Count = 1;
|
|
swapDesc.SampleDesc.Quality = 0;
|
|
swapDesc.Windowed = isWindowed ? TRUE : FALSE;
|
|
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
|
swapDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
|
|
|
UINT createFlags = 0;
|
|
#ifdef _DEBUG
|
|
createFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
|
#endif
|
|
|
|
D3D_FEATURE_LEVEL featureLevelOut = D3D_FEATURE_LEVEL_11_0;
|
|
D3D_FEATURE_LEVEL levels[] =
|
|
{
|
|
D3D_FEATURE_LEVEL_11_0,
|
|
D3D_FEATURE_LEVEL_10_1,
|
|
D3D_FEATURE_LEVEL_10_0
|
|
};
|
|
|
|
hr = D3D11CreateDeviceAndSwapChain(
|
|
nullptr,
|
|
D3D_DRIVER_TYPE_HARDWARE,
|
|
nullptr,
|
|
createFlags,
|
|
levels,
|
|
_countof(levels),
|
|
D3D11_SDK_VERSION,
|
|
&swapDesc,
|
|
&swapChain,
|
|
&d3d11Device,
|
|
&featureLevelOut,
|
|
&d3d11Context);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "D3D11CreateDeviceAndSwapChain failed");
|
|
MessageBox(NULL, TEXT("Failed to create Direct3D11 device."), TEXT("Direct3D11 Device Error"), MB_OK);
|
|
return false;
|
|
}
|
|
|
|
if (!isWindowed && modeFound)
|
|
swapChain->SetFullscreenState(TRUE, nullptr);
|
|
else
|
|
swapChain->SetFullscreenState(FALSE, nullptr);
|
|
|
|
if (!CreateRenderTarget())
|
|
return false;
|
|
|
|
D3D11_VIEWPORT vp = {};
|
|
vp.TopLeftX = 0.0f;
|
|
vp.TopLeftY = 0.0f;
|
|
vp.Width = (FLOAT)displayWidth;
|
|
vp.Height = (FLOAT)displayHeight;
|
|
vp.MinDepth = 0.0f;
|
|
vp.MaxDepth = 1.0f;
|
|
d3d11Context->RSSetViewports(1, &vp);
|
|
|
|
if (!CreateShaders())
|
|
return false;
|
|
|
|
D3D11_SAMPLER_DESC samp = {};
|
|
samp.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
|
|
samp.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
|
samp.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
|
samp.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
|
samp.MinLOD = 0.0f;
|
|
samp.MaxLOD = D3D11_FLOAT32_MAX;
|
|
|
|
hr = d3d11Device->CreateSamplerState(&samp, &samplerLinear);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "CreateSamplerState failed");
|
|
return false;
|
|
}
|
|
|
|
D3D11_BLEND_DESC blend = {};
|
|
blend.RenderTarget[0].BlendEnable = TRUE;
|
|
blend.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
|
|
blend.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
|
|
blend.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
|
|
blend.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
|
|
blend.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA;
|
|
blend.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
|
|
blend.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
|
|
|
|
hr = d3d11Device->CreateBlendState(&blend, &alphaBlendState);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "CreateBlendState failed");
|
|
return false;
|
|
}
|
|
|
|
D3D11_RASTERIZER_DESC rs = {};
|
|
rs.FillMode = D3D11_FILL_SOLID;
|
|
rs.CullMode = D3D11_CULL_NONE;
|
|
rs.ScissorEnable = FALSE;
|
|
rs.DepthClipEnable = TRUE;
|
|
|
|
hr = d3d11Device->CreateRasterizerState(&rs, &rasterState);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateD3DDevice", "CreateRasterizerState failed");
|
|
return false;
|
|
}
|
|
|
|
d3d11Context->RSSetState(rasterState.Get());
|
|
|
|
if (!CreateMenuVertexBuffer())
|
|
return false;
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::CreateD3DDevice", "Create D3D11 Object");
|
|
return true;
|
|
}
|
|
|
|
bool IDirectDrawWrapper::CreateSurfaceTexture()
|
|
{
|
|
surfaceSRV.Reset();
|
|
surfaceTexture.Reset();
|
|
vertexBuffer.Reset();
|
|
|
|
if (!d3d11Device)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture", "No D3D11 device");
|
|
return false;
|
|
}
|
|
|
|
D3D11_TEXTURE2D_DESC texDesc = {};
|
|
texDesc.Width = displayModeWidth;
|
|
texDesc.Height = displayModeHeight;
|
|
texDesc.MipLevels = 1;
|
|
texDesc.ArraySize = 1;
|
|
texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
|
texDesc.SampleDesc.Count = 1;
|
|
texDesc.Usage = D3D11_USAGE_DYNAMIC;
|
|
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
|
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
|
|
|
HRESULT hr = d3d11Device->CreateTexture2D(&texDesc, nullptr, &surfaceTexture);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture", "Unable to create surface texture");
|
|
return false;
|
|
}
|
|
|
|
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
|
|
srvDesc.Format = texDesc.Format;
|
|
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
|
srvDesc.Texture2D.MipLevels = 1;
|
|
|
|
hr = d3d11Device->CreateShaderResourceView(surfaceTexture.Get(), &srvDesc, &surfaceSRV);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture", "Unable to create SRV");
|
|
return false;
|
|
}
|
|
|
|
TLVERTEX11 vertices[4];
|
|
vertices[0] = { -1.0f, 1.0f, 0.0f, 0.0f, 0.0f };
|
|
vertices[1] = { 1.0f, 1.0f, 0.0f, 1.0f, 0.0f };
|
|
vertices[2] = { -1.0f, -1.0f, 0.0f, 0.0f, 1.0f };
|
|
vertices[3] = { 1.0f, -1.0f, 0.0f, 1.0f, 1.0f };
|
|
|
|
D3D11_BUFFER_DESC vbDesc = {};
|
|
vbDesc.ByteWidth = sizeof(vertices);
|
|
vbDesc.Usage = D3D11_USAGE_IMMUTABLE;
|
|
vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
|
|
|
D3D11_SUBRESOURCE_DATA initData = {};
|
|
initData.pSysMem = vertices;
|
|
|
|
hr = d3d11Device->CreateBuffer(&vbDesc, &initData, &vertexBuffer);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::CreateSurfaceTexture", "Unable to create vertex buffer");
|
|
return false;
|
|
}
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::CreateSurfaceTexture", "D3D11 Texture Created");
|
|
return true;
|
|
}
|
|
|
|
HRESULT IDirectDrawWrapper::Present()
|
|
{
|
|
if (!d3d11Device || !d3d11Context || !swapChain)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::Present", "Present called when D3D11 device doesn't exist");
|
|
return false;
|
|
}
|
|
|
|
if (!surfaceTexture || !surfaceSRV)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::Present", "Present called when texture doesn't exist");
|
|
return false;
|
|
}
|
|
|
|
if (lpAttachedSurface != NULL)
|
|
{
|
|
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
|
HRESULT hr = d3d11Context->Map(surfaceTexture.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::Present", "Failed to map texture memory");
|
|
return false;
|
|
}
|
|
|
|
for (DWORD y = 0; y < displayModeHeight; y++)
|
|
{
|
|
memcpy(
|
|
(BYTE*)mapped.pData + (y * mapped.RowPitch),
|
|
&lpAttachedSurface->rgbVideoMem[y * displayModeWidth],
|
|
displayModeWidth * sizeof(UINT32));
|
|
}
|
|
|
|
d3d11Context->Unmap(surfaceTexture.Get(), 0);
|
|
}
|
|
else
|
|
{
|
|
debugMessage(1, "IDirectDrawWrapper::Present", "Attempt to Present with no attached surface");
|
|
}
|
|
|
|
float clearColor[4] = { 0, 0, 0, 1 };
|
|
d3d11Context->OMSetRenderTargets(1, renderTargetView.GetAddressOf(), nullptr);
|
|
d3d11Context->ClearRenderTargetView(renderTargetView.Get(), clearColor);
|
|
|
|
D3D11_VIEWPORT vp = {};
|
|
vp.TopLeftX = 0.0f;
|
|
vp.TopLeftY = 0.0f;
|
|
vp.Width = (FLOAT)displayWidth;
|
|
vp.Height = (FLOAT)displayHeight;
|
|
vp.MinDepth = 0.0f;
|
|
vp.MaxDepth = 1.0f;
|
|
d3d11Context->RSSetViewports(1, &vp);
|
|
|
|
UINT stride = sizeof(TLVERTEX11);
|
|
UINT offset = 0;
|
|
|
|
d3d11Context->IASetInputLayout(inputLayout.Get());
|
|
d3d11Context->IASetVertexBuffers(0, 1, vertexBuffer.GetAddressOf(), &stride, &offset);
|
|
d3d11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
|
|
d3d11Context->VSSetShader(blitVS.Get(), nullptr, 0);
|
|
d3d11Context->PSSetShader(blitPS.Get(), nullptr, 0);
|
|
d3d11Context->PSSetShaderResources(0, 1, surfaceSRV.GetAddressOf());
|
|
d3d11Context->PSSetSamplers(0, 1, samplerLinear.GetAddressOf());
|
|
|
|
float blendFactor[4] = { 0, 0, 0, 0 };
|
|
d3d11Context->OMSetBlendState(nullptr, blendFactor, 0xFFFFFFFF);
|
|
|
|
d3d11Context->Draw(4, 0);
|
|
|
|
if (inMenu)
|
|
RenderMenuD3D11();
|
|
|
|
HRESULT hr = swapChain->Present(vSync ? 1 : 0, 0);
|
|
if (FAILED(hr))
|
|
{
|
|
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
|
|
{
|
|
debugMessage(1, "IDirectDrawWrapper::Present", "Device removed/reset");
|
|
return ReinitDevice();
|
|
}
|
|
|
|
debugMessage(0, "IDirectDrawWrapper::Present", "Failed to present scene");
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
BOOL IDirectDrawWrapper::MenuKey(WPARAM vKey)
|
|
{
|
|
if (vKey == VK_OEM_3)
|
|
{
|
|
if (inMenu == TRUE)
|
|
{
|
|
inMenu = FALSE;
|
|
}
|
|
else
|
|
{
|
|
curMenu = 0;
|
|
menuWindowed = isWindowed;
|
|
menuvSync = vSync;
|
|
menuWindowedResolution = 0;
|
|
menuFullscreenResolution = 0;
|
|
|
|
for (int i = 0; i < windowedResolutionCount; i++)
|
|
{
|
|
if (windowedResolutions[i].x == displayWidthWindowed && windowedResolutions[i].y == displayHeightWindowed)
|
|
{
|
|
menuWindowedResolution = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < fullscreenResolutionCount; i++)
|
|
{
|
|
if (fullscreenResolutions[i].x == displayWidthFullscreen &&
|
|
fullscreenResolutions[i].y == displayHeightFullscreen &&
|
|
fullscreenRefreshes[i] == refreshRate)
|
|
{
|
|
menuFullscreenResolution = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
inMenu = TRUE;
|
|
}
|
|
|
|
Present();
|
|
}
|
|
else if (vKey == VK_ESCAPE)
|
|
{
|
|
inMenu = FALSE;
|
|
Present();
|
|
}
|
|
else if (vKey == VK_DOWN)
|
|
{
|
|
curMenu++;
|
|
if (curMenu > 3) curMenu = 0;
|
|
Present();
|
|
}
|
|
else if (vKey == VK_UP)
|
|
{
|
|
curMenu--;
|
|
if (curMenu < 0) curMenu = 3;
|
|
Present();
|
|
}
|
|
else if (vKey == VK_RIGHT)
|
|
{
|
|
if (curMenu == 0)
|
|
{
|
|
if (menuWindowed)
|
|
{
|
|
menuWindowedResolution++;
|
|
if (menuWindowedResolution >= windowedResolutionCount)
|
|
menuWindowedResolution = 0;
|
|
}
|
|
else
|
|
{
|
|
menuFullscreenResolution++;
|
|
if (menuFullscreenResolution >= fullscreenResolutionCount)
|
|
menuFullscreenResolution = 0;
|
|
}
|
|
}
|
|
else if (curMenu == 1)
|
|
{
|
|
menuWindowed = !menuWindowed;
|
|
}
|
|
else if (curMenu == 2)
|
|
{
|
|
menuvSync = !menuvSync;
|
|
}
|
|
Present();
|
|
}
|
|
else if (vKey == VK_LEFT)
|
|
{
|
|
if (curMenu == 0)
|
|
{
|
|
if (menuWindowed)
|
|
{
|
|
menuWindowedResolution--;
|
|
if (menuWindowedResolution < 0)
|
|
menuWindowedResolution = windowedResolutionCount - 1;
|
|
}
|
|
else
|
|
{
|
|
menuFullscreenResolution--;
|
|
if (menuFullscreenResolution < 0)
|
|
menuFullscreenResolution = fullscreenResolutionCount - 1;
|
|
}
|
|
}
|
|
else if (curMenu == 1)
|
|
{
|
|
menuWindowed = !menuWindowed;
|
|
}
|
|
else if (curMenu == 2)
|
|
{
|
|
menuvSync = !menuvSync;
|
|
}
|
|
Present();
|
|
}
|
|
else if (vKey == VK_RETURN)
|
|
{
|
|
inMenu = false;
|
|
|
|
isWindowed = menuWindowed;
|
|
|
|
if (menuWindowed)
|
|
{
|
|
displayWidth = windowedResolutions[menuWindowedResolution].x;
|
|
displayHeight = windowedResolutions[menuWindowedResolution].y;
|
|
displayWidthWindowed = displayWidth;
|
|
displayHeightWindowed = displayHeight;
|
|
}
|
|
else
|
|
{
|
|
if (fullscreenResolutionCount > 0)
|
|
{
|
|
displayWidth = fullscreenResolutions[menuFullscreenResolution].x;
|
|
displayHeight = fullscreenResolutions[menuFullscreenResolution].y;
|
|
refreshRate = fullscreenRefreshes[menuFullscreenResolution];
|
|
displayWidthFullscreen = displayWidth;
|
|
displayHeightFullscreen = displayHeight;
|
|
}
|
|
}
|
|
|
|
vSync = menuvSync;
|
|
|
|
AdjustWindow();
|
|
|
|
if (swapChain)
|
|
swapChain->SetFullscreenState(isWindowed ? FALSE : TRUE, nullptr);
|
|
|
|
ReinitDevice();
|
|
Present();
|
|
|
|
wchar_t curPath[MAX_PATH];
|
|
wchar_t filename[MAX_PATH];
|
|
wchar_t temp[1024];
|
|
|
|
GetCurrentDirectory(MAX_PATH, curPath);
|
|
wsprintf(filename, TEXT("%s\\ddraw_settings.ini"), curPath);
|
|
|
|
wsprintf(temp, TEXT("%dx%d"), displayWidthWindowed, displayHeightWindowed);
|
|
WritePrivateProfileString(TEXT("video"), TEXT("windowedResolution"), temp, filename);
|
|
|
|
wsprintf(temp, TEXT("%dx%d"), displayWidthFullscreen, displayHeightFullscreen);
|
|
WritePrivateProfileString(TEXT("video"), TEXT("fullscreenResolution"), temp, filename);
|
|
|
|
wsprintf(temp, TEXT("%d"), refreshRate);
|
|
WritePrivateProfileString(TEXT("video"), TEXT("refresh"), temp, filename);
|
|
|
|
wsprintf(temp, TEXT("%d"), isWindowed ? 0 : 1);
|
|
WritePrivateProfileString(TEXT("video"), TEXT("fullscreen"), temp, filename);
|
|
|
|
wsprintf(temp, TEXT("%d"), vSync ? 1 : 0);
|
|
WritePrivateProfileString(TEXT("video"), TEXT("vsync"), temp, filename);
|
|
}
|
|
|
|
return inMenu;
|
|
}
|
|
|
|
void IDirectDrawWrapper::ToggleFullscreen()
|
|
{
|
|
if (isWindowed)
|
|
{
|
|
isWindowed = false;
|
|
displayWidth = displayWidthFullscreen;
|
|
displayHeight = displayHeightFullscreen;
|
|
}
|
|
else
|
|
{
|
|
isWindowed = true;
|
|
displayWidth = displayWidthWindowed;
|
|
displayHeight = displayHeightWindowed;
|
|
}
|
|
|
|
AdjustWindow();
|
|
|
|
if (swapChain)
|
|
swapChain->SetFullscreenState(isWindowed ? FALSE : TRUE, nullptr);
|
|
|
|
ReinitDevice();
|
|
Present();
|
|
}
|
|
|
|
void IDirectDrawWrapper::DoSnapshot()
|
|
{
|
|
if (!surfaceTexture || !d3d11Device || !d3d11Context)
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::DoSnapshot", "No surface texture to save.");
|
|
return;
|
|
}
|
|
|
|
wchar_t curPath[MAX_PATH];
|
|
GetCurrentDirectory(MAX_PATH, curPath);
|
|
|
|
wchar_t filename[MAX_PATH];
|
|
SYSTEMTIME sysTime;
|
|
GetSystemTime(&sysTime);
|
|
|
|
wchar_t title[1024];
|
|
GetWindowText(hWnd, title, 1024);
|
|
|
|
wsprintf(
|
|
filename,
|
|
TEXT("%s\\%s_%.4d%.2d%.2d_%.2d%.2d%.2d.png"),
|
|
curPath,
|
|
title,
|
|
sysTime.wYear, sysTime.wMonth, sysTime.wDay,
|
|
sysTime.wHour, sysTime.wMinute, sysTime.wSecond);
|
|
|
|
WIN32_FIND_DATA findData;
|
|
HANDLE findHandle = FindFirstFile(filename, &findData);
|
|
int curFileNum = 1;
|
|
while (findHandle != INVALID_HANDLE_VALUE)
|
|
{
|
|
FindClose(findHandle);
|
|
wsprintf(
|
|
filename,
|
|
TEXT("%s\\Diablo_%.4d%.2d%.2d_%.2d%.2d%.2d(%d).png"),
|
|
curPath,
|
|
sysTime.wYear, sysTime.wMonth, sysTime.wDay,
|
|
sysTime.wHour, sysTime.wMinute, sysTime.wSecond,
|
|
curFileNum);
|
|
curFileNum++;
|
|
findHandle = FindFirstFile(filename, &findData);
|
|
}
|
|
|
|
if (!SaveBGRA8TextureToPng(d3d11Device.Get(), d3d11Context.Get(), surfaceTexture.Get(), filename))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::DoSnapshot", "Error saving texture to file.");
|
|
return;
|
|
}
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::DoSnapshot", "Saved Screenshot");
|
|
}
|
|
|
|
void IDirectDrawWrapper::AdjustWindow()
|
|
{
|
|
if (hWnd == NULL)
|
|
return;
|
|
|
|
if (isWindowed)
|
|
{
|
|
#ifdef _WIN64
|
|
SetWindowLongPtr(hWnd, GWL_STYLE, WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
|
|
#else
|
|
SetWindowLong(hWnd, GWL_STYLE, WS_VISIBLE | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX);
|
|
#endif
|
|
|
|
RECT rc = { 0, 0, displayWidth, displayHeight };
|
|
AdjustWindowRect(&rc, GetWindowLong(hWnd, GWL_STYLE), FALSE);
|
|
|
|
SetWindowPos(
|
|
hWnd,
|
|
NULL,
|
|
lastPosition.x,
|
|
lastPosition.y,
|
|
rc.right - rc.left,
|
|
rc.bottom - rc.top,
|
|
SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
}
|
|
else
|
|
{
|
|
#ifdef _WIN64
|
|
SetWindowLongPtr(hWnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
|
#else
|
|
SetWindowLong(hWnd, GWL_STYLE, WS_VISIBLE | WS_POPUP);
|
|
#endif
|
|
|
|
SetWindowPos(
|
|
hWnd,
|
|
NULL,
|
|
0,
|
|
0,
|
|
displayWidth,
|
|
displayHeight,
|
|
SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
}
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::AdjustWindow", "Complete");
|
|
}
|
|
|
|
bool IDirectDrawWrapper::DrawMenuSprite(const RECT& srcRect, float dstX, float dstY, float dstW, float dstH)
|
|
{
|
|
if (!menuVertexBuffer || !menuSRV)
|
|
return false;
|
|
|
|
float screenW = (float)displayWidth;
|
|
float screenH = (float)displayHeight;
|
|
|
|
float x0 = PixelToNdcX(dstX, screenW);
|
|
float y0 = PixelToNdcY(dstY, screenH);
|
|
float x1 = PixelToNdcX(dstX + dstW, screenW);
|
|
float y1 = PixelToNdcY(dstY + dstH, screenH);
|
|
|
|
float u0 = (float)srcRect.left / (float)menuTextureWidth;
|
|
float v0 = (float)srcRect.top / (float)menuTextureHeight;
|
|
float u1 = (float)srcRect.right / (float)menuTextureWidth;
|
|
float v1 = (float)srcRect.bottom / (float)menuTextureHeight;
|
|
|
|
SpriteVertex11 verts[4] =
|
|
{
|
|
{ x0, y0, 0.0f, u0, v0 },
|
|
{ x1, y0, 0.0f, u1, v0 },
|
|
{ x0, y1, 0.0f, u0, v1 },
|
|
{ x1, y1, 0.0f, u1, v1 }
|
|
};
|
|
|
|
D3D11_MAPPED_SUBRESOURCE mapped = {};
|
|
HRESULT hr = d3d11Context->Map(menuVertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
|
|
if (FAILED(hr))
|
|
return false;
|
|
|
|
memcpy(mapped.pData, verts, sizeof(verts));
|
|
d3d11Context->Unmap(menuVertexBuffer.Get(), 0);
|
|
|
|
UINT stride = sizeof(SpriteVertex11);
|
|
UINT offset = 0;
|
|
|
|
d3d11Context->IASetInputLayout(inputLayout.Get());
|
|
d3d11Context->IASetVertexBuffers(0, 1, menuVertexBuffer.GetAddressOf(), &stride, &offset);
|
|
d3d11Context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
|
|
|
d3d11Context->VSSetShader(blitVS.Get(), nullptr, 0);
|
|
d3d11Context->PSSetShader(blitPS.Get(), nullptr, 0);
|
|
d3d11Context->PSSetShaderResources(0, 1, menuSRV.GetAddressOf());
|
|
d3d11Context->PSSetSamplers(0, 1, samplerLinear.GetAddressOf());
|
|
|
|
float blendFactor[4] = { 0, 0, 0, 0 };
|
|
d3d11Context->OMSetBlendState(alphaBlendState.Get(), blendFactor, 0xFFFFFFFF);
|
|
|
|
d3d11Context->Draw(4, 0);
|
|
return true;
|
|
}
|
|
|
|
void IDirectDrawWrapper::RenderMenuD3D11()
|
|
{
|
|
if (!menuSRV)
|
|
return;
|
|
|
|
float sx = (float)displayWidth / 640.0f;
|
|
float sy = (float)displayHeight / 480.0f;
|
|
|
|
int selectionLeft = 0;
|
|
int selectionRight = 0;
|
|
|
|
{
|
|
RECT r = menuSprites[17];
|
|
float x = (640.0f - (float)(r.right - r.left)) / 2.0f;
|
|
float y = 3.0f;
|
|
DrawMenuSprite(r, x * sx, y * sy, (r.right - r.left) * sx, (r.bottom - r.top) * sy);
|
|
}
|
|
|
|
{
|
|
RECT r = menuSprites[11];
|
|
float x = (640.0f - (float)(r.right - r.left)) / 2.0f;
|
|
float y = (float)menuLocations[0];
|
|
DrawMenuSprite(r, x * sx, y * sy, (r.right - r.left) * sx, (r.bottom - r.top) * sy);
|
|
}
|
|
|
|
{
|
|
char temp[1024];
|
|
if (menuWindowed)
|
|
sprintf_s(temp, 1024, "%dx%d", windowedResolutions[menuWindowedResolution].x, windowedResolutions[menuWindowedResolution].y);
|
|
else if (fullscreenResolutionCount > 0)
|
|
sprintf_s(temp, 1024, "%dx%dx%d", fullscreenResolutions[menuFullscreenResolution].x, fullscreenResolutions[menuFullscreenResolution].y, fullscreenRefreshes[menuFullscreenResolution]);
|
|
else
|
|
sprintf_s(temp, 1024, "%dx%d", displayWidth, displayHeight);
|
|
|
|
int resolutionStringWidth = 0;
|
|
for (size_t i = 0; i < strlen(temp); i++)
|
|
{
|
|
if (temp[i] != 'x')
|
|
resolutionStringWidth += menuSprites[temp[i] - '0'].right - menuSprites[temp[i] - '0'].left;
|
|
else
|
|
resolutionStringWidth += menuSprites[10].right - menuSprites[10].left;
|
|
}
|
|
|
|
float x = (640.0f - (float)resolutionStringWidth) / 2.0f;
|
|
float y = (float)menuLocations[1];
|
|
|
|
if (curMenu == 0)
|
|
{
|
|
selectionLeft = (int)x - 52;
|
|
selectionRight = (int)x + resolutionStringWidth + 10;
|
|
}
|
|
|
|
for (size_t i = 0; i < strlen(temp); i++)
|
|
{
|
|
RECT r = (temp[i] != 'x') ? menuSprites[temp[i] - '0'] : menuSprites[10];
|
|
float w = (float)(r.right - r.left);
|
|
float h = (float)(r.bottom - r.top);
|
|
DrawMenuSprite(r, x * sx, y * sy, w * sx, h * sy);
|
|
x += w;
|
|
}
|
|
}
|
|
|
|
{
|
|
RECT label = menuSprites[12];
|
|
float labelX = (640.0f - ((float)(menuSprites[12].right - menuSprites[12].left) + (float)(menuSprites[16].right - menuSprites[16].left) + 10.0f)) / 2.0f;
|
|
float y = (float)menuLocations[2];
|
|
|
|
if (curMenu == 1)
|
|
{
|
|
selectionLeft = (int)labelX - 52;
|
|
selectionRight = (int)labelX + (menuSprites[12].right - menuSprites[12].left) + (menuSprites[16].right - menuSprites[16].left) + 20;
|
|
}
|
|
|
|
DrawMenuSprite(label, labelX * sx, y * sy, (label.right - label.left) * sx, (label.bottom - label.top) * sy);
|
|
|
|
if (menuWindowed)
|
|
{
|
|
RECT offRect = menuSprites[16];
|
|
float x = labelX + (menuSprites[12].right - menuSprites[12].left) + 10.0f;
|
|
DrawMenuSprite(offRect, x * sx, y * sy, (offRect.right - offRect.left) * sx, (offRect.bottom - offRect.top) * sy);
|
|
}
|
|
else
|
|
{
|
|
RECT onRect = menuSprites[15];
|
|
float x = labelX + (menuSprites[12].right - menuSprites[12].left) + 10.0f + 14.0f;
|
|
DrawMenuSprite(onRect, x * sx, y * sy, (onRect.right - onRect.left) * sx, (onRect.bottom - onRect.top) * sy);
|
|
}
|
|
}
|
|
|
|
{
|
|
RECT label = menuSprites[13];
|
|
float labelX = (640.0f - ((float)(menuSprites[13].right - menuSprites[13].left) + (float)(menuSprites[16].right - menuSprites[16].left) + 10.0f)) / 2.0f;
|
|
float y = (float)menuLocations[3];
|
|
|
|
if (curMenu == 2)
|
|
{
|
|
selectionLeft = (int)labelX - 52;
|
|
selectionRight = (int)labelX + (menuSprites[13].right - menuSprites[13].left) + (menuSprites[16].right - menuSprites[16].left) + 20;
|
|
}
|
|
|
|
DrawMenuSprite(label, labelX * sx, y * sy, (label.right - label.left) * sx, (label.bottom - label.top) * sy);
|
|
|
|
if (!menuvSync)
|
|
{
|
|
RECT offRect = menuSprites[16];
|
|
float x = labelX + (menuSprites[13].right - menuSprites[13].left) + 10.0f;
|
|
DrawMenuSprite(offRect, x * sx, y * sy, (offRect.right - offRect.left) * sx, (offRect.bottom - offRect.top) * sy);
|
|
}
|
|
else
|
|
{
|
|
RECT onRect = menuSprites[15];
|
|
float x = labelX + (menuSprites[13].right - menuSprites[13].left) + 10.0f + 14.0f;
|
|
DrawMenuSprite(onRect, x * sx, y * sy, (onRect.right - onRect.left) * sx, (onRect.bottom - onRect.top) * sy);
|
|
}
|
|
}
|
|
|
|
{
|
|
RECT r = menuSprites[14];
|
|
float x = (640.0f - (float)(r.right - r.left)) / 2.0f;
|
|
float y = (float)menuLocations[4];
|
|
|
|
if (curMenu == 3)
|
|
{
|
|
selectionLeft = (int)x - 52;
|
|
selectionRight = (int)x + (r.right - r.left) + 10;
|
|
}
|
|
|
|
DrawMenuSprite(r, x * sx, y * sy, (r.right - r.left) * sx, (r.bottom - r.top) * sy);
|
|
}
|
|
|
|
{
|
|
RECT sLoc;
|
|
sLoc.left = 42 * (curMenuFrame % 4);
|
|
sLoc.top = 160 + (42 * (int)(curMenuFrame / 4));
|
|
sLoc.right = sLoc.left + 42;
|
|
sLoc.bottom = sLoc.top + 42;
|
|
|
|
curMenuFrame++;
|
|
if (curMenuFrame > 7)
|
|
curMenuFrame = 0;
|
|
|
|
float x = (float)selectionLeft;
|
|
float y = (float)menuLocations[curMenu + 1] - 5.0f;
|
|
DrawMenuSprite(sLoc, x * sx, y * sy, 42.0f * sx, 42.0f * sy);
|
|
|
|
x = (float)selectionRight;
|
|
DrawMenuSprite(sLoc, x * sx, y * sy, 42.0f * sx, 42.0f * sy);
|
|
}
|
|
}
|
|
|
|
bool IDirectDrawWrapper::ReinitDevice()
|
|
{
|
|
if (!swapChain || !d3d11Context)
|
|
return CreateD3DDevice();
|
|
|
|
d3d11Context->ClearState();
|
|
d3d11Context->Flush();
|
|
|
|
renderTargetView.Reset();
|
|
|
|
HRESULT hr = swapChain->ResizeBuffers(
|
|
1,
|
|
isWindowed ? 0 : displayWidth,
|
|
isWindowed ? 0 : displayHeight,
|
|
DXGI_FORMAT_R8G8B8A8_UNORM,
|
|
DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH);
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
debugMessage(0, "IDirectDrawWrapper::ReinitDevice", "ResizeBuffers failed");
|
|
return false;
|
|
}
|
|
|
|
if (!CreateRenderTarget())
|
|
return false;
|
|
|
|
D3D11_VIEWPORT vp = {};
|
|
vp.TopLeftX = 0.0f;
|
|
vp.TopLeftY = 0.0f;
|
|
vp.Width = (FLOAT)displayWidth;
|
|
vp.Height = (FLOAT)displayHeight;
|
|
vp.MinDepth = 0.0f;
|
|
vp.MaxDepth = 1.0f;
|
|
d3d11Context->RSSetViewports(1, &vp);
|
|
|
|
debugMessage(2, "IDirectDrawWrapper::ReinitDevice", "Reset device, now create texture");
|
|
|
|
return CreateSurfaceTexture();
|
|
} |