From 9843ecf116bc102e8847edea9ec667b77e30bf8b Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Tue, 13 Jan 2026 13:28:21 +0100 Subject: [PATCH] Implement partner CTR menu --- CMakeLists.txt | 2 +- .../cypress_partner_ctr_acquisition.hpp | 1 + include/Menus/MainMenu.hpp | 1 + include/Menus/PartnerCTRMenu.hpp | 41 +++++ include/capture_structs.hpp | 7 +- include/display_structs.hpp | 2 +- include/frontend.hpp | 7 + .../usb_is_twl_acquisition_capture.cpp | 8 +- .../cypress_partner_ctr_acquisition.cpp | 109 ++++++++++++- source/Menus/ISNitroMenu.cpp | 4 +- source/Menus/MainMenu.cpp | 13 ++ source/Menus/PartnerCTRMenu.cpp | 143 ++++++++++++++++++ source/WindowScreen_Menu.cpp | 90 +++++++++-- source/cc3dsfs.cpp | 47 ++++-- source/frontend.cpp | 2 +- 15 files changed, 442 insertions(+), 35 deletions(-) create mode 100644 include/Menus/PartnerCTRMenu.hpp create mode 100644 source/Menus/PartnerCTRMenu.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f08983..cae3478 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -526,7 +526,7 @@ else() set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "$<$:-O3;-funroll-loops>") endif() -set(EXECUTABLE_SOURCE_FILES source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/TextRectanglePool.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp source/Menus/AudioDeviceMenu.cpp source/Menus/SeparatorMenu.cpp source/Menus/ColorCorrectionMenu.cpp source/Menus/Main3DMenu.cpp source/Menus/SecondScreen3DRelativePositionMenu.cpp source/Menus/USBConflictResolutionMenu.cpp source/Menus/Optimize3DSMenu.cpp source/Menus/OptimizeSerialKeyAddMenu.cpp source/libgpiod_compat.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_add_table.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_next_char_table.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_prev_char_table.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/font_mono_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES}) +set(EXECUTABLE_SOURCE_FILES source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/TextRectanglePool.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/PartnerCTRMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp source/Menus/AudioDeviceMenu.cpp source/Menus/SeparatorMenu.cpp source/Menus/ColorCorrectionMenu.cpp source/Menus/Main3DMenu.cpp source/Menus/SecondScreen3DRelativePositionMenu.cpp source/Menus/USBConflictResolutionMenu.cpp source/Menus/Optimize3DSMenu.cpp source/Menus/OptimizeSerialKeyAddMenu.cpp source/libgpiod_compat.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_add_table.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_next_char_table.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_prev_char_table.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/font_mono_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES}) if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") add_compile_flag("SFML_SYSTEM_ANDROID") diff --git a/include/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.hpp b/include/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.hpp index b979ac7..9b484d8 100644 --- a/include/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.hpp +++ b/include/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.hpp @@ -25,6 +25,7 @@ uint64_t cypart_device_get_video_in_size(CaptureStatus* status, bool is_3d); uint64_t cypart_device_get_video_in_size(CaptureData* capture_data, bool is_3d); void cypart_device_acquisition_main_loop(CaptureData* capture_data); void usb_cypart_device_acquisition_cleanup(CaptureData* capture_data); +bool is_device_partner_ctr(CaptureDevice* device); void usb_cypart_device_init(); void usb_cypart_device_close(); diff --git a/include/Menus/MainMenu.hpp b/include/Menus/MainMenu.hpp index b71953c..ba7a610 100755 --- a/include/Menus/MainMenu.hpp +++ b/include/Menus/MainMenu.hpp @@ -28,6 +28,7 @@ enum MainMenuOutAction{ MAIN_MENU_ISN_SETTINGS, MAIN_MENU_IST_SETTINGS, MAIN_MENU_OPTIMIZE_3DS_SETTINGS, + MAIN_MENU_PARTNER_CTR_SETTINGS, MAIN_MENU_INPUT_SETTINGS, }; diff --git a/include/Menus/PartnerCTRMenu.hpp b/include/Menus/PartnerCTRMenu.hpp new file mode 100644 index 0000000..474c505 --- /dev/null +++ b/include/Menus/PartnerCTRMenu.hpp @@ -0,0 +1,41 @@ +#ifndef __PARTCTRMENU_HPP +#define __PARTCTRMENU_HPP + +#include "OptionSelectionMenu.hpp" +#include + +#include "TextRectangle.hpp" +#include "sfml_gfx_structs.hpp" +#include "display_structs.hpp" +#include "capture_structs.hpp" + +enum PartnerCTRMenuOutAction{ + PCTR_MENU_NO_ACTION, + PCTR_MENU_BACK, + PCTR_MENU_RESET, + PCTR_MENU_BATTERY_INC, + PCTR_MENU_BATTERY_DEC, + PCTR_MENU_AC_ADAPTER_CONNECTED_TOGGLE, + PCTR_MENU_AC_ADAPTER_CHARGING_TOGGLE, +}; + +class PartnerCTRMenu : public OptionSelectionMenu { +public: + PartnerCTRMenu(TextRectanglePool* text_pool); + ~PartnerCTRMenu(); + void prepare(float scaling_factor, int view_size_x, int view_size_y, CaptureStatus* capture_status); + void insert_data(CaptureDevice* device); + PartnerCTRMenuOutAction selected_index = PartnerCTRMenuOutAction::PCTR_MENU_NO_ACTION; + void reset_output_option(); +protected: + bool is_option_selectable(int index, int action); + bool is_option_inc_dec(int index); + void set_output_option(int index, int action); + size_t get_num_options(); + std::string get_string_option(int index, int action); + void class_setup(); +private: + int *options_indexes; + size_t num_enabled_options; +}; +#endif diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index e07d840..ca26fe0 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -371,8 +371,11 @@ struct CaptureStatus { bool key_updated = false; CaptureScreensType capture_type; CaptureSpeedsType capture_speed; - int battery_percentage; - bool ac_adapter_connected; + int is_battery_percentage; + bool is_ac_adapter_connected; + int partner_ctr_battery_percentage; + bool partner_ctr_ac_adapter_connected; + bool partner_ctr_ac_adapter_charging; // Needed for possible compatibility issues bool devices_allowed_scan[CC_POSSIBLE_DEVICES_END]; ConsumerMutex video_wait; diff --git a/include/display_structs.hpp b/include/display_structs.hpp index 4084583..523334c 100755 --- a/include/display_structs.hpp +++ b/include/display_structs.hpp @@ -26,7 +26,7 @@ enum ScreenType { TOP, BOTTOM, JOINT }; enum BottomRelativePosition { UNDER_TOP, LEFT_TOP, ABOVE_TOP, RIGHT_TOP, BOT_REL_POS_END }; enum SecondScreen3DRelativePosition { UNDER_FIRST, LEFT_FIRST, ABOVE_FIRST, RIGHT_FIRST, SECOND_SCREEN_3D_REL_POS_END }; enum NonIntegerScalingModes { SMALLER_PRIORITY, INVERSE_PROPORTIONAL_PRIORITY, EQUAL_PRIORITY, PROPORTIONAL_PRIORITY, BIGGER_PRIORITY, END_NONINT_SCALE_MODES }; -enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE, MAIN_MENU_TYPE, VIDEO_MENU_TYPE, AUDIO_MENU_TYPE, CROP_MENU_TYPE, TOP_PAR_MENU_TYPE, BOTTOM_PAR_MENU_TYPE, ROTATION_MENU_TYPE, OFFSET_MENU_TYPE, BFI_MENU_TYPE, LOAD_MENU_TYPE, SAVE_MENU_TYPE, RESOLUTION_MENU_TYPE, EXTRA_MENU_TYPE, STATUS_MENU_TYPE, LICENSES_MENU_TYPE, RELATIVE_POS_MENU_TYPE, SHORTCUTS_MENU_TYPE, ACTION_SELECTION_MENU_TYPE, SCALING_RATIO_MENU_TYPE, ISN_MENU_TYPE, VIDEO_EFFECTS_MENU_TYPE, INPUT_MENU_TYPE, AUDIO_DEVICE_MENU_TYPE, SEPARATOR_MENU_TYPE, COLOR_CORRECTION_MENU_TYPE, MAIN_3D_MENU_TYPE, SECOND_SCREEN_RELATIVE_POS_MENU_TYPE, USB_CONFLICT_RESOLUTION_MENU_TYPE, OPTIMIZE_3DS_MENU_TYPE, OPTIMIZE_SERIAL_KEY_ADD_MENU_TYPE, RECONNECT_MENU_TYPE }; +enum CurrMenuType { DEFAULT_MENU_TYPE, CONNECT_MENU_TYPE, MAIN_MENU_TYPE, VIDEO_MENU_TYPE, AUDIO_MENU_TYPE, CROP_MENU_TYPE, TOP_PAR_MENU_TYPE, BOTTOM_PAR_MENU_TYPE, ROTATION_MENU_TYPE, OFFSET_MENU_TYPE, BFI_MENU_TYPE, LOAD_MENU_TYPE, SAVE_MENU_TYPE, RESOLUTION_MENU_TYPE, EXTRA_MENU_TYPE, STATUS_MENU_TYPE, LICENSES_MENU_TYPE, RELATIVE_POS_MENU_TYPE, SHORTCUTS_MENU_TYPE, ACTION_SELECTION_MENU_TYPE, SCALING_RATIO_MENU_TYPE, ISN_MENU_TYPE, VIDEO_EFFECTS_MENU_TYPE, INPUT_MENU_TYPE, AUDIO_DEVICE_MENU_TYPE, SEPARATOR_MENU_TYPE, COLOR_CORRECTION_MENU_TYPE, MAIN_3D_MENU_TYPE, SECOND_SCREEN_RELATIVE_POS_MENU_TYPE, USB_CONFLICT_RESOLUTION_MENU_TYPE, OPTIMIZE_3DS_MENU_TYPE, OPTIMIZE_SERIAL_KEY_ADD_MENU_TYPE, RECONNECT_MENU_TYPE, PARTNER_CTR_MENU_TYPE }; enum InputColorspaceMode { FULL_COLORSPACE, DS_COLORSPACE, GBA_COLORSPACE, INPUT_COLORSPACE_END }; enum FrameBlendingMode { NO_FRAME_BLENDING, FULL_FRAME_BLENDING, DS_3D_BOTH_SCREENS_FRAME_BLENDING, FRAME_BLENDING_END }; diff --git a/include/frontend.hpp b/include/frontend.hpp index f020515..c4de0d6 100755 --- a/include/frontend.hpp +++ b/include/frontend.hpp @@ -32,6 +32,7 @@ #include "ActionSelectionMenu.hpp" #include "ScalingRatioMenu.hpp" #include "ISNitroMenu.hpp" +#include "PartnerCTRMenu.hpp" #include "VideoEffectsMenu.hpp" #include "InputMenu.hpp" #include "AudioDeviceMenu.hpp" @@ -191,6 +192,7 @@ private: ShortcutMenu *shortcut_menu; ActionSelectionMenu *action_selection_menu; ISNitroMenu *is_nitro_menu; + PartnerCTRMenu *partner_ctr_menu; ScalingRatioMenu *scaling_ratio_menu; VideoEffectsMenu *video_effects_menu; InputMenu *input_menu; @@ -299,8 +301,12 @@ private: void is_nitro_capture_type_change(bool positive); void is_nitro_capture_speed_change(bool positive); void is_nitro_capture_reset_hw(); + void generic_battery_change(bool positive, int &battery_percentage, const int *allowed_battery_levels, size_t num_levels); void is_nitro_battery_change(bool positive); void is_nitro_ac_adapter_change(); + void partner_ctr_battery_change(bool positive); + void partner_ctr_ac_adapter_connected_change(); + void partner_ctr_ac_adapter_charging_change(); void crop_value_change(int new_crop_value, bool do_print_notification = true, bool do_cycle = true); void par_value_change(int new_par_value, bool is_top); void offset_change(float &value, float change); @@ -408,6 +414,7 @@ private: void setup_relative_pos_menu(bool reset_data = true); void setup_scaling_ratio_menu(bool reset_data = true); void setup_is_nitro_menu(bool reset_data = true); + void setup_partner_ctr_menu(bool reset_data = true); void setup_video_effects_menu(bool reset_data = true); void setup_input_menu(bool reset_data = true); void setup_separator_menu(bool reset_data = true); diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp index 34eb5ff..f447ebf 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp @@ -125,8 +125,8 @@ static int CaptureResetHardware(CaptureData* capture_data, std::chrono::time_poi static int CaptureBatteryHandleHardware(CaptureData* capture_data, std::chrono::time_point &clock_last_battery_set, int &curr_battery_percentage, bool &curr_ac_adapter_connected) { is_device_device_handlers* handlers = (is_device_device_handlers*)capture_data->handle; const is_device_usb_device* usb_device_desc = (const is_device_usb_device*)capture_data->status.device.descriptor; - int loaded_battery_percentage = capture_data->status.battery_percentage; - bool loaded_ac_adapter_connected = capture_data->status.ac_adapter_connected; + int loaded_battery_percentage = capture_data->status.is_battery_percentage; + bool loaded_ac_adapter_connected = capture_data->status.is_ac_adapter_connected; const auto curr_time_battery = std::chrono::high_resolution_clock::now(); const std::chrono::duration diff_battery = curr_time_battery - clock_last_battery_set; @@ -174,8 +174,8 @@ void is_twl_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCap uint32_t last_read_frame_index = 0; CaptureScreensType curr_capture_type = capture_data->status.capture_type; CaptureSpeedsType curr_capture_speed = capture_data->status.capture_speed; - int curr_battery_percentage = capture_data->status.battery_percentage; - bool curr_ac_adapter_connected = capture_data->status.ac_adapter_connected; + int curr_battery_percentage = capture_data->status.is_battery_percentage; + bool curr_ac_adapter_connected = capture_data->status.is_ac_adapter_connected; bool audio_enabled = true; bool reprocess = false; std::chrono::time_point clock_last_frame = std::chrono::high_resolution_clock::now(); diff --git a/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp b/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp index be2c235..2e3c5cc 100644 --- a/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp +++ b/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp @@ -18,6 +18,10 @@ // Such an action is allowed under EU law. // No reverse engineering of the original software was done to create this. +#define RESET_TIMEOUT 4.0 +#define BATTERY_TIMEOUT 5.0 +#define SLEEP_RESET_TIME_MS 2000 + #define SYNCH_VALUE_PARTNER_CTR PARTNER_CTR_CAPTURE_BASE_COMMAND #define TOTAL_WANTED_CONCURRENTLY_RUNNING_BUFFER_SIZE 0x100000 @@ -809,21 +813,98 @@ static int restart_captures_cc_reads(CaptureData* capture_data, CypressPartnerCT return 0; } +static bool has_battery_stuff_changed(CaptureData* capture_data, std::chrono::time_point &clock_last_battery_set, int &curr_battery_percentage, bool &curr_ac_adapter_connected, bool &curr_ac_adapter_charging) { + int loaded_battery_percentage = capture_data->status.partner_ctr_battery_percentage; + bool loaded_ac_adapter_connected = capture_data->status.partner_ctr_ac_adapter_connected; + bool loaded_ac_adapter_charging = capture_data->status.partner_ctr_ac_adapter_charging; + + const auto curr_time_battery = std::chrono::high_resolution_clock::now(); + const std::chrono::duration diff_battery = curr_time_battery - clock_last_battery_set; + + return !(((curr_battery_percentage == loaded_battery_percentage) || (diff_battery.count() <= BATTERY_TIMEOUT)) && (curr_ac_adapter_connected == loaded_ac_adapter_connected) && (curr_ac_adapter_charging == loaded_ac_adapter_charging)); +} + +static bool hardware_reset_requested(CaptureData* capture_data, std::chrono::time_point &clock_last_reset) { + bool reset_hardware = capture_data->status.reset_hardware; + capture_data->status.reset_hardware = false; + + const auto curr_time = std::chrono::high_resolution_clock::now(); + const std::chrono::duration diff = curr_time - clock_last_reset; + // Do not reset too fast... In general. + return reset_hardware && (diff.count() > RESET_TIMEOUT); +} + +static int CaptureBatteryHandleHardware(CaptureData* capture_data, std::chrono::time_point &clock_last_battery_set, int &curr_battery_percentage, bool &curr_ac_adapter_connected, bool &curr_ac_adapter_charging, bool force = false) { + cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle; + const cypart_device_usb_device* usb_device_desc = (const cypart_device_usb_device*)capture_data->status.device.descriptor; + int loaded_battery_percentage = capture_data->status.partner_ctr_battery_percentage; + bool loaded_ac_adapter_connected = capture_data->status.partner_ctr_ac_adapter_connected; + bool loaded_ac_adapter_charging = capture_data->status.partner_ctr_ac_adapter_charging; + + const auto curr_time_battery = std::chrono::high_resolution_clock::now(); + + if(force || (curr_battery_percentage != loaded_battery_percentage)) { + int ret = set_battery_level(handlers, usb_device_desc, loaded_battery_percentage); + if(ret < 0) { + capture_error_print(true, capture_data, "Battery Set: Failed"); + return ret; + } + clock_last_battery_set = curr_time_battery; + curr_battery_percentage = loaded_battery_percentage; + } + + if(force || (curr_ac_adapter_connected != loaded_ac_adapter_connected) || (curr_ac_adapter_charging != loaded_ac_adapter_charging)) { + int ret = set_charge_kind(handlers, usb_device_desc, loaded_ac_adapter_connected, loaded_ac_adapter_charging); + if(ret < 0) { + capture_error_print(true, capture_data, "AC Adapter Set: Failed"); + return ret; + } + curr_ac_adapter_connected = loaded_ac_adapter_connected; + curr_ac_adapter_charging = loaded_ac_adapter_charging; + } + + return 0; +} + +static int CaptureResetHardware(CaptureData* capture_data, std::chrono::time_point &clock_last_reset) { + cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle; + const cypart_device_usb_device* usb_device_desc = (const cypart_device_usb_device*)capture_data->status.device.descriptor; + + const auto curr_time = std::chrono::high_resolution_clock::now(); + clock_last_reset = curr_time; + + int ret = hardware_reset(handlers, usb_device_desc); + if(ret < 0) + return ret; + default_sleep(SLEEP_RESET_TIME_MS); + return ret; +} + static bool cypart_device_acquisition_loop(CaptureData* capture_data, CypressPartnerCTRDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool &stored_is_3d, bool could_use_3d) { cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle; const cypart_device_usb_device* usb_device_desc = (const cypart_device_usb_device*)capture_data->status.device.descriptor; uint32_t index = 0; uint64_t device_id = 0; + int curr_battery_percentage = capture_data->status.partner_ctr_battery_percentage; + bool curr_ac_adapter_connected = capture_data->status.partner_ctr_ac_adapter_connected; + bool curr_ac_adapter_charging = capture_data->status.partner_ctr_ac_adapter_charging; std::string read_serial = ""; bool force_capture_start_key = false; int ret = capture_start(handlers, usb_device_desc, read_serial); std::chrono::time_point clock_last_capture_start = std::chrono::high_resolution_clock::now(); + std::chrono::time_point clock_last_reset = std::chrono::high_resolution_clock::now(); + std::chrono::time_point clock_last_battery_set = std::chrono::high_resolution_clock::now(); if (ret < 0) { capture_error_print(true, capture_data, "Capture Start: Failed"); return false; } + ret = CaptureBatteryHandleHardware(capture_data, clock_last_battery_set, curr_battery_percentage, curr_ac_adapter_connected, curr_ac_adapter_charging, true); + + if (ret < 0) + return false; + CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), 0x80000); StartCaptureDma(handlers, usb_device_desc, stored_is_3d); @@ -848,9 +929,26 @@ static bool cypart_device_acquisition_loop(CaptureData* capture_data, CypressPar } } bool is_new_3d = could_use_3d && get_3d_enabled(&capture_data->status); - if(is_new_3d != stored_is_3d) { + bool updated_battery = has_battery_stuff_changed(capture_data, clock_last_battery_set, curr_battery_percentage, curr_ac_adapter_connected, curr_ac_adapter_charging); + bool requested_reset = hardware_reset_requested(capture_data, clock_last_reset); + if((is_new_3d != stored_is_3d) || updated_battery || requested_reset) { capture_data->status.cooldown_curr_in = FIX_PARTIAL_FIRST_FRAME_NUM + NUM_PARTNER_CTR_CYPRESS_CONCURRENTLY_RUNNING_BUFFERS; wait_all_cypress_device_buffers_free(capture_data, cypress_device_capture_recv_data); + + if(updated_battery) { + ret = CaptureBatteryHandleHardware(capture_data, clock_last_battery_set, curr_battery_percentage, curr_ac_adapter_connected, curr_ac_adapter_charging); + if(ret < 0) + return false; + } + + if(requested_reset) { + ret = CaptureResetHardware(capture_data, clock_last_reset); + if(ret < 0) { + capture_error_print(true, capture_data, "Hardware Reset: Failed"); + return false; + } + } + ret = restart_captures_cc_reads(capture_data, cypress_device_capture_recv_data, index, stored_is_3d, could_use_3d, false, clock_last_capture_start); if(ret < 0) { capture_error_print(true, capture_data, "Disconnected: Update mode error"); @@ -946,6 +1044,15 @@ void usb_cypart_device_acquisition_cleanup(CaptureData* capture_data) { cypress_partner_ctr_connection_end((cy_device_device_handlers*)capture_data->handle, (const cypart_device_usb_device*)capture_data->status.device.descriptor); capture_data->handle = NULL; } + +bool is_device_partner_ctr(CaptureDevice* device) { + if(device == NULL) + return false; + if(device->cc_type != CAPTURE_CONN_PARTNER_CTR) + return false; + return true; +} + void usb_cypart_device_init() { return usb_init(); } diff --git a/source/Menus/ISNitroMenu.cpp b/source/Menus/ISNitroMenu.cpp index f557b87..e4501a7 100644 --- a/source/Menus/ISNitroMenu.cpp +++ b/source/Menus/ISNitroMenu.cpp @@ -208,10 +208,10 @@ void ISNitroMenu::prepare(float menu_scaling_factor, int view_size_x, int view_s this->labels[index]->setText(this->setTextOptionString(real_index, get_capture_speed_name(capture_status->capture_speed))); break; case ISN_MENU_BATTERY_DEC: - this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->battery_percentage)); + this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->is_battery_percentage)); break; case ISN_MENU_AC_ADAPTER_TOGGLE: - this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->ac_adapter_connected)); + this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->is_ac_adapter_connected)); break; default: break; diff --git a/source/Menus/MainMenu.cpp b/source/Menus/MainMenu.cpp index 43c87f5..5bc9c90 100755 --- a/source/Menus/MainMenu.cpp +++ b/source/Menus/MainMenu.cpp @@ -1,6 +1,7 @@ #include "MainMenu.hpp" #include "usb_is_device_acquisition.hpp" #include "cypress_optimize_3ds_acquisition.hpp" +#include "cypress_partner_ctr_acquisition.hpp" #define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0])) @@ -153,6 +154,13 @@ static const MainMenuOptionInfo opti_3ds_settings_option = { .enabled_normal_mode = true, .enabled_mono_mode = true, .is_cc_specific = true, .out_action = MAIN_MENU_OPTIMIZE_3DS_SETTINGS}; +static const MainMenuOptionInfo partner_ctr_settings_option = { +.base_name = "Partner CTR Settings", .false_name = "", +.active_fullscreen = true, .active_windowed_screen = true, +.active_joint_screen = true, .active_top_screen = true, .active_bottom_screen = true, +.enabled_normal_mode = true, .enabled_mono_mode = true, .is_cc_specific = true, +.out_action = MAIN_MENU_PARTNER_CTR_SETTINGS}; + static const MainMenuOptionInfo* pollable_options[] = { &connect_option, &windowed_option, @@ -169,6 +177,7 @@ static const MainMenuOptionInfo* pollable_options[] = { &isn_settings_option, &ist_settings_option, &opti_3ds_settings_option, +&partner_ctr_settings_option, &licenses_option, &extra_settings_option, &quit_option, @@ -212,6 +221,10 @@ static bool check_cc_specific_option(const MainMenuOptionInfo* option, CaptureDe if((option->out_action == MAIN_MENU_OPTIMIZE_3DS_SETTINGS) && is_device_optimize_3ds(device)) return true; #endif + #ifdef USE_PARTNER_CTR + if((option->out_action == MAIN_MENU_PARTNER_CTR_SETTINGS) && is_device_partner_ctr(device)) + return true; + #endif return false; } diff --git a/source/Menus/PartnerCTRMenu.cpp b/source/Menus/PartnerCTRMenu.cpp new file mode 100644 index 0000000..fbed7c0 --- /dev/null +++ b/source/Menus/PartnerCTRMenu.cpp @@ -0,0 +1,143 @@ +#include "PartnerCTRMenu.hpp" + +#define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0])) + +struct PartnerCTRMenuOptionInfo { + const std::string base_name; + const std::string false_name; + const bool is_selectable; + const bool is_inc; + const std::string dec_str; + const std::string inc_str; + const PartnerCTRMenuOutAction inc_out_action; + const PartnerCTRMenuOutAction out_action; +}; + +static const PartnerCTRMenuOptionInfo partner_ctr_reset_option = { +.base_name = "Reset Hardware", .false_name = "", .is_selectable = true, +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = PCTR_MENU_NO_ACTION, +.out_action = PCTR_MENU_RESET}; + +static const PartnerCTRMenuOptionInfo partner_ctr_battery_percentage_option = { +.base_name = "Battery Percentage", .false_name = "", .is_selectable = true, +.is_inc = true, .dec_str = "-", .inc_str = "+", .inc_out_action = PCTR_MENU_BATTERY_INC, +.out_action = PCTR_MENU_BATTERY_DEC}; + +static const PartnerCTRMenuOptionInfo partner_ctr_ac_adapter_connected_option = { +.base_name = "Disconnect AC Adapter", .false_name = "Connect AC Adapter", .is_selectable = true, +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = PCTR_MENU_NO_ACTION, +.out_action = PCTR_MENU_AC_ADAPTER_CONNECTED_TOGGLE}; + +static const PartnerCTRMenuOptionInfo partner_ctr_ac_adapter_charging_option = { +.base_name = "Disable AC charging", .false_name = "Enable AC charging", .is_selectable = true, +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = PCTR_MENU_NO_ACTION, +.out_action = PCTR_MENU_AC_ADAPTER_CHARGING_TOGGLE}; + +static const PartnerCTRMenuOptionInfo* pollable_options[] = { +&partner_ctr_reset_option, +&partner_ctr_battery_percentage_option, +&partner_ctr_ac_adapter_connected_option, +&partner_ctr_ac_adapter_charging_option, +}; + +PartnerCTRMenu::PartnerCTRMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){ + this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS]; + this->initialize(text_rectangle_pool); + this->num_enabled_options = 0; +} + +PartnerCTRMenu::~PartnerCTRMenu() { + delete []this->options_indexes; +} + +void PartnerCTRMenu::class_setup() { + this->num_options_per_screen = 5; + this->min_elements_text_scaling_factor = num_options_per_screen + 2; + this->width_factor_menu = 16; + this->width_divisor_menu = 9; + this->base_height_factor_menu = 12; + this->base_height_divisor_menu = 6; + this->min_text_size = 0.3f; + this->max_width_slack = 1.1f; + this->menu_color = sf::Color(30, 30, 60, 192); + this->title = "Partner CTR Settings"; + this->show_back_x = true; + this->show_x = false; + this->show_title = true; +} + +void PartnerCTRMenu::insert_data(CaptureDevice* device) { + this->num_enabled_options = 0; + for(size_t i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) { + bool valid = true; + if(valid) { + this->options_indexes[this->num_enabled_options] = (int)i; + this->num_enabled_options++; + } + } + this->prepare_options(); +} + +void PartnerCTRMenu::reset_output_option() { + this->selected_index = PartnerCTRMenuOutAction::PCTR_MENU_NO_ACTION; +} + +void PartnerCTRMenu::set_output_option(int index, int action) { + if(index == BACK_X_OUTPUT_OPTION) + this->selected_index = PCTR_MENU_BACK; + else if((action == INC_ACTION) && this->is_option_inc_dec(index)) + this->selected_index = pollable_options[this->options_indexes[index]]->inc_out_action; + else + this->selected_index = pollable_options[this->options_indexes[index]]->out_action; +} + +size_t PartnerCTRMenu::get_num_options() { + return this->num_enabled_options; +} + +std::string PartnerCTRMenu::get_string_option(int index, int action) { + if((action == INC_ACTION) && this->is_option_inc_dec(index)) + return pollable_options[this->options_indexes[index]]->inc_str; + if((action == DEC_ACTION) && this->is_option_inc_dec(index)) + return pollable_options[this->options_indexes[index]]->dec_str; + if(action == FALSE_ACTION) + return pollable_options[this->options_indexes[index]]->false_name; + return pollable_options[this->options_indexes[index]]->base_name; +} + +bool PartnerCTRMenu::is_option_selectable(int index, int action) { + return pollable_options[this->options_indexes[index]]->is_selectable; +} + +bool PartnerCTRMenu::is_option_inc_dec(int index) { + return pollable_options[this->options_indexes[index]]->is_inc; +} + +void PartnerCTRMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, CaptureStatus* capture_status) { + int num_pages = this->get_num_pages(); + if(this->future_data.page >= num_pages) + this->future_data.page = num_pages - 1; + int start = this->future_data.page * this->num_options_per_screen; + for(int i = 0; i < this->num_options_per_screen + 1; i++) { + int index = (i * this->single_option_multiplier) + this->elements_start_id; + if(!this->future_enabled_labels[index]) + continue; + int real_index = start + i; + int option_index = this->options_indexes[real_index]; + switch(pollable_options[option_index]->out_action) { + case PCTR_MENU_BATTERY_DEC: + this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->partner_ctr_battery_percentage)); + break; + case PCTR_MENU_AC_ADAPTER_CONNECTED_TOGGLE: + this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->partner_ctr_ac_adapter_connected)); + break; + case PCTR_MENU_AC_ADAPTER_CHARGING_TOGGLE: + this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->partner_ctr_ac_adapter_charging)); + break; + default: + break; + } + } + + this->base_prepare(menu_scaling_factor, view_size_x, view_size_y); +} diff --git a/source/WindowScreen_Menu.cpp b/source/WindowScreen_Menu.cpp index a20d7b3..0a76226 100755 --- a/source/WindowScreen_Menu.cpp +++ b/source/WindowScreen_Menu.cpp @@ -6,7 +6,8 @@ #define FPS_WINDOW_SIZE 64 -static const int battery_levels[] = {1, 5, 12, 25, 50, 100}; +static const int is_battery_levels[] = {1, 5, 12, 25, 50, 100}; +static const int partner_ctr_battery_levels[] = {0, 1, 10, 30, 60, 100}; static const sf::VideoMode default_fs_mode_4_5k_macos = sf::VideoMode({4480, 2520}); static const sf::VideoMode default_fs_mode_4k_macos = sf::VideoMode({4096, 2304}); @@ -117,6 +118,7 @@ void WindowScreen::init_menus() { this->action_selection_menu = new ActionSelectionMenu(this->text_rectangle_pool); this->scaling_ratio_menu = new ScalingRatioMenu(this->text_rectangle_pool); this->is_nitro_menu = new ISNitroMenu(this->text_rectangle_pool); + this->partner_ctr_menu = new PartnerCTRMenu(this->text_rectangle_pool); this->video_effects_menu = new VideoEffectsMenu(this->text_rectangle_pool); this->input_menu = new InputMenu(this->text_rectangle_pool); this->audio_device_menu = new AudioDeviceMenu(this->text_rectangle_pool); @@ -149,6 +151,7 @@ void WindowScreen::destroy_menus() { delete this->action_selection_menu; delete this->scaling_ratio_menu; delete this->is_nitro_menu; + delete this->partner_ctr_menu; delete this->video_effects_menu; delete this->input_menu; delete this->audio_device_menu; @@ -225,16 +228,15 @@ void WindowScreen::is_nitro_capture_reset_hw() { this->capture_status->reset_hardware = true; } -void WindowScreen::is_nitro_battery_change(bool positive) { - if(this->capture_status->battery_percentage < 1) - this->capture_status->battery_percentage = 1; - if(this->capture_status->battery_percentage > 100) - this->capture_status->battery_percentage = 100; - int closest_level = 0; +void WindowScreen::generic_battery_change(bool positive, int &battery_percentage, const int *allowed_battery_levels, size_t num_levels) { + if(battery_percentage < allowed_battery_levels[0]) + battery_percentage = allowed_battery_levels[0]; + if(battery_percentage > 100) + battery_percentage = 100; + size_t closest_level = 0; int curr_diff = 100; - const int num_levels = sizeof(battery_levels) / sizeof(battery_levels[0]); - for(int i = 0; i < num_levels; i++) { - int level_diff = abs(battery_levels[i] - this->capture_status->battery_percentage); + for(size_t i = 0; i < num_levels; i++) { + int level_diff = abs(allowed_battery_levels[i] - battery_percentage); if(level_diff < curr_diff) { closest_level = i; curr_diff = level_diff; @@ -244,13 +246,29 @@ void WindowScreen::is_nitro_battery_change(bool positive) { closest_level -= 1; if((positive) && (closest_level < (num_levels - 1))) closest_level += 1; - if(battery_levels[closest_level] != this->capture_status->battery_percentage) + if(allowed_battery_levels[closest_level] != battery_percentage) this->print_notification("Changing battery level...\nPlease wait..."); - this->capture_status->battery_percentage = battery_levels[closest_level]; + battery_percentage = allowed_battery_levels[closest_level]; +} + +void WindowScreen::is_nitro_battery_change(bool positive) { + this->generic_battery_change(positive, this->capture_status->is_battery_percentage, is_battery_levels, sizeof(is_battery_levels) / sizeof(is_battery_levels[0])); } void WindowScreen::is_nitro_ac_adapter_change() { - this->capture_status->ac_adapter_connected = !this->capture_status->ac_adapter_connected; + this->capture_status->is_ac_adapter_connected = !this->capture_status->is_ac_adapter_connected; +} + +void WindowScreen::partner_ctr_battery_change(bool positive) { + this->generic_battery_change(positive, this->capture_status->partner_ctr_battery_percentage, partner_ctr_battery_levels, sizeof(partner_ctr_battery_levels) / sizeof(partner_ctr_battery_levels[0])); +} + +void WindowScreen::partner_ctr_ac_adapter_connected_change() { + this->capture_status->partner_ctr_ac_adapter_connected = !this->capture_status->partner_ctr_ac_adapter_connected; +} + +void WindowScreen::partner_ctr_ac_adapter_charging_change() { + this->capture_status->partner_ctr_ac_adapter_charging = !this->capture_status->partner_ctr_ac_adapter_charging; } void WindowScreen::padding_change() { @@ -1179,6 +1197,15 @@ void WindowScreen::setup_is_nitro_menu(bool reset_data) { } } +void WindowScreen::setup_partner_ctr_menu(bool reset_data) { + if(!this->can_setup_menu()) + return; + if(this->curr_menu != PARTNER_CTR_MENU_TYPE) { + this->switch_to_menu(PARTNER_CTR_MENU_TYPE, this->partner_ctr_menu, reset_data); + this->partner_ctr_menu->insert_data(&this->capture_status->device); + } +} + void WindowScreen::setup_video_effects_menu(bool reset_data) { if(!this->can_setup_menu()) return; @@ -1604,6 +1631,10 @@ void WindowScreen::poll(bool do_everything) { this->setup_optimize_3ds_menu(); done = true; break; + case MAIN_MENU_PARTNER_CTR_SETTINGS: + this->setup_partner_ctr_menu(); + done = true; + break; case MAIN_MENU_SHUTDOWN: this->set_close(1); this->setup_no_menu(); @@ -2158,6 +2189,34 @@ void WindowScreen::poll(bool do_everything) { } this->loaded_menu_ptr->reset_output_option(); break; + case PARTNER_CTR_MENU_TYPE: + switch(this->partner_ctr_menu->selected_index) { + case PCTR_MENU_BACK: + this->setup_main_menu(false); + done = true; + break; + case PCTR_MENU_NO_ACTION: + break; + case PCTR_MENU_RESET: + this->is_nitro_capture_reset_hw(); + break; + case PCTR_MENU_BATTERY_DEC: + this->partner_ctr_battery_change(false); + break; + case PCTR_MENU_BATTERY_INC: + this->partner_ctr_battery_change(true); + break; + case PCTR_MENU_AC_ADAPTER_CONNECTED_TOGGLE: + this->partner_ctr_ac_adapter_connected_change(); + break; + case PCTR_MENU_AC_ADAPTER_CHARGING_TOGGLE: + this->partner_ctr_ac_adapter_charging_change(); + break; + default: + break; + } + this->loaded_menu_ptr->reset_output_option(); + break; case VIDEO_EFFECTS_MENU_TYPE: switch(this->video_effects_menu->selected_index) { case VIDEO_EFFECTS_MENU_BACK: @@ -2454,6 +2513,8 @@ void WindowScreen::update_capture_specific_settings() { } if(this->curr_menu == ISN_MENU_TYPE) this->setup_no_menu(); + if(this->curr_menu == PARTNER_CTR_MENU_TYPE) + this->setup_no_menu(); if(this->curr_menu == OPTIMIZE_3DS_MENU_TYPE) this->setup_no_menu(); if(this->curr_menu == OPTIMIZE_SERIAL_KEY_ADD_MENU_TYPE) @@ -2694,6 +2755,9 @@ void WindowScreen::prepare_menu_draws(int view_size_x, int view_size_y) { case ISN_MENU_TYPE: this->is_nitro_menu->prepare(menu_scaling_factor, view_size_x, view_size_y, this->capture_status); break; + case PARTNER_CTR_MENU_TYPE: + this->partner_ctr_menu->prepare(menu_scaling_factor, view_size_x, view_size_y, this->capture_status); + break; case VIDEO_EFFECTS_MENU_TYPE: this->video_effects_menu->prepare(menu_scaling_factor, view_size_x, view_size_y, &this->loaded_info); break; diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index 7df320a..1faf7ba 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -199,18 +199,39 @@ static bool load(const std::string path, const std::string name, ScreenInfo &top } if(key == "is_battery_percentage") { - capture_status->battery_percentage = std::stoi(value); + capture_status->is_battery_percentage = std::stoi(value); // Even though 1 is allowed, it spam-resets the Hardware... // So don't allow it as the initial value! - if(capture_status->battery_percentage <= 5) - capture_status->battery_percentage = 5; - if(capture_status->battery_percentage > 100) - capture_status->battery_percentage = 100; + if(capture_status->is_battery_percentage <= 5) + capture_status->is_battery_percentage = 5; + if(capture_status->is_battery_percentage > 100) + capture_status->is_battery_percentage = 100; continue; } if(key == "is_ac_adapter_connected") { - capture_status->ac_adapter_connected = std::stoi(value); + capture_status->is_ac_adapter_connected = std::stoi(value); + continue; + } + + if(key == "partner_ctr_battery_percentage") { + capture_status->partner_ctr_battery_percentage = std::stoi(value); + // Even though 0 is allowed, it turns off the Hardware... + // So don't allow it as the initial value! + if(capture_status->partner_ctr_battery_percentage <= 1) + capture_status->partner_ctr_battery_percentage = 1; + if(capture_status->partner_ctr_battery_percentage > 100) + capture_status->partner_ctr_battery_percentage = 100; + continue; + } + + if(key == "partner_ctr_ac_adapter_connected") { + capture_status->partner_ctr_ac_adapter_connected = std::stoi(value); + continue; + } + + if(key == "partner_ctr_ac_adapter_charging") { + capture_status->partner_ctr_ac_adapter_charging = std::stoi(value); continue; } @@ -242,8 +263,11 @@ static bool load(const std::string path, const std::string name, ScreenInfo &top static void defaults_reload(FrontendData *frontend_data, AudioData* audio_data, CaptureStatus* capture_status) { capture_status->capture_type = CAPTURE_SCREENS_BOTH; capture_status->capture_speed = CAPTURE_SPEEDS_FULL; - capture_status->battery_percentage = 100; - capture_status->ac_adapter_connected = true; + capture_status->is_battery_percentage = 100; + capture_status->is_ac_adapter_connected = true; + capture_status->partner_ctr_battery_percentage = 100; + capture_status->partner_ctr_ac_adapter_connected = false; + capture_status->partner_ctr_ac_adapter_charging = false; capture_status->request_low_bw_format = true; for(int i = 0; i < CC_POSSIBLE_DEVICES_END; i++) capture_status->devices_allowed_scan[i] = true; @@ -333,8 +357,11 @@ static bool save(const std::string path, const std::string name, const std::stri file << "last_connected_ds=" << display_data.last_connected_ds << std::endl; file << "is_screen_capture_type=" << capture_status->capture_type << std::endl; file << "is_speed_capture=" << capture_status->capture_speed << std::endl; - file << "is_battery_percentage=" << capture_status->battery_percentage << std::endl; - file << "is_ac_adapter_connected=" << capture_status->ac_adapter_connected << std::endl; + file << "is_battery_percentage=" << capture_status->is_battery_percentage << std::endl; + file << "is_ac_adapter_connected=" << capture_status->is_ac_adapter_connected << std::endl; + file << "partner_ctr_battery_percentage=" << capture_status->partner_ctr_battery_percentage << std::endl; + file << "partner_ctr_ac_adapter_connected=" << capture_status->partner_ctr_battery_percentage << std::endl; + file << "partner_ctr_ac_adapter_charging=" << capture_status->partner_ctr_battery_percentage << std::endl; file << "optimize_o3ds_scan_for=" << capture_status->devices_allowed_scan[CC_OPTIMIZE_O3DS] << std::endl; file << "nisetro_ds_scan_for=" << capture_status->devices_allowed_scan[CC_NISETRO_DS] << std::endl; file << audio_data->save_audio_data(); diff --git a/source/frontend.cpp b/source/frontend.cpp index f505a72..aaa870f 100755 --- a/source/frontend.cpp +++ b/source/frontend.cpp @@ -1131,7 +1131,7 @@ void update_connected_3ds_ds(FrontendData* frontend_data, const CaptureDevice &o } void update_connected_specific_settings(FrontendData* frontend_data, const CaptureDevice &cc_device) { - if((cc_device.cc_type == CAPTURE_CONN_IS_NITRO) || (cc_device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE)) { + if((cc_device.cc_type == CAPTURE_CONN_IS_NITRO) || (cc_device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE) || (cc_device.cc_type == CAPTURE_CONN_PARTNER_CTR)) { frontend_data->top_screen->update_capture_specific_settings(); frontend_data->bot_screen->update_capture_specific_settings(); frontend_data->joint_screen->update_capture_specific_settings();