From 36be56647f788e4ced97d8b883e4ef76dd3c63b2 Mon Sep 17 00:00:00 2001 From: ITotalJustice <47043333+ITotalJustice@users.noreply.github.com> Date: Wed, 30 Apr 2025 17:05:44 +0100 Subject: [PATCH] Revert "remove IRS menu" This reverts commit 1dafa2748c235e6930180769bad9860b5c7a033a. --- sphaira/CMakeLists.txt | 1 + sphaira/include/ui/menus/irs_menu.hpp | 67 ++++ sphaira/source/app.cpp | 5 + sphaira/source/ui/menus/irs_menu.cpp | 533 ++++++++++++++++++++++++++ sphaira/source/ui/menus/main_menu.cpp | 1 + 5 files changed, 607 insertions(+) create mode 100644 sphaira/include/ui/menus/irs_menu.hpp create mode 100644 sphaira/source/ui/menus/irs_menu.cpp diff --git a/sphaira/CMakeLists.txt b/sphaira/CMakeLists.txt index 8ab056b..3a779d4 100644 --- a/sphaira/CMakeLists.txt +++ b/sphaira/CMakeLists.txt @@ -41,6 +41,7 @@ add_executable(sphaira source/ui/menus/file_viewer.cpp source/ui/menus/filebrowser.cpp source/ui/menus/homebrew.cpp + source/ui/menus/irs_menu.cpp source/ui/menus/main_menu.cpp source/ui/menus/menu_base.cpp source/ui/menus/themezer.cpp diff --git a/sphaira/include/ui/menus/irs_menu.hpp b/sphaira/include/ui/menus/irs_menu.hpp new file mode 100644 index 0000000..12aed89 --- /dev/null +++ b/sphaira/include/ui/menus/irs_menu.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include "ui/menus/menu_base.hpp" +#include + +namespace sphaira::ui::menu::irs { + +enum Rotation { + Rotation_0, + Rotation_90, + Rotation_180, + Rotation_270, +}; + +enum Colour { + Colour_Grey, + Colour_Ironbow, + Colour_Green, + Colour_Red, + Colour_Blue, +}; + +struct Entry { + IrsIrCameraHandle m_handle{}; + IrsIrCameraStatus status{}; + bool m_update_needed{}; +}; + +struct Menu final : MenuBase { + Menu(); + ~Menu(); + + void Update(Controller* controller, TouchInfo* touch) override; + void Draw(NVGcontext* vg, Theme* theme) override; + void OnFocusGained() override; + + void PollCameraStatus(bool statup = false); + void LoadDefaultConfig(); + void UpdateConfig(const IrsImageTransferProcessorExConfig* config); + void ResetImage(); + void UpdateImage(); + void updateColourArray(); + +private: + Result m_init_rc{}; + + IrsImageTransferProcessorExConfig m_config{}; + IrsMomentProcessorConfig m_moment_config{}; + IrsClusteringProcessorConfig m_clustering_config{}; + IrsTeraPluginProcessorConfig m_tera_config{}; + IrsIrLedProcessorConfig m_led_config{}; + IrsAdaptiveClusteringProcessorConfig m_adaptive_config{}; + IrsHandAnalysisConfig m_hand_config{}; + + Entry m_entries[IRS_MAX_CAMERAS]{}; + u32 m_irs_width{}; + u32 m_irs_height{}; + std::vector m_rgba{}; + std::vector m_irs_buffer{}; + IrsImageTransferProcessorState m_prev_state{}; + Rotation m_rotation{Rotation_90}; + Colour m_colour{Colour_Grey}; + int m_image{}; + s64 m_index{}; +}; + +} // namespace sphaira::ui::menu::irs diff --git a/sphaira/source/app.cpp b/sphaira/source/app.cpp index ddafed7..91f9f77 100644 --- a/sphaira/source/app.cpp +++ b/sphaira/source/app.cpp @@ -7,6 +7,7 @@ #include "ui/error_box.hpp" #include "ui/menus/main_menu.hpp" +#include "ui/menus/irs_menu.hpp" #include "ui/menus/themezer.hpp" #include "ui/menus/ghdl.hpp" #include "ui/menus/usb_menu.hpp" @@ -1540,6 +1541,10 @@ void App::DisplayMiscOptions(bool left_side) { App::Push(std::make_shared()); })); } + + options->Add(std::make_shared("Irs (Infrared Joycon Camera)"_i18n, [](){ + App::Push(std::make_shared()); + })); } void App::DisplayAdvancedOptions(bool left_side) { diff --git a/sphaira/source/ui/menus/irs_menu.cpp b/sphaira/source/ui/menus/irs_menu.cpp new file mode 100644 index 0000000..baf910e --- /dev/null +++ b/sphaira/source/ui/menus/irs_menu.cpp @@ -0,0 +1,533 @@ +#include "ui/menus/irs_menu.hpp" +#include "ui/sidebar.hpp" +#include "ui/popup_list.hpp" +#include "app.hpp" +#include "defines.hpp" +#include "log.hpp" +#include "ui/nvg_util.hpp" +#include "i18n.hpp" +#include +#include + +namespace sphaira::ui::menu::irs { +namespace { + +// from trial and error +constexpr u32 GAIN_MIN = 1; +constexpr u32 GAIN_MAX = 16; + +consteval auto generte_iron_palette_table() { + std::array array{}; + + const u32 iron_palette[] = { + 0xff000014, 0xff000025, 0xff00002a, 0xff000032, 0xff000036, 0xff00003e, 0xff000042, 0xff00004f, + 0xff010055, 0xff010057, 0xff02005c, 0xff03005e, 0xff040063, 0xff050065, 0xff070069, 0xff0a0070, + 0xff0b0073, 0xff0d0075, 0xff0d0076, 0xff100078, 0xff120079, 0xff15007c, 0xff17007d, 0xff1c0081, + 0xff200084, 0xff220085, 0xff260087, 0xff280089, 0xff2c008a, 0xff2e008b, 0xff32008d, 0xff38008f, + 0xff390090, 0xff3c0092, 0xff3e0093, 0xff410094, 0xff420095, 0xff450096, 0xff470096, 0xff4c0097, + 0xff4f0097, 0xff510097, 0xff540098, 0xff560098, 0xff5a0099, 0xff5c0099, 0xff5f009a, 0xff64009b, + 0xff66009b, 0xff6a009b, 0xff6c009c, 0xff6f009c, 0xff70009c, 0xff73009d, 0xff75009d, 0xff7a009d, + 0xff7e009d, 0xff7f009d, 0xff83009d, 0xff84009d, 0xff87009d, 0xff89009d, 0xff8b009d, 0xff91009c, + 0xff93009c, 0xff96009b, 0xff98009b, 0xff9b009b, 0xff9c009b, 0xff9f009b, 0xffa0009b, 0xffa4009b, + 0xffa7009a, 0xffa8009a, 0xffaa0099, 0xffab0099, 0xffae0198, 0xffaf0198, 0xffb00198, 0xffb30196, + 0xffb40296, 0xffb60295, 0xffb70395, 0xffb90495, 0xffba0495, 0xffbb0593, 0xffbc0593, 0xffbf0692, + 0xffc00791, 0xffc00791, 0xffc10990, 0xffc20a8f, 0xffc30b8e, 0xffc40c8d, 0xffc60d8b, 0xffc81088, + 0xffc91187, 0xffca1385, 0xffcb1385, 0xffcc1582, 0xffcd1681, 0xffce187e, 0xffcf187c, 0xffd11b78, + 0xffd21c75, 0xffd21d74, 0xffd32071, 0xffd4216f, 0xffd5236b, 0xffd52469, 0xffd72665, 0xffd92a60, + 0xffda2b5e, 0xffdb2e5a, 0xffdb2f57, 0xffdd3051, 0xffdd314e, 0xffde3347, 0xffdf3444, 0xffe0373a, + 0xffe03933, 0xffe13a30, 0xffe23c2a, 0xffe33d26, 0xffe43f20, 0xffe4411d, 0xffe5431b, 0xffe64616, + 0xffe74715, 0xffe74913, 0xffe84a12, 0xffe84c0f, 0xffe94d0e, 0xffea4e0c, 0xffea4f0c, 0xffeb520a, + 0xffec5409, 0xffec5608, 0xffec5808, 0xffed5907, 0xffed5b06, 0xffee5c06, 0xffee5d05, 0xffef6004, + 0xffef6104, 0xfff06303, 0xfff06403, 0xfff16603, 0xfff16603, 0xfff16803, 0xfff16902, 0xfff16b02, + 0xfff26d01, 0xfff26e01, 0xfff37001, 0xfff37101, 0xfff47300, 0xfff47400, 0xfff47600, 0xfff47a00, + 0xfff57b00, 0xfff57e00, 0xfff57f00, 0xfff68100, 0xfff68200, 0xfff78400, 0xfff78500, 0xfff88800, + 0xfff88900, 0xfff88a00, 0xfff88c00, 0xfff98d00, 0xfff98e00, 0xfff98f00, 0xfff99100, 0xfffa9400, + 0xfffa9500, 0xfffb9800, 0xfffb9900, 0xfffb9c00, 0xfffc9d00, 0xfffca000, 0xfffca100, 0xfffda400, + 0xfffda700, 0xfffda800, 0xfffdab00, 0xfffdac00, 0xfffdae00, 0xfffeaf00, 0xfffeb100, 0xfffeb400, + 0xfffeb500, 0xfffeb800, 0xfffeb900, 0xfffeba00, 0xfffebb00, 0xfffebd00, 0xfffebe00, 0xfffec200, + 0xfffec400, 0xfffec500, 0xfffec700, 0xfffec800, 0xfffeca01, 0xfffeca01, 0xfffecc02, 0xfffecf04, + 0xfffecf04, 0xfffed106, 0xfffed308, 0xfffed50a, 0xfffed60a, 0xfffed80c, 0xfffed90d, 0xffffdb10, + 0xffffdc14, 0xffffdd16, 0xffffde1b, 0xffffdf1e, 0xffffe122, 0xffffe224, 0xffffe328, 0xffffe531, + 0xffffe635, 0xffffe73c, 0xffffe83f, 0xffffea46, 0xffffeb49, 0xffffec50, 0xffffed54, 0xffffee5f, + 0xffffef67, 0xfffff06a, 0xfffff172, 0xfffff177, 0xfffff280, 0xfffff285, 0xfffff38e, 0xfffff49a, + 0xfffff59e, 0xfffff5a6, 0xfffff6aa, 0xfffff7b3, 0xfffff7b6, 0xfffff8bd, 0xfffff8c1, 0xfffff9ca, + 0xfffffad1, 0xfffffad4, 0xfffffcdb, 0xfffffcdf, 0xfffffde5, 0xfffffde8, 0xfffffeee, 0xfffffff6 + }; + + for (u32 i = 0; i < 256; i++) { + const auto c = iron_palette[i]; + array[i] = RGBA8_MAXALPHA((c >> 16) & 0xFF, (c >> 8) & 0xFF, (c >> 0) & 0xFF); + } + + return array; +} + +// ARGB Ironbow palette +constexpr auto iron_palette = generte_iron_palette_table(); + +void irsConvertConfigExToNormal(const IrsImageTransferProcessorExConfig* ex, IrsImageTransferProcessorConfig* nor) { + std::memcpy(nor, ex, sizeof(*nor)); +} + +void irsConvertConfigNormalToEx(const IrsImageTransferProcessorConfig* nor, IrsImageTransferProcessorExConfig* ex) { + std::memcpy(ex, nor, sizeof(*nor)); +} + +} // namespace + +Menu::Menu() : MenuBase{"Irs"_i18n} { + SetAction(Button::B, Action{"Back"_i18n, [this](){ + SetPop(); + }}); + + SetAction(Button::X, Action{"Options"_i18n, [this](){ + auto options = std::make_shared("Options"_i18n, Sidebar::Side::RIGHT); + ON_SCOPE_EXIT(App::Push(options)); + + SidebarEntryArray::Items controller_str; + for (u32 i = 0; i < IRS_MAX_CAMERAS; i++) { + const auto& e = m_entries[i]; + std::string text = "Pad "_i18n + (i == 8 ? "HandHeld"_i18n : std::to_string(i)); + switch (e.status) { + case IrsIrCameraStatus_Available: + text += " (Available)"_i18n; + break; + case IrsIrCameraStatus_Unsupported: + text += " (Unsupported)"_i18n; + break; + case IrsIrCameraStatus_Unconnected: + text += " (Unconnected)"_i18n; + break; + } + controller_str.emplace_back(text); + } + + SidebarEntryArray::Items rotation_str; + rotation_str.emplace_back("0 (Sideways)"_i18n); + rotation_str.emplace_back("90 (Flat)"_i18n); + rotation_str.emplace_back("180 (-Sideways)"_i18n); + rotation_str.emplace_back("270 (Upside down)"_i18n); + + SidebarEntryArray::Items colour_str; + colour_str.emplace_back("Grey"_i18n); + colour_str.emplace_back("Ironbow"_i18n); + colour_str.emplace_back("Green"_i18n); + colour_str.emplace_back("Red"_i18n); + colour_str.emplace_back("Blue"_i18n); + + SidebarEntryArray::Items light_target_str; + light_target_str.emplace_back("All leds"_i18n); + light_target_str.emplace_back("Bright group"_i18n); + light_target_str.emplace_back("Dim group"_i18n); + light_target_str.emplace_back("None"_i18n); + + SidebarEntryArray::Items gain_str; + for (u32 i = GAIN_MIN; i <= GAIN_MAX; i++) { + gain_str.emplace_back(std::to_string(i)); + } + + SidebarEntryArray::Items is_negative_image_used_str; + is_negative_image_used_str.emplace_back("Normal image"_i18n); + is_negative_image_used_str.emplace_back("Negative image"_i18n); + + SidebarEntryArray::Items format_str; + format_str.emplace_back("320x240"_i18n); + format_str.emplace_back("160x120"_i18n); + format_str.emplace_back("80x60"_i18n); + if (hosversionAtLeast(4,0,0)) { + format_str.emplace_back("40x30"_i18n); + format_str.emplace_back("20x15"_i18n); + } + + options->Add(std::make_shared("Controller"_i18n, controller_str, [this](s64& index){ + irsStopImageProcessor(m_entries[m_index].m_handle); + m_index = index; + UpdateConfig(&m_config); + }, m_index)); + + options->Add(std::make_shared("Rotation"_i18n, rotation_str, [this](s64& index){ + m_rotation = (Rotation)index; + }, m_rotation)); + + options->Add(std::make_shared("Colour"_i18n, colour_str, [this](s64& index){ + m_colour = (Colour)index; + updateColourArray(); + }, m_colour)); + + options->Add(std::make_shared("Light Target"_i18n, light_target_str, [this](s64& index){ + m_config.light_target = index; + UpdateConfig(&m_config); + }, m_config.light_target)); + + options->Add(std::make_shared("Gain"_i18n, gain_str, [this](s64& index){ + m_config.gain = GAIN_MIN + index; + UpdateConfig(&m_config); + }, m_config.gain - GAIN_MIN)); + + options->Add(std::make_shared("Negative Image"_i18n, is_negative_image_used_str, [this](s64& index){ + m_config.is_negative_image_used = index; + UpdateConfig(&m_config); + }, m_config.is_negative_image_used)); + + options->Add(std::make_shared("Format"_i18n, format_str, [this](s64& index){ + m_config.orig_format = index; + m_config.trimming_format = index; + UpdateConfig(&m_config); + }, m_config.orig_format)); + + if (hosversionAtLeast(4,0,0)) { + options->Add(std::make_shared("Trimming Format"_i18n, format_str, [this](s64& index){ + // you cannot set trim a larger region than the source + if (index < m_config.orig_format) { + index = m_config.orig_format; + } else { + m_config.trimming_format = index; + UpdateConfig(&m_config); + } + }, m_config.orig_format)); + + options->Add(std::make_shared("External Light Filter"_i18n, m_config.is_external_light_filter_enabled, [this](bool& enable){ + m_config.is_external_light_filter_enabled = enable; + UpdateConfig(&m_config); + }, "Enabled"_i18n, "Disabled"_i18n)); + } + + options->Add(std::make_shared("Load Default"_i18n, [this](){ + LoadDefaultConfig(); + }, true)); + }}); + + if (R_FAILED(m_init_rc = irsInitialize())) { + return; + } + + static_assert(IRS_MAX_CAMERAS >= 9, "max camaeras has gotten smaller!"); + + // open all handles + irsGetIrCameraHandle(&m_entries[0].m_handle, HidNpadIdType_No1); + irsGetIrCameraHandle(&m_entries[1].m_handle, HidNpadIdType_No2); + irsGetIrCameraHandle(&m_entries[2].m_handle, HidNpadIdType_No3); + irsGetIrCameraHandle(&m_entries[3].m_handle, HidNpadIdType_No4); + irsGetIrCameraHandle(&m_entries[4].m_handle, HidNpadIdType_No5); + irsGetIrCameraHandle(&m_entries[5].m_handle, HidNpadIdType_No6); + irsGetIrCameraHandle(&m_entries[6].m_handle, HidNpadIdType_No7); + irsGetIrCameraHandle(&m_entries[7].m_handle, HidNpadIdType_No8); + irsGetIrCameraHandle(&m_entries[8].m_handle, HidNpadIdType_Handheld); + // get status of all handles + PollCameraStatus(true); + // load default config + LoadDefaultConfig(); +} + +Menu::~Menu() { + ResetImage(); + + for (auto& e : m_entries) { + irsStopImageProcessor(e.m_handle); + } + + // this closes all handles + irsExit(); +} + +void Menu::Update(Controller* controller, TouchInfo* touch) { + MenuBase::Update(controller, touch); + PollCameraStatus(); +} + +void Menu::Draw(NVGcontext* vg, Theme* theme) { + MenuBase::Draw(vg, theme); + + IrsImageTransferProcessorState state; + const auto rc = irsGetImageTransferProcessorState(m_entries[m_index].m_handle, m_irs_buffer.data(), m_irs_buffer.size(), &state); + if (R_SUCCEEDED(rc) && state.sampling_number != m_prev_state.sampling_number) { + m_prev_state = state; + SetSubHeading("Ambient Noise Level: "_i18n + std::to_string(m_prev_state.ambient_noise_level)); + updateColourArray(); + } + + if (m_image) { + float cx{}, cy{}; + float w{}, h{}; + float angle{}; + + switch (m_rotation) { + case Rotation_0: { + const auto scale_x = m_pos.w / float(m_irs_width); + const auto scale_y = m_pos.h / float(m_irs_height); + const auto scale = std::min(scale_x, scale_y); + w = m_irs_width * scale; + h = m_irs_height * scale; + cx = (m_pos.x + m_pos.w / 2.F) - w / 2.F; + cy = (m_pos.y + m_pos.h / 2.F) - h / 2.F; + angle = 0; + } break; + case Rotation_90: { + const auto scale_x = m_pos.w / float(m_irs_height); + const auto scale_y = m_pos.h / float(m_irs_width); + const auto scale = std::min(scale_x, scale_y); + w = m_irs_width * scale; + h = m_irs_height * scale; + cx = (m_pos.x + m_pos.w / 2.F) + h / 2.F; + cy = (m_pos.y + m_pos.h / 2.F) - w / 2.F; + angle = 90; + } break; + case Rotation_180: { + const auto scale_x = m_pos.w / float(m_irs_width); + const auto scale_y = m_pos.h / float(m_irs_height); + const auto scale = std::min(scale_x, scale_y); + w = m_irs_width * scale; + h = m_irs_height * scale; + cx = (m_pos.x + m_pos.w / 2.F) + w / 2.F; + cy = (m_pos.y + m_pos.h / 2.F) + h / 2.F; + angle = 180; + } break; + case Rotation_270: { + const auto scale_x = m_pos.w / float(m_irs_height); + const auto scale_y = m_pos.h / float(m_irs_width); + const auto scale = std::min(scale_x, scale_y); + w = m_irs_width * scale; + h = m_irs_height * scale; + cx = (m_pos.x + m_pos.w / 2.F) - h / 2.F; + cy = (m_pos.y + m_pos.h / 2.F) + w / 2.F; + angle = 270; + } break; + } + + nvgSave(vg); + nvgTranslate(vg, cx, cy); + const auto paint = nvgImagePattern(vg, 0, 0, w, h, 0, m_image, 1.f); + nvgRotate(vg, nvgDegToRad(angle)); + nvgBeginPath(vg); + nvgRect(vg, 0, 0, w, h); + nvgFillPaint(vg, paint); + nvgFill(vg); + nvgRestore(vg); + } +} + +void Menu::OnFocusGained() { + MenuBase::OnFocusGained(); +} + +void Menu::PollCameraStatus(bool statup) { + int index = 0; + for (auto& e : m_entries) { + IrsIrCameraStatus status; + if (R_FAILED(irsGetIrCameraStatus(e.m_handle, &status))) { + log_write("failed to get ir status\n"); + continue; + } + + if (e.status != status || statup) { + e.status = status; + e.m_update_needed = false; + + log_write("status changed\n"); + switch (e.status) { + case IrsIrCameraStatus_Available: + if (hosversionAtLeast(4,0,0)) { + // calling this breaks the handle, kinda + #if 0 + if (R_FAILED(irsCheckFirmwareUpdateNecessity(e.m_handle, &e.m_update_needed))) { + log_write("failed to check if update needed: %u\n", e.m_update_needed); + } else { + if (e.m_update_needed) { + log_write("update needed\n"); + } else { + log_write("no update needed\n"); + } + } + #endif + } + log_write("irs index: %d status: IrsIrCameraStatus_Available\n", index); + break; + case IrsIrCameraStatus_Unsupported: + log_write("irs index: %d status: IrsIrCameraStatus_Unsupported\n", index); + break; + case IrsIrCameraStatus_Unconnected: + log_write("irs index: %d status: IrsIrCameraStatus_Unconnected\n", index); + break; + } + } + + index++; + } +} + +void Menu::ResetImage() { + if (m_image) { + nvgDeleteImage(App::GetVg(), m_image); + m_image = 0; + } +} + +void Menu::UpdateImage() { + ResetImage(); + m_image = nvgCreateImageRGBA(App::GetVg(), m_irs_width, m_irs_height, NVG_IMAGE_NEAREST, (const unsigned char*)m_rgba.data()); +} + +void Menu::LoadDefaultConfig() { + IrsImageTransferProcessorExConfig ex_config; + + if (hosversionAtLeast(4,0,0)) { + irsGetDefaultImageTransferProcessorExConfig(&ex_config); + } else { + IrsImageTransferProcessorConfig nor_config; + irsGetDefaultImageTransferProcessorConfig(&nor_config); + irsConvertConfigNormalToEx(&nor_config, &ex_config); + } + + irsGetMomentProcessorDefaultConfig(&m_moment_config); + irsGetClusteringProcessorDefaultConfig(&m_clustering_config); + irsGetIrLedProcessorDefaultConfig(&m_led_config); + + m_tera_config = {}; + m_adaptive_config = {}; + m_hand_config = {}; + + UpdateConfig(&ex_config); +} + +void Menu::UpdateConfig(const IrsImageTransferProcessorExConfig* config) { + m_config = *config; + irsStopImageProcessor(m_entries[m_index].m_handle); + + if (R_FAILED(irsRunMomentProcessor(m_entries[m_index].m_handle, &m_moment_config))) { + log_write("failed to irsRunMomentProcessor\n"); + } else { + log_write("did irsRunMomentProcessor\n"); + } + + if (R_FAILED(irsRunClusteringProcessor(m_entries[m_index].m_handle, &m_clustering_config))) { + log_write("failed to irsRunClusteringProcessor\n"); + } else { + log_write("did irsRunClusteringProcessor\n"); + } + + if (R_FAILED(irsRunPointingProcessor(m_entries[m_index].m_handle))) { + log_write("failed to irsRunPointingProcessor\n"); + } else { + log_write("did irsRunPointingProcessor\n"); + } + + if (R_FAILED(irsRunTeraPluginProcessor(m_entries[m_index].m_handle, &m_tera_config))) { + log_write("failed to irsRunTeraPluginProcessor\n"); + } else { + log_write("did irsRunTeraPluginProcessor\n"); + } + + if (R_FAILED(irsRunIrLedProcessor(m_entries[m_index].m_handle, &m_led_config))) { + log_write("failed to irsRunIrLedProcessor\n"); + } else { + log_write("did irsRunIrLedProcessor\n"); + } + + if (R_FAILED(irsRunAdaptiveClusteringProcessor(m_entries[m_index].m_handle, &m_adaptive_config))) { + log_write("failed to irsRunAdaptiveClusteringProcessor\n"); + } else { + log_write("did irsRunAdaptiveClusteringProcessor\n"); + } + + if (R_FAILED(irsRunHandAnalysis(m_entries[m_index].m_handle, &m_hand_config))) { + log_write("failed to irsRunHandAnalysis\n"); + } else { + log_write("did irsRunHandAnalysis\n"); + } + + if (hosversionAtLeast(4,0,0)) { + m_init_rc = irsRunImageTransferExProcessor(m_entries[m_index].m_handle, &m_config, 0x10000000); + } else { + IrsImageTransferProcessorConfig nor; + irsConvertConfigExToNormal(&m_config, &nor); + m_init_rc = irsRunImageTransferProcessor(m_entries[m_index].m_handle, &nor, 0x10000000); + } + + if (R_FAILED(m_init_rc)) { + log_write("irs failed to set config!\n"); + } + + auto format = m_config.orig_format; + log_write("IRS CONFIG\n"); + log_write("\texposure_time: %lu\n", m_config.exposure_time); + log_write("\tlight_target: %u\n", m_config.light_target); + log_write("\tgain: %u\n", m_config.gain); + log_write("\tis_negative_image_used: %u\n", m_config.is_negative_image_used); + log_write("\tlight_target: %u\n", m_config.light_target); + if (hosversionAtLeast(4,0,0)) { + format = m_config.trimming_format; + log_write("\ttrimming_format: %u\n", m_config.trimming_format); + log_write("\ttrimming_start_x: %u\n", m_config.trimming_start_x); + log_write("\ttrimming_start_y: %u\n", m_config.trimming_start_y); + log_write("\tis_external_light_filter_enabled: %u\n", m_config.is_external_light_filter_enabled); + } + + switch (format) { + case IrsImageTransferProcessorFormat_320x240: + log_write("\tsetting format: %s\n", "IrsImageTransferProcessorFormat_320x240"); + m_irs_width = 320; + m_irs_height = 240; + break; + case IrsImageTransferProcessorFormat_160x120: + log_write("\tsetting format: %s\n", "IrsImageTransferProcessorFormat_160x120"); + m_irs_width = 160; + m_irs_height = 120; + break; + case IrsImageTransferProcessorFormat_80x60: + log_write("\tsetting format: %s\n", "IrsImageTransferProcessorFormat_80x60"); + m_irs_width = 80; + m_irs_height = 60; + break; + case IrsImageTransferProcessorFormat_40x30: + log_write("\tsetting format: %s\n", "IrsImageTransferProcessorFormat_40x30"); + m_irs_width = 40; + m_irs_height = 30; + break; + case IrsImageTransferProcessorFormat_20x15: + log_write("\tsetting format: %s\n", "IrsImageTransferProcessorFormat_20x15"); + m_irs_width = 20; + m_irs_height = 15; + break; + } + + m_rgba.resize(m_irs_width * m_irs_height); + m_irs_buffer.resize(m_irs_width * m_irs_height); + m_prev_state.sampling_number = UINT64_MAX; + std::fill(m_irs_buffer.begin(), m_irs_buffer.end(), 0); + updateColourArray(); +} + +void Menu::updateColourArray() { + const auto ir_width = m_irs_width; + const auto ir_height = m_irs_height; + const auto colour = m_colour; + + for (u32 y = 0; y < ir_height; y++) { + for (u32 x = 0; x < ir_width; x++) { + const u32 pos = y * ir_width + x; + const u32 pos2 = y * ir_width + x; + + switch (colour) { + case Colour_Grey: + m_rgba[pos] = RGBA8_MAXALPHA(m_irs_buffer[pos2], m_irs_buffer[pos2], m_irs_buffer[pos2]); + break; + case Colour_Ironbow: + m_rgba[pos] = iron_palette[m_irs_buffer[pos2]]; + break; + case Colour_Green: + m_rgba[pos] = RGBA8_MAXALPHA(0, m_irs_buffer[pos2], 0); + break; + case Colour_Red: + m_rgba[pos] = RGBA8_MAXALPHA(m_irs_buffer[pos2], 0, 0); + break; + case Colour_Blue: + m_rgba[pos] = RGBA8_MAXALPHA(0, 0, m_irs_buffer[pos2]); + break; + } + } + } + + UpdateImage(); +} + +} // namespace sphaira::ui::menu::irs diff --git a/sphaira/source/ui/menus/main_menu.cpp b/sphaira/source/ui/menus/main_menu.cpp index 1940d71..7c94393 100644 --- a/sphaira/source/ui/menus/main_menu.cpp +++ b/sphaira/source/ui/menus/main_menu.cpp @@ -11,6 +11,7 @@ #include "download.hpp" #include "defines.hpp" #include "i18n.hpp" +#include "ui/menus/usb_menu.hpp" #include #include