Add some on-screen display config

- Fix #37
- Fix #36
- Fix #20
This commit is contained in:
Jesse Talavera-Greenberg 2023-08-17 22:53:15 -04:00
parent 7583a84971
commit 0c7ba3339e
9 changed files with 332 additions and 19 deletions

View File

@ -16,6 +16,7 @@ add_library(libretro MODULE
config/definitions/categories.hpp
config/definitions/cpu.hpp
config/definitions/network.hpp
config/definitions/osd.hpp
config/definitions/screen.hpp
config/definitions/storage.hpp
config/definitions/system.hpp

View File

@ -193,6 +193,21 @@ namespace melonds {
#endif
}
namespace osd {
#ifndef NDEBUG
[[nodiscard]] bool ShowPointerCoordinates() noexcept;
#else
[[nodiscard]] constexpr bool ShowPointerCoordinates() noexcept { return false; }
#endif
[[nodiscard]] bool ShowUnsupportedFeatureWarnings() noexcept;
[[nodiscard]] bool ShowMicState() noexcept;
[[nodiscard]] bool ShowCameraState() noexcept;
[[nodiscard]] bool ShowBiosWarnings() noexcept;
[[nodiscard]] bool ShowCurrentLayout() noexcept;
[[nodiscard]] bool ShowLidState() noexcept;
[[nodiscard]] bool ShowBrightnessState() noexcept;
}
namespace system {
[[nodiscard]] ConsoleType ConsoleType() noexcept;
[[nodiscard]] bool DirectBoot() noexcept;

View File

@ -95,6 +95,7 @@ namespace melonds::config {
}
static void parse_jit_options() noexcept;
static void parse_osd_options() noexcept;
static void parse_system_options() noexcept;
static void parse_firmware_options() noexcept;
static void parse_audio_options() noexcept;
@ -191,6 +192,34 @@ namespace melonds::config {
#endif
}
namespace osd {
#ifndef NDEBUG
static bool showPointerCoordinates = false;
[[nodiscard]] bool ShowPointerCoordinates() noexcept { return showPointerCoordinates; }
#endif
static bool showUnsupportedFeatureWarnings = true;
[[nodiscard]] bool ShowUnsupportedFeatureWarnings() noexcept { return showUnsupportedFeatureWarnings; }
static bool showMicState = true;
[[nodiscard]] bool ShowMicState() noexcept { return showMicState; }
static bool showCameraState = true;
[[nodiscard]] bool ShowCameraState() noexcept { return showCameraState; }
static bool showBiosWarnings = true;
[[nodiscard]] bool ShowBiosWarnings() noexcept { return showBiosWarnings; }
static bool showCurrentLayout = true;
[[nodiscard]] bool ShowCurrentLayout() noexcept { return showCurrentLayout; }
static bool showLidState = false;
[[nodiscard]] bool ShowLidState() noexcept { return showLidState; }
static bool showBrightnessState = false;
[[nodiscard]] bool ShowBrightnessState() noexcept { return showBrightnessState; }
}
namespace save {
bool _dldiEnable;
bool DldiEnable() noexcept { return _dldiEnable; }
@ -315,6 +344,7 @@ void melonds::InitConfig(const optional<struct retro_game_info>& nds_info, const
ZoneScopedN("melonds::InitConfig");
config::set_core_options(nds_info, header);
config::parse_system_options();
config::parse_osd_options();
config::parse_jit_options();
config::parse_homebrew_save_options(nds_info, header);
config::parse_dsi_storage_options();
@ -349,6 +379,7 @@ void melonds::UpdateConfig(ScreenLayoutData& screenLayout, InputState& inputStat
config::parse_audio_options();
bool openGlNeedsRefresh = config::parse_video_options(false);
config::parse_screen_options();
config::parse_osd_options();
config::apply_audio_options();
config::apply_screen_options(screenLayout, inputState);
@ -507,6 +538,63 @@ static melonds::FirmwareLanguage get_firmware_language(const optional<retro_lang
}
}
static void melonds::config::parse_osd_options() noexcept {
ZoneScopedN("melonds::config::parse_osd_options");
using namespace melonds::config::osd;
using retro::get_variable;
#ifndef NDEBUG
if (optional<bool> value = ParseBoolean(get_variable(osd::POINTER_COORDINATES))) {
showPointerCoordinates = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", POINTER_COORDINATES, values::DISABLED);
showPointerCoordinates = false;
}
#endif
if (optional<bool> value = ParseBoolean(get_variable(osd::UNSUPPORTED_FEATURES))) {
showUnsupportedFeatureWarnings = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", UNSUPPORTED_FEATURES, values::ENABLED);
showUnsupportedFeatureWarnings = true;
}
if (optional<bool> value = ParseBoolean(get_variable(osd::MIC_STATE))) {
showMicState = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", MIC_STATE, values::ENABLED);
showMicState = true;
}
if (optional<bool> value = ParseBoolean(get_variable(osd::CAMERA_STATE))) {
showCameraState = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", CAMERA_STATE, values::ENABLED);
showCameraState = true;
}
if (optional<bool> value = ParseBoolean(get_variable(osd::BIOS_WARNINGS))) {
showBiosWarnings = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", BIOS_WARNINGS, values::ENABLED);
showBiosWarnings = true;
}
if (optional<bool> value = ParseBoolean(get_variable(osd::CURRENT_LAYOUT))) {
showCurrentLayout = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", CURRENT_LAYOUT, values::ENABLED);
showCurrentLayout = true;
}
if (optional<bool> value = ParseBoolean(get_variable(osd::LID_STATE))) {
showLidState = *value;
} else {
retro::warn("Failed to get value for %s; defaulting to %s", LID_STATE, values::DISABLED);
showLidState = false;
}
}
static void melonds::config::parse_jit_options() noexcept {
ZoneScopedN("melonds::config::parse_jit_options");
#ifdef HAVE_JIT
@ -1060,7 +1148,7 @@ static void melonds::config::apply_audio_options() noexcept {
retro::warn("Failed to %s microphone", is_using_host_mic ? "open" : "close");
}
} else {
if (is_using_host_mic) {
if (is_using_host_mic && osd::ShowUnsupportedFeatureWarnings()) {
retro::set_warn_message("This frontend doesn't support microphones.");
}
}

View File

@ -25,6 +25,7 @@
#include "config/definitions/audio.hpp"
#include "config/definitions/cpu.hpp"
#include "config/definitions/network.hpp"
#include "config/definitions/osd.hpp"
#include "config/definitions/screen.hpp"
#include "config/definitions/storage.hpp"
#include "config/definitions/system.hpp"
@ -43,6 +44,7 @@ namespace melonds::config::definitions {
StorageOptionDefinitions<L>,
SystemOptionDefinitions<L>,
VideoOptionDefinitions<L>,
OsdOptionDefinitions<L>,
};
template<retro_language L = RETRO_LANGUAGE_ENGLISH>

View File

@ -0,0 +1,135 @@
/*
Copyright 2023 Jesse Talavera-Greenberg
melonDS DS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS DS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS DS. If not, see http://www.gnu.org/licenses/.
*/
#ifndef MELONDS_DS_OSD_HPP
#define MELONDS_DS_OSD_HPP
#include <array>
#include <libretro.h>
#include "../constants.hpp"
namespace melonds::config::definitions {
template<retro_language L>
constexpr std::array OsdOptionDefinitions {
retro_core_option_v2_definition {
config::osd::UNSUPPORTED_FEATURES,
"Warn About Unsupported Features",
nullptr,
"Enable to display an on-screen message "
"if melonDS tries to use certain unsupported features. "
"These warnings will be logged regardless of this setting.",
nullptr,
config::osd::CATEGORY,
{
{melonds::config::values::ENABLED, nullptr},
{melonds::config::values::DISABLED, nullptr},
{nullptr, nullptr},
},
melonds::config::values::ENABLED
},
retro_core_option_v2_definition {
config::osd::BIOS_WARNINGS,
"Warn About Certain BIOS Problems",
nullptr,
"Enable to show whether your BIOS files have certain known problems.",
nullptr,
config::osd::CATEGORY,
{
{melonds::config::values::ENABLED, nullptr},
{melonds::config::values::DISABLED, nullptr},
{nullptr, nullptr},
},
melonds::config::values::ENABLED
},
retro_core_option_v2_definition {
config::osd::CURRENT_LAYOUT,
"Show Screen Layout",
nullptr,
"Enable to show which screen layout within the configured sequence is active.",
nullptr,
config::osd::CATEGORY,
{
{melonds::config::values::ENABLED, nullptr},
{melonds::config::values::DISABLED, nullptr},
{nullptr, nullptr},
},
melonds::config::values::ENABLED
},
retro_core_option_v2_definition {
config::osd::MIC_STATE,
"Show Host Microphone State",
nullptr,
"Enable to show whether your device's microphone is active.",
nullptr,
config::osd::CATEGORY,
{
{melonds::config::values::ENABLED, nullptr},
{melonds::config::values::DISABLED, nullptr},
{nullptr, nullptr},
},
melonds::config::values::ENABLED
},
retro_core_option_v2_definition {
config::osd::CAMERA_STATE,
"Show Host Camera State",
nullptr,
"Enable to show whether your device's camera is active.",
nullptr,
config::osd::CATEGORY,
{
{melonds::config::values::ENABLED, nullptr},
{melonds::config::values::DISABLED, nullptr},
{nullptr, nullptr},
},
melonds::config::values::ENABLED
},
retro_core_option_v2_definition {
config::osd::LID_STATE,
"Show Lid State",
nullptr,
"Enable to show whether the emulated screens are closed.",
nullptr,
config::osd::CATEGORY,
{
{melonds::config::values::ENABLED, nullptr},
{melonds::config::values::DISABLED, nullptr},
{nullptr, nullptr},
},
melonds::config::values::ENABLED
},
#ifndef NDEBUG
retro_core_option_v2_definition {
config::osd::POINTER_COORDINATES,
"Show Pointer Coordinates",
nullptr,
"Enable to display the coordinates of the pointer within the touch screen. "
"Used for debugging. "
"Leave disabled if unsure.",
nullptr,
config::osd::CATEGORY,
{
{melonds::config::values::ENABLED, nullptr},
{melonds::config::values::DISABLED, nullptr},
{nullptr, nullptr},
},
melonds::config::values::DISABLED
},
#endif
};
}
#endif //MELONDS_DS_OSD_HPP

View File

@ -203,20 +203,6 @@ void melonds::InputState::Update(const ScreenLayoutData& screen_layout_data) noe
touch = screen_layout_data.TransformPointerInput(pointerInput);
hybridTouch = screen_layout_data.TransformPointerInputToHybridScreen(pointerInput);
// TODO: Re-add this later when I add support for toggling it
// char text[1024];
// snprintf(text, sizeof(text), "Pointer: (%d, %d) -> (%d, %d)", pointerInput.x, pointerInput.y, touch.x, touch.y);
// retro_message_ext message{
// .msg = text,
// .duration = 60,
// .priority = 0,
// .level = RETRO_LOG_DEBUG,
// .target = RETRO_MESSAGE_TARGET_OSD,
// .type = RETRO_MESSAGE_TYPE_STATUS,
// .progress = -1
// };
// retro::set_message(&message);
}
if (cursorMode == CursorMode::Timeout) {

View File

@ -36,6 +36,7 @@ namespace melonds {
[[nodiscard]] int TouchX() const noexcept { return touch.x; }
[[nodiscard]] int TouchY() const noexcept { return touch.y; }
[[nodiscard]] glm::ivec2 TouchPosition() const noexcept { return touch; }
[[nodiscard]] glm::i16vec2 PointerInput() const noexcept { return pointerInput; }
[[nodiscard]] glm::ivec2 HybridTouchPosition() const noexcept { return hybridTouch; }
[[nodiscard]] bool CycleLayoutDown() const noexcept { return cycleLayoutButton; }
[[nodiscard]] bool CycleLayoutPressed() const noexcept { return cycleLayoutButton && !previousCycleLayoutButton; }

View File

@ -115,6 +115,7 @@ namespace melonds {
{
return isInDeinit;
}
retro::task::TaskSpec OnScreenDisplayTask() noexcept;
}
PUBLIC_SYMBOL void retro_init(void) {
@ -571,6 +572,8 @@ static void melonds::load_games(
retro::task::push(melonds::power::PowerStatusUpdateTask());
}
retro::task::push(melonds::OnScreenDisplayTask());
using retro::environment;
using retro::log;
using retro::set_message;
@ -805,8 +808,87 @@ static void melonds::ValidateFirmware() {
if (!memcmp(chk1, chk2, 0x180))
{
retro::set_warn_message("You're using a hacked firmware dump.\n"
"Firmware boot will stop working if you run any game that alters WFC settings.\n\n"
"(This would also happen on real hardware.)");
constexpr const char* const WARNING_MESSAGE =
"You're using a hacked firmware dump.\n"
"Firmware boot will stop working if you run any game that alters WFC settings.\n"
"(This would also happen on real hardware.)";
if (config::osd::ShowBiosWarnings()) {
retro::set_warn_message(WARNING_MESSAGE);
} else {
retro::warn(WARNING_MESSAGE);
}
}
}
retro::task::TaskSpec melonds::OnScreenDisplayTask() noexcept {
return retro::task::TaskSpec([](retro::task::TaskHandle& handle) {
using std::to_string;
ZoneScopedN("melonds::OnScreenDisplayTask");
constexpr const char* const OSD_DELIMITER = " || ";
constexpr const char* const OSD_YES = "";
constexpr const char* const OSD_NO = "";
if (handle.IsCancelled()) {
handle.Finish();
return;
}
std::string text;
text.reserve(1024);
if (config::osd::ShowPointerCoordinates()) {
glm::i16vec2 pointerInput = input_state.PointerInput();
glm::ivec2 touch = input_state.TouchPosition();
text += "Pointer: (" + to_string(pointerInput.x) + ", " + to_string(pointerInput.y) + ") → (" + to_string(touch.x) + ", " + to_string(touch.y) + ")";
}
if (config::osd::ShowMicState()) {
optional<bool> mic_state = retro::microphone::get_state();
if (mic_state && *mic_state) {
// If the microphone is open and turned on...
if (!text.empty()) {
text += OSD_DELIMITER;
}
// Toggle between a filled circle and an empty one every 1.5 seconds
// (kind of like a blinking "recording" light)
text += (NDS::NumFrames % 120 > 60) ? "" : "";
}
}
if (config::osd::ShowCurrentLayout()) {
if (!text.empty()) {
text += OSD_DELIMITER;
}
unsigned layout = screenLayout.LayoutIndex();
unsigned numberOfLayouts = screenLayout.NumberOfLayouts();
text += "Layout " + to_string(layout + 1) + "/" + to_string(numberOfLayouts);
}
if (config::osd::ShowLidState() && NDS::IsLidClosed()) {
if (!text.empty()) {
text += OSD_DELIMITER;
}
text += "Closed";
}
if (!text.empty()) {
retro_message_ext message {
.msg = text.c_str(),
.duration = 60,
.priority = 0,
.level = RETRO_LOG_DEBUG,
.target = RETRO_MESSAGE_TARGET_OSD,
.type = RETRO_MESSAGE_TYPE_STATUS,
.progress = -1
};
retro::set_message(&message);
}
});
}

View File

@ -17,6 +17,7 @@
#include <Platform.h>
#include <NDS.h>
#include "../environment.hpp"
#include "../config.hpp"
//! Local multiplayer is not implemented in melonDS DS.
@ -35,7 +36,9 @@ void Platform::MP_Begin() {
// The DS may turn on the radio immediately after booting,
// but we only want to alert the user of this incompatibility
// when they actually try to play a local multiplayer game.
retro::set_warn_message("melonDS DS does not support local multiplayer.");
if (melonds::config::osd::ShowUnsupportedFeatureWarnings()) {
retro::set_warn_message("melonDS DS does not support local multiplayer.");
}
_hasUnsupportedMessageBeenShown = true;
}
}