Skip to content

Commit

Permalink
Update screen layout settings
Browse files Browse the repository at this point in the history
- Add a dirty flag to ScreenLayoutData
- Remove obsolete screen settings
- Add ability to cycle through screen layouts (although aspect ratio is not updated)
  • Loading branch information
JesseTG committed Jul 10, 2023
1 parent ae8ed04 commit 684b4b2
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 140 deletions.
118 changes: 29 additions & 89 deletions src/libretro/config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,6 @@ namespace Config {
static const char* const OPENGL_FILTERING = "melonds_opengl_filtering";
static const char* const RENDER_MODE = "melonds_render_mode";
static const char* const NUMBER_OF_SCREEN_LAYOUTS = "melonds_number_of_screen_layouts";
[[deprecated("Use SCREEN_LAYOUTS instead")]] static const char* const SCREEN_LAYOUT = "melonds_screen_layout";
static const char* const SCREEN_LAYOUT1 = "melonds_screen_layout1";
static const char* const SCREEN_LAYOUT2 = "melonds_screen_layout2";
static const char* const SCREEN_LAYOUT3 = "melonds_screen_layout3";
Expand Down Expand Up @@ -102,7 +101,6 @@ namespace Config {
static const char* const CONSOLE_MODE = "melonds_console_mode";
static const char* const BOOT_DIRECTLY = "melonds_boot_directly";
static const char* const SCREEN_GAP = "melonds_screen_gap";
[[deprecated("Use SCREEN_LAYOUTS instead")]] static const char* const SWAPSCREEN_MODE = "melonds_swapscreen_mode";
static const char* const RANDOMIZE_MAC_ADDRESS = "melonds_randomize_mac_address";
static const char* const TOUCH_MODE = "melonds_touch_mode";
static const char* const MIC_INPUT_BUTTON = "melonds_mic_input_active";
Expand Down Expand Up @@ -332,9 +330,6 @@ namespace melonds::config {
static std::array<melonds::ScreenLayout, MAX_SCREEN_LAYOUTS> _screenLayouts;
std::array<melonds::ScreenLayout, MAX_SCREEN_LAYOUTS> ScreenLayouts() noexcept { return _screenLayouts; }

[[deprecated("Use ScreenLayouts instead")]] static melonds::ScreenLayout _screenLayout;
enum melonds::ScreenLayout ScreenLayout() noexcept { return _screenLayout; }

static unsigned _screenGap;
unsigned ScreenGap() noexcept { return _screenGap; }

Expand All @@ -345,9 +340,6 @@ namespace melonds::config {
unsigned HybridRatio() noexcept { return 2; }
#endif

[[deprecated("Use ScreenLayouts instead")]] static melonds::ScreenSwapMode _screenSwapMode;
melonds::ScreenSwapMode ScreenSwapMode() noexcept { return _screenSwapMode; }

static melonds::SmallScreenLayout _smallScreenLayout;
melonds::SmallScreenLayout SmallScreenLayout() noexcept { return _smallScreenLayout; }

Expand Down Expand Up @@ -469,20 +461,22 @@ void melonds::InitConfig(const optional<struct retro_game_info>& nds_info, const
config::apply_screen_options(screenLayout);

#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
if (melonds::opengl::UsingOpenGl() && openGlNeedsRefresh) {
if (melonds::opengl::UsingOpenGl() && (openGlNeedsRefresh || screenLayout.Dirty())) {
// If we're using OpenGL and the settings changed, or the screen layout changed...
melonds::opengl::RequestOpenGlRefresh();
}
#endif

if (melonds::render::CurrentRenderer() == Renderer::None) {
screenLayout.Update(config::video::ConfiguredRenderer());
} else {
screenLayout.Update(melonds::render::CurrentRenderer());
}

update_option_visibility();
}

void melonds::UpdateConfig(
const std::optional<struct retro_game_info>& nds_info,
const std::optional<NDSHeader>& header,
ScreenLayoutData& screenLayout
) noexcept {
void melonds::UpdateConfig(ScreenLayoutData& screenLayout) noexcept {
config::parse_audio_options();
bool openGlNeedsRefresh = config::parse_video_options(false);
openGlNeedsRefresh |= config::parse_screen_options();
Expand All @@ -491,12 +485,18 @@ void melonds::UpdateConfig(
config::apply_screen_options(screenLayout);

#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
if (melonds::opengl::UsingOpenGl() && openGlNeedsRefresh) {
if (melonds::opengl::UsingOpenGl() && (openGlNeedsRefresh || screenLayout.Dirty())) {
// If we're using OpenGL and the settings changed, or the screen layout changed...
melonds::opengl::RequestOpenGlRefresh();
}
#endif

if (melonds::render::CurrentRenderer() == Renderer::None) {
screenLayout.Update(config::video::ConfiguredRenderer());
} else {
screenLayout.Update(melonds::render::CurrentRenderer());
}

update_option_visibility();
}

Expand Down Expand Up @@ -552,9 +552,17 @@ bool melonds::update_option_visibility() {
// Show/hide Hybrid screen options
bool oldShowHybridOptions = ShowHybridOptions;
bool oldShowVerticalLayoutOptions = ShowVerticalLayoutOptions;
optional<ScreenLayout> layout = ParseScreenLayout(get_variable(Keys::SCREEN_LAYOUT));
ShowHybridOptions = !layout || *layout == ScreenLayout::HybridTop || *layout == ScreenLayout::HybridBottom;
ShowVerticalLayoutOptions = !layout || *layout == ScreenLayout::TopBottom || *layout == ScreenLayout::BottomTop;
bool anyHybridLayouts = false;
bool anyVerticalLayouts = false;
for (unsigned i = 0; i < config::screen::MAX_SCREEN_LAYOUTS; i++) {
optional<melonds::ScreenLayout> parsedLayout = ParseScreenLayout(get_variable(Keys::SCREEN_LAYOUTS[i]));

anyHybridLayouts |= !parsedLayout || *parsedLayout == ScreenLayout::HybridTop || *parsedLayout == ScreenLayout::HybridBottom;
anyVerticalLayouts |= !parsedLayout || *parsedLayout == ScreenLayout::TopBottom || *parsedLayout == ScreenLayout::BottomTop;
}
ShowHybridOptions = anyHybridLayouts;
ShowVerticalLayoutOptions = anyVerticalLayouts;

if (ShowHybridOptions != oldShowHybridOptions) {
set_option_visible(Keys::HYBRID_SMALL_SCREEN, ShowHybridOptions);
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
Expand Down Expand Up @@ -896,17 +904,6 @@ static bool melonds::config::parse_screen_options() noexcept {

bool needsOpenGlRefresh = false;

enum ScreenLayout oldScreenLayout = _screenLayout;
if (optional<melonds::ScreenLayout> value = ParseScreenLayout(get_variable(Keys::SCREEN_LAYOUT))) {
_screenLayout = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", Keys::SCREEN_LAYOUT, Values::TOP_BOTTOM);
_screenLayout = ScreenLayout::TopBottom;
}

if (oldScreenLayout != _screenLayout)
needsOpenGlRefresh = true;

if (const char* value = get_variable(Keys::SCREEN_GAP); !string_is_empty(value)) {
_screenGap = std::stoi(value); // TODO: Handle errors
} else {
Expand All @@ -923,7 +920,6 @@ static bool melonds::config::parse_screen_options() noexcept {
}
#endif

enum SmallScreenLayout oldHybridSmallScreen = _smallScreenLayout;
if (const char* value = get_variable(Keys::HYBRID_SMALL_SCREEN); !string_is_empty(value)) {
if (string_is_equal(value, Values::TOP))
_smallScreenLayout = SmallScreenLayout::SmallScreenTop;
Expand All @@ -936,12 +932,6 @@ static bool melonds::config::parse_screen_options() noexcept {
_smallScreenLayout = SmallScreenLayout::SmallScreenDuplicate;
}

#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
if (_smallScreenLayout != oldHybridSmallScreen) {
needsOpenGlRefresh = true;
}
#endif

enum TouchMode oldTouchMode = _touchMode;
if (const char* value = get_variable(Keys::TOUCH_MODE); !string_is_empty(value)) {
if (string_is_equal(value, Values::MOUSE))
Expand All @@ -959,20 +949,12 @@ static bool melonds::config::parse_screen_options() noexcept {

#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
if (_touchMode != oldTouchMode) {
// May need to refresh the screen if the touch mode changed,
// as we may need to start (or stop) drawing a cursor.
needsOpenGlRefresh = true;
}
#endif

if (const char* value = get_variable(Keys::SWAPSCREEN_MODE); !string_is_empty(value)) {
if (string_is_equal(value, Values::TOGGLE))
_screenSwapMode = ScreenSwapMode::Toggle;
else
_screenSwapMode = ScreenSwapMode::Hold;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", Keys::SWAPSCREEN_MODE, Values::TOGGLE);
_screenSwapMode = ScreenSwapMode::Toggle;
}

if (optional<int> value = ParseIntegerInRange(get_variable(Keys::NUMBER_OF_SCREEN_LAYOUTS), 1, MAX_SCREEN_LAYOUTS)) {
_numberOfScreenLayouts = *value;
} else {
Expand Down Expand Up @@ -1269,15 +1251,10 @@ static void melonds::config::apply_save_options(const optional<NDSHeader>& heade
}

static void melonds::config::apply_screen_options(ScreenLayoutData& screenLayout) noexcept {
screenLayout.SetLayout(screen::ScreenLayout());
screenLayout.SetLayouts(screen::ScreenLayouts(), screen::NumberOfScreenLayouts());
screenLayout.HybridSmallScreenLayout(screen::SmallScreenLayout());
screenLayout.ScreenGap(screen::ScreenGap());
screenLayout.HybridRatio(screen::HybridRatio());
if (melonds::render::CurrentRenderer() == Renderer::None) {
screenLayout.Update(video::ConfiguredRenderer());
} else {
screenLayout.Update(melonds::render::CurrentRenderer());
}
}

struct retro_core_option_v2_category option_cats_us[] = {
Expand Down Expand Up @@ -1675,43 +1652,6 @@ struct retro_core_option_v2_definition melonds::option_defs_us[] = {
},
Config::Retro::Values::MOUSE
},
{
Config::Retro::Keys::SWAPSCREEN_MODE,
"Swap Screen Mode",
nullptr,
"Choose if the 'Swap screens' button should work on press or on hold.",
nullptr,
Config::Retro::Category::SCREEN,
{
{Config::Retro::Values::TOGGLE, "Toggle"},
{Config::Retro::Values::HOLD, "Hold"},
{nullptr, nullptr},
},
Config::Retro::Values::TOGGLE
},
{
Config::Retro::Keys::SCREEN_LAYOUT,
"Screen Layout",
nullptr,
"Choose how many screens should be displayed and how they should be displayed.",
nullptr,
Config::Retro::Category::SCREEN,
{
{Config::Retro::Values::TOP_BOTTOM, "Top/Bottom"},
{Config::Retro::Values::BOTTOM_TOP, "Bottom/Top"},
{Config::Retro::Values::LEFT_RIGHT, "Left/Right"},
{Config::Retro::Values::RIGHT_LEFT, "Right/Left"},
{Config::Retro::Values::TOP, "Top Only"},
{Config::Retro::Values::BOTTOM, "Bottom Only"},
{Config::Retro::Values::HYBRID_TOP, "Hybrid (Focus Top)"},
{Config::Retro::Values::HYBRID_BOTTOM, "Hybrid (Focus Bottom)"},
{Config::Retro::Values::ROTATE_LEFT, "Rotated Left"},
{Config::Retro::Values::ROTATE_RIGHT, "Rotated Right"},
{Config::Retro::Values::UPSIDE_DOWN, "Upside Down"},
{nullptr, nullptr},
},
Config::Retro::Values::TOP_BOTTOM
},
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
{
Config::Retro::Keys::HYBRID_RATIO,
Expand Down
8 changes: 1 addition & 7 deletions src/libretro/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,7 @@ namespace melonds {
);

/// Called when settings have been updated mid-game
void UpdateConfig(
const std::optional<struct retro_game_info>& nds_info,
const std::optional<NDSHeader>& header,
ScreenLayoutData& screenLayout
) noexcept;
void UpdateConfig(ScreenLayoutData& screenLayout) noexcept;
bool update_option_visibility();
extern struct retro_core_options_v2 options_us;
extern struct retro_core_option_v2_definition option_defs_us[];
Expand Down Expand Up @@ -226,10 +222,8 @@ namespace melonds {
constexpr unsigned MAX_SCREEN_LAYOUTS = 8; // Chosen arbitrarily; if you need more, open a PR
[[nodiscard]] unsigned NumberOfScreenLayouts() noexcept;
[[nodiscard]] std::array<ScreenLayout, MAX_SCREEN_LAYOUTS> ScreenLayouts() noexcept;
[[nodiscard]] [[deprecated("Use ScreenLayouts instead")]] ScreenLayout ScreenLayout() noexcept;
[[nodiscard]] unsigned ScreenGap() noexcept;
[[nodiscard]] unsigned HybridRatio() noexcept;
[[nodiscard]] [[deprecated("Use ScreenLayouts instead")]] ScreenSwapMode ScreenSwapMode() noexcept;
[[nodiscard]] SmallScreenLayout SmallScreenLayout() noexcept;
[[nodiscard]] TouchMode TouchMode() noexcept;
}
Expand Down
10 changes: 3 additions & 7 deletions src/libretro/libretro.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ using std::nullopt;
namespace melonds {
static InputState input_state;
static ScreenLayoutData screenLayout;
static unsigned currentLayoutIndex = 0;
static bool swap_screen_toggled = false;
static bool mic_state_toggled = false;
static bool deferred_initialization_pending = false;
Expand Down Expand Up @@ -324,11 +323,9 @@ PUBLIC_SYMBOL void retro_run(void) {

if (melonds::render::ReadyToRender()) { // If the global state needed for rendering is ready...
if (melonds::input_state.CycleLayoutPressed()) {
unsigned numberOfScreenLayouts = config::screen::NumberOfScreenLayouts();
auto screenLayouts = config::screen::ScreenLayouts();
currentLayoutIndex = (currentLayoutIndex + 1) % numberOfScreenLayouts;
screenLayout.NextLayout();
retro::debug("Switched to screen layout %d of %d", screenLayout.LayoutIndex() + 1, screenLayout.NumberOfLayouts());

screenLayout.SetLayout(screenLayouts[currentLayoutIndex]);
screenLayout.Update(render::CurrentRenderer());
melonds::opengl::RequestOpenGlRefresh();
}
Expand All @@ -344,8 +341,7 @@ PUBLIC_SYMBOL void retro_run(void) {
}

if (bool updated = false; retro::environment(RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE, &updated) && updated) {
optional<NDSHeader> header = NDSCart::Cart ? std::make_optional(NDSCart::Cart->GetHeader()) : std::nullopt;
melonds::UpdateConfig(retro::content::get_loaded_nds_info(), header, screenLayout);
melonds::UpdateConfig(screenLayout);

struct retro_system_av_info updated_av_info{};
retro_get_system_av_info(&updated_av_info);
Expand Down
31 changes: 5 additions & 26 deletions src/libretro/screenlayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
melonds::ScreenLayoutData::ScreenLayoutData() {
this->buffer_ptr = nullptr;
this->hybrid_ratio = 2;
this->_dirty = true; // Uninitialized
this->_numberOfLayouts = 1;
}

melonds::ScreenLayoutData::~ScreenLayoutData() {
Expand Down Expand Up @@ -98,7 +100,7 @@ void melonds::ScreenLayoutData::CopyHybridScreen(const uint32_t* src, ScreenId s
void melonds::ScreenLayoutData::draw_cursor(int32_t x, int32_t y) {
auto *base_offset = (uint32_t *) buffer_ptr;

uint32_t scale = layout == ScreenLayout::HybridBottom ? hybrid_ratio : 1;
uint32_t scale = Layout() == ScreenLayout::HybridBottom ? hybrid_ratio : 1;
float cursorSize = melonds::config::video::CursorSize();
uint32_t start_y = std::clamp<float>(y - cursorSize, 0, screen_height) * scale;
uint32_t end_y = std::clamp<float>(y + cursorSize, 0, screen_height) * scale;
Expand Down Expand Up @@ -234,7 +236,7 @@ void melonds::ScreenLayoutData::Update(melonds::Renderer renderer) noexcept {
this->buffer_height = (this->screen_height * this->hybrid_ratio);
this->buffer_stride = this->buffer_width * pixel_size;

if (layout == ScreenLayout::HybridTop) {
if (Layout() == ScreenLayout::HybridTop) {
this->touch_offset_x = (this->screen_width * this->hybrid_ratio) + (this->hybrid_ratio / 2);
this->touch_offset_y = (this->screen_height * (this->hybrid_ratio - 1));
} else {
Expand All @@ -260,29 +262,6 @@ void melonds::ScreenLayoutData::Update(melonds::Renderer renderer) noexcept {
memset(this->buffer_ptr, 0, new_size);
}
}
}


melonds::ScreenLayout melonds::SwapLayout(ScreenLayout layout) noexcept {
switch (layout) {
case ScreenLayout::BottomOnly:
return ScreenLayout::TopOnly;
case ScreenLayout::TopOnly:
return ScreenLayout::BottomOnly;
case ScreenLayout::BottomTop:
return ScreenLayout::TopBottom;
case ScreenLayout::TopBottom:
return ScreenLayout::BottomTop;
case ScreenLayout::LeftRight:
return ScreenLayout::RightLeft;
case ScreenLayout::RightLeft:
return ScreenLayout::LeftRight;
case ScreenLayout::HybridTop:
return ScreenLayout::HybridBottom;
case ScreenLayout::HybridBottom:
return ScreenLayout::HybridTop;
default:
// No swap for other types
return layout;
}
_dirty = false;
}
Loading

0 comments on commit 684b4b2

Please sign in to comment.