diff --git a/CMakeLists.txt b/CMakeLists.txt index b30c567..70fac3e 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -377,7 +377,7 @@ if(CYPRESS_NISETRO_SUPPORT) add_compile_flag("USE_CYNI_USB") endif() if(OPTIMIZE_3DS_SUPPORT) - list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_CYPRESS_OPTIMIZE_3DS_FILES_BASE_PATH}/cypress_optimize_3ds_communications.cpp ${SOURCE_CPP_CYPRESS_OPTIMIZE_3DS_FILES_BASE_PATH}/cypress_optimize_3ds_acquisition.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_fw.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_565_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_888_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_old_3ds_fw.cpp ${TOOLS_DATA_DIR}/optimize_old_3ds_565_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_old_3ds_888_fpga_pl.cpp ${TOOLS_DATA_DIR}/adler_crc32_table_sp.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_to_byte_table.cpp) + list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_CYPRESS_OPTIMIZE_3DS_FILES_BASE_PATH}/cypress_optimize_3ds_communications.cpp ${SOURCE_CPP_CYPRESS_OPTIMIZE_3DS_FILES_BASE_PATH}/cypress_optimize_3ds_acquisition.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_fw.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_565_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_888_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_old_3ds_fw.cpp ${TOOLS_DATA_DIR}/optimize_old_3ds_565_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_old_3ds_888_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_old_2ds_2014_fw.cpp ${TOOLS_DATA_DIR}/optimize_old_2ds_2014_565_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_old_2ds_2014_888_fpga_pl.cpp ${TOOLS_DATA_DIR}/adler_crc32_table_sp.cpp ${TOOLS_DATA_DIR}/optimize_serial_key_to_byte_table.cpp) add_compile_flag("USE_CYPRESS_OPTIMIZE") endif() if(PARTNER_CTR_SUPPORT) @@ -529,7 +529,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/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}) +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/Menus/OptimizeOldFWConfigMenu.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") @@ -670,6 +670,27 @@ add_custom_command( DEPENDS ${CMAKE_SOURCE_DIR}/bin/optimize_old_3ds_888_fpga_pl.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ) +add_custom_command( + OUTPUT ${TOOLS_DATA_DIR}/optimize_old_2ds_2014_fw.cpp + COMMENT "Convert fw binary to C - Optimize Old 3DS" + COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/optimize_old_2ds_2014_fw.bin ${TOOLS_DATA_DIR} optimize_old_2ds_2014_fw optimize_old_2ds_2014_fw + DEPENDS ${CMAKE_SOURCE_DIR}/bin/optimize_old_2ds_2014_fw.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} +) + +add_custom_command( + OUTPUT ${TOOLS_DATA_DIR}/optimize_old_2ds_2014_565_fpga_pl.cpp + COMMENT "Convert FPGA 565 PL binary to C - Optimize Old 3DS" + COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/optimize_old_2ds_2014_565_fpga_pl.bin ${TOOLS_DATA_DIR} optimize_old_2ds_2014_565_fpga_pl optimize_old_2ds_2014_565_fpga_pl + DEPENDS ${CMAKE_SOURCE_DIR}/bin/optimize_old_2ds_2014_565_fpga_pl.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} +) + +add_custom_command( + OUTPUT ${TOOLS_DATA_DIR}/optimize_old_2ds_2014_888_fpga_pl.cpp + COMMENT "Convert FPGA 888 PL binary to C - Optimize Old 3DS" + COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/optimize_old_2ds_2014_888_fpga_pl.bin ${TOOLS_DATA_DIR} optimize_old_2ds_2014_888_fpga_pl optimize_old_2ds_2014_888_fpga_pl + DEPENDS ${CMAKE_SOURCE_DIR}/bin/optimize_old_2ds_2014_888_fpga_pl.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} +) + add_custom_command( OUTPUT ${TOOLS_DATA_DIR}/optimize_serial_key_to_byte_table.cpp COMMENT "Convert table to C - Optimize Key to 5 bits" diff --git a/README.md b/README.md index cb56916..3190a5f 100755 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ The main goal is to offer the ability to use the Capture Card with a TV, via ful IS Nitro Emulator (newer revisions), IS Nitro Capture and IS TWL Capture support is also present. Though results may vary (and the amount of video delay may be significantly higher based on the cable used). -Optimize Old 3DS capture boards and Optimize New 3DS capture boards are also supported. Older revisions of the capture boards may not be supported at the moment, though. +Optimize Old 3DS/2DS capture boards and Optimize New 3DS/2DS capture boards are also supported. Partner CTR Capture devices are supported. @@ -158,10 +158,11 @@ The CC3DSFS\_CFG\_DIR environment variable can be used to specify a different ta - When using IS Nitro Emulator, IS Nitro Capture or IS TWL Capture devices on Windows, cc3dsfs is compatible with both the official driver and WinUSB, with the latter being useful if you don't have access to the official driver. To install and use WinUSB, plug in your device, download a software to install drivers like [Zadig](https://zadig.akeo.ie/), select the device in question and select WinUSB. Then install the driver and wait for it to finish. The devices should now work properly with this application. - When using Partner CTR Capture devices on Windows, cc3dsfs is compatible with both the official driver and libusb-win32 (or alternatives), with the latter being useful if you don't have access to the official driver. To install and use libusb-win32 (or alternatives), plug in your device, download a software to install drivers like [Zadig](https://zadig.akeo.ie/), select the device in question and select libusb-win32 (or alternatives). Then install the driver and wait for it to finish. The devices should now work properly with this application. - When using the new 2024 Loopy DS Capture Card on Windows, the default driver (FTD2XX) adds one extra frame of latency. To remove that, consider switching to WinUSB as the driver. To change driver, download a software to install drivers like [Zadig](https://zadig.akeo.ie/), select the device in question and select WinUSB. Then install the driver and wait for it to finish. The application will now use WinUSB, with better latency (the serial shown in the Status menu will have an l where there previously was a d). -- There are multiple capture cards which use the same EZ-USB FX2LP board, creating a conflict. These are the Optimize Old 3DS capture cards and the Nisetro DS(i) capture cards. This means that when the user connects a device which uses the EZ-USB FX2LP board, they need to select one capture card among the possible ones. To avoid this extra step, the user can disable scanning for the conflicting capture cards they do not intend to use. The settings to do this are available under Extra Settings -> USB Conflict Resolution. +- There are multiple capture cards which use the same EZ-USB FX2LP board, creating a conflict. These are the Optimize Old 3DS/2DS capture cards and the Nisetro DS(i) capture cards. This means that when the user connects a device which uses the EZ-USB FX2LP board, they need to select one capture card among the possible ones. To avoid this extra step, the user can disable scanning for the conflicting capture cards they do not intend to use. The settings to do this are available under Extra Settings -> USB Conflict Resolution. - MacOS does not allow running multiple instances of the same application, normally. If you want to run multiple instances of cc3dsfs on MacOS, open the terminal in the folder where cc3dsfs is and type `open -n cc3dsfs.app`. - To properly use the Optimize capture cards with cc3dsfs, a serial key is needed. This can be added via the _Optimize 3DS Settings_, under the _Add New Serial Key_ option. You can use CTRL+V in the textbox to copy the serial key, or insert it manually. To obtain the key, get your device ID (it can be copied from the _Optimize 3DS Settings_ menu) and type it in the [Official site](https://optimize.ath.cx/productkey_en.html). Using a keyboard to do this is suggested (but not required). - Keys are saved under the keys folder inside the cc3dsfs config folder. - To reset to the default settings, besides the options shown in [Controls](#Controls), you can find the _Reset Settings_ option inside of the _Extra Settings_. - When using an Optimize Old 3DS Capture Card or a Nisetro DS(i) Capture Card on Windows, make sure either the Cypress USB drivers are installed, or the Optimize Old 3DS drivers are installed. Alternatively, it is also possible to install libusb-win32 or alternatives to use with the devices via software to install drivers like [Zadig](https://zadig.akeo.ie/). - When using an Optimize New 3DS Capture Card on Windows, make sure the Optimize New 3DS drivers are installed. Also ensure either the Cypress USB drivers are installed, or the Optimize Old 3DS drivers are installed. Alternatively, it is also possible to install libusb-win32 or alternatives to use with the device via software to install drivers like [Zadig](https://zadig.akeo.ie/). +- Depending on the 2DS Hardware revision (starting with 2DSs from late 2014 onwards), Optimize Old 2DS Capture cards may need to use a special (older) firmware. This can be selected when first connecting to the capture card. RGB888 mode works normally. RGB565 does not have sound. For these 2DS capture cards, initial synchronization must also be done upon the first connection. To do this, upon connecting the capture card, go to Optimize 3DS Settings -> Synch Settings, and change the parameters until an image is displayed. diff --git a/bin/optimize_old_2ds_2014_565_fpga_pl.bin b/bin/optimize_old_2ds_2014_565_fpga_pl.bin new file mode 100644 index 0000000..5e6d4eb Binary files /dev/null and b/bin/optimize_old_2ds_2014_565_fpga_pl.bin differ diff --git a/bin/optimize_old_2ds_2014_888_fpga_pl.bin b/bin/optimize_old_2ds_2014_888_fpga_pl.bin new file mode 100644 index 0000000..dd2ec96 Binary files /dev/null and b/bin/optimize_old_2ds_2014_888_fpga_pl.bin differ diff --git a/bin/optimize_old_2ds_2014_fw.bin b/bin/optimize_old_2ds_2014_fw.bin new file mode 100644 index 0000000..dd9aeac Binary files /dev/null and b/bin/optimize_old_2ds_2014_fw.bin differ diff --git a/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp b/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp index 6b47775..d472140 100644 --- a/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp +++ b/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp @@ -23,6 +23,8 @@ void usb_cyop_device_acquisition_cleanup(CaptureData* capture_data); bool is_device_optimize_3ds(CaptureDevice* device); bool is_device_optimize_o3ds(CaptureDevice* device); bool is_device_optimize_n3ds(CaptureDevice* device); +bool is_device_optimize_o2ds(CaptureDevice* device); +bool is_device_optimize_old_fw(CaptureDevice* device); bool cyop_is_key_for_device_id(CaptureDevice* device, std::string key); KeySaveError add_key_to_file(std::string key, bool is_for_new_3ds); void usb_cyop_device_init(); diff --git a/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.hpp b/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.hpp index 65611ed..2ee48a0 100644 --- a/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.hpp +++ b/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.hpp @@ -14,6 +14,8 @@ enum cypress_optimize_device_type { CYPRESS_OPTIMIZE_NEW_3DS_INSTANTIATED_DEVICE, CYPRESS_OPTIMIZE_OLD_3DS_BLANK_DEVICE, CYPRESS_OPTIMIZE_OLD_3DS_INSTANTIATED_DEVICE, + CYPRESS_OPTIMIZE_OLD_OLD_2DS_BLANK_DEVICE, + CYPRESS_OPTIMIZE_OLD_OLD_2DS_INSTANTIATED_DEVICE, }; struct cyop_device_usb_device { @@ -27,6 +29,8 @@ struct cyop_device_usb_device { uint8_t* fpga_pl_888; size_t fpga_pl_888_size; bool is_new_device; + bool is_old_firmware; + bool is_o2ds; cypress_optimize_device_type next_device; bool has_bcd_device_serial; PossibleCaptureDevices index_in_allowed_scan; @@ -43,7 +47,7 @@ bool load_firmware(cy_device_device_handlers* handlers, const cyop_device_usb_de bool read_firmware(cy_device_device_handlers* handlers, const cyop_device_usb_device* device, uint8_t* buffer_out, size_t read_size); bool reset_cpu(cy_device_device_handlers* handlers, const cyop_device_usb_device* device); int capture_start(cy_device_device_handlers* handlers, const cyop_device_usb_device* device, bool is_first_load, bool is_rgb888, uint64_t &device_id, std::string &read_key); -int StartCaptureDma(cy_device_device_handlers* handlers, const cyop_device_usb_device* device, bool is_rgb888, bool is_3d, std::string key); +int StartCaptureDma(cy_device_device_handlers* handlers, const cyop_device_usb_device* device, bool is_rgb888, bool is_3d, CaptureOptimizeOldFirmwareConfig *old_fw_config, std::string key); int capture_end(cy_device_device_handlers* handlers, const cyop_device_usb_device* device); int ReadFrame(cy_device_device_handlers* handlers, uint8_t* buf, int length, const cyop_device_usb_device* device_desc); int ReadFrameAsync(cy_device_device_handlers* handlers, uint8_t* buf, int length, const cyop_device_usb_device* device_desc, cy_async_callback_data* cb_data); diff --git a/include/Menus/Optimize3DSMenu.hpp b/include/Menus/Optimize3DSMenu.hpp index ce051ab..b7e5922 100644 --- a/include/Menus/Optimize3DSMenu.hpp +++ b/include/Menus/Optimize3DSMenu.hpp @@ -14,10 +14,13 @@ enum Optimize3DSMenuOutAction{ OPTIMIZE3DS_MENU_BACK, OPTIMIZE3DS_MENU_INPUT_VIDEO_FORMAT_INC, OPTIMIZE3DS_MENU_INPUT_VIDEO_FORMAT_DEC, + OPTIMIZE2DS_MENU_INPUT_VIDEO_FORMAT_INC, + OPTIMIZE2DS_MENU_INPUT_VIDEO_FORMAT_DEC, OPTIMIZE3DS_MENU_INFO_DEVICE_ID, OPTIMIZE3DS_MENU_COPY_DEVICE_ID, OPTIMIZE3DS_MENU_OPTIMIZE_SERIAL_KEY, OPTIMIZE3DS_MENU_OPTIMIZE_SERIAL_KEY_MENU, + OPTIMIZE3DS_MENU_OLD_FW_SETTINGS_MENU, }; class Optimize3DSMenu : public OptionSelectionMenu { diff --git a/include/Menus/OptimizeOldFWConfigMenu.hpp b/include/Menus/OptimizeOldFWConfigMenu.hpp new file mode 100644 index 0000000..ca75138 --- /dev/null +++ b/include/Menus/OptimizeOldFWConfigMenu.hpp @@ -0,0 +1,54 @@ +#ifndef __OPTIMIZEOLDFWCONFIGMENU_HPP +#define __OPTIMIZEOLDFWCONFIGMENU_HPP + +#include "OptionSelectionMenu.hpp" +#include + +#include "TextRectangle.hpp" +#include "sfml_gfx_structs.hpp" +#include "display_structs.hpp" +#include "capture_structs.hpp" + +enum OptimizeOldFWConfigMenuOutAction{ + OPTIMIZEOLDFWCONFIG_MENU_NO_ACTION, + OPTIMIZEOLDFWCONFIG_MENU_BACK, + OPTIMIZEOLDFWCONFIG_MENU_CHANGE_INC, + OPTIMIZEOLDFWCONFIG_MENU_CHANGE_DEC, +}; + +enum OptimizeOldFWConfigMenuSelectedOption { + OPTIMIZEOLDFWCONFIG_MENU_LOWSCREENCLK, + OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENCLK, + OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENDATA, + OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENSYNC, +}; + +enum OptimizeOldFWConfigMenuSelectedCase { + OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY, + OPTIMIZEOLDFWCONFIG_MENU_CASEREGULAR, +}; + +class OptimizeOldFWConfigMenu : public OptionSelectionMenu { +public: + OptimizeOldFWConfigMenu(TextRectanglePool* text_pool); + ~OptimizeOldFWConfigMenu(); + void prepare(float scaling_factor, int view_size_x, int view_size_y, CaptureStatus* capture_status); + void insert_data(); + uint8_t* get_data_to_edit(CaptureOptimizeOldFirmwareConfig* optimize_old_fw_cfg); + OptimizeOldFWConfigMenuOutAction selected_index = OptimizeOldFWConfigMenuOutAction::OPTIMIZEOLDFWCONFIG_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); + float get_option_text_factor(int index); + void class_setup(); +private: + int *options_indexes; + size_t num_enabled_options; + OptimizeOldFWConfigMenuSelectedOption selected_option = OptimizeOldFWConfigMenuSelectedOption::OPTIMIZEOLDFWCONFIG_MENU_LOWSCREENCLK; + OptimizeOldFWConfigMenuSelectedCase selected_case = OptimizeOldFWConfigMenuSelectedCase::OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY; +}; +#endif diff --git a/include/Menus/USBConflictResolutionMenu.hpp b/include/Menus/USBConflictResolutionMenu.hpp index 6410761..a3e66ef 100644 --- a/include/Menus/USBConflictResolutionMenu.hpp +++ b/include/Menus/USBConflictResolutionMenu.hpp @@ -14,6 +14,7 @@ enum USBConflictResolutionMenuOutAction{ USBCONRESO_MENU_BACK, USBCONRESO_MENU_NISE_DS, USBCONRESO_MENU_OPTI_O3DS, + USBCONRESO_MENU_OPTI_O2DS, }; class USBConflictResolutionMenu : public OptionSelectionMenu { diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index ca26fe0..3edfc65 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -28,7 +28,7 @@ enum CaptureConnectionType { CAPTURE_CONN_FTD3, CAPTURE_CONN_USB, CAPTURE_CONN_F enum InputVideoDataType { VIDEO_DATA_RGB, VIDEO_DATA_BGR, VIDEO_DATA_RGB16, VIDEO_DATA_BGR16 }; enum CaptureScreensType { CAPTURE_SCREENS_BOTH, CAPTURE_SCREENS_TOP, CAPTURE_SCREENS_BOTTOM, CAPTURE_SCREENS_ENUM_END }; enum CaptureSpeedsType { CAPTURE_SPEEDS_FULL, CAPTURE_SPEEDS_HALF, CAPTURE_SPEEDS_THIRD, CAPTURE_SPEEDS_QUARTER, CAPTURE_SPEEDS_ENUM_END }; -enum PossibleCaptureDevices { CC_LOOPY_OLD_DS, CC_LOOPY_NEW_DS, CC_LOOPY_OLD_3DS, CC_LOOPY_NEW_N3DSXL, CC_IS_NITRO_EMULATOR, CC_IS_NITRO_CAPTURE, CC_IS_TWL_CAPTURE, CC_NISETRO_DS, CC_OPTIMIZE_O3DS, CC_OPTIMIZE_N3DS, CC_PARTNER_CTR, CC_POSSIBLE_DEVICES_END }; +enum PossibleCaptureDevices { CC_LOOPY_OLD_DS, CC_LOOPY_NEW_DS, CC_LOOPY_OLD_3DS, CC_LOOPY_NEW_N3DSXL, CC_IS_NITRO_EMULATOR, CC_IS_NITRO_CAPTURE, CC_IS_TWL_CAPTURE, CC_NISETRO_DS, CC_OPTIMIZE_O3DS, CC_OPTIMIZE_N3DS, CC_OPTIMIZE_O_O2DS, CC_PARTNER_CTR, CC_POSSIBLE_DEVICES_END }; // Readers are Audio and Video. So 2. // Use 6 extra buffers. 5 for async writing in case the other 2 are busy, @@ -95,6 +95,13 @@ struct PACKED USB3DSOptimizeColumnInfo { uint16_t has_extra_header_data_2d_only : 1; }; +struct PACKED USB3DSOptimizeOldFirmwareColumnInfo { + uint16_t fixed : 4; // Fixed to 5...? + uint16_t column_index : 9; + uint16_t extra_column_data : 2; // Can be 1 for RGB888 in 2D mode, always 0 for RGB565...? + uint16_t is_first_column : 1; +}; + struct PACKED USB3DSOptimizeHeaderData { uint16_t magic; USB3DSOptimizeColumnInfo column_info; @@ -105,11 +112,39 @@ struct PACKED USB3DSOptimizeHeaderSoundData { USB3DSOptimizeSingleSoundData samples[2]; }; +// Old firmware RGB565 without sound. O2DS doesn't seem to have ever +// received RGB565 with sound... +struct PACKED USB5653DSOptimizeOldFirmwareHeaderData { + uint16_t magic; // Magic is 0 if column_index is 1 + uint16_t unk; + uint16_t num_pixels_passed; + uint16_t unk2; + USB3DSOptimizeOldFirmwareColumnInfo column_info; + uint16_t unk3; + uint16_t is_frame_not_2d_only; + uint16_t unk4; +}; + +struct PACKED USB8883DSOptimizeOldFirmwareHeaderData { + uint16_t magic; // Magic is 0 if column_info.column_index is 1 + USB3DSOptimizeOldFirmwareColumnInfo column_info; +}; + +struct PACKED USB8883DSOptimizeOldFirmwareHeaderSoundData { + USB8883DSOptimizeOldFirmwareHeaderData header_info; + USB3DSOptimizeSingleSoundData samples[2]; +}; + struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData { USB3DSOptimizeHeaderSoundData header_sound; USB5653DSOptimizePixelData pixel[HEIGHT_3DS][2]; }; +struct PACKED ALIGNED(16) USB5653DSOptimizeOldFirmwareInputColumnData { + USB5653DSOptimizeOldFirmwareHeaderData header; + USB5653DSOptimizePixelData pixel[HEIGHT_3DS][2]; +}; + struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData3DTopRScreen { USB3DSOptimizeHeaderSoundData header_sound; USB5653DSOptimizePixelData pixel[HEIGHT_3DS]; @@ -130,6 +165,11 @@ struct PACKED ALIGNED(16) USB8883DSOptimizeInputColumnData3D { USB8883DSOptimizePixelData pixel[HEIGHT_3DS]; }; +struct PACKED ALIGNED(16) USB8883DSOptimizeOldFirmwareInputColumnData { + USB8883DSOptimizeOldFirmwareHeaderSoundData header_sound; + USB8883DSOptimizePixelData pixel[HEIGHT_3DS][2]; +}; + struct PACKED ISNitroEmulatorVideoInputData { uint8_t screen_data[IN_VIDEO_SIZE_DS][3]; }; @@ -263,6 +303,10 @@ struct ALIGNED(16) PACKED USB5653DSOptimizeCaptureReceived_3D { USB5653DSOptimizeInputColumnData bottom_only_column; }; +struct ALIGNED(16) PACKED USB5653DSOptimizeOldFirmwareCaptureReceived { + USB5653DSOptimizeOldFirmwareInputColumnData columns_data[TOP_WIDTH_3DS + 1]; +}; + struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived { USB8883DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS]; USB8883DSOptimizePixelData bottom_only_column[HEIGHT_3DS][2]; @@ -277,6 +321,10 @@ struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScre USB8883DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS + 1]; }; +struct ALIGNED(16) PACKED USB8883DSOptimizeOldFirmwareCaptureReceived { + USB8883DSOptimizeOldFirmwareInputColumnData columns_data[TOP_WIDTH_3DS + 1]; +}; + struct ALIGNED(16) PACKED USB5653DSOptimizeCaptureReceivedExtraHeader { USB5653DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS + 1]; }; @@ -305,9 +353,11 @@ union CaptureReceived { CypressNisetroDSCaptureReceived cypress_nisetro_capture_received; USB5653DSOptimizeCaptureReceived cypress_optimize_received_565; USB5653DSOptimizeCaptureReceived_3D cypress_optimize_received_565_3d; + USB5653DSOptimizeOldFirmwareCaptureReceived cypress_optimize_old_firmware_received_565; USB8883DSOptimizeCaptureReceived cypress_optimize_received_888; USB8883DSOptimizeCaptureReceived_3D cypress_optimize_received_888_3d; USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen cypress_optimize_received_888_3d_2d; + USB8883DSOptimizeOldFirmwareCaptureReceived cypress_optimize_old_firmware_received_888; USB5653DSOptimizeCaptureReceivedExtraHeader cypress_optimize_received_565_extra_header; USB8883DSOptimizeCaptureReceivedExtraHeader cypress_optimize_received_888_extra_header; }; @@ -354,6 +404,55 @@ struct CaptureDevice { AudioSampleRate sample_rate = SAMPLE_RATE_DS; }; +struct CaptureOptimizeOldFirmwareConfigCase { + uint8_t low_screen_clock = 4; // 0...15 + uint8_t top_screen_clock = 5; // 0...7 + uint8_t top_screen_data = 3; // 0...7 + uint8_t top_screen_sync = 2; // 0...5 +}; // Covered by sanitize_capture_optimize_old_fw_config_case + +struct CaptureOptimizeOldFirmwareConfig { + CaptureOptimizeOldFirmwareConfigCase mode_2d_only; + CaptureOptimizeOldFirmwareConfigCase mode_regular; +}; + +struct CaptureStatusOptimize { + // Capture-device specific data... + // Optimize devices + bool request_low_bw_format = true; + bool request_low_bw_format_old_2ds = false; + bool key_updated = false; + CaptureOptimizeOldFirmwareConfig old_fw_config_full_bw_format = {}; + CaptureOptimizeOldFirmwareConfig old_fw_config_low_bw_format = {}; +}; + +struct CaptureStatusIS { + // Capture-device specific data... + // IS devices + volatile int curr_delay = 0; + volatile bool reset_hardware = false; + CaptureScreensType capture_type; + CaptureSpeedsType capture_speed; + int battery_percentage; + bool ac_adapter_connected; +}; + +struct CaptureStatusPartnerCTR { + // Capture-device specific data... + // Partner CTR Capture + volatile bool reset_hardware = false; + int battery_percentage; + bool ac_adapter_connected; + bool ac_adapter_charging; +}; + +struct CaptureStatusDeviceSpecific { + // Capture-device specific data... + CaptureStatusOptimize optimize_status; + CaptureStatusIS is_status; + CaptureStatusPartnerCTR partner_ctr_status; +}; + struct CaptureStatus { CaptureDevice device; std::string graphical_error_text; @@ -364,18 +463,8 @@ struct CaptureStatus { volatile bool connected = false; volatile bool running = true; volatile bool close_success = true; - volatile int curr_delay = 0; - volatile bool reset_hardware = false; bool requested_3d = false; - bool request_low_bw_format = true; - bool key_updated = false; - CaptureScreensType capture_type; - CaptureSpeedsType capture_speed; - 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; + CaptureStatusDeviceSpecific device_specific_status; // Needed for possible compatibility issues bool devices_allowed_scan[CC_POSSIBLE_DEVICES_END]; ConsumerMutex video_wait; diff --git a/include/devicecapture.hpp b/include/devicecapture.hpp index 175b99a..26540e8 100755 --- a/include/devicecapture.hpp +++ b/include/devicecapture.hpp @@ -40,6 +40,8 @@ bool set_3d_enabled(CaptureStatus* capture_status, bool new_value); float get_framerate_multiplier(CaptureStatus* capture_status); KeySaveError save_cc_key(std::string key, CaptureConnectionType conn_type, bool differentiator); void check_device_serial_key_update(CaptureStatus* capture_status, bool differentiator, std::string key); +void sanitize_capture_optimize_old_fw_config_case(CaptureOptimizeOldFirmwareConfigCase* config_case); +void sanitize_capture_optimize_old_fw_config(CaptureOptimizeOldFirmwareConfig* config); void setup_reconnection_device(void* info); bool wait_reconnection_device(void* info); void end_reconnection_device(void* info); diff --git a/include/display_structs.hpp b/include/display_structs.hpp index aaa2059..ee5e401 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, PARTNER_CTR_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, OPTIMIZE_OLD_FW_CONFIG_MENU, 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 e02cc62..e28e417 100755 --- a/include/frontend.hpp +++ b/include/frontend.hpp @@ -43,6 +43,7 @@ #include "USBConflictResolutionMenu.hpp" #include "Optimize3DSMenu.hpp" #include "OptimizeSerialKeyAddMenu.hpp" +#include "OptimizeOldFWConfigMenu.hpp" #include "display_structs.hpp" #include "event_structs.hpp" #include "shaders_list.hpp" @@ -211,6 +212,7 @@ private: USBConflictResolutionMenu *usb_conflict_resolution_menu; Optimize3DSMenu* optimize_3ds_menu; OptimizeSerialKeyAddMenu* optimize_serial_key_add_menu; + OptimizeOldFWConfigMenu* optimize_old_fw_config_menu; std::vector possible_crops; std::vector possible_crops_ds; @@ -311,6 +313,7 @@ private: 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_reset_hw(); void partner_ctr_battery_change(bool positive); void partner_ctr_ac_adapter_connected_change(); void partner_ctr_ac_adapter_charging_change(); @@ -338,8 +341,9 @@ private: void second_screen_3d_pos_change(int new_second_screen_3d_pos); void second_screen_3d_match_bottom_pos_change(); void devices_allowed_change(PossibleCaptureDevices device); - void input_video_data_format_request_change(bool positive); + void input_video_data_format_request_change(bool positive, bool &target_format); void change_ratio_cycle(); + void optimize_old_fw_menu_change_param(bool positive); bool add_new_cc_key(std::string key, CaptureConnectionType conn_type, bool discriminator); bool query_reset_request(); void reset_held_times(bool force = true); @@ -432,6 +436,7 @@ private: void setup_usb_conflict_resolution_menu(bool reset_data = true); void setup_optimize_3ds_menu(bool reset_data = true); void setup_optimize_serial_key_add_menu(bool reset_data = true); + void setup_optimize_old_fw_config_menu(bool reset_data = true); void update_connection(); bool has_menu_textbox(); }; diff --git a/include/utils.hpp b/include/utils.hpp index 3e953f7..0d7be21 100755 --- a/include/utils.hpp +++ b/include/utils.hpp @@ -57,6 +57,7 @@ void ActualConsoleOutTextError(std::string out_string); void ActualConsoleOutText(std::string out_string); std::string get_base_path(bool for_presets, bool do_existence_check=true); std::string get_base_path_keys(); +std::string get_base_path_device_specific_configs(); std::string LayoutNameGenerator(int index); std::string LayoutPathGenerator(int index); std::string load_layout_name(int index, bool &success); diff --git a/source/CaptureDeviceSpecific/CypressShared/cypress_shared_driver_comms.cpp b/source/CaptureDeviceSpecific/CypressShared/cypress_shared_driver_comms.cpp index eeca8a8..a0e2b75 100644 --- a/source/CaptureDeviceSpecific/CypressShared/cypress_shared_driver_comms.cpp +++ b/source/CaptureDeviceSpecific/CypressShared/cypress_shared_driver_comms.cpp @@ -504,7 +504,8 @@ void cypress_driver_list_devices(std::vector &devices_list, bool* cypress_insert_device(devices_list, usb_device_desc, read_serial, path); } cypress_driver_end_connection(&handlers); - break; + // Do not break, as there can be multiple CCs with the same PID and VID + //break; } } } diff --git a/source/CaptureDeviceSpecific/CypressShared/cypress_shared_libusb_comms.cpp b/source/CaptureDeviceSpecific/CypressShared/cypress_shared_libusb_comms.cpp index 8c30c42..94fec19 100644 --- a/source/CaptureDeviceSpecific/CypressShared/cypress_shared_libusb_comms.cpp +++ b/source/CaptureDeviceSpecific/CypressShared/cypress_shared_libusb_comms.cpp @@ -321,7 +321,8 @@ void cypress_libusb_list_devices(std::vector &devices_list, bool* no_access_elems[j] = true; if(result == LIBUSB_ERROR_NOT_SUPPORTED) not_supported_elems[j] = true; - break; + // Do not break, as there can be multiple CCs with the same PID and VID + //break; } #ifdef _WIN32 // The IntraOral vendor overwrote the Infineon driver in a recent Windows Update... diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp index 58b57c2..ce9ab5b 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_device_acquisition.cpp @@ -152,7 +152,7 @@ uint64_t usb_is_device_get_video_in_size(CaptureScreensType capture_type, is_dev uint64_t usb_is_device_get_video_in_size(CaptureStatus* status) { - return usb_is_device_get_video_in_size(status->capture_type, ((const is_device_usb_device*)(status->device.descriptor))->device_type); + return usb_is_device_get_video_in_size(status->device_specific_status.is_status.capture_type, ((const is_device_usb_device*)(status->device.descriptor))->device_type); } @@ -443,7 +443,7 @@ void is_device_acquisition_main_loop(CaptureData* capture_data) { is_device_capture_recv_data[i].cb_data.is_data_ready = false; } SetupISDeviceAsyncThread((is_device_device_handlers*)capture_data->handle, is_device_capture_recv_data, &async_processing_thread, &is_done_thread, &has_data_been_processed); - capture_data->status.reset_hardware = false; + capture_data->status.device_specific_status.is_status.reset_hardware = false; switch(((const is_device_usb_device*)(capture_data->status.device.descriptor))->device_type) { case IS_NITRO_EMULATOR_DEVICE: is_nitro_acquisition_emulator_main_loop(capture_data, is_device_capture_recv_data); diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_capture.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_capture.cpp index a551546..176a76f 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_capture.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_capture.cpp @@ -41,8 +41,8 @@ static int StartAcquisitionCapture(CaptureData* capture_data, ISDeviceCaptureRec } static int LidReopenCaptureCheck(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType &curr_capture_type, CaptureSpeedsType &curr_capture_speed, bool* is_acquisition_off, uint32_t &index) { - curr_capture_type = capture_data->status.capture_type; - curr_capture_speed = capture_data->status.capture_speed; + curr_capture_type = capture_data->status.device_specific_status.is_status.capture_type; + curr_capture_speed = capture_data->status.device_specific_status.is_status.capture_speed; int ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, is_acquisition_off, index); if(ret < 0) return ret; @@ -54,8 +54,8 @@ static int LidReopenCaptureCheck(CaptureData* capture_data, ISDeviceCaptureRecei static int CaptureResetHardware(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data, CaptureScreensType &curr_capture_type, CaptureSpeedsType &curr_capture_speed, bool *is_acquisition_off, std::chrono::time_point &clock_last_reset, uint32_t &index) { 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; - bool reset_hardware = capture_data->status.reset_hardware; - capture_data->status.reset_hardware = false; + bool reset_hardware = capture_data->status.device_specific_status.is_status.reset_hardware; + capture_data->status.device_specific_status.is_status.reset_hardware = false; int ret = LIBUSB_SUCCESS; if(!reset_hardware) return ret; @@ -78,8 +78,8 @@ static int CaptureResetHardware(CaptureData* capture_data, ISDeviceCaptureReceiv return ret; if(!(*is_acquisition_off)) { default_sleep(SLEEP_RESET_TIME_MS); - curr_capture_type = capture_data->status.capture_type; - curr_capture_speed = capture_data->status.capture_speed; + curr_capture_type = capture_data->status.device_specific_status.is_status.capture_type; + curr_capture_speed = capture_data->status.device_specific_status.is_status.capture_speed; ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, is_acquisition_off, index); } if(ret < 0) @@ -104,8 +104,8 @@ int EndAcquisitionCapture(const is_device_usb_device* usb_device_desc, is_device void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCaptureReceivedData* is_device_capture_recv_data) { bool is_acquisition_off = true; uint32_t index = 0; - CaptureScreensType curr_capture_type = capture_data->status.capture_type; - CaptureSpeedsType curr_capture_speed = capture_data->status.capture_speed; + CaptureScreensType curr_capture_type = capture_data->status.device_specific_status.is_status.capture_type; + CaptureSpeedsType curr_capture_speed = capture_data->status.device_specific_status.is_status.capture_speed; int ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index); if(ret < 0) { capture_error_print(true, capture_data, "Capture Start: Failed"); @@ -142,14 +142,14 @@ void is_nitro_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceC } is_device_read_frame_request(capture_data, is_device_get_free_buffer(capture_data, is_device_capture_recv_data), curr_capture_type, index++); - if((curr_capture_type != capture_data->status.capture_type) || (curr_capture_speed != capture_data->status.capture_speed)) { + if((curr_capture_type != capture_data->status.device_specific_status.is_status.capture_type) || (curr_capture_speed != capture_data->status.device_specific_status.is_status.capture_speed)) { ret = EndAcquisition(capture_data, is_device_capture_recv_data, true, 0, curr_capture_type); if(ret < 0) { capture_error_print(true, capture_data, "Capture End: Failed"); return; } - curr_capture_type = capture_data->status.capture_type; - curr_capture_speed = capture_data->status.capture_speed; + curr_capture_type = capture_data->status.device_specific_status.is_status.capture_type; + curr_capture_speed = capture_data->status.device_specific_status.is_status.capture_speed; ret = StartAcquisitionCapture(capture_data, is_device_capture_recv_data, curr_capture_type, curr_capture_speed, &is_acquisition_off, index); if(ret < 0) { capture_error_print(true, capture_data, "Capture Restart: Failed"); diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_emulator.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_emulator.cpp index 249084f..d860475 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_emulator.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_nitro_acquisition_emulator.cpp @@ -324,8 +324,8 @@ void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISDevice uint16_t last_frame_counter = 0; float single_frame_time = 0; uint16_t curr_frame_counter = 0; - CaptureScreensType curr_capture_type = capture_data->status.capture_type; - CaptureSpeedsType curr_capture_speed = capture_data->status.capture_speed; + CaptureScreensType curr_capture_type = capture_data->status.device_specific_status.is_status.capture_type; + CaptureSpeedsType curr_capture_speed = capture_data->status.device_specific_status.is_status.capture_speed; int ret = StartAcquisitionEmulator(handlers, last_frame_counter, single_frame_time, curr_capture_type, curr_capture_speed, usb_device_desc); if (ret < 0) { capture_error_print(true, capture_data, "Capture Start: Failed"); @@ -351,8 +351,8 @@ void is_nitro_acquisition_emulator_main_loop(CaptureData* capture_data, ISDevice clock_last_reset = std::chrono::high_resolution_clock::now(); default_sleep(SLEEP_CHECKS_TIME_MS); } - capture_data->status.curr_delay = last_frame_counter % FRAME_BUFFER_SIZE; - ret = reset_acquisition_frames(capture_data, curr_frame_counter, last_frame_counter, single_frame_time, clock_last_reset, curr_capture_type, capture_data->status.capture_type, curr_capture_speed, capture_data->status.capture_speed, is_device_capture_recv_data); + capture_data->status.device_specific_status.is_status.curr_delay = last_frame_counter % FRAME_BUFFER_SIZE; + ret = reset_acquisition_frames(capture_data, curr_frame_counter, last_frame_counter, single_frame_time, clock_last_reset, curr_capture_type, capture_data->status.device_specific_status.is_status.capture_type, curr_capture_speed, capture_data->status.device_specific_status.is_status.capture_speed, is_device_capture_recv_data); if(ret < 0) { capture_error_print(true, capture_data, "Disconnected: Frame counter reset error"); break; diff --git a/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp b/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp index f447ebf..d33dbe8 100644 --- a/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp +++ b/source/CaptureDeviceSpecific/ISDevices/usb_is_twl_acquisition_capture.cpp @@ -100,8 +100,8 @@ static int process_frame_and_read(CaptureData* capture_data, int internal_index, static int CaptureResetHardware(CaptureData* capture_data, std::chrono::time_point &clock_last_reset) { 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; - bool reset_hardware = capture_data->status.reset_hardware; - capture_data->status.reset_hardware = false; + bool reset_hardware = capture_data->status.device_specific_status.is_status.reset_hardware; + capture_data->status.device_specific_status.is_status.reset_hardware = false; int ret = LIBUSB_SUCCESS; if(!reset_hardware) return ret; @@ -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.is_battery_percentage; - bool loaded_ac_adapter_connected = capture_data->status.is_ac_adapter_connected; + int loaded_battery_percentage = capture_data->status.device_specific_status.is_status.battery_percentage; + bool loaded_ac_adapter_connected = capture_data->status.device_specific_status.is_status.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; @@ -172,10 +172,10 @@ void is_twl_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCap const is_device_usb_device* usb_device_desc = (const is_device_usb_device*)capture_data->status.device.descriptor; bool is_acquisition_off = true; 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.is_battery_percentage; - bool curr_ac_adapter_connected = capture_data->status.is_ac_adapter_connected; + CaptureScreensType curr_capture_type = capture_data->status.device_specific_status.is_status.capture_type; + CaptureSpeedsType curr_capture_speed = capture_data->status.device_specific_status.is_status.capture_speed; + int curr_battery_percentage = capture_data->status.device_specific_status.is_status.battery_percentage; + bool curr_ac_adapter_connected = capture_data->status.device_specific_status.is_status.ac_adapter_connected; bool audio_enabled = true; bool reprocess = false; std::chrono::time_point clock_last_frame = std::chrono::high_resolution_clock::now(); @@ -235,7 +235,7 @@ void is_twl_acquisition_capture_main_loop(CaptureData* capture_data, ISDeviceCap return; } if(processed) { - curr_capture_speed = capture_data->status.capture_speed; + curr_capture_speed = capture_data->status.device_specific_status.is_status.capture_speed; ret = SetLastFrameInfo(handlers, video_address, video_length, audio_address, audio_length, usb_device_desc); if(ret < 0) { capture_error_print(true, capture_data, "Frame Info Set: Failed"); diff --git a/source/CaptureDeviceSpecific/Nisetro/cypress_nisetro_communications.cpp b/source/CaptureDeviceSpecific/Nisetro/cypress_nisetro_communications.cpp index a1a893e..620564a 100644 --- a/source/CaptureDeviceSpecific/Nisetro/cypress_nisetro_communications.cpp +++ b/source/CaptureDeviceSpecific/Nisetro/cypress_nisetro_communications.cpp @@ -33,7 +33,7 @@ #define NISETRO_DS_WANTED_VALUE_BASE 0xFC00 static const cyni_device_usb_device cypress_fx2_generic_device = { -.name = "FX2LP->NiseTro DS", .long_name = "EZ-USB FX2LP -> NiseTro DS(i)", +.name = "FX2> NiseTro DS", .long_name = "EZ-USB FX2LP -> NiseTro DS(i)", .device_type = CYPRESS_NISETRO_BLANK_DEVICE, .video_data_type = VIDEO_DATA_RGB, .firmware_to_load = nisetro_ds_fw, .firmware_size = nisetro_ds_fw_len, diff --git a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp index 7d80bd1..eb9647c 100644 --- a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp +++ b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp @@ -26,6 +26,8 @@ // No reverse engineering of the original software was done to create this. #define SYNCH_VALUE_OPTIMIZE 0xCC33 +#define SYNCH_VALUE_OPTIMIZE_OLD_FW_565 0xF800 +#define SYNCH_VALUE_OPTIMIZE_OLD_FW_888 0xFF00 #define TOTAL_WANTED_CONCURRENTLY_RUNNING_BUFFER_SIZE 0x100000 #define SINGLE_RING_BUFFER_SLICE_SIZE 0x4000 @@ -37,6 +39,7 @@ #define MAX_TIME_WAIT 1.0 #define CAPTURE_START_AGAIN_NO_KEY_TIME 260.0 +#define CAPTURE_START_FAILING_TIME_SINCE_LAST_PARAM_EDIT 180.0 #define OPTIMIZE_3DS_CYPRESS_USB_WINDOWS_DRIVER CYPRESS_WINDOWS_OPTIMIZE_USB_DRIVER @@ -72,6 +75,8 @@ static int get_cypress_device_status(CypressOptimize3DSDeviceCaptureReceivedData static void error_cypress_device_status(CypressOptimize3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val); static std::string read_key_for_device_id_from_file(uint64_t device_id, bool is_new_device); static void add_key_for_device_id_to_file(uint64_t device_id, std::string key, bool is_new_device); +static void read_old_firmware_config_from_file(uint64_t device_id, CaptureOptimizeOldFirmwareConfig* out_full, CaptureOptimizeOldFirmwareConfig* out_limited); +static void write_old_firmware_config_to_file(uint64_t device_id, CaptureOptimizeOldFirmwareConfig* to_save_full, CaptureOptimizeOldFirmwareConfig* to_save_limited); static cy_device_device_handlers* usb_find_by_serial_number(const cyop_device_usb_device* usb_device_desc, std::string wanted_serial_number, CaptureDevice* new_device) { cy_device_device_handlers* final_handlers = NULL; @@ -220,8 +225,13 @@ bool cyop_device_connect_usb(bool print_failed, CaptureData* capture_data, Captu return true; } -uint64_t cyop_device_get_video_in_size(bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { +uint64_t cyop_device_get_video_in_size(const cyop_device_usb_device* usb_device_info, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; + if(usb_device_info->is_old_firmware) { + if(is_rgb888) + return sizeof(USB8883DSOptimizeOldFirmwareCaptureReceived); + return sizeof(USB5653DSOptimizeOldFirmwareCaptureReceived); + } if(is_rgb888) { if(should_be_3d) { if(is_3d) @@ -235,8 +245,13 @@ uint64_t cyop_device_get_video_in_size(bool is_3d, bool should_be_3d, InputVideo return sizeof(USB5653DSOptimizeCaptureReceived); } -uint64_t cyop_device_get_video_in_size_extra_header(bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { +uint64_t cyop_device_get_video_in_size_extra_header(const cyop_device_usb_device* usb_device_info, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; + if(usb_device_info->is_old_firmware) { + if(is_rgb888) + return sizeof(USB8883DSOptimizeOldFirmwareCaptureReceived); + return sizeof(USB5653DSOptimizeOldFirmwareCaptureReceived); + } if(is_rgb888) { if(should_be_3d) { if(is_3d) @@ -252,7 +267,7 @@ uint64_t cyop_device_get_video_in_size_extra_header(bool is_3d, bool should_be_3 uint64_t cyop_device_get_video_in_size(CaptureStatus* status, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { - return cyop_device_get_video_in_size(is_3d, should_be_3d, video_data_type); + return cyop_device_get_video_in_size((const cyop_device_usb_device*)status->device.descriptor, is_3d, should_be_3d, video_data_type); } @@ -281,12 +296,25 @@ bool is_device_optimize_o3ds(CaptureDevice* device) { return does_device_match_type(device, CYPRESS_OPTIMIZE_OLD_3DS_INSTANTIATED_DEVICE); } +bool is_device_optimize_o2ds(CaptureDevice* device) { + const cyop_device_usb_device* usb_device_info = (const cyop_device_usb_device*)device->descriptor; + return usb_device_info->is_o2ds; +} + +bool is_device_optimize_old_fw(CaptureDevice* device) { + const cyop_device_usb_device* usb_device_info = (const cyop_device_usb_device*)device->descriptor; + return usb_device_info->is_old_firmware; +} + bool is_device_optimize_n3ds(CaptureDevice* device) { return does_device_match_type(device, CYPRESS_OPTIMIZE_NEW_3DS_INSTANTIATED_DEVICE); } static InputVideoDataType extract_wanted_input_video_data_type(CaptureStatus* capture_status) { - return capture_status->request_low_bw_format ? OPTIMIZE_RGB565_FORMAT : OPTIMIZE_RGB888_FORMAT; + const cyop_device_usb_device* usb_device_info = (const cyop_device_usb_device*)capture_status->device.descriptor; + if(usb_device_info->is_o2ds) + return capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds ? OPTIMIZE_RGB565_FORMAT : OPTIMIZE_RGB888_FORMAT; + return capture_status->device_specific_status.optimize_status.request_low_bw_format ? OPTIMIZE_RGB565_FORMAT : OPTIMIZE_RGB888_FORMAT; } static InputVideoDataType extract_wanted_input_video_data_type(CaptureData* capture_data) { @@ -299,6 +327,12 @@ static bool key_missing_capture_start_again_check_time(const std::chrono::time_p return diff.count() > CAPTURE_START_AGAIN_NO_KEY_TIME; } +static bool param_change_capture_allow_issues_time(const std::chrono::time_point &start_time) { + const auto curr_time = std::chrono::high_resolution_clock::now(); + const std::chrono::duration diff = curr_time - start_time; + return diff.count() <= CAPTURE_START_FAILING_TIME_SINCE_LAST_PARAM_EDIT; +} + static int cypress_device_read_frame_request(CaptureData* capture_data, CypressOptimize3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data, uint32_t index, bool is_3d, InputVideoDataType video_data_type) { if(cypress_device_capture_recv_data == NULL) return LIBUSB_SUCCESS; @@ -307,7 +341,7 @@ static int cypress_device_read_frame_request(CaptureData* capture_data, CypressO const cyop_device_usb_device* usb_device_info = (const cyop_device_usb_device*)capture_data->status.device.descriptor; cypress_device_capture_recv_data->index = index; cypress_device_capture_recv_data->cb_data.function = cypress_device_read_frame_cb; - //size_t read_size = cyop_device_get_video_in_size(is_3d, is_3d, video_data_type); + //size_t read_size = cyop_device_get_video_in_size(usb_device_info, is_3d, is_3d, video_data_type); size_t read_size = SINGLE_RING_BUFFER_SLICE_SIZE; int new_buffer_slice_index = ((*cypress_device_capture_recv_data->last_ring_buffer_slice_allocated) + 1) % NUM_TOTAL_OPTIMIZE_3DS_CYPRESS_BUFFERS; uint8_t* buffer = &cypress_device_capture_recv_data->ring_slice_buffer_arr[new_buffer_slice_index * SINGLE_RING_BUFFER_SLICE_SIZE]; @@ -364,104 +398,174 @@ static USB3DSOptimizeColumnInfo convert_to_column_info(uint16_t value) { return column_info; } -static bool get_expect_extra_header_in_buffer(uint16_t value) { +static USB3DSOptimizeOldFirmwareColumnInfo convert_to_column_info_old_fw(uint16_t value) { + // The macos compiler requires this... :/ + USB3DSOptimizeOldFirmwareColumnInfo column_info; + column_info.is_first_column = (value >> 15) & 1; + column_info.extra_column_data = (value >> 13) & 3; + column_info.column_index = (value >> 4) & 0x1FF; + column_info.fixed = value & 0x0F; + return column_info; +} + +static bool get_expect_extra_header_in_buffer(const cyop_device_usb_device* usb_device_desc, uint16_t value) { + if(usb_device_desc->is_old_firmware) + return false; return convert_to_column_info(value).has_extra_header_data_2d_only; } -static bool get_is_data_2d_only(uint16_t value) { +static bool get_is_data_2d_only(const cyop_device_usb_device* usb_device_desc, uint16_t value) { + if(usb_device_desc->is_o2ds) + return true; return convert_to_column_info(value).has_extra_header_data_2d_only; } -static bool get_is_pos_column_synch_in_buffer(uint8_t* buffer, size_t pos_to_check, uint16_t column_index) { +static bool is_old_fw_column_magic_valid(USB3DSOptimizeOldFirmwareColumnInfo old_fw_column_info, uint16_t magic, uint16_t expected_magic_value) { + if(old_fw_column_info.fixed != 5) + return false; + if((old_fw_column_info.column_index == 1) && (magic != 0)) + return false; + if((old_fw_column_info.column_index != 1) && (magic != expected_magic_value)) + return false; + if((old_fw_column_info.column_index == 0) && (old_fw_column_info.is_first_column == 0)) + return false; + if((old_fw_column_info.column_index != 0) && (old_fw_column_info.is_first_column != 0)) + return false; + return true; +} + +static bool get_is_pos_column_synch_in_buffer(const cyop_device_usb_device* usb_device_desc, bool is_rgb888, uint8_t* buffer, size_t pos_to_check, uint16_t column_index) { + if(usb_device_desc->is_old_firmware) { + USB3DSOptimizeOldFirmwareColumnInfo old_fw_column_info = convert_to_column_info_old_fw(read_le16(buffer + pos_to_check + 8)); + uint16_t magic = read_le16(buffer + pos_to_check); + if(is_rgb888) { + magic ^= 0xA5A5; // For some reason, all bytes are xorred with 0xA5 for Old FW RGB888... + old_fw_column_info = convert_to_column_info_old_fw(read_le16(buffer + pos_to_check + 2) ^ 0xA5A5); + // extra_column_data is 1 for rgb888 on 2ds...? Would make sense, as it is 2d only... + if(!is_old_fw_column_magic_valid(old_fw_column_info, magic, SYNCH_VALUE_OPTIMIZE_OLD_FW_888)) + return false; + return old_fw_column_info.column_index == column_index; + } + // extra_column_data is 0 for rgb565...? + if(!is_old_fw_column_magic_valid(old_fw_column_info, magic, SYNCH_VALUE_OPTIMIZE_OLD_FW_565)) + return false; + return old_fw_column_info.column_index == column_index; + } if(read_le16(buffer + pos_to_check) != SYNCH_VALUE_OPTIMIZE) return false; return convert_to_column_info(read_le16(buffer + pos_to_check + 2)).column_index == column_index; } -static bool get_is_pos_column_synch_in_buffer(USB3DSOptimizeHeaderSoundData* in_ptr, uint16_t column_index) { - return get_is_pos_column_synch_in_buffer((uint8_t*)&in_ptr->header_info, 0, column_index); +static bool get_is_pos_column_synch_in_buffer(const cyop_device_usb_device* usb_device_desc, bool is_rgb888, uint8_t* buffer, uint16_t column_index) { + return get_is_pos_column_synch_in_buffer(usb_device_desc, is_rgb888, buffer, 0, column_index); } -static bool get_is_pos_first_synch_in_buffer(uint8_t* buffer, size_t pos_to_check) { - return get_is_pos_column_synch_in_buffer(buffer, pos_to_check, 0); +static bool get_is_pos_first_synch_in_buffer(const cyop_device_usb_device* usb_device_desc, bool is_rgb888, uint8_t* buffer, size_t pos_to_check) { + return get_is_pos_column_synch_in_buffer(usb_device_desc, is_rgb888, buffer, pos_to_check, 0); } -static bool get_is_buffer_rgb565_fully_synced(CaptureReceived* buffer) { +static bool get_is_pos_first_synch_in_buffer(const cyop_device_usb_device* usb_device_desc, InputVideoDataType video_data_type, uint8_t* buffer, size_t pos_to_check) { + return get_is_pos_first_synch_in_buffer(usb_device_desc, video_data_type == OPTIMIZE_RGB888_FORMAT, buffer, pos_to_check); +} + +static bool get_is_buffer_rgb565_fully_synced(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer) { USB5653DSOptimizeCaptureReceived* real_buffer = &buffer->cypress_optimize_received_565; USB5653DSOptimizeCaptureReceivedExtraHeader* real_buffer_special = &buffer->cypress_optimize_received_565_extra_header; - bool is_special = get_expect_extra_header_in_buffer(read_le16((uint8_t*)&real_buffer->columns_data[0].header_sound.header_info.column_info)); + bool is_special = get_expect_extra_header_in_buffer(usb_device_desc, read_le16((uint8_t*)&real_buffer->columns_data[0].header_sound.header_info.column_info)); for(int i = 0; i < TOP_WIDTH_3DS; i++) - if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].header_sound, i)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, false, (uint8_t*)&real_buffer->columns_data[i].header_sound, i)) return false; - if(is_special && (!get_is_pos_column_synch_in_buffer(&real_buffer_special->columns_data[TOP_WIDTH_3DS].header_sound, TOP_WIDTH_3DS))) + if(is_special && (!get_is_pos_column_synch_in_buffer(usb_device_desc, false, (uint8_t*)&real_buffer_special->columns_data[TOP_WIDTH_3DS].header_sound, TOP_WIDTH_3DS))) return false; return true; } -static bool get_is_buffer_rgb565_3d_fully_synced(CaptureReceived* buffer) { +static bool get_is_buffer_rgb565_3d_fully_synced(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer) { USB5653DSOptimizeCaptureReceived_3D* real_buffer = &buffer->cypress_optimize_received_565_3d; for(int i = 0; i < TOP_WIDTH_3DS; i++) { - if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].top_r_screen_column.header_sound, i * 2)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, false, (uint8_t*)&real_buffer->columns_data[i].top_r_screen_column.header_sound, i * 2)) return false; - if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].bot_top_l_screens_column.header_sound, (i * 2) + 1)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, false, (uint8_t*)&real_buffer->columns_data[i].bot_top_l_screens_column.header_sound, (i * 2) + 1)) return false; } - if(!get_is_pos_column_synch_in_buffer(&real_buffer->bottom_only_column.header_sound, TOP_WIDTH_3DS * 2)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, false, (uint8_t*)&real_buffer->bottom_only_column.header_sound, TOP_WIDTH_3DS * 2)) return false; return true; } -static bool get_is_buffer_rgb888_fully_synced(CaptureReceived* buffer) { +static bool get_is_buffer_rgb565_old_firmware_fully_synced(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer) { + USB5653DSOptimizeOldFirmwareCaptureReceived* real_buffer = &buffer->cypress_optimize_old_firmware_received_565; + for(int i = 0; i < TOP_WIDTH_3DS + 1; i++) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, false, (uint8_t*)&real_buffer->columns_data[i].header, i)) { + return false; + } + return true; +} + +static bool get_is_buffer_rgb888_fully_synced(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer) { USB8883DSOptimizeCaptureReceived* real_buffer = &buffer->cypress_optimize_received_888; USB8883DSOptimizeCaptureReceivedExtraHeader* real_buffer_special = &buffer->cypress_optimize_received_888_extra_header; - bool is_special = get_expect_extra_header_in_buffer(read_le16((uint8_t*)&real_buffer->columns_data[0].header_sound.header_info.column_info)); + bool is_special = get_expect_extra_header_in_buffer(usb_device_desc, read_le16((uint8_t*)&real_buffer->columns_data[0].header_sound.header_info.column_info)); for(int i = 0; i < TOP_WIDTH_3DS; i++) - if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].header_sound, i)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, true, (uint8_t*)&real_buffer->columns_data[i].header_sound, i)) return false; - if(is_special && (!get_is_pos_column_synch_in_buffer(&real_buffer_special->columns_data[TOP_WIDTH_3DS].header_sound, TOP_WIDTH_3DS))) + if(is_special && (!get_is_pos_column_synch_in_buffer(usb_device_desc, true, (uint8_t*)&real_buffer_special->columns_data[TOP_WIDTH_3DS].header_sound, TOP_WIDTH_3DS))) return false; return true; } -static bool get_is_buffer_rgb888_3d_fully_synced(CaptureReceived* buffer) { +static bool get_is_buffer_rgb888_3d_fully_synced(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer) { USB8883DSOptimizeCaptureReceived_3D* real_buffer = &buffer->cypress_optimize_received_888_3d; for(int i = 0; i < TOP_WIDTH_3DS; i++) { - if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i][0].header_sound, i * 2)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, true, (uint8_t*)&real_buffer->columns_data[i][0].header_sound, i * 2)) return false; - if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i][1].header_sound, (i * 2) + 1)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, true, (uint8_t*)&real_buffer->columns_data[i][1].header_sound, (i * 2) + 1)) return false; } - if(!get_is_pos_column_synch_in_buffer(&real_buffer->bottom_only_column.header_sound, TOP_WIDTH_3DS * 2)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, true, (uint8_t*)&real_buffer->bottom_only_column.header_sound, TOP_WIDTH_3DS * 2)) return false; return true; } -static bool get_is_buffer_rgb888_3d_2d_fully_synced(CaptureReceived* buffer) { +static bool get_is_buffer_rgb888_3d_2d_fully_synced(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer) { USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen* real_buffer = &buffer->cypress_optimize_received_888_3d_2d; for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) { - if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].header_sound, i)) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, true, (uint8_t*)&real_buffer->columns_data[i].header_sound, i)) return false; } return true; } -static bool get_is_buffer_fully_synched(CaptureReceived* buffer, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { - bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; - if(!is_rgb888) { - if(!is_3d) - return get_is_buffer_rgb565_fully_synced(buffer); - return get_is_buffer_rgb565_3d_fully_synced(buffer); - } - if(is_3d) - return get_is_buffer_rgb888_3d_fully_synced(buffer); - if(should_be_3d) - return get_is_buffer_rgb888_3d_2d_fully_synced(buffer); - return get_is_buffer_rgb888_fully_synced(buffer); +static bool get_is_buffer_rgb888_old_firmware_fully_synced(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer) { + USB8883DSOptimizeOldFirmwareCaptureReceived* real_buffer = &buffer->cypress_optimize_old_firmware_received_888; + for(int i = 0; i < TOP_WIDTH_3DS + 1; i++) + if(!get_is_pos_column_synch_in_buffer(usb_device_desc, true, (uint8_t*)&real_buffer->columns_data[i].header_sound, i)) + return false; + return true; } -static size_t get_pos_first_synch_in_buffer(uint8_t* buffer, size_t start_pos) { +static bool get_is_buffer_fully_synched(const cyop_device_usb_device* usb_device_desc, CaptureReceived* buffer, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { + bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; + if(usb_device_desc->is_old_firmware) { + if(is_rgb888) + return get_is_buffer_rgb888_old_firmware_fully_synced(usb_device_desc, buffer); + return get_is_buffer_rgb565_old_firmware_fully_synced(usb_device_desc, buffer); + } + if(!is_rgb888) { + if(!is_3d) + return get_is_buffer_rgb565_fully_synced(usb_device_desc, buffer); + return get_is_buffer_rgb565_3d_fully_synced(usb_device_desc, buffer); + } + if(is_3d) + return get_is_buffer_rgb888_3d_fully_synced(usb_device_desc, buffer); + if(should_be_3d) + return get_is_buffer_rgb888_3d_2d_fully_synced(usb_device_desc, buffer); + return get_is_buffer_rgb888_fully_synced(usb_device_desc, buffer); +} + +static size_t get_pos_first_synch_in_buffer(const cyop_device_usb_device* usb_device_desc, InputVideoDataType video_data_type, uint8_t* buffer, size_t start_pos) { for(size_t i = (start_pos / 2); i < (SINGLE_RING_BUFFER_SLICE_SIZE / 2); i++) { - if(get_is_pos_first_synch_in_buffer(buffer, i * 2)) + if(get_is_pos_first_synch_in_buffer(usb_device_desc, video_data_type, buffer, i * 2)) return i * 2; } return SINGLE_RING_BUFFER_SLICE_SIZE + 1; @@ -494,14 +598,27 @@ static void copy_slice_data_to_buffer(uint8_t* dst, uint8_t *src, size_t start_s } } +static void process_data_buffer(const cyop_device_usb_device* usb_device_desc, InputVideoDataType video_data_type, uint64_t* data, size_t size) { + if(!usb_device_desc->is_old_firmware) + return; + bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; + if(!is_rgb888) + return; + // Annoying, but needed to simplify code elsewhere... + for(size_t i = 0; i < (size / sizeof(uint64_t)); i++) + data[i] ^= 0xA5A5A5A5A5A5A5A5; +} + static void cypress_output_to_thread(CaptureData* capture_data, uint8_t *buffer_arr, size_t start_slice_index, size_t start_slice_pos, int internal_index, std::chrono::time_point* clock_start, size_t read_size, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { // Output to the other threads... + const cyop_device_usb_device* usb_device_desc = (const cyop_device_usb_device*)capture_data->status.device.descriptor; CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(internal_index); copy_slice_data_to_buffer((uint8_t*)&data_buf->capture_buf, buffer_arr, start_slice_index, start_slice_pos, read_size); - if(!get_is_buffer_fully_synched(&data_buf->capture_buf, is_3d, should_be_3d, video_data_type)) { + if(!get_is_buffer_fully_synched(usb_device_desc, &data_buf->capture_buf, is_3d, should_be_3d, video_data_type)) { capture_data->data_buffers.ReleaseWriterBuffer(internal_index, false); return; } + process_data_buffer(usb_device_desc, video_data_type, (uint64_t*)&data_buf->capture_buf, read_size); const auto curr_time = std::chrono::high_resolution_clock::now(); const std::chrono::duration diff = curr_time - (*clock_start); *clock_start = curr_time; @@ -513,6 +630,8 @@ static void cypress_output_to_thread(CaptureData* capture_data, uint8_t *buffer_ } static bool cypress_device_read_frame_not_synchronized(CypressOptimize3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data, int &error) { + const cyop_device_usb_device* usb_device_desc = (const cyop_device_usb_device*)cypress_device_capture_recv_data->capture_data->status.device.descriptor; + InputVideoDataType video_data_type = *cypress_device_capture_recv_data->stored_video_data_type; volatile int first_slice_to_check = *cypress_device_capture_recv_data->first_usable_ring_buffer_slice_index; volatile int original_first_slice_to_check = first_slice_to_check; volatile int first_slice_pos_to_check = (int)*cypress_device_capture_recv_data->last_used_ring_buffer_slice_pos; @@ -541,7 +660,7 @@ static bool cypress_device_read_frame_not_synchronized(CypressOptimize3DSDeviceC // Increase by two to prevent looping... if(check_index == original_first_slice_to_check) start_result = first_slice_pos_to_check + 2; - size_t result = get_pos_first_synch_in_buffer(&cypress_device_capture_recv_data->ring_slice_buffer_arr[check_index * SINGLE_RING_BUFFER_SLICE_SIZE], start_result); + size_t result = get_pos_first_synch_in_buffer(usb_device_desc, video_data_type, &cypress_device_capture_recv_data->ring_slice_buffer_arr[check_index * SINGLE_RING_BUFFER_SLICE_SIZE], start_result); if(result >= SINGLE_RING_BUFFER_SLICE_SIZE) { unlock_buffer_slice_index(cypress_device_capture_recv_data, check_index, true); } @@ -558,28 +677,41 @@ static bool cypress_device_read_frame_not_synchronized(CypressOptimize3DSDeviceC return true; } +static size_t get_header_size_optimize_packet(const cyop_device_usb_device* usb_device_desc, InputVideoDataType video_data_type) { + if(!usb_device_desc->is_old_firmware) + return sizeof(USB3DSOptimizeHeaderData); + bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; + if(is_rgb888) + return sizeof(USB8883DSOptimizeOldFirmwareHeaderData); + return sizeof(USB5653DSOptimizeOldFirmwareHeaderData); +} + static void cypress_device_read_frame_synchronized(CypressOptimize3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data) { + const cyop_device_usb_device* usb_device_desc = (const cyop_device_usb_device*)cypress_device_capture_recv_data->capture_data->status.device.descriptor; volatile int read_slice_index = *cypress_device_capture_recv_data->first_usable_ring_buffer_slice_index; volatile size_t read_slice_pos = *cypress_device_capture_recv_data->last_used_ring_buffer_slice_pos; int num_consecutive_ready_buffers = get_num_consecutive_ready_ring_buffer_slices(cypress_device_capture_recv_data, read_slice_index); bool should_be_3d_data = *cypress_device_capture_recv_data->stored_is_3d; + if(usb_device_desc->is_o2ds) + should_be_3d_data = false; bool is_3d_data = should_be_3d_data; InputVideoDataType video_data_type = *cypress_device_capture_recv_data->stored_video_data_type; - size_t video_in_size = (size_t)cyop_device_get_video_in_size(is_3d_data, should_be_3d_data, video_data_type); + size_t video_in_size = (size_t)cyop_device_get_video_in_size(usb_device_desc, is_3d_data, should_be_3d_data, video_data_type); size_t curr_consecutive_available_bytes = (num_consecutive_ready_buffers * SINGLE_RING_BUFFER_SLICE_SIZE) - read_slice_pos; - if(curr_consecutive_available_bytes >= sizeof(USB3DSOptimizeHeaderData)) { - uint8_t tmp_buffer[sizeof(USB3DSOptimizeHeaderData)]; - copy_slice_data_to_buffer(tmp_buffer, cypress_device_capture_recv_data->ring_slice_buffer_arr, read_slice_index, read_slice_pos, sizeof(USB3DSOptimizeHeaderData)); - if(!get_is_pos_first_synch_in_buffer(tmp_buffer, 0)) { + size_t header_packet_size = get_header_size_optimize_packet(usb_device_desc, video_data_type); + if(curr_consecutive_available_bytes >= header_packet_size) { + uint8_t tmp_buffer[sizeof(USB5653DSOptimizeOldFirmwareHeaderData)]; + copy_slice_data_to_buffer(tmp_buffer, cypress_device_capture_recv_data->ring_slice_buffer_arr, read_slice_index, read_slice_pos, header_packet_size); + if(!get_is_pos_first_synch_in_buffer(usb_device_desc, video_data_type, tmp_buffer, 0)) { *cypress_device_capture_recv_data->is_synchronized = false; return; } else { - if(get_expect_extra_header_in_buffer(read_le16(tmp_buffer, 1))) - video_in_size = (size_t)cyop_device_get_video_in_size_extra_header(is_3d_data, should_be_3d_data, video_data_type); - if(get_is_data_2d_only(read_le16(tmp_buffer, 1))) { + if(get_expect_extra_header_in_buffer(usb_device_desc, read_le16(tmp_buffer, 1))) + video_in_size = (size_t)cyop_device_get_video_in_size_extra_header(usb_device_desc, is_3d_data, should_be_3d_data, video_data_type); + if(get_is_data_2d_only(usb_device_desc, read_le16(tmp_buffer, 1))) { is_3d_data = false; - video_in_size = (size_t)cyop_device_get_video_in_size_extra_header(is_3d_data, should_be_3d_data, video_data_type); + video_in_size = (size_t)cyop_device_get_video_in_size_extra_header(usb_device_desc, is_3d_data, should_be_3d_data, video_data_type); } } } @@ -791,7 +923,26 @@ static void reset_buffer_processing_data(CypressOptimize3DSDeviceCaptureReceived } } -static int restart_captures_cc_reads(CaptureData* capture_data, CypressOptimize3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data, uint32_t &index, InputVideoDataType &stored_video_data_type, bool &stored_is_3d, bool could_use_3d, bool force_capture_start, std::string read_key, std::chrono::time_point &clock_last_capture_start) { +static bool are_old_fw_config_cases_different(CaptureOptimizeOldFirmwareConfigCase &first, CaptureOptimizeOldFirmwareConfigCase &second) { + return (first.low_screen_clock != second.low_screen_clock) || (first.top_screen_clock != second.top_screen_clock) || (first.top_screen_data != second.top_screen_data) || (first.top_screen_sync != second.top_screen_sync); +} + +static bool are_old_fw_configs_different(CaptureOptimizeOldFirmwareConfig &first, CaptureOptimizeOldFirmwareConfig &second) { + return are_old_fw_config_cases_different(first.mode_2d_only, second.mode_2d_only) || are_old_fw_config_cases_different(first.mode_regular, second.mode_regular); +} + +static bool are_there_changes_present_to_old_fw_config(CaptureData* capture_data, InputVideoDataType &stored_video_data_type, CaptureOptimizeOldFirmwareConfig &stored_old_fw_cfg_full, CaptureOptimizeOldFirmwareConfig &stored_old_fw_cfg_limited) { + const cyop_device_usb_device* usb_device_desc = (const cyop_device_usb_device*)capture_data->status.device.descriptor; + if(!usb_device_desc->is_old_firmware) + return false; + + if(stored_video_data_type == OPTIMIZE_RGB888_FORMAT) + return are_old_fw_configs_different(capture_data->status.device_specific_status.optimize_status.old_fw_config_full_bw_format, stored_old_fw_cfg_full); + + return are_old_fw_configs_different(capture_data->status.device_specific_status.optimize_status.old_fw_config_low_bw_format, stored_old_fw_cfg_limited); +} + +static int restart_captures_cc_reads(CaptureData* capture_data, CypressOptimize3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data, uint64_t device_id, uint32_t &index, InputVideoDataType &stored_video_data_type, bool &stored_is_3d, bool could_use_3d, CaptureOptimizeOldFirmwareConfig &stored_old_fw_cfg_full, CaptureOptimizeOldFirmwareConfig &stored_old_fw_cfg_limited, bool force_capture_start, std::string read_key, std::chrono::time_point &clock_last_capture_start, std::chrono::time_point &clock_last_param_edit) { cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle; const cyop_device_usb_device* usb_device_desc = (const cyop_device_usb_device*)capture_data->status.device.descriptor; int retval = end_capture_from_capture_data(capture_data); @@ -809,6 +960,7 @@ static int restart_captures_cc_reads(CaptureData* capture_data, CypressOptimize3 std::string read_key_dummy; retval = capture_start(handlers, usb_device_desc, false, stored_video_data_type == OPTIMIZE_RGB888_FORMAT, device_id_dummy, read_key_dummy); clock_last_capture_start = std::chrono::high_resolution_clock::now(); + clock_last_param_edit = std::chrono::high_resolution_clock::now(); // Changing the format changes the loaded parameters... capture_data->status.device.video_data_type = stored_video_data_type; if(retval < 0) return retval; @@ -821,7 +973,15 @@ static int restart_captures_cc_reads(CaptureData* capture_data, CypressOptimize3 } if(set_max_again) - CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(stored_is_3d, stored_is_3d, stored_video_data_type)); + CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(usb_device_desc, stored_is_3d, stored_is_3d, stored_video_data_type)); + + bool present_new_old_fw_config = are_there_changes_present_to_old_fw_config(capture_data, stored_video_data_type, stored_old_fw_cfg_full, stored_old_fw_cfg_limited); + if(present_new_old_fw_config) { + stored_old_fw_cfg_full = capture_data->status.device_specific_status.optimize_status.old_fw_config_full_bw_format; + stored_old_fw_cfg_limited = capture_data->status.device_specific_status.optimize_status.old_fw_config_low_bw_format; + write_old_firmware_config_to_file(device_id, &stored_old_fw_cfg_full, &stored_old_fw_cfg_limited); + clock_last_param_edit = std::chrono::high_resolution_clock::now(); + } index = 0; reset_buffer_processing_data(cypress_device_capture_recv_data); @@ -829,7 +989,8 @@ static int restart_captures_cc_reads(CaptureData* capture_data, CypressOptimize3 if(!schedule_all_reads(capture_data, cypress_device_capture_recv_data, index, stored_video_data_type, stored_is_3d, "")) return -1; capture_data->status.cooldown_curr_in = FIX_PARTIAL_FIRST_FRAME_NUM; - StartCaptureDma(handlers, usb_device_desc, stored_video_data_type == OPTIMIZE_RGB888_FORMAT, stored_is_3d, read_key); + CaptureOptimizeOldFirmwareConfig* to_use_old_fw_cfg = stored_video_data_type == OPTIMIZE_RGB888_FORMAT ? &stored_old_fw_cfg_full : &stored_old_fw_cfg_limited; + StartCaptureDma(handlers, usb_device_desc, stored_video_data_type == OPTIMIZE_RGB888_FORMAT, stored_is_3d, to_use_old_fw_cfg, read_key); return 0; } @@ -854,7 +1015,7 @@ static void cyop_key_check_and_interrogate_file(CaptureStatus* capture_status, c capture_status->device.device_id = device_id; capture_status->device.key = read_key; - capture_status->key_updated = false; + capture_status->device_specific_status.optimize_status.key_updated = false; } static bool cyop_device_acquisition_loop(CaptureData* capture_data, CypressOptimize3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data, InputVideoDataType &stored_video_data_type, bool &stored_is_3d, bool could_use_3d) { @@ -864,35 +1025,47 @@ static bool cyop_device_acquisition_loop(CaptureData* capture_data, CypressOptim uint64_t device_id = 0; std::string read_key = ""; bool force_capture_start_key = false; + CaptureOptimizeOldFirmwareConfig stored_old_fw_cfg_full = {}; + CaptureOptimizeOldFirmwareConfig stored_old_fw_cfg_limited = {}; int ret = capture_start(handlers, usb_device_desc, true, stored_video_data_type == OPTIMIZE_RGB888_FORMAT, device_id, read_key); capture_data->status.title_check_id += 1; - capture_data->status.key_updated = false; + capture_data->status.device_specific_status.optimize_status.key_updated = false; std::chrono::time_point clock_last_capture_start = std::chrono::high_resolution_clock::now(); + std::chrono::time_point clock_last_param_edit = std::chrono::high_resolution_clock::now(); bool is_key_valid = false; cyop_key_check_and_interrogate_file(&capture_data->status, usb_device_desc, device_id, is_key_valid, read_key); + + if(usb_device_desc->is_old_firmware) + read_old_firmware_config_from_file(device_id, &stored_old_fw_cfg_full, &stored_old_fw_cfg_limited); + capture_data->status.device_specific_status.optimize_status.old_fw_config_full_bw_format = stored_old_fw_cfg_full; + capture_data->status.device_specific_status.optimize_status.old_fw_config_low_bw_format = stored_old_fw_cfg_limited; + capture_data->status.device.video_data_type = stored_video_data_type; if (ret < 0) { capture_error_print(true, capture_data, "Capture Start: Failed"); return false; } - CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(stored_is_3d, stored_is_3d, stored_video_data_type)); + + CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(usb_device_desc, stored_is_3d, stored_is_3d, stored_video_data_type)); if(!schedule_all_reads(capture_data, cypress_device_capture_recv_data, index, stored_video_data_type, stored_is_3d, "Initial Reads: Failed")) return false; - StartCaptureDma(handlers, usb_device_desc, stored_video_data_type == OPTIMIZE_RGB888_FORMAT, stored_is_3d, read_key); + CaptureOptimizeOldFirmwareConfig* to_use_old_fw_cfg = stored_video_data_type == OPTIMIZE_RGB888_FORMAT ? &stored_old_fw_cfg_full : &stored_old_fw_cfg_limited; + StartCaptureDma(handlers, usb_device_desc, stored_video_data_type == OPTIMIZE_RGB888_FORMAT, stored_is_3d, to_use_old_fw_cfg, read_key); while (capture_data->status.connected && capture_data->status.running) { ret = get_cypress_device_status(cypress_device_capture_recv_data); + if(ret < 0) { int cause_error = ret; capture_data->status.cooldown_curr_in = FIX_PARTIAL_FIRST_FRAME_NUM + NUM_OPTIMIZE_3DS_CYPRESS_CONCURRENTLY_RUNNING_BUFFERS; wait_all_cypress_device_buffers_free(capture_data, cypress_device_capture_recv_data); bool has_recovered = false; - if(cause_error == LIBUSB_ERROR_TIMEOUT) { + if((cause_error == LIBUSB_ERROR_TIMEOUT) || ((cause_error == LIBUSB_ERROR_OTHER) && usb_device_desc->is_old_firmware && param_change_capture_allow_issues_time(clock_last_param_edit))) { force_capture_start_key = (!check_key_matches_device_id(device_id, read_key, usb_device_desc)) && key_missing_capture_start_again_check_time(clock_last_capture_start); cyop_key_check_and_interrogate_file(&capture_data->status, usb_device_desc, device_id, is_key_valid, read_key); - int timeout_ret = restart_captures_cc_reads(capture_data, cypress_device_capture_recv_data, index, stored_video_data_type, stored_is_3d, could_use_3d, force_capture_start_key, read_key, clock_last_capture_start); + int timeout_ret = restart_captures_cc_reads(capture_data, cypress_device_capture_recv_data, device_id, index, stored_video_data_type, stored_is_3d, could_use_3d, stored_old_fw_cfg_full, stored_old_fw_cfg_limited, force_capture_start_key, read_key, clock_last_capture_start, clock_last_param_edit); if(timeout_ret >= 0) { has_recovered = true; if(force_capture_start_key && (!is_key_valid)) @@ -904,14 +1077,16 @@ static bool cyop_device_acquisition_loop(CaptureData* capture_data, CypressOptim return false; } } + bool is_new_3d = could_use_3d && get_3d_enabled(&capture_data->status); + bool present_new_old_fw_config = are_there_changes_present_to_old_fw_config(capture_data, stored_video_data_type, stored_old_fw_cfg_full, stored_old_fw_cfg_limited); InputVideoDataType wanted_input_video_data_type = extract_wanted_input_video_data_type(capture_data); force_capture_start_key = (!is_key_valid) && (!check_key_matches_device_id(device_id, read_key, usb_device_desc)) && key_missing_capture_start_again_check_time(clock_last_capture_start); - if((wanted_input_video_data_type != stored_video_data_type) || (is_new_3d != stored_is_3d) || force_capture_start_key || capture_data->status.key_updated) { + if((wanted_input_video_data_type != stored_video_data_type) || (is_new_3d != stored_is_3d) || force_capture_start_key || capture_data->status.device_specific_status.optimize_status.key_updated || present_new_old_fw_config) { capture_data->status.cooldown_curr_in = FIX_PARTIAL_FIRST_FRAME_NUM + NUM_OPTIMIZE_3DS_CYPRESS_CONCURRENTLY_RUNNING_BUFFERS; wait_all_cypress_device_buffers_free(capture_data, cypress_device_capture_recv_data); cyop_key_check_and_interrogate_file(&capture_data->status, usb_device_desc, device_id, is_key_valid, read_key); - ret = restart_captures_cc_reads(capture_data, cypress_device_capture_recv_data, index, stored_video_data_type, stored_is_3d, could_use_3d, force_capture_start_key, read_key, clock_last_capture_start); + ret = restart_captures_cc_reads(capture_data, cypress_device_capture_recv_data, device_id, index, stored_video_data_type, stored_is_3d, could_use_3d, stored_old_fw_cfg_full, stored_old_fw_cfg_limited, force_capture_start_key, read_key, clock_last_capture_start, clock_last_param_edit); if(ret < 0) { capture_error_print(true, capture_data, "Disconnected: Update mode error"); return false; @@ -1012,6 +1187,106 @@ void usb_cyop_device_acquisition_cleanup(CaptureData* capture_data) { capture_data->handle = NULL; } +static std::string get_old_fw_config_file_path(uint64_t device_id) { + std::string path = get_base_path_device_specific_configs(); + + path += "optimize_old_fw_" + to_hex_u60(device_id) + ".txt"; + return path; +} + +static std::string write_old_firmware_config_case_string(std::string base, CaptureOptimizeOldFirmwareConfigCase* config_case) { + std::string out_str = ""; + + out_str += base + "_low_screen_clk" + "=" + std::to_string(config_case->low_screen_clock) + "\n"; + out_str += base + "_top_screen_clk" + "=" + std::to_string(config_case->top_screen_clock) + "\n"; + out_str += base + "_top_screen_data" + "=" + std::to_string(config_case->top_screen_data) + "\n"; + out_str += base + "_top_screen_sync" + "=" + std::to_string(config_case->top_screen_sync) + "\n"; + + return out_str; +} + +static bool read_old_firmware_config_case_string(std::string key, std::string value, std::string base, CaptureOptimizeOldFirmwareConfigCase* config_case) { + + if(key == (base + "_low_screen_clk")) { + config_case->low_screen_clock = std::stoi(value); + return true; + } + + if(key == (base + "_top_screen_clk")) { + config_case->top_screen_clock = std::stoi(value); + return true; + } + + if(key == (base + "_top_screen_data")) { + config_case->top_screen_data = std::stoi(value); + return true; + } + + if(key == (base + "_top_screen_sync")) { + config_case->top_screen_sync = std::stoi(value); + return true; + } + + return false; +} + +static void read_old_firmware_config_from_file(uint64_t device_id, CaptureOptimizeOldFirmwareConfig* out_full, CaptureOptimizeOldFirmwareConfig* out_limited) { + std::ifstream file(get_old_fw_config_file_path(device_id)); + std::string line; + + *out_full = {}; + *out_limited = {}; + sanitize_capture_optimize_old_fw_config(out_full); + sanitize_capture_optimize_old_fw_config(out_limited); + + if((!file) || (!file.is_open()) || (!file.good())) + return; + + try { + while(std::getline(file, line)) { + std::istringstream kvp(line); + std::string key; + + if(std::getline(kvp, key, '=')) { + std::string value; + + if(std::getline(kvp, value)) { + if(read_old_firmware_config_case_string(key, value, "full_2d_mode", &out_full->mode_2d_only)) + continue; + + if(read_old_firmware_config_case_string(key, value, "full_regular_mode", &out_full->mode_regular)) + continue; + + if(read_old_firmware_config_case_string(key, value, "limited_2d_mode", &out_limited->mode_2d_only)) + continue; + + if(read_old_firmware_config_case_string(key, value, "limited_regular_mode", &out_limited->mode_regular)) + continue; + } + } + } + } + catch(...) { + } + + sanitize_capture_optimize_old_fw_config(out_full); + sanitize_capture_optimize_old_fw_config(out_limited); +} + +static void write_old_firmware_config_to_file(uint64_t device_id, CaptureOptimizeOldFirmwareConfig* to_save_full, CaptureOptimizeOldFirmwareConfig* to_save_limited) { + std::ofstream file(get_old_fw_config_file_path(device_id)); + if(!file.good()) + return; + + file << write_old_firmware_config_case_string("full_2d_mode", &to_save_full->mode_2d_only); + file << write_old_firmware_config_case_string("full_regular_mode", &to_save_full->mode_regular); + + file << write_old_firmware_config_case_string("limited_2d_mode", &to_save_limited->mode_2d_only); + file << write_old_firmware_config_case_string("limited_regular_mode", &to_save_limited->mode_regular); + + file.close(); +} + bool cyop_is_key_for_device(CaptureDevice* device, std::string key) { return check_key_matches_device_id(device->device_id, key, (const cyop_device_usb_device*)device->descriptor); } diff --git a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.cpp b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.cpp index 0d34730..5d38a52 100644 --- a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.cpp +++ b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_communications.cpp @@ -13,6 +13,10 @@ #include "optimize_old_3ds_565_fpga_pl.h" #include "optimize_old_3ds_888_fpga_pl.h" +#include "optimize_old_2ds_2014_fw.h" +#include "optimize_old_2ds_2014_565_fpga_pl.h" +#include "optimize_old_2ds_2014_888_fpga_pl.h" + #include "optimize_serial_key_to_byte_table.h" // CRC32 table is a slightly edited crc32-adler. @@ -39,6 +43,7 @@ #define OPTIMIZE_NEW_3DS_WANTED_VALUE_BASE 0xFE00 #define OPTIMIZE_OLD_3DS_WANTED_VALUE_BASE 0xFD00 +#define OPTIMIZE_OLD_2DS_2014_WANTED_VALUE_BASE 0xFB00 #define OPTIMIZE_NUM_KEY_CHARS SERIAL_KEY_OPTIMIZE_NO_DASHES_SIZE #define OPTIMIZE_NUM_KEY_CHARS_WITH_DASHES SERIAL_KEY_OPTIMIZE_WITH_DASHES_SIZE @@ -49,22 +54,24 @@ const size_t key_bytes_to_serial_bytes_map[OPTIMIZE_NUM_KEY_BYTES] = {0, 7, 8, 9, 1, 4, 6, 3, 10, 2, 11, 5}; -const uint8_t start_capture_setup_key_buffer_565_new[] = { 0x61, 0x07, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xF8, 0x00, 0x38, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; -const uint8_t start_capture_setup_key_buffer_565_3d_new[] = { 0x61, 0x07, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xF8, 0x00, 0x3C, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; -const uint8_t start_capture_setup_key_buffer_888_new[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x28, 0x00, 0x62, 0x00, 0x3A, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; -const uint8_t start_capture_setup_key_buffer_888_3d_new[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x28, 0x00, 0x62, 0x00, 0x16, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; -const uint8_t start_capture_setup_key_buffer_565_old[] = { 0x61, 0x07, 0x00, 0x26, 0x00, 0x22, 0x00, 0x98, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x18, 0x00 }; -const uint8_t start_capture_setup_key_buffer_565_3d_old[] = { 0x61, 0x07, 0x00, 0x26, 0x00, 0x22, 0x00, 0x98, 0x00, 0x08, 0x00, 0x0F, 0x00, 0x00, 0x18, 0x00 }; -const uint8_t start_capture_setup_key_buffer_888_old[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x20, 0x00, 0x98, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x18, 0x00 }; -const uint8_t start_capture_setup_key_buffer_888_3d_old[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x20, 0x00, 0x98, 0x00, 0x08, 0x00, 0x05, 0x00, 0x00, 0x18, 0x00 }; +const uint8_t start_capture_setup_key_buffer_565_new[] = { 0x61, 0x07, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xF8, 0x00, 0x38, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; +const uint8_t start_capture_setup_key_buffer_565_3d_new[] = { 0x61, 0x07, 0x00, 0x0F, 0x00, 0x3E, 0x00, 0xF8, 0x00, 0x3C, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; +const uint8_t start_capture_setup_key_buffer_888_new[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x28, 0x00, 0x62, 0x00, 0x3A, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; +const uint8_t start_capture_setup_key_buffer_888_3d_new[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x28, 0x00, 0x62, 0x00, 0x16, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00 }; +const uint8_t start_capture_setup_key_buffer_565_old[] = { 0x61, 0x07, 0x00, 0x26, 0x00, 0x22, 0x00, 0x98, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x18, 0x00 }; +const uint8_t start_capture_setup_key_buffer_565_3d_old[] = { 0x61, 0x07, 0x00, 0x26, 0x00, 0x22, 0x00, 0x98, 0x00, 0x08, 0x00, 0x0F, 0x00, 0x00, 0x18, 0x00 }; +const uint8_t start_capture_setup_key_buffer_888_old[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x20, 0x00, 0x98, 0x00, 0x08, 0x00, 0x0E, 0x00, 0x00, 0x18, 0x00 }; +const uint8_t start_capture_setup_key_buffer_888_3d_old[] = { 0x61, 0x07, 0x00, 0xA6, 0x00, 0x20, 0x00, 0x98, 0x00, 0x08, 0x00, 0x05, 0x00, 0x00, 0x18, 0x00 }; +const uint8_t start_capture_setup_key_buffer_565_old_old2ds[] = { 0x61, 0x09, 0x00, 0xA0, 0x00, 0x51, 0x00, 0xA0, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEB, 0x80, 0x71, 0x01, 0x07 }; +const uint8_t start_capture_setup_key_buffer_888_old_old2ds[] = { 0x61, 0x09, 0x00, 0x90, 0x00, 0x51, 0x00, 0x90, 0x00, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00, 0xEB, 0x80, 0x71, 0x01, 0x07 }; static const cyop_device_usb_device cypress_optimize_new_3ds_generic_device = { -.name = "FX2LO->Opt. N3DS", .long_name = "EZ-USB FX2LPO -> Optimize New 3DS", +.name = "FX2O> Opt. N3DS", .long_name = "EZ-USB FX2LPO -> Optimize New 3DS", .device_type = CYPRESS_OPTIMIZE_NEW_3DS_BLANK_DEVICE, .firmware_to_load = optimize_new_3ds_fw, .firmware_size = optimize_new_3ds_fw_len, .fpga_pl_565 = NULL, .fpga_pl_565_size = 0, .fpga_pl_888 = NULL, .fpga_pl_888_size = 0, -.is_new_device = true, +.is_new_device = true, .is_old_firmware = false, .is_o2ds = false, .next_device = CYPRESS_OPTIMIZE_NEW_3DS_INSTANTIATED_DEVICE, .has_bcd_device_serial = false, .index_in_allowed_scan = CC_OPTIMIZE_N3DS, @@ -92,7 +99,7 @@ static const cyop_device_usb_device cypress_optimize_new_3ds_instantiated_device .firmware_to_load = NULL, .firmware_size = 0, .fpga_pl_565 = optimize_new_3ds_565_fpga_pl, .fpga_pl_565_size = optimize_new_3ds_565_fpga_pl_len, .fpga_pl_888 = optimize_new_3ds_888_fpga_pl, .fpga_pl_888_size = optimize_new_3ds_888_fpga_pl_len, -.is_new_device = true, +.is_new_device = true, .is_old_firmware = false, .is_o2ds = false, .next_device = CYPRESS_OPTIMIZE_NEW_3DS_INSTANTIATED_DEVICE, .has_bcd_device_serial = true, .index_in_allowed_scan = CC_OPTIMIZE_N3DS, @@ -115,12 +122,12 @@ static const cyop_device_usb_device cypress_optimize_new_3ds_instantiated_device }; static const cyop_device_usb_device cypress_optimize_old_3ds_generic_device = { -.name = "FX2LP->Opt. O3DS", .long_name = "EZ-USB FX2LP -> Optimize Old 3DS", +.name = "FX2> Opt. O3DS", .long_name = "EZ-USB FX2LP -> Optimize Old 3DS", .device_type = CYPRESS_OPTIMIZE_OLD_3DS_BLANK_DEVICE, .firmware_to_load = optimize_old_3ds_fw, .firmware_size = optimize_old_3ds_fw_len, .fpga_pl_565 = NULL, .fpga_pl_565_size = 0, .fpga_pl_888 = NULL, .fpga_pl_888_size = 0, -.is_new_device = false, +.is_new_device = false, .is_old_firmware = false, .is_o2ds = false, .next_device = CYPRESS_OPTIMIZE_OLD_3DS_INSTANTIATED_DEVICE, .has_bcd_device_serial = false, .index_in_allowed_scan = CC_OPTIMIZE_O3DS, @@ -148,7 +155,7 @@ static const cyop_device_usb_device cypress_optimize_old_3ds_instantiated_device .firmware_to_load = NULL, .firmware_size = 0, .fpga_pl_565 = optimize_old_3ds_565_fpga_pl, .fpga_pl_565_size = optimize_old_3ds_565_fpga_pl_len, .fpga_pl_888 = optimize_old_3ds_888_fpga_pl, .fpga_pl_888_size = optimize_old_3ds_888_fpga_pl_len, -.is_new_device = false, +.is_new_device = false, .is_old_firmware = false, .is_o2ds = false, .next_device = CYPRESS_OPTIMIZE_OLD_3DS_INSTANTIATED_DEVICE, .has_bcd_device_serial = true, .index_in_allowed_scan = CC_OPTIMIZE_O3DS, @@ -170,11 +177,69 @@ static const cyop_device_usb_device cypress_optimize_old_3ds_instantiated_device } }; +static const cyop_device_usb_device cypress_optimize_old_old_2ds_generic_device = { +.name = "FX2> Opt. O2DS 2014", .long_name = "EZ-USB FX2LP -> Optimize Old 2DS Late 2014", +.device_type = CYPRESS_OPTIMIZE_OLD_OLD_2DS_BLANK_DEVICE, +.firmware_to_load = optimize_old_2ds_2014_fw, .firmware_size = optimize_old_2ds_2014_fw_len, +.fpga_pl_565 = NULL, .fpga_pl_565_size = 0, +.fpga_pl_888 = NULL, .fpga_pl_888_size = 0, +.is_new_device = false, .is_old_firmware = true, .is_o2ds = true, +.next_device = CYPRESS_OPTIMIZE_OLD_OLD_2DS_INSTANTIATED_DEVICE, +.has_bcd_device_serial = false, +.index_in_allowed_scan = CC_OPTIMIZE_O_O2DS, +.usb_device_info = { + .vid = 0x04B4, .pid = 0x8613, + .default_config = 1, .default_interface = 0, + .bulk_timeout = 500, + .ep_ctrl_bulk_in = 0, .ep_ctrl_bulk_out = 0, + .ep_bulk_in = 0, + .max_usb_packet_size = CYPRESS_BASE_USB_PACKET_LIMIT, + .do_pipe_clear_reset = false, + .alt_interface = 1, + .full_data = &cypress_optimize_old_old_2ds_generic_device, + .get_serial_requires_setup = false, + .get_serial_fn = cypress_optimize_3ds_get_serial, + .create_device_fn = cypress_optimize_3ds_create_device, + .bcd_device_mask = 0x0000, + .bcd_device_wanted_value = 0x0000 +} +}; + +static const cyop_device_usb_device cypress_optimize_old_old_2ds_instantiated_device = { +.name = "Opt. O2DS Late 2014", .long_name = "Optimize Old 2DS Late 2014", +.device_type = CYPRESS_OPTIMIZE_OLD_OLD_2DS_INSTANTIATED_DEVICE, +.firmware_to_load = NULL, .firmware_size = 0, +.fpga_pl_565 = optimize_old_2ds_2014_565_fpga_pl, .fpga_pl_565_size = optimize_old_2ds_2014_565_fpga_pl_len, +.fpga_pl_888 = optimize_old_2ds_2014_888_fpga_pl, .fpga_pl_888_size = optimize_old_2ds_2014_888_fpga_pl_len, +.is_new_device = false, .is_old_firmware = true, .is_o2ds = true, +.next_device = CYPRESS_OPTIMIZE_OLD_OLD_2DS_INSTANTIATED_DEVICE, +.has_bcd_device_serial = true, +.index_in_allowed_scan = CC_OPTIMIZE_O_O2DS, +.usb_device_info = { + .vid = 0x04B4, .pid = 0x1004, + .default_config = 1, .default_interface = 0, + .bulk_timeout = 500, + .ep_ctrl_bulk_in = 1 | LIBUSB_ENDPOINT_IN, .ep_ctrl_bulk_out = 1 | LIBUSB_ENDPOINT_OUT, + .ep_bulk_in = 2 | LIBUSB_ENDPOINT_IN, + .max_usb_packet_size = CYPRESS_OPTIMIZE_OLD_3DS_USB_PACKET_LIMIT, + .do_pipe_clear_reset = true, + .alt_interface = 0, + .full_data = &cypress_optimize_old_old_2ds_instantiated_device, + .get_serial_requires_setup = false, + .get_serial_fn = cypress_optimize_3ds_get_serial, + .create_device_fn = cypress_optimize_3ds_create_device, + .bcd_device_mask = 0xFF00, + .bcd_device_wanted_value = OPTIMIZE_OLD_2DS_2014_WANTED_VALUE_BASE +} +}; + static const cyop_device_usb_device* all_usb_cyop_device_devices_desc[] = { &cypress_optimize_new_3ds_generic_device, &cypress_optimize_new_3ds_instantiated_device, &cypress_optimize_old_3ds_generic_device, &cypress_optimize_old_3ds_instantiated_device, + &cypress_optimize_old_old_2ds_generic_device, + &cypress_optimize_old_old_2ds_instantiated_device, }; static uint32_t calc_crc32_adler(uint8_t* data, size_t size) { @@ -508,7 +573,7 @@ static int read_device_id_serial(cy_device_device_handlers* handlers, const cyop int ret = cypress_ctrl_bulk_out_transfer(handlers, get_cy_usb_info(device), first_buffer, sizeof(first_buffer), &transferred); if(ret < 0) return ret; - if(device->is_new_device) { + if(device->is_new_device || device->is_old_firmware) { ret = read_first_unk_value(handlers, device, value32); if(ret < 0) return ret; @@ -602,9 +667,15 @@ static int insert_device_id(cy_device_device_handlers* handlers, const cyop_devi return ret; uint8_t device_id_buffer_new_3ds[] = {0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xC3, 0x00, 0x00, 0x02, 0x30, 0xFF, 0x60, 0x65 }; uint8_t device_id_buffer_old_3ds[] = {0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A, 0x0B, 0x01, 0x00, 0x02, 0x30, 0xFF, 0x60, 0x65 }; - uint8_t* target_device_id_buffer = device_id_buffer_new_3ds; - if(!device->is_new_device) - target_device_id_buffer = device_id_buffer_old_3ds; + //uint8_t device_id_buffer_old_3ds_old_fw[] = {0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x7B, 0x00, 0x00, 0x02, 0x30, 0xFF, 0x60, 0x65 }; + uint8_t device_id_buffer_old_2ds_old_fw[] = {0x71, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x82, 0x00, 0x00, 0x02, 0x30, 0xFF, 0x60, 0x65 }; + uint8_t* target_device_id_buffer = device_id_buffer_old_3ds; + if(device->is_new_device) + target_device_id_buffer = device_id_buffer_new_3ds; + //if(device->is_old_firmware) + // target_device_id_buffer = device_id_buffer_old_3ds_old_fw; + if(device->is_o2ds) + target_device_id_buffer = device_id_buffer_old_2ds_old_fw; write_le64(target_device_id_buffer + 1, device_id); ret = cypress_ctrl_bulk_out_transfer(handlers, get_cy_usb_info(device), target_device_id_buffer, sizeof(device_id_buffer_new_3ds), &transferred); if(ret < 0) @@ -633,7 +704,8 @@ int capture_start(cy_device_device_handlers* handlers, const cyop_device_usb_dev if(ret < 0) return ret; } - ret = start_command_send(handlers, device); + if(!device->is_old_firmware) + ret = start_command_send(handlers, device); if(ret < 0) return ret; if(device->is_new_device) { @@ -681,6 +753,11 @@ static const uint8_t* get_start_capture_setup_key_buffer(const cyop_device_usb_d return start_capture_setup_key_buffer_565_3d_new; return start_capture_setup_key_buffer_565_new; } + if(device->is_o2ds) { + if(is_rgb888) + return start_capture_setup_key_buffer_888_old_old2ds; + return start_capture_setup_key_buffer_565_old_old2ds; + } if(is_rgb888) { if(is_3d) return start_capture_setup_key_buffer_888_3d_old; @@ -691,6 +768,18 @@ static const uint8_t* get_start_capture_setup_key_buffer(const cyop_device_usb_d return start_capture_setup_key_buffer_565_old; } +static size_t get_start_capture_setup_key_buffer_size(const cyop_device_usb_device* device, bool is_rgb888, bool is_3d) { + if(device->is_old_firmware) + return sizeof(start_capture_setup_key_buffer_888_old_old2ds); + return sizeof(start_capture_setup_key_buffer_888_new); +} + +static size_t get_start_capture_setup_answer_size(const cyop_device_usb_device* device, bool is_rgb888, bool is_3d) { + if(device->is_old_firmware) + return 9; + return 7; +} + uint64_t get_device_id_from_key(std::string key, bool is_new_device) { uint8_t key_bytes[OPTIMIZE_NUM_KEY_BYTES]; bool is_key_valid = key_to_data(key, key_bytes, is_new_device); @@ -725,6 +814,27 @@ bool check_key_valid(std::string key, const cyop_device_usb_device* device) { return check_key_valid(key, device->is_new_device); } +static void populate_capture_setup_old_fw_config_case(uint8_t* setup_buffer, CaptureOptimizeOldFirmwareConfigCase* config_case_to_use, bool is_3d_case) { + uint8_t low_byte_pos = 3; + uint8_t high_byte_pos = 5; + + if(is_3d_case) { + low_byte_pos = 7; + high_byte_pos = 9; + } + + CaptureOptimizeOldFirmwareConfigCase copied_config = *config_case_to_use; + sanitize_capture_optimize_old_fw_config_case(&copied_config); + + setup_buffer[low_byte_pos] = (1 << copied_config.top_screen_sync) | (copied_config.top_screen_clock << 6); + setup_buffer[high_byte_pos] = (copied_config.top_screen_clock >> 2) | (copied_config.top_screen_data << 1) | (copied_config.low_screen_clock << 4); +} + +static void populate_capture_setup_old_fw_config(uint8_t* setup_buffer, CaptureOptimizeOldFirmwareConfig* config_to_use) { + populate_capture_setup_old_fw_config_case(setup_buffer, &config_to_use->mode_2d_only, false); + populate_capture_setup_old_fw_config_case(setup_buffer, &config_to_use->mode_regular, true); +} + static void populate_capture_setup_key_buffer(const cyop_device_usb_device* device, uint8_t* setup_key_buffer, std::string key) { if(key == "") return; @@ -740,12 +850,17 @@ static void populate_capture_setup_key_buffer(const cyop_device_usb_device* devi setup_key_buffer[13] = key_bytes[10]; return; } + if(device->is_old_firmware) { + setup_key_buffer[15] = key_bytes[11]; + setup_key_buffer[17] = key_bytes[10]; + return; + } setup_key_buffer[11] |= (key_bytes[11] & 0xF) << 4; setup_key_buffer[13] = ((key_bytes[10] & 0xF) << 4) | (key_bytes[11] >> 4); setup_key_buffer[15] = key_bytes[10] >> 4; } -int StartCaptureDma(cy_device_device_handlers* handlers, const cyop_device_usb_device* device, bool is_rgb888, bool is_3d, std::string key) { +int StartCaptureDma(cy_device_device_handlers* handlers, const cyop_device_usb_device* device, bool is_rgb888, bool is_3d, CaptureOptimizeOldFirmwareConfig *old_fw_config, std::string key) { const uint8_t mono_buffer[] = { 0x40 }; int transferred = 0; int ret = cypress_ctrl_bulk_out_transfer(handlers, get_cy_usb_info(device), mono_buffer, sizeof(mono_buffer), &transferred); @@ -756,14 +871,17 @@ int StartCaptureDma(cy_device_device_handlers* handlers, const cyop_device_usb_d if(ret < 0) return ret; const uint8_t* base_setup_key_buffer = get_start_capture_setup_key_buffer(device, is_rgb888, is_3d); - uint8_t setup_key_buffer[sizeof(start_capture_setup_key_buffer_888_new)]; - memcpy(setup_key_buffer, base_setup_key_buffer, sizeof(setup_key_buffer)); + size_t size_setup_key_buffer = get_start_capture_setup_key_buffer_size(device, is_rgb888, is_3d); + uint8_t setup_key_buffer[sizeof(start_capture_setup_key_buffer_888_old_old2ds)]; + memcpy(setup_key_buffer, base_setup_key_buffer, size_setup_key_buffer); populate_capture_setup_key_buffer(device, setup_key_buffer, key); - ret = cypress_ctrl_bulk_out_transfer(handlers, get_cy_usb_info(device), setup_key_buffer, sizeof(setup_key_buffer), &transferred); + if(device->is_old_firmware) + populate_capture_setup_old_fw_config(setup_key_buffer, old_fw_config); + ret = cypress_ctrl_bulk_out_transfer(handlers, get_cy_usb_info(device), setup_key_buffer, (int)size_setup_key_buffer, &transferred); if(ret < 0) return ret; - uint8_t in_buffer[7]; - ret = cypress_ctrl_bulk_in_transfer(handlers, get_cy_usb_info(device), in_buffer, sizeof(in_buffer), &transferred); + uint8_t in_buffer[0x10]; + ret = cypress_ctrl_bulk_in_transfer(handlers, get_cy_usb_info(device), in_buffer, (int)get_start_capture_setup_answer_size(device, is_rgb888, is_3d), &transferred); if(ret < 0) return ret; ret = start_command_send(handlers, device); diff --git a/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp b/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp index f8b97b3..020c43b 100644 --- a/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp +++ b/source/CaptureDeviceSpecific/Partner_CTR/cypress_partner_ctr_acquisition.cpp @@ -815,9 +815,9 @@ static int restart_captures_cc_reads(CaptureData* capture_data, CypressPartnerCT } 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; + int loaded_battery_percentage = capture_data->status.device_specific_status.partner_ctr_status.battery_percentage; + bool loaded_ac_adapter_connected = capture_data->status.device_specific_status.partner_ctr_status.ac_adapter_connected; + bool loaded_ac_adapter_charging = capture_data->status.device_specific_status.partner_ctr_status.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; @@ -826,8 +826,8 @@ static bool has_battery_stuff_changed(CaptureData* capture_data, std::chrono::ti } 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; + bool reset_hardware = capture_data->status.device_specific_status.partner_ctr_status.reset_hardware; + capture_data->status.device_specific_status.partner_ctr_status.reset_hardware = false; const auto curr_time = std::chrono::high_resolution_clock::now(); const std::chrono::duration diff = curr_time - clock_last_reset; @@ -838,9 +838,9 @@ static bool hardware_reset_requested(CaptureData* capture_data, std::chrono::tim 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; + int loaded_battery_percentage = capture_data->status.device_specific_status.partner_ctr_status.battery_percentage; + bool loaded_ac_adapter_connected = capture_data->status.device_specific_status.partner_ctr_status.ac_adapter_connected; + bool loaded_ac_adapter_charging = capture_data->status.device_specific_status.partner_ctr_status.ac_adapter_charging; const auto curr_time_battery = std::chrono::high_resolution_clock::now(); @@ -886,9 +886,9 @@ static bool cypart_device_acquisition_loop(CaptureData* capture_data, CypressPar 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; + int curr_battery_percentage = capture_data->status.device_specific_status.partner_ctr_status.battery_percentage; + bool curr_ac_adapter_connected = capture_data->status.device_specific_status.partner_ctr_status.ac_adapter_connected; + bool curr_ac_adapter_charging = capture_data->status.device_specific_status.partner_ctr_status.ac_adapter_charging; std::string read_serial = ""; bool force_capture_start_key = false; int ret = capture_start(handlers, usb_device_desc, read_serial); diff --git a/source/Menus/ISNitroMenu.cpp b/source/Menus/ISNitroMenu.cpp index e4501a7..00f0e9b 100644 --- a/source/Menus/ISNitroMenu.cpp +++ b/source/Menus/ISNitroMenu.cpp @@ -199,19 +199,19 @@ void ISNitroMenu::prepare(float menu_scaling_factor, int view_size_x, int view_s int option_index = this->options_indexes[real_index]; switch(pollable_options[option_index]->out_action) { case ISN_MENU_DELAY: - this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->curr_delay)); + this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->device_specific_status.is_status.curr_delay)); break; case ISN_MENU_TYPE_DEC: - this->labels[index]->setText(this->setTextOptionString(real_index, get_capture_type_name(capture_status->capture_type))); + this->labels[index]->setText(this->setTextOptionString(real_index, get_capture_type_name(capture_status->device_specific_status.is_status.capture_type))); break; case ISN_MENU_SPEED_INC: - this->labels[index]->setText(this->setTextOptionString(real_index, get_capture_speed_name(capture_status->capture_speed))); + this->labels[index]->setText(this->setTextOptionString(real_index, get_capture_speed_name(capture_status->device_specific_status.is_status.capture_speed))); break; case ISN_MENU_BATTERY_DEC: - this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->is_battery_percentage)); + this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->device_specific_status.is_status.battery_percentage)); break; case ISN_MENU_AC_ADAPTER_TOGGLE: - this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->is_ac_adapter_connected)); + this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->device_specific_status.is_status.ac_adapter_connected)); break; default: break; diff --git a/source/Menus/Optimize3DSMenu.cpp b/source/Menus/Optimize3DSMenu.cpp index 20026d0..8a6bd94 100644 --- a/source/Menus/Optimize3DSMenu.cpp +++ b/source/Menus/Optimize3DSMenu.cpp @@ -9,6 +9,7 @@ struct Optimize3DSMenuOptionInfo { const bool is_selectable; const bool optimize_o3ds_valid; const bool optimize_n3ds_valid; + const bool optimize_o2ds_valid; const bool is_inc; const std::string dec_str; const std::string inc_str; @@ -18,82 +19,100 @@ struct Optimize3DSMenuOptionInfo { static const Optimize3DSMenuOptionInfo optimize_o3ds_device_id_option = { .base_name = "Old 3DS Device ID:", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = false, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = false, .optimize_o2ds_valid = false, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_n3ds_device_id_option = { .base_name = "New 3DS Device ID:", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = false, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = false, .optimize_n3ds_valid = true, .optimize_o2ds_valid = false, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_3ds_device_id_option = { .base_name = "Device ID", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_INFO_DEVICE_ID}; static const Optimize3DSMenuOptionInfo optimize_copy_3ds_device_id_option = { .base_name = "Copy Device ID to clipboard", .false_name = "", .is_selectable = true, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_COPY_DEVICE_ID}; static const Optimize3DSMenuOptionInfo optimize_serial_key_info_option = { .base_name = "Serial Key:", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_serial_key_option = { .base_name = "", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_OPTIMIZE_SERIAL_KEY}; static const Optimize3DSMenuOptionInfo optimize_serial_key_menu_option = { .base_name = "Add New Serial Key", .false_name = "", .is_selectable = true, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_OPTIMIZE_SERIAL_KEY_MENU}; static const Optimize3DSMenuOptionInfo optimize_3ds_format_explanation_0 = { .base_name = "Possible Data Types:", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_3ds_format_explanation_1 = { -.base_name = "RGB888 - Full color Format", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.base_name = "RGB888 - Full color", .false_name = "", .is_selectable = false, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_3ds_format_explanation_2 = { .base_name = "more demanding on USB host.", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_3ds_format_explanation_3 = { -.base_name = "RGB565 - Reduced color Format", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.base_name = "RGB565 - Reduced color", .false_name = "", .is_selectable = false, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = false, +.is_inc = false, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, +.out_action = OPTIMIZE3DS_MENU_NO_ACTION}; + +static const Optimize3DSMenuOptionInfo optimize_3ds_format_explanation_3_alt = { +.base_name = "RGB565 - No Sound", .false_name = "", .is_selectable = false, +.optimize_o3ds_valid = false, .optimize_n3ds_valid = false, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_3ds_format_explanation_4 = { .base_name = "less demanding on USB host.", .false_name = "", .is_selectable = false, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = true, .is_inc = false, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, .out_action = OPTIMIZE3DS_MENU_NO_ACTION}; static const Optimize3DSMenuOptionInfo optimize_3ds_change_format = { .base_name = "Data Type", .false_name = "", .is_selectable = true, -.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, +.optimize_o3ds_valid = true, .optimize_n3ds_valid = true, .optimize_o2ds_valid = false, .is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_INPUT_VIDEO_FORMAT_INC, .out_action = OPTIMIZE3DS_MENU_INPUT_VIDEO_FORMAT_DEC}; +static const Optimize3DSMenuOptionInfo optimize_2ds_change_format = { +.base_name = "Data Type", .false_name = "", .is_selectable = true, +.optimize_o3ds_valid = false, .optimize_n3ds_valid = false, .optimize_o2ds_valid = true, +.is_inc = true, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE2DS_MENU_INPUT_VIDEO_FORMAT_INC, +.out_action = OPTIMIZE2DS_MENU_INPUT_VIDEO_FORMAT_DEC}; + +static const Optimize3DSMenuOptionInfo optimize_old_fw_settings_menu = { +.base_name = "Synch Settings", .false_name = "", .is_selectable = true, +.optimize_o3ds_valid = false, .optimize_n3ds_valid = false, .optimize_o2ds_valid = true, +.is_inc = false, .dec_str = "<", .inc_str = ">", .inc_out_action = OPTIMIZE3DS_MENU_NO_ACTION, +.out_action = OPTIMIZE3DS_MENU_OLD_FW_SETTINGS_MENU}; + static const Optimize3DSMenuOptionInfo* pollable_options[] = { //&optimize_o3ds_device_id_option, //&optimize_n3ds_device_id_option, @@ -106,8 +125,11 @@ static const Optimize3DSMenuOptionInfo* pollable_options[] = { &optimize_3ds_format_explanation_1, //&optimize_3ds_format_explanation_2, &optimize_3ds_format_explanation_3, +&optimize_3ds_format_explanation_3_alt, //&optimize_3ds_format_explanation_4, &optimize_3ds_change_format, +&optimize_2ds_change_format, +&optimize_old_fw_settings_menu, }; Optimize3DSMenu::Optimize3DSMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){ @@ -139,9 +161,11 @@ void Optimize3DSMenu::class_setup() { void Optimize3DSMenu::insert_data(CaptureDevice* device) { bool is_o3ds = false; bool is_n3ds = false; + bool is_o2ds = false; #ifdef USE_CYPRESS_OPTIMIZE is_o3ds = is_device_optimize_o3ds(device); is_n3ds = is_device_optimize_n3ds(device); + is_o2ds = is_device_optimize_o2ds(device); #endif this->num_enabled_options = 0; for(size_t i = 0; i < NUM_TOTAL_MENU_OPTIONS; i++) { @@ -150,6 +174,8 @@ void Optimize3DSMenu::insert_data(CaptureDevice* device) { valid = valid && pollable_options[i]->optimize_o3ds_valid; if(is_n3ds) valid = valid && pollable_options[i]->optimize_n3ds_valid; + if(is_o2ds) + valid = valid && pollable_options[i]->optimize_o2ds_valid; if(valid) { this->options_indexes[this->num_enabled_options] = (int)i; this->num_enabled_options++; @@ -200,7 +226,7 @@ static std::string get_data_format_name(bool request_low_bw_format) { float Optimize3DSMenu::get_option_text_factor(int index) { if(index <= 0) return 1.0f; - if(index >= ((int)NUM_TOTAL_MENU_OPTIONS)) + if(index >= ((int)this->num_enabled_options)) return 1.0f; index = this->options_indexes[index]; if(pollable_options[index]->out_action == OPTIMIZE3DS_MENU_OPTIMIZE_SERIAL_KEY) @@ -221,7 +247,10 @@ void Optimize3DSMenu::prepare(float menu_scaling_factor, int view_size_x, int vi int option_index = this->options_indexes[real_index]; switch(pollable_options[option_index]->out_action) { case OPTIMIZE3DS_MENU_INPUT_VIDEO_FORMAT_DEC: - this->labels[index]->setText(this->setTextOptionString(real_index, get_data_format_name(capture_status->request_low_bw_format))); + this->labels[index]->setText(this->setTextOptionString(real_index, get_data_format_name(capture_status->device_specific_status.optimize_status.request_low_bw_format))); + break; + case OPTIMIZE2DS_MENU_INPUT_VIDEO_FORMAT_DEC: + this->labels[index]->setText(this->setTextOptionString(real_index, get_data_format_name(capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds))); break; case OPTIMIZE3DS_MENU_INFO_DEVICE_ID: this->labels[index]->setText(this->setTextOptionString(real_index, get_device_id_string(capture_status))); diff --git a/source/Menus/OptimizeOldFWConfigMenu.cpp b/source/Menus/OptimizeOldFWConfigMenu.cpp new file mode 100644 index 0000000..08b49b6 --- /dev/null +++ b/source/Menus/OptimizeOldFWConfigMenu.cpp @@ -0,0 +1,212 @@ +#include "OptimizeOldFWConfigMenu.hpp" +#include "cypress_optimize_3ds_acquisition.hpp" + +#define NUM_TOTAL_MENU_OPTIONS (sizeof(pollable_options)/sizeof(pollable_options[0])) + +struct OptimizeOldFWConfigMenuOptionInfo { + const OptimizeOldFWConfigMenuSelectedCase selected_case_menu; + const OptimizeOldFWConfigMenuSelectedOption selected_option_menu; +}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_2donly_lowscreenclk_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_LOWSCREENCLK}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_2donly_topscreenclk_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENCLK}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_2donly_topscreendata_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENDATA}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_2donly_topscreensync_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENSYNC}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_regular_lowscreenclk_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASEREGULAR, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_LOWSCREENCLK}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_regular_topscreenclk_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASEREGULAR, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENCLK}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_regular_topscreendata_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASEREGULAR, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENDATA}; + +static const OptimizeOldFWConfigMenuOptionInfo optimize_ofwcfg_regular_topscreensync_option = { +.selected_case_menu = OPTIMIZEOLDFWCONFIG_MENU_CASEREGULAR, .selected_option_menu = OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENSYNC}; + +static const OptimizeOldFWConfigMenuOptionInfo* pollable_options[] = { +&optimize_ofwcfg_2donly_lowscreenclk_option, +&optimize_ofwcfg_2donly_topscreenclk_option, +&optimize_ofwcfg_2donly_topscreendata_option, +&optimize_ofwcfg_2donly_topscreensync_option, +&optimize_ofwcfg_regular_lowscreenclk_option, +&optimize_ofwcfg_regular_topscreenclk_option, +&optimize_ofwcfg_regular_topscreendata_option, +&optimize_ofwcfg_regular_topscreensync_option, +}; + +OptimizeOldFWConfigMenu::OptimizeOldFWConfigMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){ + this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS]; + this->initialize(text_rectangle_pool); + this->num_enabled_options = 0; +} + +OptimizeOldFWConfigMenu::~OptimizeOldFWConfigMenu() { + delete []this->options_indexes; +} + +void OptimizeOldFWConfigMenu::class_setup() { + this->num_options_per_screen = 4; + 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 = "Opt. Synch Settings"; + this->show_back_x = true; + this->show_x = false; + this->show_title = true; +} + +void OptimizeOldFWConfigMenu::insert_data() { + 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 OptimizeOldFWConfigMenu::reset_output_option() { + this->selected_index = OptimizeOldFWConfigMenuOutAction::OPTIMIZEOLDFWCONFIG_MENU_NO_ACTION; +} + +void OptimizeOldFWConfigMenu::set_output_option(int index, int action) { + if(index == BACK_X_OUTPUT_OPTION) { + this->selected_index = OPTIMIZEOLDFWCONFIG_MENU_BACK; + return; + } + else if((action == INC_ACTION) && this->is_option_inc_dec(index)) + this->selected_index = OPTIMIZEOLDFWCONFIG_MENU_CHANGE_INC; + else + this->selected_index = OPTIMIZEOLDFWCONFIG_MENU_CHANGE_DEC; + this->selected_case = pollable_options[index]->selected_case_menu; + this->selected_option = pollable_options[index]->selected_option_menu; +} + +size_t OptimizeOldFWConfigMenu::get_num_options() { + return this->num_enabled_options; +} + +static uint8_t* _get_data_to_edit_in_case(CaptureOptimizeOldFirmwareConfigCase* optimize_old_fw_cfg_case, OptimizeOldFWConfigMenuSelectedOption selected_option) { + switch(selected_option) { + case OPTIMIZEOLDFWCONFIG_MENU_LOWSCREENCLK: + return &optimize_old_fw_cfg_case->low_screen_clock; + case OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENCLK: + return &optimize_old_fw_cfg_case->top_screen_clock; + case OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENDATA: + return &optimize_old_fw_cfg_case->top_screen_data; + case OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENSYNC: + return &optimize_old_fw_cfg_case->top_screen_sync; + default: + return &optimize_old_fw_cfg_case->low_screen_clock; + } + +} + +static uint8_t* _get_data_to_edit(CaptureOptimizeOldFirmwareConfig* optimize_old_fw_cfg, OptimizeOldFWConfigMenuSelectedCase selected_case, OptimizeOldFWConfigMenuSelectedOption selected_option) { + switch(selected_case) { + case OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY: + return _get_data_to_edit_in_case(&optimize_old_fw_cfg->mode_2d_only, selected_option); + case OPTIMIZEOLDFWCONFIG_MENU_CASEREGULAR: + return _get_data_to_edit_in_case(&optimize_old_fw_cfg->mode_regular, selected_option); + default: + return _get_data_to_edit_in_case(&optimize_old_fw_cfg->mode_2d_only, selected_option); + } +} + +static uint8_t* _get_data_to_edit(CaptureOptimizeOldFirmwareConfig* optimize_old_fw_cfg, const OptimizeOldFWConfigMenuOptionInfo* option) { + return _get_data_to_edit(optimize_old_fw_cfg, option->selected_case_menu, option->selected_option_menu); +} + +uint8_t* OptimizeOldFWConfigMenu::get_data_to_edit(CaptureOptimizeOldFirmwareConfig* optimize_old_fw_cfg) { + return _get_data_to_edit(optimize_old_fw_cfg, this->selected_case, this->selected_option); +} + +static std::string _get_string_for_option(const OptimizeOldFWConfigMenuOptionInfo* option) { + std::string out_str = ""; + switch(option->selected_case_menu) { + case OPTIMIZEOLDFWCONFIG_MENU_CASE2DONLY: + out_str = "2D Only "; + break; + case OPTIMIZEOLDFWCONFIG_MENU_CASEREGULAR: + out_str = "Regular "; + break; + default: + break; + } + + switch(option->selected_option_menu) { + case OPTIMIZEOLDFWCONFIG_MENU_LOWSCREENCLK: + out_str += "Low Clk"; + break; + case OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENCLK: + out_str += "Top Clk"; + break; + case OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENDATA: + out_str += "Top Data"; + break; + case OPTIMIZEOLDFWCONFIG_MENU_TOPSCREENSYNC: + out_str += "Top Sync"; + break; + default: + break; + } + + return out_str; +} + +std::string OptimizeOldFWConfigMenu::get_string_option(int index, int action) { + if((action == INC_ACTION) && this->is_option_inc_dec(index)) + return "+"; + if((action == DEC_ACTION) && this->is_option_inc_dec(index)) + return "-"; + return _get_string_for_option(pollable_options[this->options_indexes[index]]); +} + +bool OptimizeOldFWConfigMenu::is_option_selectable(int index, int action) { + return true; +} + +bool OptimizeOldFWConfigMenu::is_option_inc_dec(int index) { + return true; +} + +float OptimizeOldFWConfigMenu::get_option_text_factor(int index) { + return 0.85f; +} + +void OptimizeOldFWConfigMenu::prepare(float menu_scaling_factor, int view_size_x, int view_size_y, CaptureStatus* capture_status) { + CaptureOptimizeOldFirmwareConfig* to_display_fw_config = &capture_status->device_specific_status.optimize_status.old_fw_config_full_bw_format; + if(capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds) + to_display_fw_config = &capture_status->device_specific_status.optimize_status.old_fw_config_low_bw_format; + + 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]; + this->labels[index]->setText(this->setTextOptionInt(real_index, *_get_data_to_edit(to_display_fw_config, pollable_options[real_index]))); + } + + this->base_prepare(menu_scaling_factor, view_size_x, view_size_y); +} diff --git a/source/Menus/PartnerCTRMenu.cpp b/source/Menus/PartnerCTRMenu.cpp index fbed7c0..c151882 100644 --- a/source/Menus/PartnerCTRMenu.cpp +++ b/source/Menus/PartnerCTRMenu.cpp @@ -126,13 +126,13 @@ void PartnerCTRMenu::prepare(float menu_scaling_factor, int view_size_x, int vie 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)); + this->labels[index]->setText(this->setTextOptionInt(real_index, capture_status->device_specific_status.partner_ctr_status.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)); + this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->device_specific_status.partner_ctr_status.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)); + this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->device_specific_status.partner_ctr_status.ac_adapter_charging)); break; default: break; diff --git a/source/Menus/USBConflictResolutionMenu.cpp b/source/Menus/USBConflictResolutionMenu.cpp index 9216efc..8b973cc 100644 --- a/source/Menus/USBConflictResolutionMenu.cpp +++ b/source/Menus/USBConflictResolutionMenu.cpp @@ -6,10 +6,20 @@ #undef EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS #endif -#if (defined(USE_CYNI_USB) && defined(USE_CYPRESS_OPTIMIZE)) +#ifdef EXISTENCE_VALUE_CONFLICT_NISE + #undef EXISTENCE_VALUE_CONFLICT_NISE +#endif + +#if defined(USE_CYPRESS_OPTIMIZE) #define EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS true + #if defined(USE_CYNI_USB) + #define EXISTENCE_VALUE_CONFLICT_NISE true + #else + #define EXISTENCE_VALUE_CONFLICT_NISE false + #endif #else #define EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS false + #define EXISTENCE_VALUE_CONFLICT_NISE false #endif struct USBConflictResolutionMenuOptionInfo { @@ -25,20 +35,32 @@ struct USBConflictResolutionMenuOptionInfo { }; static const USBConflictResolutionMenuOptionInfo warning_nise_opti_conflict_0 = { +.base_name = "There are three capture cards", +.false_name = "", .exists = EXISTENCE_VALUE_CONFLICT_NISE, .is_selectable = false, +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, +.out_action = USBCONRESO_MENU_NO_ACTION}; + +static const USBConflictResolutionMenuOptionInfo warning_nise_opti_conflict_0_alt = { .base_name = "There are two capture cards", -.false_name = "", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS, .is_selectable = false, +.false_name = "", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS && (!EXISTENCE_VALUE_CONFLICT_NISE), .is_selectable = false, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, .out_action = USBCONRESO_MENU_NO_ACTION}; static const USBConflictResolutionMenuOptionInfo warning_nise_opti_conflict_1 = { -.base_name = "which use the FX2LP board.", +.base_name = "that use the FX2LP board.", .false_name = "", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS, .is_selectable = false, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, .out_action = USBCONRESO_MENU_NO_ACTION}; static const USBConflictResolutionMenuOptionInfo warning_nise_opti_conflict_2 = { -.base_name = "You may disable one to make", -.false_name = "", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS, .is_selectable = false, +.base_name = "You can disable two to make", +.false_name = "", .exists = EXISTENCE_VALUE_CONFLICT_NISE, .is_selectable = false, +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, +.out_action = USBCONRESO_MENU_NO_ACTION}; + +static const USBConflictResolutionMenuOptionInfo warning_nise_opti_conflict_2_alt = { +.base_name = "You can disable one to make", +.false_name = "", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS && (!EXISTENCE_VALUE_CONFLICT_NISE), .is_selectable = false, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, .out_action = USBCONRESO_MENU_NO_ACTION}; @@ -50,23 +72,32 @@ static const USBConflictResolutionMenuOptionInfo warning_nise_opti_conflict_3 = static const USBConflictResolutionMenuOptionInfo nisetro_ds_disable_option = { .base_name = "Disable Nisetro DS(i)", -.false_name = "Enable Nisetro DS(i)", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS, .is_selectable = true, +.false_name = "Enable Nisetro DS(i)", .exists = EXISTENCE_VALUE_CONFLICT_NISE, .is_selectable = true, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, .out_action = USBCONRESO_MENU_NISE_DS}; static const USBConflictResolutionMenuOptionInfo optimize_o3ds_disable_option = { -.base_name = "Disable Optimize Old 3DS", -.false_name = "Enable Optimize Old 3DS", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS, .is_selectable = true, +.base_name = "Disable Opt. O3DS", +.false_name = "Enable Opt. O3DS", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS, .is_selectable = true, .is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, .out_action = USBCONRESO_MENU_OPTI_O3DS}; +static const USBConflictResolutionMenuOptionInfo optimize_o2ds_disable_option = { +.base_name = "Disable Opt. O2DS Late 2014", +.false_name = "Enable Opt. O2DS Late 2014", .exists = EXISTENCE_VALUE_CONFLICT_NISE_OPTI_O3DS, .is_selectable = true, +.is_inc = false, .dec_str = "", .inc_str = "", .inc_out_action = USBCONRESO_MENU_NO_ACTION, +.out_action = USBCONRESO_MENU_OPTI_O2DS}; + static const USBConflictResolutionMenuOptionInfo* pollable_options[] = { &warning_nise_opti_conflict_0, +&warning_nise_opti_conflict_0_alt, &warning_nise_opti_conflict_1, &warning_nise_opti_conflict_2, +&warning_nise_opti_conflict_2_alt, &warning_nise_opti_conflict_3, -&nisetro_ds_disable_option, &optimize_o3ds_disable_option, +&optimize_o2ds_disable_option, +&nisetro_ds_disable_option, }; USBConflictResolutionMenu::USBConflictResolutionMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){ @@ -80,7 +111,7 @@ USBConflictResolutionMenu::~USBConflictResolutionMenu() { } void USBConflictResolutionMenu::class_setup() { - this->num_options_per_screen = 5; + this->num_options_per_screen = 6; this->min_elements_text_scaling_factor = num_options_per_screen + 2; this->width_factor_menu = 16; this->width_divisor_menu = 9; @@ -174,6 +205,9 @@ void USBConflictResolutionMenu::prepare(float menu_scaling_factor, int view_size case USBCONRESO_MENU_OPTI_O3DS: this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->devices_allowed_scan[CC_OPTIMIZE_O3DS])); break; + case USBCONRESO_MENU_OPTI_O2DS: + this->labels[index]->setText(this->setTextOptionBool(real_index, capture_status->devices_allowed_scan[CC_OPTIMIZE_O_O2DS])); + break; default: break; } diff --git a/source/WindowScreen_Menu.cpp b/source/WindowScreen_Menu.cpp index c0be51e..27f1bfc 100755 --- a/source/WindowScreen_Menu.cpp +++ b/source/WindowScreen_Menu.cpp @@ -133,6 +133,7 @@ void WindowScreen::init_menus() { this->usb_conflict_resolution_menu = new USBConflictResolutionMenu(this->text_rectangle_pool); this->optimize_3ds_menu = new Optimize3DSMenu(this->text_rectangle_pool); this->optimize_serial_key_add_menu = new OptimizeSerialKeyAddMenu(this->text_rectangle_pool); + this->optimize_old_fw_config_menu = new OptimizeOldFWConfigMenu(this->text_rectangle_pool); } void WindowScreen::destroy_menus() { @@ -166,6 +167,7 @@ void WindowScreen::destroy_menus() { delete this->usb_conflict_resolution_menu; delete this->optimize_3ds_menu; delete this->optimize_serial_key_add_menu; + delete this->optimize_old_fw_config_menu; } void WindowScreen::set_close(int ret_val) { @@ -211,25 +213,25 @@ void WindowScreen::fast_poll_change() { } void WindowScreen::is_nitro_capture_type_change(bool positive) { - int new_value = (int)(this->capture_status->capture_type); + int new_value = (int)(this->capture_status->device_specific_status.is_status.capture_type); if(positive) new_value += 1; else new_value += CAPTURE_SCREENS_ENUM_END - 1; - this->capture_status->capture_type = static_cast(new_value % CAPTURE_SCREENS_ENUM_END); + this->capture_status->device_specific_status.is_status.capture_type = static_cast(new_value % CAPTURE_SCREENS_ENUM_END); } void WindowScreen::is_nitro_capture_speed_change(bool positive) { - int new_value = (int)(this->capture_status->capture_speed); + int new_value = (int)(this->capture_status->device_specific_status.is_status.capture_speed); if(positive) new_value += 1; else new_value += CAPTURE_SPEEDS_ENUM_END - 1; - this->capture_status->capture_speed = static_cast(new_value % CAPTURE_SPEEDS_ENUM_END); + this->capture_status->device_specific_status.is_status.capture_speed = static_cast(new_value % CAPTURE_SPEEDS_ENUM_END); } void WindowScreen::is_nitro_capture_reset_hw() { - this->capture_status->reset_hardware = true; + this->capture_status->device_specific_status.is_status.reset_hardware = true; } void WindowScreen::generic_battery_change(bool positive, int &battery_percentage, const int *allowed_battery_levels, size_t num_levels) { @@ -256,23 +258,27 @@ void WindowScreen::generic_battery_change(bool positive, int &battery_percentage } 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])); + this->generic_battery_change(positive, this->capture_status->device_specific_status.is_status.battery_percentage, is_battery_levels, sizeof(is_battery_levels) / sizeof(is_battery_levels[0])); } void WindowScreen::is_nitro_ac_adapter_change() { - this->capture_status->is_ac_adapter_connected = !this->capture_status->is_ac_adapter_connected; + this->capture_status->device_specific_status.is_status.ac_adapter_connected = !this->capture_status->device_specific_status.is_status.ac_adapter_connected; +} + +void WindowScreen::partner_ctr_reset_hw() { + this->capture_status->device_specific_status.partner_ctr_status.reset_hardware = true; } 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])); + this->generic_battery_change(positive, this->capture_status->device_specific_status.partner_ctr_status.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; + this->capture_status->device_specific_status.partner_ctr_status.ac_adapter_connected = !this->capture_status->device_specific_status.partner_ctr_status.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; + this->capture_status->device_specific_status.partner_ctr_status.ac_adapter_charging = !this->capture_status->device_specific_status.partner_ctr_status.ac_adapter_charging; } void WindowScreen::padding_change() { @@ -618,16 +624,33 @@ void WindowScreen::devices_allowed_change(PossibleCaptureDevices device) { this->capture_status->devices_allowed_scan[device] = !this->capture_status->devices_allowed_scan[device]; } -void WindowScreen::input_video_data_format_request_change(bool positive) { +void WindowScreen::input_video_data_format_request_change(bool positive, bool &target_format) { std::chrono::time_point curr_time = std::chrono::high_resolution_clock::now(); const std::chrono::duration diff = curr_time - this->last_data_format_change_time; if(diff.count() < this->input_data_format_change_timeout) return; - this->capture_status->request_low_bw_format = !this->capture_status->request_low_bw_format; + target_format = !target_format; this->print_notification("Changing data format...\nPlease wait..."); this->last_data_format_change_time = curr_time; } +void WindowScreen::optimize_old_fw_menu_change_param(bool positive) { + CaptureOptimizeOldFirmwareConfig* to_edit_fw_config = &this->capture_status->device_specific_status.optimize_status.old_fw_config_full_bw_format; + if(this->capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds) + to_edit_fw_config = &this->capture_status->device_specific_status.optimize_status.old_fw_config_low_bw_format; + + CaptureOptimizeOldFirmwareConfig base_fw_config = *to_edit_fw_config; + + uint8_t* to_edit = this->optimize_old_fw_config_menu->get_data_to_edit(&base_fw_config); + if(positive) + *to_edit += 1; + else + *to_edit -= 1; + sanitize_capture_optimize_old_fw_config(&base_fw_config); + + *to_edit_fw_config = base_fw_config; +} + bool WindowScreen::add_new_cc_key(std::string key, CaptureConnectionType conn_type, bool discriminator) { bool ret = false; KeySaveError save_error = save_cc_key(key, conn_type, discriminator); @@ -1287,6 +1310,15 @@ void WindowScreen::setup_optimize_serial_key_add_menu(bool reset_data) { } } +void WindowScreen::setup_optimize_old_fw_config_menu(bool reset_data) { + if(!this->can_setup_menu()) + return; + if(this->curr_menu != OPTIMIZE_OLD_FW_CONFIG_MENU) { + this->switch_to_menu(OPTIMIZE_OLD_FW_CONFIG_MENU, this->optimize_old_fw_config_menu, reset_data); + this->optimize_old_fw_config_menu->insert_data(); + } +} + void WindowScreen::update_save_menu() { if(this->curr_menu == SAVE_MENU_TYPE) { this->curr_menu = DEFAULT_MENU_TYPE; @@ -2213,7 +2245,7 @@ void WindowScreen::poll(bool do_everything) { case PCTR_MENU_NO_ACTION: break; case PCTR_MENU_RESET: - this->is_nitro_capture_reset_hw(); + this->partner_ctr_reset_hw(); break; case PCTR_MENU_BATTERY_DEC: this->partner_ctr_battery_change(false); @@ -2426,6 +2458,9 @@ void WindowScreen::poll(bool do_everything) { case USBCONRESO_MENU_OPTI_O3DS: this->devices_allowed_change(CC_OPTIMIZE_O3DS); break; + case USBCONRESO_MENU_OPTI_O2DS: + this->devices_allowed_change(CC_OPTIMIZE_O_O2DS); + break; default: break; } @@ -2450,11 +2485,20 @@ void WindowScreen::poll(bool do_everything) { case OPTIMIZE3DS_MENU_OPTIMIZE_SERIAL_KEY_MENU: this->setup_optimize_serial_key_add_menu(); break; + case OPTIMIZE3DS_MENU_OLD_FW_SETTINGS_MENU: + this->setup_optimize_old_fw_config_menu(); + break; case OPTIMIZE3DS_MENU_INPUT_VIDEO_FORMAT_INC: - this->input_video_data_format_request_change(true); + this->input_video_data_format_request_change(true, this->capture_status->device_specific_status.optimize_status.request_low_bw_format); break; case OPTIMIZE3DS_MENU_INPUT_VIDEO_FORMAT_DEC: - this->input_video_data_format_request_change(false); + this->input_video_data_format_request_change(false, this->capture_status->device_specific_status.optimize_status.request_low_bw_format); + break; + case OPTIMIZE2DS_MENU_INPUT_VIDEO_FORMAT_INC: + this->input_video_data_format_request_change(true, this->capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds); + break; + case OPTIMIZE2DS_MENU_INPUT_VIDEO_FORMAT_DEC: + this->input_video_data_format_request_change(false, this->capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds); break; default: break; @@ -2493,6 +2537,25 @@ void WindowScreen::poll(bool do_everything) { } this->loaded_menu_ptr->reset_output_option(); break; + case OPTIMIZE_OLD_FW_CONFIG_MENU: + switch(this->optimize_old_fw_config_menu->selected_index) { + case OPTIMIZEOLDFWCONFIG_MENU_BACK: + this->setup_optimize_3ds_menu(false); + done = true; + break; + case OPTIMIZEOLDFWCONFIG_MENU_NO_ACTION: + break; + case OPTIMIZEOLDFWCONFIG_MENU_CHANGE_INC: + optimize_old_fw_menu_change_param(true); + break; + case OPTIMIZEOLDFWCONFIG_MENU_CHANGE_DEC: + optimize_old_fw_menu_change_param(false); + break; + default: + break; + } + this->loaded_menu_ptr->reset_output_option(); + break; default: break; } @@ -2534,6 +2597,8 @@ void WindowScreen::update_capture_specific_settings() { this->setup_no_menu(); if(this->curr_menu == OPTIMIZE_SERIAL_KEY_ADD_MENU_TYPE) this->setup_no_menu(); + if(this->curr_menu == OPTIMIZE_OLD_FW_CONFIG_MENU) + this->setup_no_menu(); } int WindowScreen::load_data() { @@ -2819,6 +2884,9 @@ void WindowScreen::prepare_menu_draws(int view_size_x, int view_size_y) { case OPTIMIZE_SERIAL_KEY_ADD_MENU_TYPE: this->optimize_serial_key_add_menu->prepare(menu_scaling_factor, view_size_x, view_size_y); break; + case OPTIMIZE_OLD_FW_CONFIG_MENU: + this->optimize_old_fw_config_menu->prepare(menu_scaling_factor, view_size_x, view_size_y, this->capture_status); + break; default: break; } diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index 1415f6a..e8f7fe8 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -45,6 +45,7 @@ struct override_all_data { bool auto_close = false; bool force_disable_nisetro_ds = false; bool force_disable_optimize_old_3ds = false; + bool force_disable_optimize_old_old_2ds = false; bool auto_save = true; int loaded_profile = STARTUP_FILE_INDEX; bool mono_app = false; @@ -191,7 +192,17 @@ static bool load(const std::string path, const std::string name, ScreenInfo &top } if(key == "request_low_bw_format") { - capture_status->request_low_bw_format = std::stoi(value); + capture_status->device_specific_status.optimize_status.request_low_bw_format = std::stoi(value); + continue; + } + + if(key == "request_low_bw_format_optimize") { + capture_status->device_specific_status.optimize_status.request_low_bw_format = std::stoi(value); + continue; + } + + if(key == "request_low_bw_format_old_2ds_optimize") { + capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds = std::stoi(value); continue; } @@ -201,49 +212,49 @@ static bool load(const std::string path, const std::string name, ScreenInfo &top } if(key == "is_screen_capture_type") { - capture_status->capture_type = static_cast(std::stoi(value) % CaptureScreensType::CAPTURE_SCREENS_ENUM_END); + capture_status->device_specific_status.is_status.capture_type = static_cast(std::stoi(value) % CaptureScreensType::CAPTURE_SCREENS_ENUM_END); continue; } if(key == "is_speed_capture") { - capture_status->capture_speed = static_cast(std::stoi(value) % CaptureSpeedsType::CAPTURE_SPEEDS_ENUM_END); + capture_status->device_specific_status.is_status.capture_speed = static_cast(std::stoi(value) % CaptureSpeedsType::CAPTURE_SPEEDS_ENUM_END); continue; } if(key == "is_battery_percentage") { - capture_status->is_battery_percentage = std::stoi(value); + capture_status->device_specific_status.is_status.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->is_battery_percentage <= 5) - capture_status->is_battery_percentage = 5; - if(capture_status->is_battery_percentage > 100) - capture_status->is_battery_percentage = 100; + if(capture_status->device_specific_status.is_status.battery_percentage <= 5) + capture_status->device_specific_status.is_status.battery_percentage = 5; + if(capture_status->device_specific_status.is_status.battery_percentage > 100) + capture_status->device_specific_status.is_status.battery_percentage = 100; continue; } if(key == "is_ac_adapter_connected") { - capture_status->is_ac_adapter_connected = std::stoi(value); + capture_status->device_specific_status.is_status.ac_adapter_connected = std::stoi(value); continue; } if(key == "partner_ctr_battery_percentage") { - capture_status->partner_ctr_battery_percentage = std::stoi(value); + capture_status->device_specific_status.partner_ctr_status.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; + if(capture_status->device_specific_status.partner_ctr_status.battery_percentage <= 1) + capture_status->device_specific_status.partner_ctr_status.battery_percentage = 1; + if(capture_status->device_specific_status.partner_ctr_status.battery_percentage > 100) + capture_status->device_specific_status.partner_ctr_status.battery_percentage = 100; continue; } if(key == "partner_ctr_ac_adapter_connected") { - capture_status->partner_ctr_ac_adapter_connected = std::stoi(value); + capture_status->device_specific_status.partner_ctr_status.ac_adapter_connected = std::stoi(value); continue; } if(key == "partner_ctr_ac_adapter_charging") { - capture_status->partner_ctr_ac_adapter_charging = std::stoi(value); + capture_status->device_specific_status.partner_ctr_status.ac_adapter_charging = std::stoi(value); continue; } @@ -252,6 +263,11 @@ static bool load(const std::string path, const std::string name, ScreenInfo &top continue; } + if(key == "optimize_oo2ds_scan_for") { + capture_status->devices_allowed_scan[CC_OPTIMIZE_O_O2DS] = std::stoi(value); + continue; + } + if(key == "nisetro_ds_scan_for") { capture_status->devices_allowed_scan[CC_NISETRO_DS] = std::stoi(value); continue; @@ -273,14 +289,15 @@ 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->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; + capture_status->device_specific_status.is_status.capture_type = CAPTURE_SCREENS_BOTH; + capture_status->device_specific_status.is_status.capture_speed = CAPTURE_SPEEDS_FULL; + capture_status->device_specific_status.is_status.battery_percentage = 100; + capture_status->device_specific_status.is_status.ac_adapter_connected = true; + capture_status->device_specific_status.partner_ctr_status.battery_percentage = 100; + capture_status->device_specific_status.partner_ctr_status.ac_adapter_connected = false; + capture_status->device_specific_status.partner_ctr_status.ac_adapter_charging = false; + capture_status->device_specific_status.optimize_status.request_low_bw_format = true; + capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds = false; for(int i = 0; i < CC_POSSIBLE_DEVICES_END; i++) capture_status->devices_allowed_scan[i] = true; reset_screen_info(frontend_data->top_screen->m_info); @@ -367,16 +384,18 @@ static bool save(const std::string path, const std::string name, const std::stri file << "requested_3d=" << capture_status->requested_3d << std::endl; file << "interleaved_3d=" << display_data.interleaved_3d << std::endl; file << "do_ratio_cycling=" << display_data.do_ratio_cycling << std::endl; - file << "request_low_bw_format=" << capture_status->request_low_bw_format << std::endl; + file << "request_low_bw_format_optimize=" << capture_status->device_specific_status.optimize_status.request_low_bw_format << std::endl; + file << "request_low_bw_format_old_2ds_optimize=" << capture_status->device_specific_status.optimize_status.request_low_bw_format_old_2ds << std::endl; 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->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_ac_adapter_connected << std::endl; - file << "partner_ctr_ac_adapter_charging=" << capture_status->partner_ctr_ac_adapter_charging << std::endl; + file << "is_screen_capture_type=" << capture_status->device_specific_status.is_status.capture_type << std::endl; + file << "is_speed_capture=" << capture_status->device_specific_status.is_status.capture_speed << std::endl; + file << "is_battery_percentage=" << capture_status->device_specific_status.is_status.battery_percentage << std::endl; + file << "is_ac_adapter_connected=" << capture_status->device_specific_status.is_status.ac_adapter_connected << std::endl; + file << "partner_ctr_battery_percentage=" << capture_status->device_specific_status.partner_ctr_status.battery_percentage << std::endl; + file << "partner_ctr_ac_adapter_connected=" << capture_status->device_specific_status.partner_ctr_status.ac_adapter_connected << std::endl; + file << "partner_ctr_ac_adapter_charging=" << capture_status->device_specific_status.partner_ctr_status.ac_adapter_charging << std::endl; file << "optimize_o3ds_scan_for=" << capture_status->devices_allowed_scan[CC_OPTIMIZE_O3DS] << std::endl; + file << "optimize_oo2ds_scan_for=" << capture_status->devices_allowed_scan[CC_OPTIMIZE_O_O2DS] << std::endl; file << "nisetro_ds_scan_for=" << capture_status->devices_allowed_scan[CC_NISETRO_DS] << std::endl; file << audio_data->save_audio_data(); @@ -595,7 +614,7 @@ static float get_time_multiplier(CaptureData* capture_data, bool should_ignore_d return 2.0; if(capture_data->status.device.cc_type != CAPTURE_CONN_IS_NITRO) return 1.0; - switch(capture_data->status.capture_speed) { + switch(capture_data->status.device_specific_status.is_status.capture_speed) { case CAPTURE_SPEEDS_HALF: return 2.0; case CAPTURE_SPEEDS_THIRD: @@ -612,6 +631,7 @@ static void populate_force_disable_ccs(bool* force_cc_disables, override_all_dat force_cc_disables[i] = false; force_cc_disables[CC_NISETRO_DS] = override_data.force_disable_nisetro_ds; force_cc_disables[CC_OPTIMIZE_O3DS] = override_data.force_disable_optimize_old_3ds; + force_cc_disables[CC_OPTIMIZE_O_O2DS] = override_data.force_disable_optimize_old_old_2ds; } static void check_for_first_connection(bool &did_first_connection, std::chrono::time_point &start_time, CaptureData* capture_data, FrontendData *frontend_data, bool* force_cc_disables, override_all_data &override_data, OutTextData &out_text_data, int &ret_val, std::chrono::time_point &last_connection_time) { @@ -904,6 +924,7 @@ static bool create_out_folder() { create_folder(get_base_path(false)); create_folder(get_base_path(true)); create_folder(get_base_path_keys()); + create_folder(get_base_path_device_specific_configs()); return success; } @@ -1019,6 +1040,8 @@ int main(int argc, char **argv) { continue; if(parse_existence_arg(i, argv, override_data.force_disable_optimize_old_3ds, true, "--no_opt_o3ds_cc")) continue; + if(parse_existence_arg(i, argv, override_data.force_disable_optimize_old_old_2ds, true, "--no_opt_o2ds_cc")) + continue; if(parse_int_arg(i, argc, argv, override_data.loaded_profile, "--profile")) continue; if(parse_existence_arg(i, argv, override_data.auto_save, false, "--no_auto_save")) @@ -1076,6 +1099,7 @@ int main(int argc, char **argv) { ActualConsoleOutText(" --auto_close Automatically closes the software on disconnect."); ActualConsoleOutText(" --no_nisetro Force disables Nisetro DS(i) Capture Card."); ActualConsoleOutText(" --no_opt_o3ds_cc Force disables Optimize Old 3DS Capture Card."); + ActualConsoleOutText(" --no_opt_o2ds_cc Force disables Optimize Old 2DS 2014 Capture Card."); ActualConsoleOutText(" --profile Loads the profile with the specified ID at startup"); ActualConsoleOutText(" instead of the default one. When the program closes,"); ActualConsoleOutText(" the data is also saved to the specified profile."); diff --git a/source/conversions.cpp b/source/conversions.cpp index c6df2a1..3b428c3 100755 --- a/source/conversions.cpp +++ b/source/conversions.cpp @@ -94,6 +94,22 @@ static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptLE(deinterle } } +static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptReversedLE(deinterleaved_rgb565_pixels* out_ptr_top, deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline, int multiplier_top = 1) { + //de-interleave pixels + const int bottom_pos = 1; + const int top_pos = 0; + const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; + for(size_t i = 0; i < real_num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * real_num_iters) + i; + size_t output_halfline_pixel_bottom = (output_halfline * real_num_iters) + i; + size_t output_halfline_pixel_top = (output_halfline * real_num_iters * multiplier_top) + i; + for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) + out_ptr_bottom[output_halfline_pixel_bottom].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][bottom_pos]; + for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) + out_ptr_top[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_pos]; + } +} + static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(deinterleaved_rgb565_pixels* out_ptr_top, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline, int multiplier_top = 1) { //de-interleave pixels const int top_pos = 1; @@ -134,6 +150,22 @@ static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptBE(deinterle } } +static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptReversedBE(deinterleaved_rgb565_pixels* out_ptr_top, deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline, int multiplier_top = 1) { + //de-interleave pixels + const int bottom_pos = 1; + const int top_pos = 0; + const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; + for(size_t i = 0; i < real_num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * real_num_iters) + i; + size_t output_halfline_pixel_bottom = (output_halfline * real_num_iters) + i; + size_t output_halfline_pixel_top = (output_halfline * real_num_iters * multiplier_top) + i; + for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) + out_ptr_bottom[output_halfline_pixel_bottom].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][bottom_pos]); + for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) + out_ptr_top[output_halfline_pixel_top].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][top_pos]); + } +} + static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(deinterleaved_rgb565_pixels* out_ptr_top, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline, int multiplier_top = 1) { //de-interleave pixels const int top_pos = 1; @@ -173,6 +205,21 @@ static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOpt(deinterl } } +static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOptReversed(deinterleaved_rgb888_u16_pixels* out_ptr_top, deinterleaved_rgb888_u16_pixels* out_ptr_bottom, interleaved_rgb888_u16_pixels* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline) { + //de-interleave pixels + const int bottom_pos = 1; + const int top_pos = 0; + const size_t real_num_iters = num_iters / INTERLEAVED_RGB888_PIXEL_NUM; + for(size_t i = 0; i < real_num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * real_num_iters) + i; + size_t output_halfline_pixel = (output_halfline * real_num_iters) + i; + for(size_t j = 0; j < INTERLEAVED_RGB888_TOTAL_SIZE; j++) + out_ptr_bottom[output_halfline_pixel].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][bottom_pos]; + for(size_t j = 0; j < INTERLEAVED_RGB888_TOTAL_SIZE; j++) + out_ptr_top[output_halfline_pixel].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_pos]; + } +} + static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoTop(deinterleaved_rgb888_u16_pixels* out_ptr_top, interleaved_rgb888_u16_pixels* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline) { //de-interleave pixels const int top_pos = 1; @@ -197,6 +244,64 @@ static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoBotto } } +static inline void usb_rgb888convertInterleaveU8VideoToOutputDirectOpt(uint8_t* out_ptr_top, uint8_t* out_ptr_bottom, uint8_t* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline) { + //de-interleave pixels + const int bottom_pos = 0; + const int top_pos = 1; + const size_t real_num_iters = num_iters; + size_t pixel_size = sizeof(VideoPixelRGB); + for(size_t i = 0; i < real_num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * real_num_iters) + i; + size_t output_halfline_pixel = (output_halfline * real_num_iters) + i; + for(size_t j = 0; j < pixel_size; j++) { + // Wonder if this could be made faster, somehow...? + out_ptr_bottom[(output_halfline_pixel * pixel_size) + j] = in_ptr[(input_halfline_pixel * pixel_size * 2) + (j * 2) + bottom_pos]; + out_ptr_top[(output_halfline_pixel * pixel_size) + j] = in_ptr[(input_halfline_pixel * pixel_size * 2) + (j * 2) + top_pos]; + } + } +} + +static inline void usb_rgb888convertInterleaveU8VideoToOutputDirectOptReversed(uint8_t* out_ptr_top, uint8_t* out_ptr_bottom, uint8_t* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline) { + //de-interleave pixels + const int bottom_pos = 1; + const int top_pos = 0; + const size_t real_num_iters = num_iters; + size_t pixel_size = sizeof(VideoPixelRGB); + for(size_t i = 0; i < real_num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * real_num_iters) + i; + size_t output_halfline_pixel = (output_halfline * real_num_iters) + i; + for(size_t j = 0; j < pixel_size; j++) { + out_ptr_top[(output_halfline_pixel * pixel_size) + j] = in_ptr[(input_halfline_pixel * pixel_size * 2) + (j * 2) + top_pos]; + out_ptr_bottom[(output_halfline_pixel * pixel_size) + j] = in_ptr[(input_halfline_pixel * pixel_size * 2) + (j * 2) + bottom_pos]; + } + } +} + +static inline void usb_rgb888convertInterleaveU8VideoToOutputDirectOptMonoTop(uint8_t* out_ptr_top, uint8_t* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline) { + //de-interleave pixels + const int top_pos = 1; + const size_t real_num_iters = num_iters; + size_t pixel_size = sizeof(VideoPixelRGB); + for(size_t i = 0; i < real_num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * real_num_iters) + i; + size_t output_halfline_pixel = (output_halfline * real_num_iters) + i; + for(size_t j = 0; j < pixel_size; j++) + out_ptr_top[(output_halfline_pixel * pixel_size) + j] = in_ptr[(input_halfline_pixel * pixel_size * 2) + (j * 2) + top_pos]; + } +} + +static inline void usb_rgb888convertInterleaveU8VideoToOutputDirectOptMonoBottom(uint8_t* out_ptr_bottom, uint8_t* in_ptr, uint32_t num_iters, size_t input_halfline, size_t output_halfline) { + //de-interleave pixels + const int bottom_pos = 0; + const size_t real_num_iters = num_iters; + size_t pixel_size = sizeof(VideoPixelRGB); + for(size_t i = 0; i < real_num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * real_num_iters) + i; + size_t output_halfline_pixel = (output_halfline * real_num_iters) + i; + for(size_t j = 0; j < pixel_size; j++) + out_ptr_bottom[(output_halfline_pixel * pixel_size) + j] = in_ptr[(input_halfline_pixel * pixel_size * 2) + (j * 2) + bottom_pos]; + } +} static inline void convertVideoToOutputChunk(RGB83DSVideoInputData *p_in, VideoOutputData *p_out, size_t iters, size_t start_in, size_t start_out) { memcpy(&p_out->rgb_video_output_data.screen_data[start_out], &p_in->screen_data[start_in], iters * sizeof(VideoPixelRGB)); @@ -473,6 +578,62 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB56 } } +static inline void usb_3DS565OptimizeOldFirmwareconvertVideoToOutputLineDirectOptLE(USB5653DSOptimizeOldFirmwareCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) { + //de-interleave pixels + const int pixels_size = sizeof(VideoPixelRGB16); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 3; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 1; + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data; + deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size) - ((HEIGHT_3DS * pixels_size) / ptr_out_size); + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].pixel; + const uint32_t num_iters = HEIGHT_3DS; + if(column == column_last_bot_pos) { + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_top, in_ptr, num_iters, 0, TOP_WIDTH_3DS); + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 3); + } + else if((column >= column_pre_last_bot_pos) && (column < column_start_bot_pos)) { + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_top, in_ptr, num_iters, 0, column); + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last + (column - column_pre_last_bot_pos)); + } + else if(column < column_start_bot_pos) + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_top, in_ptr, num_iters, 0, column); + else { + out_ptr_top += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + usb_rgb565convertInterleaveVideoToOutputDirectOptReversedLE(out_ptr_top, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos); + } +} + +static inline void usb_3DS565OptimizeOldFirmwareconvertVideoToOutputLineDirectOptBE(USB5653DSOptimizeOldFirmwareCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) { + //de-interleave pixels + const int pixels_size = sizeof(VideoPixelRGB16); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 3; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 1; + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data; + deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size) - ((HEIGHT_3DS * pixels_size) / ptr_out_size); + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].pixel; + const uint32_t num_iters = HEIGHT_3DS; + if(column == column_last_bot_pos) { + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_top, in_ptr, num_iters, 0, TOP_WIDTH_3DS); + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 3); + } + else if((column >= column_pre_last_bot_pos) && (column < column_start_bot_pos)) { + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_top, in_ptr, num_iters, 0, column); + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last + (column - column_pre_last_bot_pos)); + } + else if(column < column_start_bot_pos) + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_top, in_ptr, num_iters, 0, column); + else { + out_ptr_top += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + usb_rgb565convertInterleaveVideoToOutputDirectOptReversedBE(out_ptr_top, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos); + } +} + static inline void usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(USB8883DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column, bool is_n3ds) { //de-interleave pixels const int pixels_size = sizeof(VideoPixelRGB); @@ -594,6 +755,36 @@ static inline void usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(USB8883 memcpy(out_ptr_top_r + (column * HEIGHT_3DS * pixels_size * multiplier_top), (uint8_t*)p_in->columns_data[column][1].pixel, HEIGHT_3DS * pixels_size); } +static inline void usb_3DS888OptimizeOldFirmwareconvertVideoToOutputLineDirectOpt(USB8883DSOptimizeOldFirmwareCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) { + //de-interleave pixels + const int pixels_size = sizeof(VideoPixelRGB); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(uint8_t); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 3; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 1; + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + uint8_t* out_ptr_bottom = (uint8_t*)p_out->rgb_video_output_data.screen_data; + uint8_t* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); + uint8_t* in_ptr = (uint8_t*)p_in->columns_data[column].pixel; + const uint32_t num_iters = HEIGHT_3DS; + if(column == column_last_bot_pos) { + usb_rgb888convertInterleaveU8VideoToOutputDirectOptMonoTop(out_ptr_top, in_ptr, num_iters, 0, column - 1); + usb_rgb888convertInterleaveU8VideoToOutputDirectOptMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 3); + } + else if((column >= column_pre_last_bot_pos) && (column < column_start_bot_pos)) { + usb_rgb888convertInterleaveU8VideoToOutputDirectOptMonoTop(out_ptr_top, in_ptr, num_iters, 0, column - 1); + usb_rgb888convertInterleaveU8VideoToOutputDirectOptMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last + (column - column_pre_last_bot_pos)); + } + else if(column == 0) + return; + else if(column < column_start_bot_pos) + usb_rgb888convertInterleaveU8VideoToOutputDirectOptMonoTop(out_ptr_top, in_ptr, num_iters, 0, column - 1); + else { + out_ptr_top += ((column_start_bot_pos - 1) * HEIGHT_3DS * pixels_size) / ptr_out_size; + usb_rgb888convertInterleaveU8VideoToOutputDirectOpt(out_ptr_top, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos); + } +} + static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, const bool is_big_endian) { #ifndef SIMPLE_DS_FRAME_SKIP if(!p_in->frameinfo.valid) { //LCD was off @@ -739,6 +930,21 @@ static void usb_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOu } } +static void usb_3ds_optimize_old_firmware_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, const bool is_big_endian, bool is_rgb888) { + if(!is_rgb888) { + if(!is_big_endian) + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_3DS565OptimizeOldFirmwareconvertVideoToOutputLineDirectOptLE(&p_in->cypress_optimize_old_firmware_received_565, p_out, i); + else + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_3DS565OptimizeOldFirmwareconvertVideoToOutputLineDirectOptBE(&p_in->cypress_optimize_old_firmware_received_565, p_out, i); + } + else { + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_3DS888OptimizeOldFirmwareconvertVideoToOutputLineDirectOpt(&p_in->cypress_optimize_old_firmware_received_888, p_out, i); + } +} + static void usb_is_device_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureStatus* status, CaptureScreensType capture_type) { bool is_nitro = true; #ifdef USE_IS_DEVICES_USB @@ -995,7 +1201,11 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt if(status->device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE) { bool is_rgb888 = video_data_type == VIDEO_DATA_RGB; bool is_n3ds = is_device_optimize_n3ds(&status->device); - usb_3ds_optimize_convertVideoToOutput(p_in, p_out, is_data_3d, should_be_3d, is_big_endian, interleaved_3d, is_3d_requested, is_rgb888, is_n3ds); + bool is_using_old_firmware = is_device_optimize_old_fw(&status->device); + if(is_using_old_firmware) + usb_3ds_optimize_old_firmware_convertVideoToOutput(p_in, p_out, is_big_endian, is_rgb888); + else + usb_3ds_optimize_convertVideoToOutput(p_in, p_out, is_data_3d, should_be_3d, is_big_endian, interleaved_3d, is_3d_requested, is_rgb888, is_n3ds); converted = true; } #endif @@ -1068,7 +1278,7 @@ static inline void copyAudioFromSoundDataOptimize3DSBE(std::int16_t *p_out, USB3 last_inserted_index = read_index; } -static void copyAudioOptimize3DSLE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888) { +static void copyAudioOptimize3DSLE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888, bool force_check_extra_header) { uint64_t num_inserted = 0; int last_inserted_index = last_buffer_index; for(int i = 0; i < TOP_WIDTH_3DS; i++) { @@ -1077,7 +1287,7 @@ static void copyAudioOptimize3DSLE(std::int16_t *p_out, uint64_t &n_samples, uin copyAudioFromSoundDataOptimize3DSLE(p_out, &curr_column_data->samples[1], num_inserted, last_inserted_index); } USB3DSOptimizeHeaderSoundData* initial_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, 0); - if(usb_OptimizeHasExtraHeaderSoundData(initial_column_data)) { + if(force_check_extra_header || usb_OptimizeHasExtraHeaderSoundData(initial_column_data)) { USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DSExtraHeader(buffer, is_rgb888, TOP_WIDTH_3DS); copyAudioFromSoundDataOptimize3DSLE(p_out, &curr_column_data->samples[0], num_inserted, last_inserted_index); copyAudioFromSoundDataOptimize3DSLE(p_out, &curr_column_data->samples[1], num_inserted, last_inserted_index); @@ -1113,7 +1323,7 @@ static void copyAudioOptimize3DS3DForced2DLE(std::int16_t *p_out, uint64_t &n_sa n_samples = num_inserted * 2; } -static void copyAudioOptimize3DSBE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888) { +static void copyAudioOptimize3DSBE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888, bool force_check_extra_header) { uint64_t num_inserted = 0; int last_inserted_index = last_buffer_index; for(int i = 0; i < TOP_WIDTH_3DS; i++) { @@ -1122,7 +1332,7 @@ static void copyAudioOptimize3DSBE(std::int16_t *p_out, uint64_t &n_samples, uin copyAudioFromSoundDataOptimize3DSBE(p_out, &curr_column_data->samples[1], num_inserted, last_inserted_index); } USB3DSOptimizeHeaderSoundData* initial_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, 0); - if(usb_OptimizeHasExtraHeaderSoundData(initial_column_data)) { + if(force_check_extra_header || usb_OptimizeHasExtraHeaderSoundData(initial_column_data)) { USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DSExtraHeader(buffer, is_rgb888, TOP_WIDTH_3DS); copyAudioFromSoundDataOptimize3DSBE(p_out, &curr_column_data->samples[0], num_inserted, last_inserted_index); copyAudioFromSoundDataOptimize3DSBE(p_out, &curr_column_data->samples[1], num_inserted, last_inserted_index); @@ -1200,8 +1410,10 @@ static void usb_partner_ctr_convertAudioToOutput(CaptureReceived *p_in, std::int } bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status) { - if(!status->device.has_audio) + if(!status->device.has_audio) { + n_samples = 0; return true; + } bool is_data_3d = data_buffer->is_3d; bool should_be_3d = data_buffer->should_be_3d; InputVideoDataType video_data_type = data_buffer->buffer_video_data_type; @@ -1248,6 +1460,13 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &la #ifdef USE_CYPRESS_OPTIMIZE if(status->device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE) { bool is_rgb888 = video_data_type == VIDEO_DATA_RGB; + // O2DS has no sound in RGB565 mode... Sadly. + // In general, there is no old_fw with RGB565 sound. + // Keep both checks in case this changes in the future... + if((!is_rgb888) && (is_device_optimize_old_fw(&status->device) || is_device_optimize_o2ds(&status->device))) { + n_samples = 0; + return true; + } if(is_big_endian) { if(is_data_3d) copyAudioOptimize3DS3DBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); @@ -1255,7 +1474,7 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &la if(should_be_3d && is_rgb888) copyAudioOptimize3DS3DForced2DBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf); else - copyAudioOptimize3DSBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + copyAudioOptimize3DSBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888, is_device_optimize_old_fw(&status->device)); } } else { @@ -1265,7 +1484,7 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &la if(should_be_3d && is_rgb888) copyAudioOptimize3DS3DForced2DLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf); else - copyAudioOptimize3DSLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + copyAudioOptimize3DSLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888, is_device_optimize_old_fw(&status->device)); } } return true; diff --git a/source/devicecapture.cpp b/source/devicecapture.cpp index a19d100..1996e53 100755 --- a/source/devicecapture.cpp +++ b/source/devicecapture.cpp @@ -130,12 +130,12 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten for(size_t i = 0; i < CC_POSSIBLE_DEVICES_END; i++) devices_allowed_scan[i] = capture_data->status.devices_allowed_scan[i] & (!force_cc_disables[i]); - #ifdef USE_CYNI_USB - list_devices_cyni_device(devices_list, no_access_list, devices_allowed_scan); - #endif #ifdef USE_CYPRESS_OPTIMIZE list_devices_cyop_device(devices_list, no_access_list, devices_allowed_scan); #endif + #ifdef USE_CYNI_USB + list_devices_cyni_device(devices_list, no_access_list, devices_allowed_scan); + #endif #ifdef USE_FTD3 list_devices_ftd3(devices_list, no_access_list, devices_allowed_scan); #endif @@ -379,7 +379,7 @@ std::string get_device_serial_key_string(CaptureStatus* capture_status) { void check_device_serial_key_update(CaptureStatus* capture_status, bool differentiator, std::string key) { if(get_device_serial_key_string(capture_status) != NO_SERIAL_KEY_STR) return; - if(capture_status->key_updated) + if(capture_status->device_specific_status.optimize_status.key_updated) return; switch(capture_status->device.cc_type) { @@ -388,7 +388,7 @@ void check_device_serial_key_update(CaptureStatus* capture_status, bool differen if(differentiator != is_device_optimize_n3ds(&capture_status->device)) break; if(cyop_is_key_for_device_id(&capture_status->device, key)) - capture_status->key_updated = true; + capture_status->device_specific_status.optimize_status.key_updated = true; #endif break; default: @@ -431,6 +431,11 @@ bool get_device_can_do_3d(CaptureStatus* capture_status) { return false; if(!capture_status->device.is_3ds) return false; + #ifdef USE_CYPRESS_OPTIMIZE + // O2DS has no 3D, obviously... + if((capture_status->device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE) && is_device_optimize_o2ds(&capture_status->device)) + return false; + #endif return capture_status->device.has_3d; } @@ -441,6 +446,13 @@ bool get_device_3d_implemented(CaptureStatus* capture_status) { case CAPTURE_CONN_FTD3: return true; case CAPTURE_CONN_CYPRESS_OPTIMIZE: + #ifdef USE_CYPRESS_OPTIMIZE + // O2DS has no 3D, obviously. + // Also, no old_fw that can do 3D... + // Keep both checks in case this changes in the future... + if(is_device_optimize_old_fw(&capture_status->device) || is_device_optimize_o2ds(&capture_status->device)) + return false; + #endif return true; case CAPTURE_CONN_PARTNER_CTR: return true; @@ -482,7 +494,7 @@ float get_framerate_multiplier(CaptureStatus* capture_status) { return 1; if(!get_3d_enabled(capture_status)) return 1; - if(capture_status->request_low_bw_format) + if(capture_status->device_specific_status.optimize_status.request_low_bw_format) return 1; return 0.5; } @@ -503,6 +515,20 @@ KeySaveError save_cc_key(std::string key, CaptureConnectionType conn_type, bool return error; } +void sanitize_capture_optimize_old_fw_config_case(CaptureOptimizeOldFirmwareConfigCase* config_case) { + config_case->low_screen_clock &= 0xF; // 0..15, already covers going negative + config_case->top_screen_clock &= 7; // 0..7, already covers going negative + config_case->top_screen_data &= 7; // 0..7, already covers going negative + while(config_case->top_screen_sync >= 0x80) + config_case->top_screen_sync += 6; // 0..5, cover going negative with this + config_case->top_screen_sync %= 6; // Do the regular check +} + +void sanitize_capture_optimize_old_fw_config(CaptureOptimizeOldFirmwareConfig* config) { + sanitize_capture_optimize_old_fw_config_case(&config->mode_2d_only); + sanitize_capture_optimize_old_fw_config_case(&config->mode_regular); +} + void capture_init() { #ifdef USE_DS_3DS_USB usb_ds_3ds_init(); diff --git a/source/utils.cpp b/source/utils.cpp index 890d986..e22a232 100755 --- a/source/utils.cpp +++ b/source/utils.cpp @@ -406,6 +406,10 @@ std::string get_base_path_keys() { return get_base_path(false) + "keys/"; } +std::string get_base_path_device_specific_configs() { + return get_base_path(false) + "device_specific_configs/"; +} + std::string LayoutPathGenerator(int index) { return get_base_path(index != STARTUP_FILE_INDEX); }