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.
297 lines
8.4 KiB
C++
297 lines
8.4 KiB
C++
#include "Render/DX7/DeviceOwnerDX7.h"
|
|
#include "Render/DX7/SurfaceDX7.h"
|
|
|
|
#include <algorithm>
|
|
#include <cstring>
|
|
|
|
namespace {
|
|
// INLINED
|
|
std::uint32_t AlignDimension(int value) {
|
|
const std::uint32_t dimension = value;
|
|
return dimension + ((0u - dimension) & 3);
|
|
}
|
|
|
|
// INLINED
|
|
DDSURFACEDESC2 Description(DeviceOwnerDX7& owner, DWORD width, DWORD height) {
|
|
DDSURFACEDESC2 description{};
|
|
description.dwSize = sizeof(description);
|
|
description.dwFlags = DDSD_CAPS | DDSD_WIDTH | DDSD_HEIGHT | DDSD_CKSRCBLT;
|
|
description.dwWidth = width;
|
|
description.dwHeight = height;
|
|
description.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_SYSTEMMEMORY;
|
|
description.ddpfPixelFormat = owner.primaryDescription.ddpfPixelFormat;
|
|
description.ddckCKSrcBlt.dwColorSpaceLowValue = description.ddpfPixelFormat.dwRBitMask | description.ddpfPixelFormat.dwBBitMask;
|
|
description.ddckCKSrcBlt.dwColorSpaceHighValue = description.ddckCKSrcBlt.dwColorSpaceLowValue;
|
|
|
|
return description;
|
|
}
|
|
|
|
// INLINED
|
|
std::uint16_t Channel(unsigned value, const DeviceOwnerDX7::Channel& channel) {
|
|
return static_cast<std::uint16_t>((value >> (channel.expansion & 31)) << (channel.shift & 31));
|
|
}
|
|
|
|
// FUNCTION: fn_01787
|
|
std::uint16_t Color(DeviceOwnerDX7& owner, unsigned red, unsigned green, unsigned blue) {
|
|
return static_cast<std::uint16_t>(Channel(red, owner.red) + Channel(green, owner.green) + Channel(blue, owner.blue));
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00542B50
|
|
// FUNCTION: fn_01776
|
|
CSurfaceDX7::CSurfaceDX7(DeviceOwnerDX7& owner, int width, int height)
|
|
: m_owner(&owner), m_surface(nullptr), m_width(AlignDimension(width)), m_height(AlignDimension(height)) {
|
|
auto description = Description(owner, this->m_width, this->m_height);
|
|
owner.draw->CreateSurface(&description, &this->m_surface, nullptr);
|
|
}
|
|
|
|
// OFFSET: 0x00542C80
|
|
// FUNCTION: fn_01777
|
|
CSurfaceDX7::CSurfaceDX7(DeviceOwnerDX7& owner, IDirectDrawSurface7* surface) : m_owner(&owner), m_surface(nullptr), m_width(0), m_height(0) {
|
|
if (surface) {
|
|
DDSURFACEDESC2 description{};
|
|
description.dwSize = sizeof(description);
|
|
|
|
if (SUCCEEDED(surface->GetSurfaceDesc(&description))) {
|
|
this->m_width = description.dwWidth;
|
|
this->m_height = description.dwHeight;
|
|
this->m_surface = surface;
|
|
surface->AddRef();
|
|
}
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00542DC0
|
|
// OFFSET: 0x00542E60
|
|
// FUNCTION: fn_01779
|
|
CSurfaceDX7::~CSurfaceDX7() {
|
|
if (this->m_surface) {
|
|
this->m_surface->Release();
|
|
this->m_surface = nullptr;
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00543360
|
|
// FUNCTION: fn_01801
|
|
std::uint32_t CSurfaceDX7::Width() {
|
|
return this->m_width;
|
|
}
|
|
|
|
// OFFSET: 0x00543310
|
|
// FUNCTION: fn_01796
|
|
std::uint32_t CSurfaceDX7::Height() {
|
|
return this->m_height;
|
|
}
|
|
|
|
// OFFSET: 0x00543000
|
|
// FUNCTION: fn_01784
|
|
bool CSurfaceDX7::Resize(int width, int height) {
|
|
this->m_width = AlignDimension(width);
|
|
this->m_height = AlignDimension(height);
|
|
|
|
if (this->m_surface) {
|
|
this->m_surface->Release();
|
|
this->m_surface = nullptr;
|
|
}
|
|
|
|
auto description = Description(*this->m_owner, this->m_width, this->m_height);
|
|
return SUCCEEDED(this->m_owner->draw->CreateSurface(&description, &this->m_surface, nullptr));
|
|
}
|
|
|
|
// OFFSET: 0x00543370
|
|
// FUNCTION: fn_01802
|
|
SurfaceLock CSurfaceDX7::Lock() {
|
|
SurfaceLock output{};
|
|
|
|
if (this->m_surface) {
|
|
DDSURFACEDESC2 description{};
|
|
|
|
if (SUCCEEDED(this->m_surface->Lock(nullptr, &description, DDLOCK_WAIT, nullptr))) {
|
|
output.success = true;
|
|
output.pixels = description.lpSurface;
|
|
output.pitch = description.lPitch;
|
|
output.width = description.dwWidth;
|
|
output.height = description.dwHeight;
|
|
output.bitsPerPixel = description.ddpfPixelFormat.dwRGBBitCount;
|
|
}
|
|
}
|
|
|
|
return output;
|
|
}
|
|
|
|
// OFFSET: 0x00543710
|
|
// FUNCTION: fn_01804
|
|
void CSurfaceDX7::Unlock() {
|
|
if (this->m_surface) {
|
|
this->m_surface->Unlock(nullptr);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x005432A0
|
|
// FUNCTION: fn_01791
|
|
bool CSurfaceDX7::GetDC(HDC* output) {
|
|
return this->m_surface && SUCCEEDED(this->m_surface->GetDC(output));
|
|
}
|
|
|
|
// OFFSET: 0x00543400
|
|
// FUNCTION: fn_01803
|
|
void CSurfaceDX7::ReleaseDC(HDC dc) {
|
|
if (this->m_surface) {
|
|
this->m_surface->ReleaseDC(dc);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x00543730
|
|
// FUNCTION: fn_01805
|
|
void CSurfaceDX7::Upload(int x, int y, int width, int height, const std::uint32_t* pixels, int, int sourceWidth) {
|
|
if (!this->m_surface || !width || !height) {
|
|
return;
|
|
}
|
|
|
|
const unsigned stride = sourceWidth ? sourceWidth : width;
|
|
RECT rectangle{x, y, x + width, y + height};
|
|
DDSURFACEDESC2 description{};
|
|
description.dwSize = sizeof(description);
|
|
|
|
if (FAILED(this->m_surface->Lock(&rectangle, &description, DDLOCK_WAIT | DDLOCK_WRITEONLY, nullptr))) {
|
|
return;
|
|
}
|
|
|
|
const auto transparent = Color(*this->m_owner, 255, 0, 255);
|
|
auto* output = static_cast<unsigned char*>(description.lpSurface);
|
|
|
|
for (int row = 0; row < height; ++row) {
|
|
if (description.ddpfPixelFormat.dwRGBBitCount == 16) {
|
|
for (int column = 0; column < width; ++column) {
|
|
const auto pixel = pixels[column];
|
|
const auto value = Color(*this->m_owner, (pixel >> 16) & 255, (pixel >> 8) & 255, pixel & 255);
|
|
|
|
if (value != transparent) {
|
|
std::memcpy(output + column * sizeof(value), &value, sizeof(value));
|
|
}
|
|
}
|
|
} else {
|
|
for (int column = 0; column < width; ++column) {
|
|
if ((pixels[column] & 0xFFFFFF) != 0xFF00FF) {
|
|
const std::uint32_t value = pixels[column];
|
|
std::memcpy(output + column * sizeof(value), &value, sizeof(value));
|
|
}
|
|
}
|
|
}
|
|
|
|
output += description.lPitch;
|
|
pixels += stride;
|
|
}
|
|
|
|
this->m_surface->Unlock(nullptr);
|
|
}
|
|
|
|
// OFFSET: 0x00542F70
|
|
// FUNCTION: fn_01783
|
|
void CSurfaceDX7::Fill(const RECT* rectangle, std::uint32_t color) {
|
|
if (this->m_surface) {
|
|
DDBLTFX effects;
|
|
effects.dwSize = sizeof(effects);
|
|
|
|
effects.dwFillColor = Color(*this->m_owner, color & 255, (color >> 8) & 255, (color >> 16) & 255);
|
|
this->m_surface->Blt(const_cast<RECT*>(rectangle), nullptr, nullptr, DDBLT_COLORFILL | DDBLT_WAIT, &effects);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x005430F0
|
|
// FUNCTION: fn_01785
|
|
void CSurfaceDX7::Draw(int x, int y, int width, int height, std::uint32_t) {
|
|
RECT source{0, 0, width, height};
|
|
const int right = x + width;
|
|
const int bottom = y + height;
|
|
|
|
if (right > static_cast<int>(this->m_owner->width)) {
|
|
source.right = this->m_owner->width - x;
|
|
}
|
|
|
|
if (bottom > static_cast<int>(this->m_owner->height)) {
|
|
source.bottom = this->m_owner->height - y;
|
|
}
|
|
|
|
source.left = x < 0 ? -x : 0;
|
|
source.top = y < 0 ? -y : 0;
|
|
|
|
if (source.right > source.left && source.bottom > source.top) {
|
|
this->m_owner->renderTarget->BltFast(std::max(x, 0), std::max(y, 0), this->m_surface, &source, DDBLTFAST_SRCCOLORKEY | DDBLTFAST_WAIT);
|
|
}
|
|
}
|
|
|
|
// OFFSET: 0x005431C0
|
|
// FUNCTION: fn_01786
|
|
void CSurfaceDX7::Stretch(int, int, int width, int height) {
|
|
RECT destination{0, 0, width, height};
|
|
this->m_owner->renderTarget->Blt(&destination, this->m_surface, nullptr, DDBLT_WAIT, nullptr);
|
|
}
|
|
|
|
// FUNCTION: fn_01788
|
|
DWORD DeviceOwnerDX7::BlueMask() {
|
|
return this->blueMask;
|
|
}
|
|
|
|
// FUNCTION: fn_01789
|
|
DWORD DeviceOwnerDX7::BlueExpansion() {
|
|
return this->blue.expansion;
|
|
}
|
|
|
|
// FUNCTION: fn_01790
|
|
DWORD DeviceOwnerDX7::BlueShift() {
|
|
return this->blue.shift;
|
|
}
|
|
|
|
// FUNCTION: fn_01792
|
|
IDirectDraw7* DeviceOwnerDX7::DirectDraw() {
|
|
return this->draw;
|
|
}
|
|
|
|
// FUNCTION: fn_01793
|
|
DWORD DeviceOwnerDX7::GreenMask() {
|
|
return this->greenMask;
|
|
}
|
|
|
|
// FUNCTION: fn_01794
|
|
DWORD DeviceOwnerDX7::GreenExpansion() {
|
|
return this->green.expansion;
|
|
}
|
|
|
|
// FUNCTION: fn_01795
|
|
DWORD DeviceOwnerDX7::GreenShift() {
|
|
return this->green.shift;
|
|
}
|
|
|
|
// FUNCTION: fn_01797
|
|
DWORD DeviceOwnerDX7::RedMask() {
|
|
return this->redMask;
|
|
}
|
|
|
|
// FUNCTION: fn_01798
|
|
DWORD DeviceOwnerDX7::RedExpansion() {
|
|
return this->red.expansion;
|
|
}
|
|
|
|
// FUNCTION: fn_01799
|
|
DWORD DeviceOwnerDX7::RedShift() {
|
|
return this->red.shift;
|
|
}
|
|
|
|
// FUNCTION: fn_01800
|
|
IDirectDrawSurface7* DeviceOwnerDX7::RenderTarget() {
|
|
return this->renderTarget;
|
|
}
|
|
|
|
// OFFSET: 0x00542D60
|
|
// FUNCTION: fn_01778
|
|
CSurfaceWallpaperDX7::CSurfaceWallpaperDX7(DeviceOwnerDX7& owner, int width, int height) : CSurfaceDX7(owner, width, height) {
|
|
}
|
|
|
|
// OFFSET: 0x00543990
|
|
// FUNCTION: fn_01806
|
|
void CSurfaceWallpaperDX7::Upload(int, int, int width, int height, const std::uint32_t* pixels, int, int) {
|
|
CSurfaceDX7 temporary(*this->m_owner, width, height);
|
|
temporary.Upload(0, 0, width, height, pixels, 0, 0);
|
|
this->m_surface->Blt(nullptr, temporary.m_surface, nullptr, DDBLT_WAIT, nullptr);
|
|
}
|