Proper 4:3 support
This commit is contained in:
committed by
Radosław Gliński
parent
49166f0bd1
commit
c4e930ed4c
@@ -49,6 +49,12 @@ DEFINE_int32(
|
||||
"Video");
|
||||
|
||||
DEFINE_bool(use_50Hz_mode, false, "Enables usage of PAL-50 mode.", "Video");
|
||||
DEFINE_bool(interlaced, false, "Toggles interlaced mode.", "Video");
|
||||
|
||||
// TODO: This is stored in XConfig somewhere, probably in video flags.
|
||||
DEFINE_bool(widescreen, true, "Toggles between 16:9 and 4:3 aspect ratio.",
|
||||
"Video");
|
||||
|
||||
// BT.709 on modern monitors and TVs looks the closest to the Xbox 360 connected
|
||||
// to an HDTV.
|
||||
DEFINE_uint32(kernel_display_gamma_type, 2,
|
||||
@@ -88,6 +94,51 @@ inline constexpr static float GetVideoRefreshRate() {
|
||||
return cvars::use_50Hz_mode ? 50.0f : 60.0f;
|
||||
}
|
||||
|
||||
inline constexpr static std::pair<uint16_t, uint16_t> GetDisplayAspectRatio() {
|
||||
if (cvars::widescreen) {
|
||||
return {16, 9};
|
||||
}
|
||||
|
||||
return {4, 3};
|
||||
}
|
||||
|
||||
static std::pair<uint32_t, uint32_t> CalculateScaledAspectRatio(uint32_t fb_x,
|
||||
uint32_t fb_y) {
|
||||
// Calculate the game's final aspect ratio as it would appear on a physical
|
||||
// TV.
|
||||
auto dar = GetDisplayAspectRatio();
|
||||
uint32_t display_x = dar.first;
|
||||
uint32_t display_y = dar.second;
|
||||
|
||||
auto res = GetInternalDisplayResolution();
|
||||
uint32_t res_x = res.first;
|
||||
uint32_t res_y = res.second;
|
||||
|
||||
uint32_t x_factor = std::gcd(fb_x, res_x);
|
||||
res_x /= x_factor;
|
||||
fb_x /= x_factor;
|
||||
uint32_t y_factor = std::gcd(fb_y, res_y);
|
||||
res_y /= y_factor;
|
||||
fb_y /= y_factor;
|
||||
|
||||
display_x = display_x * res_x - display_x * (res_x - fb_x);
|
||||
display_y *= res_x;
|
||||
|
||||
display_y = display_y * res_y - display_y * (res_y - fb_y);
|
||||
display_x *= res_y;
|
||||
|
||||
uint32_t aspect_factor = std::gcd(display_x, display_y);
|
||||
display_x /= aspect_factor;
|
||||
display_y /= aspect_factor;
|
||||
|
||||
XELOGI(
|
||||
"Hardware scaler: width ratio {}:{}, height ratio {}:{}, final aspect "
|
||||
"ratio {}:{}",
|
||||
fb_x, res_x, fb_y, res_y, display_x, display_y);
|
||||
|
||||
return {display_x, display_y};
|
||||
}
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xboxkrnl {
|
||||
@@ -184,6 +235,7 @@ void VdGetCurrentDisplayInformation_entry(
|
||||
display_info->display_width = (uint16_t)mode.display_width;
|
||||
display_info->display_height = (uint16_t)mode.display_height;
|
||||
display_info->display_refresh_rate = mode.refresh_rate;
|
||||
display_info->display_interlaced = mode.is_interlaced;
|
||||
display_info->actual_display_width = (uint16_t)mode.display_width;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(VdGetCurrentDisplayInformation, kVideo, kStub);
|
||||
@@ -196,9 +248,8 @@ void VdQueryVideoMode(X_VIDEO_MODE* video_mode) {
|
||||
|
||||
video_mode->display_width = display_res.first;
|
||||
video_mode->display_height = display_res.second;
|
||||
video_mode->is_interlaced = 0;
|
||||
video_mode->is_widescreen =
|
||||
((video_mode->display_width / 4) > (video_mode->display_height / 3));
|
||||
video_mode->is_interlaced = cvars::interlaced;
|
||||
video_mode->is_widescreen = cvars::widescreen;
|
||||
video_mode->is_hi_def = video_mode->display_width >= 0x400;
|
||||
video_mode->refresh_rate = GetVideoRefreshRate();
|
||||
video_mode->video_standard = GetVideoStandard();
|
||||
@@ -350,6 +401,14 @@ dword_result_t VdInitializeScalerCommandBuffer_entry(
|
||||
for (size_t i = 0; i < dest_count; ++i) {
|
||||
dest[i] = 0x80000000;
|
||||
}
|
||||
|
||||
uint32_t fb_x = (scaled_output_wh >> 16) & 0xFFFF;
|
||||
uint32_t fb_y = scaled_output_wh & 0xFFFF;
|
||||
auto aspect = CalculateScaledAspectRatio(fb_x, fb_y);
|
||||
|
||||
auto graphics_system = kernel_state()->emulator()->graphics_system();
|
||||
graphics_system->SetScaledAspectRatio(aspect.first, aspect.second);
|
||||
|
||||
return (uint32_t)dest_count;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT2(VdInitializeScalerCommandBuffer, kVideo, kImplemented,
|
||||
|
||||
Reference in New Issue
Block a user