mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-08-01 14:20:42 -07:00
graphics: custom full screen resolution (#274)
## Link to GitHub Issue, if one exists
n/a
## Description of change
Adds a new option to forcibly set the full screen resolution.
Same idea as -windowscale.
## Compiling
🔺
## Testing
Seems to be showing similar results as -windowscale:
* Works GREAT for IIDX/SDVX
* popn launches at correct resolution but only draws a small image (at
native res) - can be scaled with F11 menu
* nostalgia is broken in weird ways, image is drawn correctly but bottom
`credits` text draws at wrong offset, game's wintouch logic broken
(perhaps expectedly)
## Other notes
In theory this could enable "play sdvx in landscape mode" option but the
image scaling doesn't quite work with extreme values.
This commit is contained in:
@@ -680,7 +680,12 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDevice(
|
||||
|
||||
// dump presentation parameters
|
||||
for (size_t i = 0; i < num_adapters; i++) {
|
||||
const auto *params = &pPresentationParameters[i];
|
||||
auto *params = &pPresentationParameters[i];
|
||||
|
||||
if (!GRAPHICS_WINDOWED && i == 0 && GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
||||
params->BackBufferWidth = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
||||
params->BackBufferHeight = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
||||
}
|
||||
|
||||
log_info("graphics::d3d9",
|
||||
"D3D9 presentation parameters for adapter {}: BackBufferWidth: {}, BackBufferHeight: {}, "
|
||||
@@ -846,7 +851,12 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDeviceEx(
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < num_adapters; i++) {
|
||||
const auto *params = &pPresentationParameters[i];
|
||||
auto *params = &pPresentationParameters[i];
|
||||
|
||||
if (!GRAPHICS_WINDOWED && i == 0 && GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
||||
params->BackBufferWidth = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
||||
params->BackBufferHeight = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
||||
}
|
||||
|
||||
log_info("graphics::d3d9",
|
||||
"D3D9Ex presentation parameters for adapter {}: BackBufferWidth: {}, BackBufferHeight: {}, "
|
||||
@@ -870,7 +880,12 @@ HRESULT STDMETHODCALLTYPE WrappedIDirect3D9::CreateDeviceEx(
|
||||
}
|
||||
if (pFullscreenDisplayMode) {
|
||||
for (size_t i = 0; i < num_adapters; i++) {
|
||||
const auto *fullscreen_display_mode = &pFullscreenDisplayMode[i];
|
||||
auto *fullscreen_display_mode = &pFullscreenDisplayMode[i];
|
||||
|
||||
if (!GRAPHICS_WINDOWED && i == 0 && GRAPHICS_FS_CUSTOM_RESOLUTION.has_value()) {
|
||||
fullscreen_display_mode->Width = GRAPHICS_FS_CUSTOM_RESOLUTION.value().first;
|
||||
fullscreen_display_mode->Height = GRAPHICS_FS_CUSTOM_RESOLUTION.value().second;
|
||||
}
|
||||
|
||||
log_info("graphics::d3d9",
|
||||
"D3D9Ex fullscreen display mode for adapter {}: Width: {}, Height: {}, RefreshRate: {}, "
|
||||
|
||||
@@ -67,6 +67,7 @@ graphics_dx9on12_state GRAPHICS_9_ON_12_STATE = DX9ON12_AUTO;
|
||||
bool GRAPHICS_9_ON_12_REQUESTED_BY_GAME = false;
|
||||
bool SUBSCREEN_FORCE_REDRAW = false;
|
||||
bool D3D9_DEVICE_HOOK_DISABLE = false;
|
||||
std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_FS_CUSTOM_RESOLUTION;
|
||||
|
||||
// settings
|
||||
std::string GRAPHICS_DEVICEID = "PCI\\VEN_1002&DEV_7146";
|
||||
|
||||
@@ -35,6 +35,7 @@ extern UINT GRAPHICS_FORCE_REFRESH;
|
||||
extern std::optional<int> GRAPHICS_FORCE_VSYNC_BUFFER;
|
||||
extern bool GRAPHICS_FORCE_SINGLE_ADAPTER;
|
||||
extern bool GRAPHICS_PREVENT_SECONDARY_WINDOW;
|
||||
extern std::optional<std::pair<uint32_t, uint32_t>> GRAPHICS_FS_CUSTOM_RESOLUTION;
|
||||
|
||||
extern graphics_dx9on12_state GRAPHICS_9_ON_12_STATE;
|
||||
extern bool GRAPHICS_9_ON_12_REQUESTED_BY_GAME;
|
||||
|
||||
@@ -123,10 +123,6 @@ void graphics_load_windowed_parameters() {
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_load_windowed_parameters called");
|
||||
const auto remove_spaces = [](const char& c) {
|
||||
return c == ' ';
|
||||
};
|
||||
|
||||
if (GRAPHICS_WINDOW_STYLE.has_value()) {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
@@ -148,13 +144,11 @@ void graphics_load_windowed_parameters() {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_WINDOW_POS");
|
||||
int32_t x, y;
|
||||
auto s = GRAPHICS_WINDOW_POS.value();
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%d,%d", &x, &y) == 2) {
|
||||
std::pair<uint32_t, uint32_t> result;
|
||||
if (parse_width_height(GRAPHICS_WINDOW_POS.value(), result)) {
|
||||
cfg::SCREENRESIZE->enable_window_resize = true;
|
||||
cfg::SCREENRESIZE->window_offset_x = x;
|
||||
cfg::SCREENRESIZE->window_offset_y = y;
|
||||
cfg::SCREENRESIZE->window_offset_x = result.first;
|
||||
cfg::SCREENRESIZE->window_offset_y = result.second;
|
||||
} else {
|
||||
log_warning("graphics-windowed", "failed to parse -windowpos");
|
||||
}
|
||||
@@ -174,20 +168,16 @@ void graphics_load_windowed_subscreen_parameters() {
|
||||
}
|
||||
|
||||
log_debug("graphics-windowed", "graphics_load_windowed_subscreen_parameters called");
|
||||
const auto remove_spaces = [](const char& c) {
|
||||
return c == ' ';
|
||||
};
|
||||
|
||||
|
||||
if (GRAPHICS_IIDX_WSUB_SIZE.has_value()) {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_IIDX_WSUB_SIZE");
|
||||
uint32_t w, h;
|
||||
auto s = GRAPHICS_IIDX_WSUB_SIZE.value();
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%u,%u", &w, &h) == 2) {
|
||||
GRAPHICS_IIDX_WSUB_WIDTH = w;
|
||||
GRAPHICS_IIDX_WSUB_HEIGHT = h;
|
||||
|
||||
std::pair<uint32_t, uint32_t> result;
|
||||
if (parse_width_height(GRAPHICS_IIDX_WSUB_SIZE.value(), result)) {
|
||||
GRAPHICS_IIDX_WSUB_WIDTH = result.first;
|
||||
GRAPHICS_IIDX_WSUB_HEIGHT = result.second;
|
||||
} else {
|
||||
log_warning("graphics-windowed", "failed to parse -wsubsize");
|
||||
}
|
||||
@@ -197,12 +187,11 @@ void graphics_load_windowed_subscreen_parameters() {
|
||||
log_debug(
|
||||
"graphics-windowed",
|
||||
"graphics_load_windowed_parameters - load GRAPHICS_IIDX_WSUB_POS");
|
||||
int32_t x, y;
|
||||
auto s = GRAPHICS_IIDX_WSUB_POS.value();
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%d,%d", &x, &y) == 2) {
|
||||
GRAPHICS_IIDX_WSUB_X = x;
|
||||
GRAPHICS_IIDX_WSUB_Y = y;
|
||||
|
||||
std::pair<uint32_t, uint32_t> result;
|
||||
if (parse_width_height(GRAPHICS_IIDX_WSUB_POS.value(), result)) {
|
||||
GRAPHICS_IIDX_WSUB_X = result.first;
|
||||
GRAPHICS_IIDX_WSUB_Y = result.second;
|
||||
} else {
|
||||
log_warning("graphics-windowed", "failed to parse -wsubpos");
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
#include "util/sysutils.h"
|
||||
#include "util/tapeled.h"
|
||||
#include "util/time.h"
|
||||
#include "util/utils.h"
|
||||
#include "avs/ssl.h"
|
||||
#include "nvapi/nvapi.h"
|
||||
#include "hooks/graphics/nvapi_hook.h"
|
||||
@@ -366,6 +367,15 @@ int main_implementation(int argc, char *argv[]) {
|
||||
GRAPHICS_FORCE_SINGLE_ADAPTER = false;
|
||||
}
|
||||
|
||||
if (options[launcher::Options::FullscreenResolution].is_active()) {
|
||||
std::pair<uint32_t, uint32_t> result;
|
||||
if (parse_width_height(options[launcher::Options::FullscreenResolution].value_text(), result)) {
|
||||
GRAPHICS_FS_CUSTOM_RESOLUTION = result;
|
||||
} else {
|
||||
log_warning("launcher", "failed to parse -forceres");
|
||||
}
|
||||
}
|
||||
|
||||
if (options[launcher::Options::spice2x_NvapiProfile].value_bool() && !cfg::CONFIGURATOR_STANDALONE) {
|
||||
nvapi::ADD_PROFILE = true;
|
||||
}
|
||||
@@ -952,12 +962,9 @@ int main_implementation(int argc, char *argv[]) {
|
||||
GRAPHICS_WINDOW_STYLE = options[launcher::Options::spice2x_WindowBorder].value_uint32();
|
||||
}
|
||||
if (options[launcher::Options::spice2x_WindowSize].is_active()) {
|
||||
auto s = options[launcher::Options::spice2x_WindowSize].value_text();
|
||||
uint32_t w, h;
|
||||
const auto remove_spaces = [](const char& c) { return c == ' '; };
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%u,%u", &w, &h) == 2) {
|
||||
GRAPHICS_WINDOW_SIZE = std::pair(w, h);
|
||||
std::pair<uint32_t, uint32_t> result;
|
||||
if (parse_width_height(options[launcher::Options::spice2x_WindowSize].value_text(), result)) {
|
||||
GRAPHICS_WINDOW_SIZE = result;
|
||||
} else {
|
||||
log_warning("launcher", "failed to parse -windowsize");
|
||||
}
|
||||
|
||||
@@ -189,6 +189,14 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.type = OptionType::Integer,
|
||||
.category = "Graphics (Common)",
|
||||
},
|
||||
{
|
||||
.title = "Only Use One Monitor",
|
||||
.name = "graphics-force-single-adapter",
|
||||
.desc = "Force the graphics device to be opened utilizing only one adapter in multi-monitor systems.\n\n"
|
||||
"May cause unstable framerate and desyncs, especially if monitors have different refresh rates!",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Graphics (Common)",
|
||||
},
|
||||
{
|
||||
.title = "Force Refresh Rate",
|
||||
.name = "graphics-force-refresh",
|
||||
@@ -197,12 +205,16 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.category = "Graphics (Common)",
|
||||
},
|
||||
{
|
||||
.title = "Only Use One Monitor",
|
||||
.name = "graphics-force-single-adapter",
|
||||
.desc = "Force the graphics device to be opened utilizing only one adapter in multi-monitor systems.\n\n"
|
||||
"May cause unstable framerate and desyncs, especially if monitors have different refresh rates!",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Graphics (Common)",
|
||||
// FullscreenResolution
|
||||
.title = "Force Full Screen Resolution",
|
||||
.name = "forceres",
|
||||
.desc =
|
||||
"For full screen mode, forcibly set a custom resolution.\n\n"
|
||||
"Works great for some games, but can COMPLETELY BREAK other games - YMMV!\n\n"
|
||||
"This should only be used as last resort if your GPU/monitor can't display the resolution required by the game",
|
||||
.type = OptionType::Text,
|
||||
.setting_name = "1280,720",
|
||||
.category = "Graphics (Common)"
|
||||
},
|
||||
{
|
||||
// Graphics9On12
|
||||
@@ -1783,7 +1795,7 @@ static const std::vector<OptionDefinition> OPTION_DEFINITIONS = {
|
||||
.title = "Window Forced Render Scaling",
|
||||
.name = "windowscale",
|
||||
.desc = "For windowed mode: forcibly set DX9 back buffer dimensions to match window size. "
|
||||
"Reduces pixelated scaling artifacts. Works great on some games, but completely broken on others",
|
||||
"Reduces pixelated scaling artifacts. Works great for some games, but can COMPLETELY BREAK other games - YMMV!",
|
||||
.type = OptionType::Bool,
|
||||
.category = "Graphics (Windowed)",
|
||||
},
|
||||
|
||||
@@ -27,8 +27,9 @@ namespace launcher {
|
||||
CaptureCursor,
|
||||
ShowCursor,
|
||||
DisplayAdapter,
|
||||
GraphicsForceRefresh,
|
||||
GraphicsForceSingleAdapter,
|
||||
GraphicsForceRefresh,
|
||||
FullscreenResolution,
|
||||
Graphics9On12,
|
||||
spice2x_Dx9On12,
|
||||
NoLegacy,
|
||||
|
||||
@@ -298,3 +298,16 @@ static inline int get_async_secondary_mouse() {
|
||||
int vk = GetSystemMetrics(SM_SWAPBUTTON) ? VK_LBUTTON : VK_RBUTTON;
|
||||
return GetAsyncKeyState(vk);
|
||||
}
|
||||
|
||||
static inline bool parse_width_height(const std::string wh, std::pair<uint32_t, uint32_t> &result) {
|
||||
std::string s = wh;
|
||||
uint32_t w, h;
|
||||
const auto remove_spaces = [](const char& c) { return c == ' '; };
|
||||
s.erase(std::remove_if(s.begin(), s.end(), remove_spaces), s.end());
|
||||
if (sscanf(s.c_str(), "%u,%u", &w, &h) == 2) {
|
||||
result = std::pair(w, h);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user