diff --git a/CMakeLists.txt b/CMakeLists.txt index 3295644..bba70ca 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -394,7 +394,14 @@ execute_process(COMMAND ${CMAKE_COMMAND} --build ${TOOLS_DATA_DIR}) set(OUTPUT_NAME cc3dsfs) +if(MSVC) + set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "/O2") +else() + set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "-O3") +endif() add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.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/CaptureDataBuffers.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${SOURCE_CPP_EXTRA_FILES}) + + if(NOT ("${EXTRA_DEPENDENCIES}" STREQUAL "")) add_dependencies(${OUTPUT_NAME} ${EXTRA_DEPENDENCIES}) endif() diff --git a/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp b/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp index a2da5d2..73569df 100644 --- a/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp +++ b/include/CaptureDeviceSpecific/3dscapture_ftd3.hpp @@ -12,7 +12,6 @@ void list_devices_ftd3(std::vector &devices_list, std::vector &devices_list, std::vector bool is_nitro_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device); void is_nitro_acquisition_main_loop(CaptureData* capture_data); void usb_is_nitro_acquisition_cleanup(CaptureData* capture_data); -void usb_is_nitro_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureScreensType capture_type); uint64_t usb_is_nitro_get_video_in_size(CaptureData* capture_data); +uint64_t usb_is_nitro_get_video_in_size(CaptureScreensType capture_type); bool is_nitro_is_capture(CaptureDevice* device); void usb_is_nitro_init(); void usb_is_nitro_close(); diff --git a/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_general.hpp b/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_general.hpp index 02cdde7..403671f 100644 --- a/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_general.hpp +++ b/include/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_general.hpp @@ -21,7 +21,6 @@ struct ISNitroCaptureReceivedData { isn_async_callback_data cb_data; }; -uint64_t _is_nitro_get_video_in_size(CaptureScreensType capture_type); int set_acquisition_mode(is_nitro_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_nitro_usb_device* usb_device_desc); int EndAcquisition(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type); int EndAcquisition(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type); diff --git a/include/CaptureDeviceSpecific/dscapture_ftd2.hpp b/include/CaptureDeviceSpecific/dscapture_ftd2.hpp index 55a487f..db1bafb 100644 --- a/include/CaptureDeviceSpecific/dscapture_ftd2.hpp +++ b/include/CaptureDeviceSpecific/dscapture_ftd2.hpp @@ -12,7 +12,6 @@ void list_devices_ftd2(std::vector &devices_list, std::vector &devices_list, std::vector &no_access_list); bool connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device); void usb_capture_main_loop(CaptureData* capture_data); void usb_capture_cleanup(CaptureData* capture_data); -void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureDevice* capture_device, bool enabled_3d); uint64_t usb_get_video_in_size(CaptureData* capture_data); void usb_ds_3ds_init(); void usb_ds_3ds_close(); diff --git a/include/hw_defs.hpp b/include/hw_defs.hpp index 0c11320..ddf1224 100755 --- a/include/hw_defs.hpp +++ b/include/hw_defs.hpp @@ -40,6 +40,7 @@ #define HEIGHT_NES 240 #define TOP_SIZE_3DS (TOP_WIDTH_3DS * HEIGHT_3DS) +#define BOT_SIZE_3DS (BOT_WIDTH_3DS * HEIGHT_3DS) #define TOP_SIZE_DS (WIDTH_DS * HEIGHT_DS) #define IN_VIDEO_WIDTH_3DS HEIGHT_3DS @@ -49,7 +50,8 @@ #define IN_VIDEO_BPP_SIZE_3DS 24 #define IN_VIDEO_WIDTH_3DS_3D HEIGHT_3DS -#define IN_VIDEO_HEIGHT_3DS_3D (TOP_WIDTH_3DS + TOP_WIDTH_3DS + BOT_WIDTH_3DS) +#define IN_VIDEO_HEIGHT_3DS_3D (TOP_WIDTH_3DS + BOT_WIDTH_3DS + TOP_WIDTH_3DS) +#define IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D (((TOP_WIDTH_3DS - BOT_WIDTH_3DS) * HEIGHT_3DS) * 2) #define IN_VIDEO_SIZE_3DS_3D (IN_VIDEO_WIDTH_3DS_3D * IN_VIDEO_HEIGHT_3DS_3D) #define IN_VIDEO_BPP_SIZE_3DS_3D 24 diff --git a/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp b/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp index 6f6b88e..27249ee 100644 --- a/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp +++ b/source/CaptureDeviceSpecific/3dscapture_ftd3.cpp @@ -312,23 +312,3 @@ void ftd3_capture_cleanup(CaptureData* capture_data) { capture_error_print(true, capture_data, "Disconnected: Close failed"); } } - -static inline void convertVideoToOutputChunk(RGB83DSVideoInputData *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) { - memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3); -} - -static inline void convertVideoToOutputChunk_3D(RGB83DSVideoInputData_3D *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) { - memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3); -} - -void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d) { - if(!enabled_3d) { - convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_NO_BOTTOM_SIZE_3DS, 0, 0); - - for(int i = 0; i < ((IN_VIDEO_SIZE_3DS - IN_VIDEO_NO_BOTTOM_SIZE_3DS) / (IN_VIDEO_WIDTH_3DS * 2)); i++) { - convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, ((i * 2) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, TOP_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS)); - convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, (((i * 2) + 1) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, IN_VIDEO_NO_BOTTOM_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS)); - } - } -} - diff --git a/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp b/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp index e9a11c4..b1fbbdd 100644 --- a/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp +++ b/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition.cpp @@ -129,14 +129,15 @@ bool is_nitro_connect_usb(bool print_failed, CaptureData* capture_data, CaptureD return true; } -uint64_t _is_nitro_get_video_in_size(CaptureScreensType capture_type) { +uint64_t usb_is_nitro_get_video_in_size(CaptureScreensType capture_type) { if((capture_type == CAPTURE_SCREENS_TOP) || (capture_type == CAPTURE_SCREENS_BOTTOM)) return sizeof(ISNitroEmulatorVideoInputData) / 2; return sizeof(ISNitroEmulatorVideoInputData); } + uint64_t usb_is_nitro_get_video_in_size(CaptureData* capture_data) { - return _is_nitro_get_video_in_size(capture_data->status.capture_type); + return usb_is_nitro_get_video_in_size(capture_data->status.capture_type); } int set_acquisition_mode(is_nitro_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_nitro_usb_device* usb_device_desc) { @@ -185,7 +186,7 @@ static void output_to_thread(CaptureData* capture_data, CaptureReceived* capture const auto curr_time = std::chrono::high_resolution_clock::now(); const std::chrono::duration diff = curr_time - (*clock_start); *clock_start = curr_time; - capture_data->data_buffers.WriteToBuffer(capture_buf, _is_nitro_get_video_in_size(curr_capture_type), diff.count(), &capture_data->status.device, curr_capture_type); + capture_data->data_buffers.WriteToBuffer(capture_buf, usb_is_nitro_get_video_in_size(curr_capture_type), diff.count(), &capture_data->status.device, curr_capture_type); if (capture_data->status.cooldown_curr_in) capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1; @@ -194,7 +195,7 @@ static void output_to_thread(CaptureData* capture_data, CaptureReceived* capture } int is_nitro_read_frame_and_output(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point &clock_start) { - int ret = ReadFrame((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, _is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor); + int ret = ReadFrame((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, usb_is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor); if (ret < 0) return ret; output_to_thread(capture_data, capture_buf, curr_capture_type, &clock_start); @@ -207,7 +208,7 @@ void is_nitro_read_frame_request(CaptureData* capture_data, ISNitroCaptureReceiv is_nitro_capture_recv_data->index = index; is_nitro_capture_recv_data->curr_capture_type = curr_capture_type; is_nitro_capture_recv_data->cb_data.function = is_nitro_read_frame_cb; - ReadFrameAsync((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)&is_nitro_capture_recv_data->buffer, _is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor, &is_nitro_capture_recv_data->cb_data); + ReadFrameAsync((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)&is_nitro_capture_recv_data->buffer, usb_is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor, &is_nitro_capture_recv_data->cb_data); } static void end_is_nitro_read_frame_cb(ISNitroCaptureReceivedData* is_nitro_capture_recv_data) { @@ -364,21 +365,6 @@ void usb_is_nitro_acquisition_cleanup(CaptureData* capture_data) { capture_data->handle = NULL; } -void usb_is_nitro_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureScreensType capture_type) { - if(!usb_is_initialized()) - return; - int num_pixels = _is_nitro_get_video_in_size(capture_type) / 3; - int out_start_pos = 0; - int out_clear_pos = num_pixels; - if(capture_type == CAPTURE_SCREENS_BOTTOM) { - out_start_pos = num_pixels; - out_clear_pos = 0; - } - if((capture_type == CAPTURE_SCREENS_BOTTOM) || (capture_type == CAPTURE_SCREENS_TOP)) - memset(p_out->screen_data[out_clear_pos], 0, num_pixels * 3); - memcpy(p_out->screen_data[out_start_pos], p_in->is_nitro_capture_received.video_in.screen_data, num_pixels * 3); -} - bool is_nitro_is_capture(CaptureDevice* device) { const is_nitro_usb_device* usb_device_info = (const is_nitro_usb_device*)device->descriptor; return usb_device_info->is_capture; diff --git a/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_emulator.cpp b/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_emulator.cpp index 7206be7..c9f3d0f 100644 --- a/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_emulator.cpp +++ b/source/CaptureDeviceSpecific/ISNitro/usb_is_nitro_acquisition_emulator.cpp @@ -1,5 +1,6 @@ #include "devicecapture.hpp" #include "usb_is_nitro_communications.hpp" +#include "usb_is_nitro_acquisition.hpp" #include "usb_is_nitro_acquisition_general.hpp" #include "usb_is_nitro_acquisition_emulator.hpp" @@ -35,7 +36,7 @@ static int drain_frames(is_nitro_device_handlers* handlers, int num_frames, int start_frames, CaptureScreensType capture_type, const is_nitro_usb_device* usb_device_desc) { ISNitroEmulatorVideoInputData* video_in_buffer = new ISNitroEmulatorVideoInputData; for (int i = start_frames; i < num_frames; i++) { - int ret = ReadFrame(handlers, (uint8_t*)video_in_buffer, _is_nitro_get_video_in_size(capture_type), usb_device_desc); + int ret = ReadFrame(handlers, (uint8_t*)video_in_buffer, usb_is_nitro_get_video_in_size(capture_type), usb_device_desc); if(ret < 0) { delete video_in_buffer; return ret; diff --git a/source/CaptureDeviceSpecific/dscapture_ftd2.cpp b/source/CaptureDeviceSpecific/dscapture_ftd2.cpp index f30b657..bbe8247 100644 --- a/source/CaptureDeviceSpecific/dscapture_ftd2.cpp +++ b/source/CaptureDeviceSpecific/dscapture_ftd2.cpp @@ -29,7 +29,3 @@ void ftd2_capture_main_loop(CaptureData* capture_data) { void ftd2_capture_cleanup(CaptureData* capture_data) { } - -void ftd2_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d) { -} - diff --git a/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp b/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp index 2b18827..408b8d6 100644 --- a/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp +++ b/source/CaptureDeviceSpecific/usb_ds_3ds_capture.cpp @@ -16,8 +16,6 @@ #define FIRST_3D_VERSION 6 #define CAPTURE_SKIP_TIMEOUT_SECONDS 1.0 -#define SIMPLE_DS_FRAME_SKIP - #define NUM_DS_3DS_CONCURRENT_DATA_BUFFERS 4 #define NUM_DS_3DS_CONCURRENT_REQUESTS 4 @@ -331,55 +329,6 @@ static usb_capture_status capture_read_oldds_3ds(usb_ds_3ds_general_data* chosen return USB_CAPTURE_SUCCESS; } -static inline void usb_oldDSconvertVideoToOutputHalfLine(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) { - //de-interleave pixels - uint16_t* out_ptr_top = (uint16_t*)p_out->screen_data; - uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS); - uint16_t* in_ptr = (uint16_t*)p_in->video_in.screen_data; - for(int i = 0; i < WIDTH_DS / 2 ; i++) { - uint32_t input_halfline_pixel = (input_halfline * (WIDTH_DS / 2)) + i; - uint32_t output_halfline_pixel = (output_halfline * (WIDTH_DS / 2)) + i; - out_ptr_bottom[output_halfline_pixel] = in_ptr[input_halfline_pixel * 2]; - out_ptr_top[output_halfline_pixel] = in_ptr[(input_halfline_pixel * 2) + 1]; - } -} - -static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out) { - #ifndef SIMPLE_DS_FRAME_SKIP - if(!p_in->frameinfo.valid) { //LCD was off - memset(p_out->screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * sizeof(uint16_t)); - return; - } - - // Handle first line being off, if needed - memset(p_out->screen_data, 0, WIDTH_DS * sizeof(uint16_t)); - - int input_halfline = 0; - for(int i = 0; i < 2; i++) { - if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7))) - usb_oldDSconvertVideoToOutputHalfLine(p_in, p_out, input_halfline++, i); - } - - for(int i = 2; i < HEIGHT_DS * 2; i++) { - if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7))) - usb_oldDSconvertVideoToOutputHalfLine(p_in, p_out, input_halfline++, i); - else { // deal with missing half-line - uint16_t* out_ptr_top = (uint16_t*)&p_out->screen_data; - uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS); - memcpy(&out_ptr_top[i * (WIDTH_DS / 2)], &out_ptr_top[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t)); - memcpy(&out_ptr_bottom[i * (WIDTH_DS / 2)], &out_ptr_bottom[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t)); - } - } - #else - for(int i = 0; i < HEIGHT_DS * 2; i++) - usb_oldDSconvertVideoToOutputHalfLine(p_in, p_out, i, i); - #endif -} - -static void usb_3DSconvertVideoToOutput(USB3DSCaptureReceived *p_in, VideoOutputData *p_out) { - memcpy(p_out->screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3); -} - static void process_usb_capture_result(usb_capture_status result, std::chrono::time_point* clock_start, bool* done, usb_ds_3ds_general_data* chosen_buffer) { const auto curr_time = std::chrono::high_resolution_clock::now(); const std::chrono::duration diff = curr_time - (*clock_start); @@ -556,17 +505,6 @@ void usb_capture_cleanup(CaptureData* capture_data) { capture_end((libusb_device_handle*)capture_data->handle, usb_device_desc); } -void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureDevice* capture_device, bool enabled_3d) { - if(!usb_is_initialized()) - return; - if(capture_device->is_3ds) { - if(!enabled_3d) - usb_3DSconvertVideoToOutput(&p_in->usb_received_3ds, p_out); - } - else - usb_oldDSconvertVideoToOutput(&p_in->usb_received_old_ds, p_out); -} - void usb_ds_3ds_init() { return usb_init(); } diff --git a/source/conversions.cpp b/source/conversions.cpp index 389814d..ef8c82b 100755 --- a/source/conversions.cpp +++ b/source/conversions.cpp @@ -7,29 +7,168 @@ #include +struct interleaved_ds_pixels { + uint16_t bottom_first; + uint16_t top_first; + uint16_t bottom_second; + uint16_t top_second; + uint16_t bottom_third; + uint16_t top_third; + uint16_t bottom_fourth; + uint16_t top_fourth; +}; + +struct deinterleaved_ds_pixels { + uint32_t first : 16; + uint32_t second : 16; + uint32_t third : 16; + uint32_t fourth : 16; +}; + +#ifdef USE_FTD3 +static inline void convertVideoToOutputChunk(RGB83DSVideoInputData *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) { + memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3); +} + +static inline void convertVideoToOutputChunk_3D(RGB83DSVideoInputData_3D *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) { + memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3); +} + +static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d) { + if(!enabled_3d) { + convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_NO_BOTTOM_SIZE_3DS, 0, 0); + + for(int i = 0; i < ((IN_VIDEO_SIZE_3DS - IN_VIDEO_NO_BOTTOM_SIZE_3DS) / (IN_VIDEO_WIDTH_3DS * 2)); i++) { + convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, ((i * 2) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, TOP_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS)); + convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, (((i * 2) + 1) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, IN_VIDEO_NO_BOTTOM_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS)); + } + } + else { + for(int i = 0; i < (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / (IN_VIDEO_WIDTH_3DS_3D * 2)); i++) { + convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (i * 2) * IN_VIDEO_WIDTH_3DS_3D, i * IN_VIDEO_WIDTH_3DS_3D); + convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, ((i * 2) + 1) * IN_VIDEO_WIDTH_3DS_3D, TOP_SIZE_3DS + BOT_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS_3D)); + } + + for(int i = 0; i < ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)); i++) { + convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, ((i * 3) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, TOP_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS_3D)); + convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D)); + convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, TOP_SIZE_3DS + BOT_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D)); + } + } +} +#endif + +#ifdef USE_FTD2 +static void ftd2_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out) { +} +#endif + +#ifdef USE_DS_3DS_USB +static inline void usb_oldDSconvertVideoToOutputHalfLineDirectOpt(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) { + //de-interleave pixels + deinterleaved_ds_pixels* out_ptr_top = (deinterleaved_ds_pixels*)p_out->screen_data; + deinterleaved_ds_pixels* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS / (sizeof(deinterleaved_ds_pixels) / 2)); + interleaved_ds_pixels* in_ptr = (interleaved_ds_pixels*)p_in->video_in.screen_data; + const uint32_t halfline_iters = WIDTH_DS / (sizeof(interleaved_ds_pixels) / 2); + for(int i = 0; i < halfline_iters; i++) { + uint32_t input_halfline_pixel = (input_halfline * halfline_iters) + i; + uint32_t output_halfline_pixel = (output_halfline * halfline_iters) + i; + out_ptr_bottom[output_halfline_pixel].first = in_ptr[input_halfline_pixel].bottom_first; + out_ptr_bottom[output_halfline_pixel].second = in_ptr[input_halfline_pixel].bottom_second; + out_ptr_bottom[output_halfline_pixel].third = in_ptr[input_halfline_pixel].bottom_third; + out_ptr_bottom[output_halfline_pixel].fourth = in_ptr[input_halfline_pixel].bottom_fourth; + out_ptr_top[output_halfline_pixel].first = in_ptr[input_halfline_pixel].top_first; + out_ptr_top[output_halfline_pixel].second = in_ptr[input_halfline_pixel].top_second; + out_ptr_top[output_halfline_pixel].third = in_ptr[input_halfline_pixel].top_third; + out_ptr_top[output_halfline_pixel].fourth = in_ptr[input_halfline_pixel].top_fourth; + } +} + +static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out) { + #ifndef SIMPLE_DS_FRAME_SKIP + if(!p_in->frameinfo.valid) { //LCD was off + memset(p_out->screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * sizeof(uint16_t)); + return; + } + + // Handle first line being off, if needed + memset(p_out->screen_data, 0, WIDTH_DS * sizeof(uint16_t)); + + int input_halfline = 0; + for(int i = 0; i < 2; i++) { + if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7))) + usb_oldDSconvertVideoToOutputHalfLineDirectOpt(p_in, p_out, input_halfline++, i); + } + + for(int i = 2; i < HEIGHT_DS * 2; i++) { + if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7))) + usb_oldDSconvertVideoToOutputHalfLineDirectOpt(p_in, p_out, input_halfline++, i); + else { // deal with missing half-line + uint16_t* out_ptr_top = (uint16_t*)&p_out->screen_data; + uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS); + memcpy(&out_ptr_top[i * (WIDTH_DS / 2)], &out_ptr_top[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t)); + memcpy(&out_ptr_bottom[i * (WIDTH_DS / 2)], &out_ptr_bottom[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t)); + } + } + #else + for(int i = 0; i < HEIGHT_DS * 2; i++) + usb_oldDSconvertVideoToOutputHalfLineDirectOpt(p_in, p_out, i, i); + #endif +} + +static void usb_3DSconvertVideoToOutput(USB3DSCaptureReceived *p_in, VideoOutputData *p_out) { + memcpy(p_out->screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3); +} + +static void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureDevice* capture_device, bool enabled_3d) { + if(capture_device->is_3ds) { + if(!enabled_3d) + usb_3DSconvertVideoToOutput(&p_in->usb_received_3ds, p_out); + } + else + usb_oldDSconvertVideoToOutput(&p_in->usb_received_old_ds, p_out); +} +#endif + +#ifdef USE_IS_NITRO_USB +static void usb_is_nitro_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureScreensType capture_type) { + int num_pixels = usb_is_nitro_get_video_in_size(capture_type) / 3; + int out_start_pos = 0; + int out_clear_pos = num_pixels; + if(capture_type == CAPTURE_SCREENS_BOTTOM) { + out_start_pos = num_pixels; + out_clear_pos = 0; + } + if((capture_type == CAPTURE_SCREENS_BOTTOM) || (capture_type == CAPTURE_SCREENS_TOP)) + memset(p_out->screen_data[out_clear_pos], 0, num_pixels * 3); + memcpy(p_out->screen_data[out_start_pos], p_in->is_nitro_capture_received.video_in.screen_data, num_pixels * 3); +} +#endif + bool convertVideoToOutput(VideoOutputData *p_out, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status) { CaptureReceived *p_in = &data_buffer->capture_buf; bool converted = false; + CaptureDevice* chosen_device = &status->device; #ifdef USE_FTD3 - if(status->device.cc_type == CAPTURE_CONN_FTD3) { + if(chosen_device->cc_type == CAPTURE_CONN_FTD3) { ftd3_convertVideoToOutput(p_in, p_out, status->enabled_3d); converted = true; } #endif #ifdef USE_FTD2 - if(status->device.cc_type == CAPTURE_CONN_FTD2) { - ftd2_convertVideoToOutput(p_in, p_out, status->enabled_3d); + if(chosen_device->cc_type == CAPTURE_CONN_FTD2) { + ftd2_convertVideoToOutput(p_in, p_out); converted = true; } #endif #ifdef USE_DS_3DS_USB - if(status->device.cc_type == CAPTURE_CONN_USB) { - usb_convertVideoToOutput(p_in, p_out, &status->device, status->enabled_3d); + if(chosen_device->cc_type == CAPTURE_CONN_USB) { + usb_convertVideoToOutput(p_in, p_out, chosen_device, status->enabled_3d); converted = true; } #endif #ifdef USE_IS_NITRO_USB - if(status->device.cc_type == CAPTURE_CONN_IS_NITRO) { + if(chosen_device->cc_type == CAPTURE_CONN_IS_NITRO) { usb_is_nitro_convertVideoToOutput(p_in, p_out, data_buffer->capture_type); converted = true; }