2023-01-31 04:58:54 +00:00
|
|
|
// Copyright 2023 Dolphin Emulator Project
|
|
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
|
|
|
|
#include "VideoCommon/Widescreen.h"
|
|
|
|
|
|
|
|
#include "Common/ChunkFile.h"
|
|
|
|
#include "Core/Config/SYSCONFSettings.h"
|
2024-01-31 01:56:56 +00:00
|
|
|
#include "Core/System.h"
|
2023-01-31 04:58:54 +00:00
|
|
|
|
|
|
|
#include "VideoCommon/VertexManagerBase.h"
|
|
|
|
|
|
|
|
std::unique_ptr<WidescreenManager> g_widescreen;
|
|
|
|
|
|
|
|
WidescreenManager::WidescreenManager()
|
|
|
|
{
|
|
|
|
Update();
|
|
|
|
|
2023-01-31 06:21:15 +00:00
|
|
|
m_config_changed = ConfigChangedEvent::Register(
|
|
|
|
[this](u32 bits) {
|
|
|
|
if (bits & (CONFIG_CHANGE_BIT_ASPECT_RATIO))
|
|
|
|
Update();
|
|
|
|
},
|
|
|
|
"Widescreen");
|
2023-01-31 04:58:54 +00:00
|
|
|
|
|
|
|
// VertexManager doesn't maintain statistics in Wii mode.
|
2024-01-31 01:56:56 +00:00
|
|
|
auto& system = Core::System::GetInstance();
|
|
|
|
if (!system.IsWii())
|
2023-01-31 04:58:54 +00:00
|
|
|
{
|
2024-01-31 18:12:06 +00:00
|
|
|
m_update_widescreen = AfterFrameEvent::Register(
|
|
|
|
[this](Core::System&) { UpdateWidescreenHeuristic(); }, "WideScreen Heuristic");
|
2023-01-31 04:58:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidescreenManager::Update()
|
|
|
|
{
|
2024-02-20 00:42:52 +00:00
|
|
|
std::optional<bool> is_game_widescreen;
|
|
|
|
|
2024-01-31 01:56:56 +00:00
|
|
|
auto& system = Core::System::GetInstance();
|
|
|
|
if (system.IsWii())
|
2024-02-20 00:42:52 +00:00
|
|
|
is_game_widescreen = Config::Get(Config::SYSCONF_WIDESCREEN);
|
2023-01-31 04:58:54 +00:00
|
|
|
|
|
|
|
// suggested_aspect_mode overrides SYSCONF_WIDESCREEN
|
2023-12-12 22:27:01 +00:00
|
|
|
if (g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceStandard)
|
2024-02-20 00:42:52 +00:00
|
|
|
is_game_widescreen = false;
|
2023-12-12 22:27:01 +00:00
|
|
|
else if (g_ActiveConfig.suggested_aspect_mode == AspectMode::ForceWide)
|
2024-02-20 00:42:52 +00:00
|
|
|
is_game_widescreen = true;
|
2023-01-31 04:58:54 +00:00
|
|
|
|
|
|
|
// If widescreen hack is disabled override game's AR if UI is set to 4:3 or 16:9.
|
|
|
|
if (!g_ActiveConfig.bWidescreenHack)
|
|
|
|
{
|
|
|
|
const auto aspect_mode = g_ActiveConfig.aspect_mode;
|
2023-12-12 22:27:01 +00:00
|
|
|
if (aspect_mode == AspectMode::ForceStandard)
|
2024-02-20 00:42:52 +00:00
|
|
|
is_game_widescreen = false;
|
2023-12-12 22:27:01 +00:00
|
|
|
else if (aspect_mode == AspectMode::ForceWide)
|
2024-02-20 00:42:52 +00:00
|
|
|
is_game_widescreen = true;
|
|
|
|
|
|
|
|
// Reset settings to default if heuristics aren't currently running and
|
|
|
|
// the user selected the automatic aspect ratio.
|
|
|
|
if (!is_game_widescreen.has_value() && !m_widescreen_heuristics_active_and_successful &&
|
|
|
|
aspect_mode == AspectMode::Auto)
|
|
|
|
{
|
|
|
|
is_game_widescreen = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_game_widescreen.has_value())
|
|
|
|
{
|
|
|
|
m_is_game_widescreen = is_game_widescreen.value();
|
2023-01-31 04:58:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Heuristic to detect if a GameCube game is in 16:9 anamorphic widescreen mode.
|
2023-09-09 12:48:37 +00:00
|
|
|
// Cheats that change the game aspect ratio to natively unsupported ones won't be recognized here.
|
2023-01-31 04:58:54 +00:00
|
|
|
void WidescreenManager::UpdateWidescreenHeuristic()
|
|
|
|
{
|
|
|
|
const auto flush_statistics = g_vertex_manager->ResetFlushAspectRatioCount();
|
|
|
|
|
|
|
|
// If suggested_aspect_mode (GameINI) is configured don't use heuristic.
|
|
|
|
if (g_ActiveConfig.suggested_aspect_mode != AspectMode::Auto)
|
2024-02-20 00:42:52 +00:00
|
|
|
{
|
|
|
|
m_widescreen_heuristics_active_and_successful = false;
|
2023-01-31 04:58:54 +00:00
|
|
|
return;
|
2024-02-20 00:42:52 +00:00
|
|
|
}
|
2023-01-31 04:58:54 +00:00
|
|
|
|
|
|
|
Update();
|
|
|
|
|
2024-02-20 00:42:52 +00:00
|
|
|
m_widescreen_heuristics_active_and_successful = false;
|
|
|
|
|
|
|
|
// If widescreen hack isn't active and aspect_mode (UI) is 4:3 or 16:9 don't use heuristic.
|
2023-12-12 22:27:01 +00:00
|
|
|
if (!g_ActiveConfig.bWidescreenHack && (g_ActiveConfig.aspect_mode == AspectMode::ForceStandard ||
|
|
|
|
g_ActiveConfig.aspect_mode == AspectMode::ForceWide))
|
2023-01-31 04:58:54 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
// Modify the threshold based on which aspect ratio we're already using:
|
|
|
|
// If the game's in 4:3, it probably won't switch to anamorphic, and vice-versa.
|
2023-01-09 05:25:11 +00:00
|
|
|
const u32 transition_threshold = g_ActiveConfig.widescreen_heuristic_transition_threshold;
|
2023-01-31 04:58:54 +00:00
|
|
|
|
2023-01-09 05:25:11 +00:00
|
|
|
const auto looks_normal = [transition_threshold](auto& counts) {
|
|
|
|
return counts.normal_vertex_count > counts.anamorphic_vertex_count * transition_threshold;
|
2023-01-31 04:58:54 +00:00
|
|
|
};
|
2023-01-09 05:25:11 +00:00
|
|
|
const auto looks_anamorphic = [transition_threshold](auto& counts) {
|
|
|
|
return counts.anamorphic_vertex_count > counts.normal_vertex_count * transition_threshold;
|
2023-01-31 04:58:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
const auto& persp = flush_statistics.perspective;
|
|
|
|
const auto& ortho = flush_statistics.orthographic;
|
|
|
|
|
|
|
|
const auto ortho_looks_anamorphic = looks_anamorphic(ortho);
|
|
|
|
|
|
|
|
if (looks_anamorphic(persp) || ortho_looks_anamorphic)
|
|
|
|
{
|
|
|
|
// If either perspective or orthographic projections look anamorphic, it's a safe bet.
|
|
|
|
m_is_game_widescreen = true;
|
2024-02-20 00:42:52 +00:00
|
|
|
m_widescreen_heuristics_active_and_successful = true;
|
2023-01-31 04:58:54 +00:00
|
|
|
}
|
|
|
|
else if (looks_normal(persp) || (m_was_orthographically_anamorphic && looks_normal(ortho)))
|
|
|
|
{
|
|
|
|
// Many widescreen games (or AR/GeckoCodes) use anamorphic perspective projections
|
|
|
|
// with NON-anamorphic orthographic projections.
|
|
|
|
// This can cause incorrect changes to 4:3 when perspective projections are temporarily not
|
|
|
|
// shown. e.g. Animal Crossing's inventory menu.
|
|
|
|
// Unless we were in a situation which was orthographically anamorphic
|
|
|
|
// we won't consider orthographic data for changes from 16:9 to 4:3.
|
|
|
|
m_is_game_widescreen = false;
|
2024-02-20 00:42:52 +00:00
|
|
|
m_widescreen_heuristics_active_and_successful = true;
|
2023-01-31 04:58:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_was_orthographically_anamorphic = ortho_looks_anamorphic;
|
|
|
|
}
|
|
|
|
|
|
|
|
void WidescreenManager::DoState(PointerWrap& p)
|
|
|
|
{
|
|
|
|
p.Do(m_is_game_widescreen);
|
|
|
|
|
|
|
|
if (p.IsReadMode())
|
|
|
|
{
|
|
|
|
m_was_orthographically_anamorphic = false;
|
2024-02-20 00:42:52 +00:00
|
|
|
m_widescreen_heuristics_active_and_successful = false;
|
2023-01-31 04:58:54 +00:00
|
|
|
}
|
2023-01-31 06:21:15 +00:00
|
|
|
}
|