1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Added DisplayAspectRatio setting

This commit is contained in:
narzoul 2022-12-20 18:17:01 +01:00
parent 6425c6c767
commit d6f07bac76
24 changed files with 395 additions and 95 deletions

View File

@ -28,7 +28,7 @@ public:
{
static unsigned origVtableSize = 0;
auto vtableSize = getVtableSize(version);
memcpy(const_cast<Vtable*>(&vtable), &s_origVtable, min(vtableSize, origVtableSize));
memcpy(const_cast<Vtable*>(&vtable), &s_origVtable, std::min(vtableSize, origVtableSize));
class NullLock {};
hookVtable<NullLock>(vtable, version);

141
DDrawCompat/Common/Vector.h Normal file
View File

@ -0,0 +1,141 @@
#pragma once
#include <algorithm>
#include <array>
#include <cmath>
#include <Windows.h>
template <typename Elem, std::size_t size>
class VectorRepresentation
{
private:
Elem values[size];
};
template <typename Elem>
class VectorRepresentation<Elem, 2>
{
public:
Elem x;
Elem y;
};
template <typename Elem, std::size_t size>
class Vector : public VectorRepresentation<Elem, size>
{
public:
template <typename... Values>
Vector(Values... v)
{
asArray() = { static_cast<Elem>(v)... };
}
Vector(SIZE s) : Vector(s.cx, s.cy)
{
}
template <typename OtherElem>
Vector(const Vector<OtherElem, size>& other)
{
for (std::size_t i = 0; i < size; ++i)
{
(*this)[i] = static_cast<Elem>(other[i]);
}
}
template <typename Value>
Vector(Value v)
{
asArray().fill(static_cast<Elem>(v));
}
Elem& operator[](std::size_t index)
{
return asArray()[index];
}
const Elem& operator[](std::size_t index) const
{
return const_cast<Vector*>(this)->asArray()[index];
}
#define DEFINE_COMPOUND_ASSIGNMENT_OPERATOR(op) \
Vector& operator##op##=(const Vector& other) \
{ \
return *this = *this op other; \
}
DEFINE_COMPOUND_ASSIGNMENT_OPERATOR(+);
DEFINE_COMPOUND_ASSIGNMENT_OPERATOR(-);
DEFINE_COMPOUND_ASSIGNMENT_OPERATOR(*);
DEFINE_COMPOUND_ASSIGNMENT_OPERATOR(/);
#undef DEFINE_COMPOUND_ASSIGNMENT_OPERATOR
private:
std::array<Elem, size>& asArray()
{
return *reinterpret_cast<std::array<Elem, size>*>(this);
}
};
template <typename Elem, std::size_t size, typename Operator>
Vector<Elem, size> binaryOperation(Operator op, const Vector<Elem, size>& lhs, const Vector<Elem, size>& rhs)
{
Vector<Elem, size> result;
for (std::size_t i = 0; i < size; ++i)
{
result[i] = op(lhs[i], rhs[i]);
}
return result;
}
template <typename Elem, std::size_t size, typename Operator>
Vector<Elem, size> unaryOperation(Operator op, const Vector<Elem, size>& vec)
{
Vector<Elem, size> result;
for (std::size_t i = 0; i < size; ++i)
{
result[i] = op(vec[i]);
}
return result;
}
#define DEFINE_VECTOR_BINARY_OPERATOR(name, ...) \
template <typename Elem, std::size_t size> \
inline Vector<Elem, size> name(const Vector<Elem, size>& lhs, const Vector<Elem, size>& rhs) \
{ \
return binaryOperation([](Elem x, Elem y) { return __VA_ARGS__; }, lhs, rhs); \
}
#define DEFINE_VECTOR_UNARY_OPERATOR(name, ...) \
template <typename Elem, std::size_t size> \
inline Vector<Elem, size> name(const Vector<Elem, size>& vec) \
{ \
return unaryOperation([](Elem x) { return __VA_ARGS__; }, vec); \
}
#define DEFINE_VECTOR_BUILTIN_BINARY_OPERATOR(op) DEFINE_VECTOR_BINARY_OPERATOR(operator ## op, x op y)
#define DEFINE_VECTOR_STD_BINARY_OPERATOR(op) DEFINE_VECTOR_BINARY_OPERATOR(op, std::op(x, y))
#define DEFINE_VECTOR_STD_UNARY_OPERATOR(op) DEFINE_VECTOR_UNARY_OPERATOR(op, std::op(x))
DEFINE_VECTOR_BUILTIN_BINARY_OPERATOR(+);
DEFINE_VECTOR_BUILTIN_BINARY_OPERATOR(-);
DEFINE_VECTOR_BUILTIN_BINARY_OPERATOR(*);
DEFINE_VECTOR_BUILTIN_BINARY_OPERATOR(/);
DEFINE_VECTOR_STD_BINARY_OPERATOR(max);
DEFINE_VECTOR_STD_BINARY_OPERATOR(min);
DEFINE_VECTOR_STD_UNARY_OPERATOR(ceil);
DEFINE_VECTOR_STD_UNARY_OPERATOR(floor);
#undef DEFINE_VECTOR_BINARY_OPERATOR
#undef DEFINE_VECTOR_UNARY_OPERATOR
#undef DEFINE_VECTOR_BUILTIN_BINARY_OPERATOR
#undef DEFINE_VECTOR_STD_BINARY_OPERATOR
#undef DEFINE_VECTOR_STD_UNARY_OPERATOR
typedef Vector<float, 2> Float2;
typedef Vector<int, 2> Int2;

View File

@ -8,6 +8,7 @@
#include <Config/Settings/CpuAffinityRotation.h>
#include <Config/Settings/DepthFormat.h>
#include <Config/Settings/DesktopColorDepth.h>
#include <Config/Settings/DisplayAspectRatio.h>
#include <Config/Settings/DisplayFilter.h>
#include <Config/Settings/DisplayRefreshRate.h>
#include <Config/Settings/DisplayResolution.h>
@ -48,6 +49,7 @@ namespace Config
Settings::CpuAffinity cpuAffinity;
Settings::CpuAffinityRotation cpuAffinityRotation;
Settings::DepthFormat depthFormat;
Settings::DisplayAspectRatio displayAspectRatio;
Settings::DesktopColorDepth desktopColorDepth;
Settings::DisplayFilter displayFilter;
Settings::DisplayRefreshRate displayRefreshRate;

View File

@ -150,6 +150,23 @@ namespace Config
}
}
SIZE parseAspectRatio(const std::string& value)
{
try
{
auto pos = value.find(':');
if (pos != std::string::npos)
{
return { parseInt(value.substr(0, pos), 1, MAXUINT16), parseInt(value.substr(pos + 1), 1, MAXUINT16) };
}
}
catch (ParsingError&)
{
}
throw ParsingError("invalid aspect ratio: '" + value + "'");
}
int parseInt(const std::string& value, int min, int max)
{
if (value.empty() || std::string::npos != value.find_first_not_of("+-0123456789") ||

View File

@ -20,8 +20,9 @@ namespace Config
{
std::filesystem::path getOverlayConfigPath();
void loadAllConfigFiles(const std::filesystem::path& processPath);
SIZE parseResolution(const std::string& value);
SIZE parseAspectRatio(const std::string& value);
int parseInt(const std::string& value, int min, int max);
SIZE parseResolution(const std::string& value);
void registerSetting(Setting& setting);
std::string removeParam(const std::string& value);
std::string tolower(const std::string& str);

View File

@ -0,0 +1,39 @@
#include <Config/Settings/DisplayAspectRatio.h>
namespace Config
{
namespace Settings
{
DisplayAspectRatio::DisplayAspectRatio()
: MappedSetting("DisplayAspectRatio", "app", { {"app", APP}, {"display", DISPLAY} })
{
}
std::string DisplayAspectRatio::getValueStr() const
{
try
{
return MappedSetting::getValueStr();
}
catch (const ParsingError&)
{
return std::to_string(m_value.cx) + ':' + std::to_string(m_value.cy);
}
}
void DisplayAspectRatio::setValue(const std::string& value)
{
try
{
MappedSetting::setValue(value);
}
catch (const ParsingError&)
{
m_value = Parser::parseAspectRatio(value);
}
}
const SIZE DisplayAspectRatio::APP = { 0, 0 };
const SIZE DisplayAspectRatio::DISPLAY = { 1, 0 };
}
}

View File

@ -0,0 +1,27 @@
#pragma once
#include <Windows.h>
#include <Common/Comparison.h>
#include <Config/MappedSetting.h>
namespace Config
{
namespace Settings
{
class DisplayAspectRatio : public MappedSetting<SIZE>
{
public:
static const SIZE APP;
static const SIZE DISPLAY;
DisplayAspectRatio();
protected:
std::string getValueStr() const override;
void setValue(const std::string& value) override;
};
}
extern Settings::DisplayAspectRatio displayAspectRatio;
}

View File

@ -5,6 +5,7 @@
#include <Common/Comparison.h>
#include <Common/CompatVtable.h>
#include <Config/Settings/Antialiasing.h>
#include <Config/Settings/DisplayAspectRatio.h>
#include <Config/Settings/PalettizedTextures.h>
#include <Config/Settings/ResolutionScale.h>
#include <Config/Settings/SupportedDepthFormats.h>
@ -15,6 +16,7 @@
#include <D3dDdi/DeviceFuncs.h>
#include <D3dDdi/FormatInfo.h>
#include <D3dDdi/KernelModeThunks.h>
#include <Win32/DisplayMode.h>
namespace
{
@ -59,6 +61,25 @@ namespace D3dDdi
{
}
Int2 Adapter::getAspectRatio(Win32::DisplayMode::Resolution res) const
{
SIZE ar = Config::displayAspectRatio.get();
if (Config::Settings::DisplayAspectRatio::APP == ar)
{
return 0 != res.app.cx ? res.app : Win32::DisplayMode::getAppResolution(m_deviceName);
}
else if (Config::Settings::DisplayAspectRatio::DISPLAY == ar)
{
return 0 != res.display.cx ? res.display : Win32::DisplayMode::getDisplayResolution(m_deviceName);
}
return ar;
}
Int2 Adapter::getAspectRatio() const
{
return getAspectRatio({});
}
const Adapter::AdapterInfo& Adapter::getInfo() const
{
auto it = s_adapterInfos.find(m_luid);
@ -122,14 +143,6 @@ namespace D3dDdi
return result;
}
float Adapter::getMaxScaleFactor(SIZE size) const
{
const auto& caps = getInfo().d3dExtendedCaps;
const float scaleX = static_cast<float>(caps.dwMaxTextureWidth) / size.cx;
const float scaleY = static_cast<float>(caps.dwMaxTextureHeight) / size.cy;
return min(scaleX, scaleY);
}
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> Adapter::getMultisampleConfig(D3DDDIFORMAT format) const
{
UINT samples = Config::antialiasing.get();
@ -154,54 +167,62 @@ namespace D3dDdi
levels.Format = D3DDDIFMT_X8R8G8B8;
levels.MsType = static_cast<D3DDDIMULTISAMPLE_TYPE>(samples);
getCaps(D3DDDICAPS_GETMULTISAMPLEQUALITYLEVELS, levels);
return { levels.MsType, min(static_cast<UINT>(Config::antialiasing.getParam()), levels.QualityLevels - 1) };
return { levels.MsType, std::min(static_cast<UINT>(Config::antialiasing.getParam()), levels.QualityLevels - 1) };
}
SIZE Adapter::getScaledSize(SIZE size) const
SIZE Adapter::getScaledSize(Int2 size) const
{
DEVMODEW dm = {};
dm.dmSize = sizeof(dm);
EnumDisplaySettingsExW(m_deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm, 0);
const SIZE emulatedDisplaySize = { static_cast<long>(dm.dmPelsHeight), static_cast<long>(dm.dmPelsHeight) };
const float displayMaxScaleFactor = getMaxScaleFactor(emulatedDisplaySize);
const float resourceMaxScaleFactor = getMaxScaleFactor(size);
float maxScaleFactor = min(displayMaxScaleFactor, resourceMaxScaleFactor);
if (Config::resolutionScale.getParam() > 0)
{
maxScaleFactor = floor(maxScaleFactor);
}
SIZE baseSize = Config::resolutionScale.get();
const auto scaleFactor = getScaleFactor();
const int multiplier = Config::resolutionScale.getParam();
if (Config::Settings::ResolutionScale::APP == baseSize)
{
baseSize = emulatedDisplaySize;
}
else if (Config::Settings::ResolutionScale::DISPLAY == baseSize)
{
CALL_ORIG_FUNC(EnumDisplaySettingsExW)(m_deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm, 0);
baseSize = { static_cast<long>(dm.dmPelsHeight), static_cast<long>(dm.dmPelsHeight) };
}
float scaleX = static_cast<float>(baseSize.cx) / emulatedDisplaySize.cx;
float scaleY = static_cast<float>(baseSize.cy) / emulatedDisplaySize.cy;
float scale = min(scaleX, scaleY) * abs(multiplier);
if (multiplier > 0)
{
scale = ceil(scale);
}
scale = max(scale, 1.0f);
scale = min(scale, maxScaleFactor);
size.cx = static_cast<LONG>(size.cx * scale);
size.cy = static_cast<LONG>(size.cy * scale);
const auto& caps = getInfo().d3dExtendedCaps;
size.cx = min(size.cx, static_cast<LONG>(caps.dwMaxTextureWidth));
size.cy = min(size.cy, static_cast<LONG>(caps.dwMaxTextureHeight));
return size;
Int2 maxSize = { caps.dwMaxTextureWidth, caps.dwMaxTextureHeight };
if (multiplier < 0)
{
maxSize = maxSize / size * size;
}
Int2 scaledSize = Float2(size) * scaleFactor;
scaledSize = min(scaledSize, maxSize);
scaledSize = max(scaledSize, size);
return { scaledSize.x, scaledSize.y };
}
Float2 Adapter::getScaleFactor() const
{
const SIZE resolutionScale = Config::resolutionScale.get();
const int multiplier = Config::resolutionScale.getParam();
if (0 == multiplier ||
Config::Settings::ResolutionScale::APP == resolutionScale && 1 == multiplier)
{
return 1;
}
const auto res = Win32::DisplayMode::getResolution(m_deviceName);
Int2 targetResolution = resolutionScale;
if (Config::Settings::ResolutionScale::APP == resolutionScale)
{
targetResolution = res.app;
}
else if (Config::Settings::ResolutionScale::DISPLAY == resolutionScale)
{
targetResolution = res.display;
}
targetResolution *= abs(multiplier);
const Int2 ar = getAspectRatio(res);
if (targetResolution.y * ar.x / ar.y <= targetResolution.x)
{
targetResolution.x = targetResolution.y * ar.x / ar.y;
}
else
{
targetResolution.y = targetResolution.x * ar.y / ar.x;
}
const auto scaleFactor = Float2(targetResolution) / Float2(res.app);
return multiplier < 0 ? scaleFactor : ceil(scaleFactor);
}
std::string Adapter::getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const

View File

@ -8,7 +8,9 @@
#include <d3dumddi.h>
#include <Common/CompatPtr.h>
#include <Common/Vector.h>
#include <DDraw/DirectDraw.h>
#include <Win32/DisplayMode.h>
namespace D3dDdi
{
@ -31,12 +33,13 @@ namespace D3dDdi
operator HANDLE() const { return m_adapter; }
Int2 getAspectRatio() const;
const AdapterInfo& getInfo() const;
LUID getLuid() const { return m_luid; }
std::pair<D3DDDIMULTISAMPLE_TYPE, UINT> getMultisampleConfig(D3DDDIFORMAT format) const;
const D3DDDI_ADAPTERFUNCS& getOrigVtable() const { return m_origVtable; }
CompatWeakPtr<IDirectDraw7> getRepository() const { return m_repository; }
SIZE getScaledSize(SIZE size) const;
SIZE getScaledSize(Int2 size) const;
HRESULT pfnCloseAdapter();
HRESULT pfnCreateDevice(D3DDDIARG_CREATEDEVICE* pCreateData);
@ -50,8 +53,9 @@ namespace D3dDdi
template <typename Data>
HRESULT getCaps(D3DDDICAPS_TYPE type, Data& data, UINT size = sizeof(Data)) const;
Int2 getAspectRatio(Win32::DisplayMode::Resolution res) const;
std::map<D3DDDIFORMAT, FORMATOP> getFormatOps() const;
float getMaxScaleFactor(SIZE size) const;
Float2 getScaleFactor() const;
std::string getSupportedMsaaModes(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;
DWORD getSupportedZBufferBitDepths(const std::map<D3DDDIFORMAT, FORMATOP>& formatOps) const;

View File

@ -223,7 +223,7 @@ namespace D3dDdi
m_changedStates |= CS_TEXTURE_STAGE;
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSU);
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSV);
m_maxChangedTextureStage = max(stage, m_maxChangedTextureStage);
m_maxChangedTextureStage = std::max(stage, m_maxChangedTextureStage);
}
void DeviceState::flush()
@ -502,7 +502,7 @@ namespace D3dDdi
m_changedRenderStates.set(D3DDDIRS_COLORKEYENABLE);
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSU);
m_changedTextureStageStates[stage].set(D3DDDITSS_ADDRESSV);
m_maxChangedTextureStage = max(stage, m_maxChangedTextureStage);
m_maxChangedTextureStage = std::max(stage, m_maxChangedTextureStage);
return S_OK;
}
@ -514,7 +514,7 @@ namespace D3dDdi
m_app.textureStageState[data->Stage][D3DDDITSS_ADDRESSV] = data->Value;
m_changedTextureStageStates[data->Stage].set(D3DDDITSS_ADDRESSU);
m_changedTextureStageStates[data->Stage].set(D3DDDITSS_ADDRESSV);
m_maxChangedTextureStage = max(data->Stage, m_maxChangedTextureStage);
m_maxChangedTextureStage = std::max(data->Stage, m_maxChangedTextureStage);
return S_OK;
}
@ -531,7 +531,7 @@ namespace D3dDdi
m_app.textureStageState[data->Stage][data->State] = data->Value;
m_changedTextureStageStates[data->Stage].set(data->State);
m_maxChangedTextureStage = max(data->Stage, m_maxChangedTextureStage);
m_maxChangedTextureStage = std::max(data->Stage, m_maxChangedTextureStage);
return S_OK;
}
@ -775,7 +775,7 @@ namespace D3dDdi
{
setTexture(stage, texture);
m_changedStates |= CS_TEXTURE_STAGE;
m_maxChangedTextureStage = max(stage, m_maxChangedTextureStage);
m_maxChangedTextureStage = std::max(stage, m_maxChangedTextureStage);
}
void DeviceState::setTempTextureStageState(const D3DDDIARG_TEXTURESTAGESTATE& tss)
@ -783,7 +783,7 @@ namespace D3dDdi
setTextureStageState(tss);
m_changedStates |= CS_TEXTURE_STAGE;
m_changedTextureStageStates[tss.Stage].set(tss.State);
m_maxChangedTextureStage = max(tss.Stage, m_maxChangedTextureStage);
m_maxChangedTextureStage = std::max(tss.Stage, m_maxChangedTextureStage);
}
void DeviceState::setTempVertexShaderDecl(HANDLE decl)

