Owner-authorized source migration: 31 helper-only translation units were merged into their callers or existing inline headers; both build manifests updated. Includes the preserved source payload, Lua configuration matching wowdecomp, and exact malloca expansion without diagnostic pragmas. 449 native units compiled locally and 449 staged units compiled by the pinned server toolchain. No previously byte-matched function regressed. Compiler mapping diagnostics remain recorded as needs_cleanup, not accepted or peer-confirmed. Existing independent review records are preserved. README.md is intentionally unchanged.
588 lines
18 KiB
C++
588 lines
18 KiB
C++
#include "Render/DX7/DeviceOwnerDX7.h"
|
|
|
|
#include <cstring>
|
|
|
|
namespace {
|
|
// INLINED
|
|
HRESULT DeviceError(unsigned code) {
|
|
return static_cast<HRESULT>(0x82000000u | code);
|
|
}
|
|
|
|
// OFFSET: 0x00548C00
|
|
// FUNCTION: fn_01862
|
|
DDSURFACEDESC2 SurfaceDescription(DWORD flags, DWORD caps) {
|
|
DDSURFACEDESC2 result{};
|
|
result.dwSize = sizeof(result);
|
|
result.dwFlags = flags;
|
|
result.ddsCaps.dwCaps = caps;
|
|
result.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
|
|
|
|
return result;
|
|
}
|
|
|
|
// OFFSET: 0x0054AA50
|
|
// FUNCTION: fn_01900
|
|
RECT ClientRectangle(HWND window, const RECT& monitor) {
|
|
RECT result;
|
|
GetClientRect(window, &result);
|
|
POINT point{result.left, result.top};
|
|
ClientToScreen(window, &point);
|
|
result.left = point.x - monitor.left;
|
|
result.top = point.y - monitor.top;
|
|
point = {result.right, result.bottom};
|
|
ClientToScreen(window, &point);
|
|
result.right = point.x - monitor.left;
|
|
result.bottom = point.y - monitor.top;
|
|
|
|
return result;
|
|
}
|
|
|
|
// OFFSET: 0x0054A970
|
|
// FUNCTION: fn_01899
|
|
HRESULT CALLBACK SelectDepthFormat(DDPIXELFORMAT* candidate, void* context) {
|
|
auto* selected = static_cast<DDPIXELFORMAT*>(context);
|
|
|
|
if (!candidate || !selected) {
|
|
return D3DENUMRET_CANCEL;
|
|
}
|
|
|
|
if (candidate->dwFlags != selected->dwFlags || candidate->dwZBufferBitDepth <= selected->dwZBufferBitDepth) {
|
|
return D3DENUMRET_OK;
|
|
}
|
|
|
|
*selected = *candidate;
|
|
return candidate->dwZBufferBitDepth < 32 ? D3DENUMRET_OK : D3DENUMRET_CANCEL;
|
|
}
|
|
|
|
// INLINED
|
|
void ChannelMask(DeviceOwnerDX7::Channel& channel, DWORD mask) {
|
|
channel = {0, 8};
|
|
|
|
if (!mask) {
|
|
return;
|
|
}
|
|
|
|
while (!(mask & 1)) {
|
|
++channel.shift;
|
|
mask >>= 1;
|
|
}
|
|
|
|
do {
|
|
--channel.expansion;
|
|
mask >>= 1;
|
|
} while (mask);
|
|
}
|
|
|
|
// INLINED
|
|
HRESULT SurfaceError(HRESULT status, unsigned code) {
|
|
return status == DDERR_OUTOFVIDEOMEMORY ? status : DeviceError(code);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x005493B0
|
|
// FUNCTION: fn_01888
|
|
DeviceOwnerDX7::DeviceOwnerDX7()
|
|
: window(nullptr), width(0), height(0), primary(nullptr), backBuffer(nullptr), renderTarget(nullptr), depthBuffer(nullptr), draw(nullptr),
|
|
direct3D(nullptr), device(nullptr), depthMemory(0), fullscreen(0), presentationOption(0), captureSurface(nullptr), red{0, 8}, green{0, 8}, blue{0, 8},
|
|
alpha{0, 8}, bitDepth(0), redMask(0), greenMask(0), blueMask(0), alphaMask(0), surfacesLost(false) {
|
|
}
|
|
|
|
// OFFSET: 0x005498A0
|
|
// FUNCTION: fn_01894
|
|
HRESULT DeviceOwnerDX7::CreateSurfaces(const DDSURFACEDESC2* mode, DWORD flags, const RECT& monitor) {
|
|
const bool buffered = (flags & 2) != 0;
|
|
DDSURFACEDESC2 description = SurfaceDescription(DDSD_CAPS, 0);
|
|
HRESULT status;
|
|
|
|
if (flags & 1) {
|
|
SetRect(&this->source, 0, 0, mode->dwWidth, mode->dwHeight);
|
|
this->width = this->source.right;
|
|
this->height = this->source.bottom;
|
|
this->destination = this->source;
|
|
const DWORD modeFlags = this->width == 320 && this->height == 200 && mode->ddpfPixelFormat.dwRGBBitCount == 8 ? DDSDM_STANDARDVGAMODE : 0;
|
|
|
|
if (FAILED(this->draw->SetDisplayMode(this->width, this->height, mode->ddpfPixelFormat.dwRGBBitCount, mode->dwRefreshRate, modeFlags))) {
|
|
return DeviceError(9);
|
|
}
|
|
|
|
description.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
|
|
|
|
if (buffered) {
|
|
description.dwFlags |= DDSD_BACKBUFFERCOUNT;
|
|
description.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE | DDSCAPS_COMPLEX | DDSCAPS_FLIP;
|
|
description.dwBackBufferCount = 1;
|
|
}
|
|
|
|
status = this->draw->CreateSurface(&description, &this->primary, nullptr);
|
|
|
|
if (FAILED(status)) {
|
|
return SurfaceError(status, 7);
|
|
}
|
|
|
|
if (buffered) {
|
|
DDSCAPS2 caps{DDSCAPS_BACKBUFFER};
|
|
status = this->primary->GetAttachedSurface(&caps, &this->backBuffer);
|
|
|
|
if (FAILED(status)) {
|
|
return SurfaceError(status, 10);
|
|
}
|
|
}
|
|
} else {
|
|
GetClientRect(this->window, &this->source);
|
|
this->width = this->source.right;
|
|
this->height = this->source.bottom;
|
|
this->destination = ClientRectangle(this->window, monitor);
|
|
description.ddsCaps.dwCaps = buffered ? DDSCAPS_PRIMARYSURFACE : DDSCAPS_PRIMARYSURFACE | DDSCAPS_3DDEVICE;
|
|
status = this->draw->CreateSurface(&description, &this->primary, nullptr);
|
|
|
|
if (FAILED(status)) {
|
|
return SurfaceError(status, 7);
|
|
}
|
|
}
|
|
|
|
IDirectDrawClipper* clipper;
|
|
|
|
if (FAILED(this->draw->CreateClipper(0, &clipper, nullptr))) {
|
|
return DeviceError(8);
|
|
}
|
|
|
|
clipper->SetHWnd(0, this->window);
|
|
this->primary->SetClipper(clipper);
|
|
|
|
if (clipper) {
|
|
clipper->Release();
|
|
}
|
|
|
|
if (!(flags & 1)) {
|
|
if (buffered) {
|
|
description.dwWidth = this->width;
|
|
description.dwHeight = this->height;
|
|
description.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
description.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_3DDEVICE;
|
|
status = this->draw->CreateSurface(&description, &this->backBuffer, nullptr);
|
|
|
|
if (FAILED(status)) {
|
|
return SurfaceError(status, 10);
|
|
}
|
|
} else {
|
|
POINT topLeft{this->source.left, this->source.top};
|
|
ClientToScreen(this->window, &topLeft);
|
|
this->source.left = topLeft.x;
|
|
this->source.top = topLeft.y;
|
|
POINT bottomRight{this->source.right, this->source.bottom};
|
|
ClientToScreen(this->window, &bottomRight);
|
|
this->source.right = bottomRight.x;
|
|
this->source.bottom = bottomRight.y;
|
|
}
|
|
}
|
|
|
|
this->primaryDescription = SurfaceDescription(DDSD_CAPS, 0);
|
|
this->primary->GetSurfaceDesc(&this->primaryDescription);
|
|
const auto& format = this->primaryDescription.ddpfPixelFormat;
|
|
this->bitDepth = format.dwRGBBitCount;
|
|
this->redMask = format.dwRBitMask;
|
|
this->greenMask = format.dwGBitMask;
|
|
this->blueMask = format.dwBBitMask;
|
|
this->alphaMask = format.dwRGBAlphaBitMask;
|
|
ChannelMask(this->red, this->redMask);
|
|
ChannelMask(this->green, this->greenMask);
|
|
ChannelMask(this->blue, this->blueMask);
|
|
ChannelMask(this->alpha, this->alphaMask);
|
|
this->renderTarget = buffered ? this->backBuffer : this->primary;
|
|
this->renderTarget->AddRef();
|
|
description = SurfaceDescription(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY);
|
|
description.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
|
|
description.dwWidth = this->width;
|
|
description.dwHeight = this->height;
|
|
status = this->draw->CreateSurface(&description, &this->captureSurface, nullptr);
|
|
|
|
return FAILED(status) ? E_OUTOFMEMORY : S_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054A000
|
|
// FUNCTION: fn_01895
|
|
HRESULT DeviceOwnerDX7::CreateDevice(GUID* drawIdentity, const GUID* renderIdentity, const DDSURFACEDESC2* mode, DWORD flags, const RECT& monitor) {
|
|
this->depthMemory =
|
|
std::memcmp(renderIdentity, &IID_IDirect3DHALDevice, sizeof(GUID)) == 0 || std::memcmp(renderIdentity, &IID_IDirect3DTnLHalDevice, sizeof(GUID)) == 0
|
|
? DDSCAPS_VIDEOMEMORY
|
|
: DDSCAPS_SYSTEMMEMORY;
|
|
|
|
if (FAILED(DirectDrawCreateEx(drawIdentity, reinterpret_cast<void**>(&this->draw), IID_IDirectDraw7, nullptr))) {
|
|
return DeviceError(1);
|
|
}
|
|
|
|
auto description = SurfaceDescription(0, 0);
|
|
this->draw->GetDisplayMode(&description);
|
|
this->desktopBitDepth = description.ddpfPixelFormat.dwRGBBitCount;
|
|
DWORD cooperative = this->fullscreen ? DDSCL_FULLSCREEN | DDSCL_ALLOWREBOOT | DDSCL_EXCLUSIVE : DDSCL_NORMAL;
|
|
|
|
if (!(flags & 16)) {
|
|
cooperative |= DDSCL_FPUSETUP;
|
|
}
|
|
|
|
if (FAILED(this->draw->SetCooperativeLevel(this->window, cooperative | DDSCL_MULTITHREADED))) {
|
|
return DeviceError(2);
|
|
}
|
|
|
|
const HRESULT status = this->CreateSurfaces(mode, flags, monitor);
|
|
|
|
if (FAILED(status)) {
|
|
return status;
|
|
}
|
|
|
|
if (renderIdentity) {
|
|
if (FAILED(this->draw->QueryInterface(IID_IDirect3D7, reinterpret_cast<void**>(&this->direct3D)))) {
|
|
return DeviceError(3);
|
|
}
|
|
|
|
if (FAILED(this->direct3D->CreateDevice(*renderIdentity, this->renderTarget, &this->device))) {
|
|
return DeviceError(4);
|
|
}
|
|
|
|
D3DVIEWPORT7 viewport{0, 0, this->width, this->height, 0.0f, 1.0f};
|
|
|
|
if (FAILED(this->device->SetViewport(&viewport))) {
|
|
return DeviceError(6);
|
|
}
|
|
|
|
this->depthFormat = {};
|
|
this->depthFormat.dwFlags = DDPF_ZBUFFER | ((flags & 8) ? DDPF_STENCILBUFFER : 0);
|
|
this->direct3D->EnumZBufferFormats(*renderIdentity, SelectDepthFormat, &this->depthFormat);
|
|
|
|
if (this->depthFormat.dwSize != sizeof(this->depthFormat)) {
|
|
return DeviceError(5);
|
|
}
|
|
|
|
this->device->GetCaps(&this->caps);
|
|
|
|
if (!(this->caps.dpcTriCaps.dwRasterCaps & D3DPRASTERCAPS_ZBUFFERLESSHSR)) {
|
|
description = SurfaceDescription(DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT, this->depthMemory | DDSCAPS_ZBUFFER);
|
|
description.dwWidth = this->width;
|
|
description.dwHeight = this->height;
|
|
description.ddpfPixelFormat = this->depthFormat;
|
|
const HRESULT depthStatus = this->draw->CreateSurface(&description, &this->depthBuffer, nullptr);
|
|
|
|
if (FAILED(depthStatus)) {
|
|
return SurfaceError(depthStatus, 5);
|
|
}
|
|
|
|
if (FAILED(this->renderTarget->AddAttachedSurface(this->depthBuffer)) || FAILED(this->device->SetRenderTarget(this->renderTarget, 0))) {
|
|
return DeviceError(5);
|
|
}
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054A7D0
|
|
// FUNCTION: fn_01897
|
|
HRESULT DeviceOwnerDX7::Close() {
|
|
ULONG deviceReferences = 0;
|
|
|
|
if (this->device) {
|
|
deviceReferences = this->device->Release();
|
|
|
|
if (static_cast<std::int32_t>(deviceReferences) > 0) {
|
|
do {
|
|
deviceReferences = this->device->Release();
|
|
} while (deviceReferences);
|
|
}
|
|
}
|
|
|
|
this->device = nullptr;
|
|
|
|
if (!this->fullscreen && this->backBuffer) {
|
|
this->backBuffer->Release();
|
|
this->backBuffer = nullptr;
|
|
}
|
|
|
|
if (this->depthBuffer) {
|
|
this->depthBuffer->Release();
|
|
this->depthBuffer = nullptr;
|
|
}
|
|
|
|
if (this->renderTarget) {
|
|
this->renderTarget->Release();
|
|
this->renderTarget = nullptr;
|
|
}
|
|
|
|
if (this->primary) {
|
|
this->primary->Release();
|
|
this->primary = nullptr;
|
|
}
|
|
|
|
if (this->direct3D) {
|
|
this->direct3D->Release();
|
|
this->direct3D = nullptr;
|
|
}
|
|
|
|
if (this->captureSurface) {
|
|
this->captureSurface->Release();
|
|
this->captureSurface = nullptr;
|
|
}
|
|
|
|
ULONG drawReferences = 0;
|
|
|
|
if (this->draw) {
|
|
this->draw->SetCooperativeLevel(this->window, DDSCL_NORMAL);
|
|
drawReferences = this->draw->Release();
|
|
}
|
|
|
|
this->draw = nullptr;
|
|
return drawReferences || deviceReferences ? DeviceError(11) : S_OK;
|
|
}
|
|
|
|
// OFFSET: 0x0054AAD0
|
|
// FUNCTION: fn_01901
|
|
HRESULT DeviceOwnerDX7::Initialize(
|
|
HWND value, GUID* drawIdentity, const GUID* renderIdentity, const DDSURFACEDESC2* mode, DWORD flags, HWND applicationWindow, const RECT& monitor
|
|
) {
|
|
this->window = value;
|
|
|
|
if (!value || !renderIdentity || (!mode && (flags & 1))) {
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
this->fullscreen = flags & 1;
|
|
|
|
if (this->fullscreen) {
|
|
SetWindowLongA(applicationWindow, GWL_STYLE, static_cast<LONG>(WS_POPUP));
|
|
ShowWindow(applicationWindow, SW_MAXIMIZE);
|
|
}
|
|
|
|
const HRESULT status = this->CreateDevice(drawIdentity, renderIdentity, mode, flags, monitor);
|
|
|
|
if (FAILED(status)) {
|
|
this->Close();
|
|
|
|
if (status == E_FAIL) {
|
|
return DeviceError(0);
|
|
}
|
|
}
|
|
|
|
if (this->device) {
|
|
const struct {
|
|
D3DRENDERSTATETYPE state;
|
|
DWORD value;
|
|
} states[] = {
|
|
{D3DRENDERSTATE_CULLMODE, D3DCULL_NONE},
|
|
{D3DRENDERSTATE_ZFUNC, D3DCMP_LESSEQUAL},
|
|
{D3DRENDERSTATE_TEXTUREPERSPECTIVE, TRUE},
|
|
{D3DRENDERSTATE_ALPHAFUNC, D3DCMP_GREATEREQUAL},
|
|
{D3DRENDERSTATE_ALPHAREF, 240},
|
|
{D3DRENDERSTATE_COLORKEYENABLE, TRUE},
|
|
{D3DRENDERSTATE_ZENABLE, D3DZB_TRUE},
|
|
{D3DRENDERSTATE_ZWRITEENABLE, TRUE},
|
|
{D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA},
|
|
{D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA}
|
|
};
|
|
|
|
for (const auto& state : states) {
|
|
this->device->SetRenderState(state.state, state.value);
|
|
}
|
|
|
|
const struct {
|
|
DWORD stage;
|
|
D3DTEXTURESTAGESTATETYPE state;
|
|
DWORD value;
|
|
} stages[] = {{0, D3DTSS_TEXCOORDINDEX, 0}, {0, D3DTSS_COLOROP, D3DTOP_MODULATE},
|
|
{0, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {0, D3DTSS_COLORARG2, D3DTA_DIFFUSE},
|
|
{0, D3DTSS_ALPHAOP, D3DTOP_MODULATE}, {0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE},
|
|
{0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE}, {1, D3DTSS_TEXCOORDINDEX, 1},
|
|
{1, D3DTSS_COLORARG1, D3DTA_TEXTURE}, {1, D3DTSS_COLOROP, D3DTOP_MODULATEALPHA_ADDCOLOR},
|
|
{1, D3DTSS_COLORARG2, D3DTA_CURRENT}, {1, D3DTSS_ALPHAOP, D3DTOP_DISABLE},
|
|
{2, D3DTSS_COLOROP, D3DTOP_DISABLE}, {2, D3DTSS_ALPHAOP, D3DTOP_DISABLE},
|
|
{0, D3DTSS_MAGFILTER, D3DTFG_LINEAR}, {0, D3DTSS_MINFILTER, D3DTFN_LINEAR},
|
|
{1, D3DTSS_MAGFILTER, D3DTFG_LINEAR}, {1, D3DTSS_MINFILTER, D3DTFN_LINEAR},
|
|
{0, D3DTSS_ADDRESS, D3DTADDRESS_CLAMP}, {1, D3DTSS_ADDRESS, D3DTADDRESS_BORDER},
|
|
{1, D3DTSS_BORDERCOLOR, 0xFF000000}};
|
|
|
|
for (const auto& state : stages) {
|
|
this->device->SetTextureStageState(state.stage, state.state, state.value);
|
|
}
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
// OFFSET: 0x005496D0
|
|
// FUNCTION: fn_01892
|
|
HRESULT DeviceOwnerDX7::Clear(DWORD color) {
|
|
D3DRECT rectangle{0, 0, static_cast<LONG>(this->width), static_cast<LONG>(this->height)};
|
|
return this->device->Clear(1, &rectangle, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, color, 1.0f, 0);
|
|
}
|
|
|
|
// OFFSET: 0x00549730
|
|
// FUNCTION: fn_01893
|
|
HRESULT DeviceOwnerDX7::ClearDepth() {
|
|
D3DRECT rectangle{0, 0, static_cast<LONG>(this->width), static_cast<LONG>(this->height)};
|
|
return this->device->Clear(1, &rectangle, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
|
|
}
|
|
|
|
// OFFSET: 0x0054AF10
|
|
// FUNCTION: fn_01903
|
|
void DeviceOwnerDX7::MarkSurfacesLost() {
|
|
this->surfacesLost = true;
|
|
}
|
|
|
|
// OFFSET: 0x005495C0
|
|
// FUNCTION: fn_01891
|
|
bool DeviceOwnerDX7::RestoreLostSurfaces() {
|
|
if (!this->surfacesLost) {
|
|
return false;
|
|
}
|
|
|
|
const HRESULT primaryStatus = this->primary->IsLost();
|
|
const HRESULT depthStatus = this->depthBuffer ? this->depthBuffer->IsLost() : S_OK;
|
|
|
|
if (primaryStatus == DDERR_SURFACELOST && depthStatus == DDERR_SURFACELOST) {
|
|
if (this->depthBuffer) {
|
|
this->depthBuffer->Restore();
|
|
}
|
|
|
|
this->draw->RestoreAllSurfaces();
|
|
this->surfacesLost = false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// OFFSET: 0x0054AF20
|
|
// FUNCTION: fn_01904
|
|
HRESULT DeviceOwnerDX7::Present(bool wait, const RECT& monitor) {
|
|
if (!this->primary) {
|
|
return DeviceError(14);
|
|
}
|
|
|
|
if (!this->backBuffer) {
|
|
return this->primary->IsLost();
|
|
}
|
|
|
|
if (wait && (!this->fullscreen || this->presentationOption)) {
|
|
this->destination = ClientRectangle(this->window, monitor);
|
|
this->draw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, nullptr);
|
|
return this->primary->Blt(&this->destination, this->backBuffer, &this->source, DDBLT_WAIT, nullptr);
|
|
}
|
|
|
|
GetClientRect(this->window, &this->destination);
|
|
POINT topLeft{this->destination.left, this->destination.top};
|
|
ClientToScreen(this->window, &topLeft);
|
|
this->destination.left = topLeft.x;
|
|
this->destination.top = topLeft.y;
|
|
POINT bottomRight{this->destination.right, this->destination.bottom};
|
|
ClientToScreen(this->window, &bottomRight);
|
|
this->destination.right = bottomRight.x;
|
|
this->destination.bottom = bottomRight.y;
|
|
|
|
if (wait) {
|
|
this->draw->WaitForVerticalBlank(DDWAITVB_BLOCKBEGIN, nullptr);
|
|
return this->primary->Blt(nullptr, this->backBuffer, nullptr, DDBLT_WAIT, nullptr);
|
|
}
|
|
|
|
return this->primary->Blt(&this->destination, this->backBuffer, &this->source, DDBLT_WAIT, nullptr);
|
|
}
|
|
|
|
// OFFSET: 0x005494C0
|
|
// FUNCTION: fn_01890
|
|
void DeviceOwnerDX7::AdjustTextureDimensions(std::uint32_t& width, std::uint32_t& height) const {
|
|
std::uint32_t selectedWidth = 1;
|
|
|
|
while (selectedWidth < width) {
|
|
selectedWidth *= 2;
|
|
}
|
|
|
|
if (selectedWidth < this->minTextureWidth) {
|
|
selectedWidth = this->minTextureWidth;
|
|
}
|
|
|
|
if (selectedWidth > this->maxTextureWidth) {
|
|
selectedWidth = this->maxTextureWidth;
|
|
}
|
|
|
|
std::uint32_t selectedHeight = 1;
|
|
|
|
while (selectedHeight < height) {
|
|
selectedHeight *= 2;
|
|
}
|
|
|
|
if (selectedHeight < this->minTextureHeight) {
|
|
selectedHeight = this->minTextureHeight;
|
|
}
|
|
|
|
if (selectedHeight > this->maxTextureHeight) {
|
|
selectedHeight = this->maxTextureHeight;
|
|
}
|
|
|
|
const auto aspect = this->maxTextureAspectRatio;
|
|
|
|
if (aspect) {
|
|
if (selectedWidth / selectedHeight > aspect) {
|
|
selectedHeight = selectedWidth / aspect;
|
|
}
|
|
|
|
if (selectedHeight / selectedWidth > aspect) {
|
|
selectedWidth = selectedHeight / aspect;
|
|
}
|
|
}
|
|
|
|
width = selectedWidth;
|
|
height = selectedHeight;
|
|
}
|
|
|
|
// OFFSET: 0x0054AE50
|
|
// FUNCTION: fn_01902
|
|
bool DeviceOwnerDX7::SupportsTextureDimensions(std::uint32_t width, std::uint32_t height) const {
|
|
return this->minTextureWidth <= width && width <= this->maxTextureWidth && this->minTextureHeight <= height && height <= this->maxTextureHeight;
|
|
}
|
|
|
|
// OFFSET: 0x0056B890
|
|
// FUNCTION: fn_02324
|
|
void DeviceOwnerDX7::PrepareErrorDialog() {
|
|
if (this->direct3D) {
|
|
this->direct3D->EvictManagedTextures();
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x0056B8B0
|
|
// FUNCTION: fn_02325
|
|
void DeviceOwnerDX7::RestoreDisplayMode() {
|
|
if (this->draw) {
|
|
if (this->backBuffer) {
|
|
this->backBuffer->Unlock(nullptr);
|
|
}
|
|
|
|
if (this->primary) {
|
|
this->primary->Unlock(nullptr);
|
|
}
|
|
|
|
this->draw->FlipToGDISurface();
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x0056C4B0
|
|
// FUNCTION: fn_02336
|
|
HRESULT DeviceOwnerDX7::RestoreAllSurfaces() {
|
|
return this->draw->RestoreAllSurfaces();
|
|
}
|
|
|
|
// OFFSET: 0x0054A8D0
|
|
// FUNCTION: fn_45420
|
|
void DeviceOwnerDX7::SetDialogClipper(int enabled) {
|
|
if (!this->fullscreen) {
|
|
return;
|
|
}
|
|
|
|
IDirectDrawClipper* clipper = nullptr;
|
|
|
|
if (enabled == 1) {
|
|
this->draw->CreateClipper(0, &clipper, nullptr);
|
|
clipper->SetHWnd(0, this->window);
|
|
}
|
|
|
|
this->primary->SetClipper(clipper);
|
|
|
|
if (clipper) {
|
|
clipper->Release();
|
|
}
|
|
}
|