View File

@ -222,13 +222,13 @@ namespace
const ULONGLONG maxMem = 0x3FFF0000;
if (info->DedicatedVideoMemorySize < maxMem)
{
auto addedMem = min(maxMem - info->DedicatedVideoMemorySize, info->SharedSystemMemorySize);
auto addedMem = std::min(maxMem - info->DedicatedVideoMemorySize, info->SharedSystemMemorySize);
info->DedicatedVideoMemorySize += addedMem;
info->SharedSystemMemorySize -= addedMem;
}
info->DedicatedVideoMemorySize = min(info->DedicatedVideoMemorySize, maxMem);
info->SharedSystemMemorySize = min(info->SharedSystemMemorySize, maxMem);
info->DedicatedVideoMemorySize = std::min(info->DedicatedVideoMemorySize, maxMem);
info->SharedSystemMemorySize = std::min(info->SharedSystemMemorySize, maxMem);
break;
}
}

View File

@ -59,11 +59,6 @@ namespace
return rect;
}
RECT calculatePresentationRect()
{
return calculateScaledRect(DDraw::PrimarySurface::getMonitorRect(), DDraw::RealPrimarySurface::getMonitorRect());
}
LONG divCeil(LONG n, LONG d)
{
return (n + d - 1) / d;
@ -669,8 +664,8 @@ namespace D3dDdi
{
while (srcWidth > 2 * dstWidth || srcHeight > 2 * dstHeight)
{
const LONG newSrcWidth = max(dstWidth, (srcWidth + 1) / 2);
const LONG newSrcHeight = max(dstHeight, (srcHeight + 1) / 2);
const LONG newSrcWidth = std::max(dstWidth, (srcWidth + 1) / 2);
const LONG newSrcHeight = std::max(dstHeight, (srcHeight + 1) / 2);
auto& nextRt = getNextRenderTarget(rt, newSrcWidth, newSrcHeight);
if (!nextRt.resource)
{
@ -1444,7 +1439,8 @@ namespace D3dDdi
if (isFullscreen)
{
g_presentationRect = calculatePresentationRect();
const Int2 ar = m_device.getAdapter().getAspectRatio();
g_presentationRect = calculateScaledRect({ 0, 0, ar.x, ar.y }, DDraw::RealPrimarySurface::getMonitorRect());
auto& si = m_origData.pSurfList[0];
RECT primaryRect = { 0, 0, static_cast<LONG>(si.Width), static_cast<LONG>(si.Height) };

View File

@ -261,7 +261,8 @@ namespace D3dDdi
SurfaceRepository::Surface& SurfaceRepository::getTempSurface(Surface& surface, DWORD width, DWORD height,
D3DDDIFORMAT format, DWORD caps, UINT surfaceCount)
{
return getSurface(surface, max(width, surface.width), max(height, surface.height), format, caps, surfaceCount);
return getSurface(surface, std::max(width, surface.width), std::max(height, surface.height),
format, caps, surfaceCount);
}
SurfaceRepository::Surface& SurfaceRepository::getTempSysMemSurface(DWORD width, DWORD height)

View File

@ -63,7 +63,7 @@
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;CINTERFACE;_NO_DDRAWINT_NO_COM;PSAPI_VERSION=1;WIN32;_DEBUG;_WINDOWS;_USRDLL;DDRAWCOMPAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;NOMINMAX;CINTERFACE;_NO_DDRAWINT_NO_COM;PSAPI_VERSION=1;WIN32;_DEBUG;_WINDOWS;_USRDLL;DDRAWCOMPAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
@ -101,7 +101,7 @@
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level4</WarningLevel>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;CINTERFACE;_NO_DDRAWINT_NO_COM;PSAPI_VERSION=1;WIN32;NDEBUG;_WINDOWS;_USRDLL;DDRAWCOMPAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32_LEAN_AND_MEAN;NOMINMAX;CINTERFACE;_NO_DDRAWINT_NO_COM;PSAPI_VERSION=1;WIN32;NDEBUG;_WINDOWS;_USRDLL;DDRAWCOMPAT_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ObjectFileName>$(IntDir)%(RelativeDir)</ObjectFileName>
@ -146,6 +146,7 @@
<ClInclude Include="Common\Rect.h" />
<ClInclude Include="Common\ScopedSrwLock.h" />
<ClInclude Include="Common\ScopedThreadPriority.h" />
<ClInclude Include="Common\Vector.h" />
<ClInclude Include="Common\VtableHookVisitor.h" />
<ClInclude Include="Common\VtableSizeVisitor.h" />
<ClInclude Include="Common\VtableVisitor.h" />
@ -169,6 +170,7 @@
<ClInclude Include="Config\Settings\CpuAffinityRotation.h" />
<ClInclude Include="Config\Settings\DepthFormat.h" />
<ClInclude Include="Config\Settings\DesktopColorDepth.h" />
<ClInclude Include="Config\Settings\DisplayAspectRatio.h" />
<ClInclude Include="Config\Settings\DisplayFilter.h" />
<ClInclude Include="Config\Settings\DisplayRefreshRate.h" />
<ClInclude Include="Config\Settings\DisplayResolution.h" />
@ -330,6 +332,7 @@
<ClCompile Include="Config\Setting.cpp" />
<ClCompile Include="Config\Settings\Antialiasing.cpp" />
<ClCompile Include="Config\Settings\CpuAffinity.cpp" />
<ClCompile Include="Config\Settings\DisplayAspectRatio.cpp" />
<ClCompile Include="Config\Settings\DisplayFilter.cpp" />
<ClCompile Include="Config\Settings\DisplayRefreshRate.cpp" />
<ClCompile Include="Config\Settings\DisplayResolution.cpp" />

View File

@ -651,6 +651,12 @@
<ClInclude Include="Config\Settings\DepthFormat.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
<ClInclude Include="Config\Settings\DisplayAspectRatio.h">
<Filter>Header Files\Config\Settings</Filter>
</ClInclude>
<ClInclude Include="Common\Vector.h">
<Filter>Header Files\Common</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Gdi\Gdi.cpp">
@ -1028,6 +1034,9 @@
<ClCompile Include="Config\Settings\SupportedDepthFormats.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
<ClCompile Include="Config\Settings\DisplayAspectRatio.cpp">
<Filter>Source Files\Config\Settings</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="DDrawCompat.rc">

View File

@ -339,7 +339,7 @@ namespace
{
RECT parentRect = {};
GetWindowRect(parent, &parentRect);
wp.x = max(parentRect.left + 3 - wp.cx, 0);
wp.x = std::max<int>(parentRect.left + 3 - wp.cx, 0);
}
else
{

View File

@ -42,19 +42,16 @@ namespace
BOOL CALLBACK addMonitorRectToRegion(
HMONITOR hMonitor, HDC /*hdcMonitor*/, LPRECT lprcMonitor, LPARAM dwData)
{
MONITORINFOEX mi = {};
MONITORINFOEXW mi = {};
mi.cbSize = sizeof(mi);
CALL_ORIG_FUNC(GetMonitorInfoA)(hMonitor, &mi);
DEVMODE dm = {};
dm.dmSize = sizeof(dm);
CALL_ORIG_FUNC(EnumDisplaySettingsExA)(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm, 0);
CALL_ORIG_FUNC(GetMonitorInfoW)(hMonitor, &mi);
auto res = Win32::DisplayMode::getDisplayResolution(mi.szDevice);
RECT rect = *lprcMonitor;
if (0 != dm.dmPelsWidth && 0 != dm.dmPelsHeight)
if (0 != res.cx && 0 != res.cy)
{
rect.right = rect.left + dm.dmPelsWidth;
rect.bottom = rect.top + dm.dmPelsHeight;
rect.right = rect.left + res.cx;
rect.bottom = rect.top + res.cy;
}
Gdi::Region& virtualScreenRegion = *reinterpret_cast<Gdi::Region*>(dwData);

View File

@ -120,8 +120,8 @@ namespace
auto& llHook = *reinterpret_cast<MSLLHOOKSTRUCT*>(lParam);
cp.x += (llHook.pt.x - origCp.x);
cp.y += (llHook.pt.y - origCp.y);
cp.x = min(max(g_monitorRect.left, cp.x), g_monitorRect.right);
cp.y = min(max(g_monitorRect.top, cp.y), g_monitorRect.bottom);
cp.x = std::min(std::max(g_monitorRect.left, cp.x), g_monitorRect.right);
cp.y = std::min(std::max(g_monitorRect.top, cp.y), g_monitorRect.bottom);
g_cursorPos = cp;
DDraw::RealPrimarySurface::scheduleOverlayUpdate();
}

View File

@ -116,8 +116,8 @@ namespace Overlay
{
const auto minPos = m_leftArrow.right + ARROW_SIZE / 2;
const auto maxPos = m_rightArrow.left - ARROW_SIZE / 2;
pos.x = max(pos.x, minPos);
pos.x = min(pos.x, maxPos);
pos.x = std::max(pos.x, minPos);
pos.x = std::min(pos.x, maxPos);
setPos(m_min + roundDiv((pos.x - minPos) * (m_max - m_min), maxPos - minPos));
}
@ -128,8 +128,8 @@ namespace Overlay
void ScrollBarControl::setPos(int pos)
{
pos = max(pos, m_min);
pos = min(pos, m_max);
pos = std::max(pos, m_min);
pos = std::min(pos, m_max);
if (pos != m_pos)
{
m_pos = pos;

View File

@ -206,8 +206,8 @@ namespace Overlay
int scaleX = (monitorRect.right - monitorRect.left) / 640;
int scaleY = (monitorRect.bottom - monitorRect.top) / 480;
m_scaleFactor = min(scaleX, scaleY);
m_scaleFactor = max(1, m_scaleFactor);
m_scaleFactor = std::min(scaleX, scaleY);
m_scaleFactor = std::max(1, m_scaleFactor);
m_rect = calculateRect({ monitorRect.left / m_scaleFactor, monitorRect.top / m_scaleFactor,
monitorRect.right / m_scaleFactor, monitorRect.bottom / m_scaleFactor });

View File

@ -370,6 +370,18 @@ namespace
return CALL_ORIG_FUNC(GdiEntry13)() + g_displaySettingsUniquenessBias;
}
SIZE getAppResolution(const std::wstring& deviceName, SIZE displayResolution = {})
{
{
Compat::ScopedSrwLockShared srwLock(g_srwLock);
if (deviceName == g_emulatedDisplayMode.deviceName)
{
return { static_cast<LONG>(g_emulatedDisplayMode.width), static_cast<LONG>(g_emulatedDisplayMode.height) };
}
}
return 0 != displayResolution.cx ? displayResolution : Win32::DisplayMode::getDisplayResolution(deviceName);
}
template <typename Char>
DWORD getConfiguredRefreshRate(const Char* deviceName)
{
@ -722,11 +734,24 @@ namespace Win32
{
namespace DisplayMode
{
SIZE getAppResolution(const std::wstring& deviceName)
{
return ::getAppResolution(deviceName);
}
DWORD getBpp()
{
return getEmulatedDisplayMode().bpp;
}
SIZE getDisplayResolution(const std::wstring& deviceName)
{
DEVMODEW dm = {};
dm.dmSize = sizeof(dm);
CALL_ORIG_FUNC(EnumDisplaySettingsExW)(deviceName.c_str(), ENUM_CURRENT_SETTINGS, &dm, 0);
return { static_cast<LONG>(dm.dmPelsWidth), static_cast<LONG>(dm.dmPelsHeight) };
}
EmulatedDisplayMode getEmulatedDisplayMode()
{
Compat::ScopedSrwLockShared lock(g_srwLock);
@ -741,6 +766,14 @@ namespace Win32
return mi;
}
Resolution getResolution(const std::wstring& deviceName)
{
Resolution res = {};
res.display = getDisplayResolution(deviceName);
res.app = ::getAppResolution(deviceName, res.display);
return res;
}
ULONG queryDisplaySettingsUniqueness()
{
return CALL_ORIG_FUNC(GdiEntry13)();

View File

@ -25,9 +25,18 @@ namespace Win32
SIZE diff;
};
struct Resolution
{
SIZE app;
SIZE display;
};
SIZE getAppResolution(const std::wstring& deviceName);
DWORD getBpp();
SIZE getDisplayResolution(const std::wstring& deviceName);
EmulatedDisplayMode getEmulatedDisplayMode();
MONITORINFOEXW getMonitorInfo(const std::wstring& deviceName);
Resolution getResolution(const std::wstring& deviceName);
ULONG queryDisplaySettingsUniqueness();
void installHooks();

View File

@ -93,7 +93,7 @@ namespace
std::ostream& logOsVersionInfo(std::ostream& os, const OsVersionInfo& vi)
{
OsVersionInfoEx viEx = {};
memcpy(&viEx, &vi, min(sizeof(viEx), vi.dwOSVersionInfoSize));
memcpy(&viEx, &vi, std::min<DWORD>(sizeof(viEx), vi.dwOSVersionInfoSize));
return logOsVersionInfoEx(os, viEx);
}
}

View File

@ -140,7 +140,7 @@ namespace
oss << i + 1 << ", ";
}
}
return oss.str().substr(0, max(0, oss.str().length() - 2));
return oss.str().substr(0, std::max<std::size_t>(0, oss.str().length() - 2));
}
DWORD rotateMask(DWORD mask)