From c3939a056bac09bfc10cdc8ad33fe1f3d115ca31 Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Mon, 31 Mar 2025 04:23:35 +0200 Subject: [PATCH] Add Optimize New 3DS data conversions --- CMakeLists.txt | 2 +- include/capture_structs.hpp | 16 +- include/conversions.hpp | 2 +- include/devicecapture.hpp | 2 +- include/hw_defs.hpp | 4 + source/cc3dsfs.cpp | 8 +- source/conversions.cpp | 771 ++++++++++++++++++++++++++++++++++-- source/devicecapture.cpp | 8 +- 8 files changed, 760 insertions(+), 53 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 86cc252..65ba750 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -550,7 +550,7 @@ add_custom_command( add_custom_command( OUTPUT ${TOOLS_DATA_DIR}/is_twl_cap_init_seed_table.cpp - COMMENT "Convert binary to C - IS TWL CRC32 table" + COMMENT "Convert binary to C - IS TWL Init Seed table" COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/is_twl_cap_init_seed_table.bin ${TOOLS_DATA_DIR} is_twl_cap_init_seed_table is_twl_cap_init_seed_table DEPENDS ${CMAKE_SOURCE_DIR}/bin/is_twl_cap_init_seed_table.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ) diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index a378c0f..c49b9f5 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -20,7 +20,7 @@ #define FTD2_INTRA_PACKET_HEADER_SIZE 2 #define MAX_PACKET_SIZE_FTD2 (MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE) -enum CaptureConnectionType { CAPTURE_CONN_FTD3, CAPTURE_CONN_USB, CAPTURE_CONN_FTD2, CAPTURE_CONN_IS_NITRO, CAPTURE_CONN_CYPRESS_NISETRO }; +enum CaptureConnectionType { CAPTURE_CONN_FTD3, CAPTURE_CONN_USB, CAPTURE_CONN_FTD2, CAPTURE_CONN_IS_NITRO, CAPTURE_CONN_CYPRESS_NISETRO, CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE }; 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 }; @@ -76,8 +76,8 @@ struct PACKED USB888New3DSOptimizePixelData { struct PACKED USBNew3DSOptimizeSingleSoundData { uint16_t sample_index; - uint16_t sample_r; uint16_t sample_l; + uint16_t sample_r; }; struct PACKED USBNew3DSOptimizeHeaderSoundData { @@ -201,19 +201,23 @@ struct ALIGNED(16) PACKED ISTWLCaptureReceived { }; struct ALIGNED(16) PACKED USB565New3DSOptimizeCaptureReceived { - USB565New3DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS + 1]; + USB565New3DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS]; + USB565New3DSOptimizePixelData bottom_only_column[HEIGHT_3DS][2]; }; struct ALIGNED(16) PACKED USB565New3DSOptimizeCaptureReceived_3D { - USB565New3DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS + 1]; + USB565New3DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS]; + USB565New3DSOptimizePixelData bottom_only_column[HEIGHT_3DS][3]; }; struct ALIGNED(16) PACKED USB888New3DSOptimizeCaptureReceived { - USB888New3DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS + 1]; + USB888New3DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS]; + USB888New3DSOptimizePixelData bottom_only_column[HEIGHT_3DS][2]; }; struct ALIGNED(16) PACKED USB888New3DSOptimizeCaptureReceived_3D { - USB888New3DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS + 1]; + USB888New3DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS]; + USB888New3DSOptimizePixelData bottom_only_column[HEIGHT_3DS][3]; }; #pragma pack(pop) diff --git a/include/conversions.hpp b/include/conversions.hpp index 07d4369..3fb0fea 100755 --- a/include/conversions.hpp +++ b/include/conversions.hpp @@ -5,5 +5,5 @@ #include "display_structs.hpp" bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool interleaved_3d, bool is_data_3d); -bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool is_data_3d); +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, bool is_data_3d); #endif diff --git a/include/devicecapture.hpp b/include/devicecapture.hpp index e4e81ae..27c8112 100755 --- a/include/devicecapture.hpp +++ b/include/devicecapture.hpp @@ -21,7 +21,7 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten void captureCall(CaptureData* capture_data); void capture_error_print(bool print_failed, CaptureData* capture_data, std::string error_string); void capture_error_print(bool print_failed, CaptureData* capture_data, std::string graphical_string, std::string detailed_string); -uint64_t get_audio_n_samples(CaptureData* capture_data, uint64_t read, bool is_3d); +uint64_t get_audio_n_samples(CaptureData* capture_data, CaptureDataSingleBuffer* data_buffer); uint64_t get_video_in_size(CaptureData* capture_data, bool is_3d); std::string get_name_of_device(CaptureStatus* capture_status, bool use_long = false); int get_usb_speed_of_device(CaptureStatus* capture_status); diff --git a/include/hw_defs.hpp b/include/hw_defs.hpp index 172fc39..bcd2839 100755 --- a/include/hw_defs.hpp +++ b/include/hw_defs.hpp @@ -39,6 +39,10 @@ #define WIDTH_NES 256 #define HEIGHT_NES 240 +#define SCREEN_WIDTH_DIFFERENCE_3DS (TOP_WIDTH_3DS - BOT_WIDTH_3DS) +#define SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS (SCREEN_WIDTH_DIFFERENCE_3DS / 2) +#define SCREEN_WIDTH_LAST_PIXEL_BOTTOM_3DS (BOT_WIDTH_3DS + SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS) + #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) diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index 2633cea..6cf5442 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -405,6 +405,7 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data) { std::int16_t (*out_buf)[MAX_SAMPLES_IN] = new std::int16_t[NUM_CONCURRENT_AUDIO_BUFFERS][MAX_SAMPLES_IN]; Audio audio(audio_data); int audio_buf_counter = 0; + uint16_t last_buffer_index = -1; const bool endianness = is_big_endian(); volatile int loaded_samples; audio_output_device_data in_use_audio_output_device_data; @@ -419,10 +420,10 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data) { CaptureDataSingleBuffer* data_buffer = capture_data->data_buffers.GetReaderBuffer(CAPTURE_READER_AUDIO); if(data_buffer != NULL) { loaded_samples = audio.samples.size(); - if((data_buffer->read > get_video_in_size(capture_data, data_buffer->is_3d)) && (loaded_samples < MAX_MAX_AUDIO_LATENCY) && capture_data->status.connected) { - uint64_t n_samples = get_audio_n_samples(capture_data, data_buffer->read, data_buffer->is_3d); + if((data_buffer->read >= get_video_in_size(capture_data, data_buffer->is_3d)) && (loaded_samples < MAX_MAX_AUDIO_LATENCY) && capture_data->status.connected) { + uint64_t n_samples = get_audio_n_samples(capture_data, data_buffer); double out_time = data_buffer->time_in_buf; - bool conversion_success = convertAudioToOutput(out_buf[audio_buf_counter], n_samples, endianness, data_buffer, &capture_data->status, data_buffer->is_3d); + bool conversion_success = convertAudioToOutput(out_buf[audio_buf_counter], n_samples, last_buffer_index, endianness, data_buffer, &capture_data->status, data_buffer->is_3d); if(!conversion_success) audio_data->signal_conversion_error(); audio.samples.emplace(out_buf[audio_buf_counter], n_samples, out_time); @@ -461,6 +462,7 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data) { } } else { + last_buffer_index = -1; audio.stop_audio(); audio.stop(); default_sleep(); diff --git a/source/conversions.cpp b/source/conversions.cpp index 9aaccba..17be0ce 100755 --- a/source/conversions.cpp +++ b/source/conversions.cpp @@ -7,7 +7,9 @@ #include -struct interleaved_ds_pixels { +#define OPTIMIZE_AUDIO_BUFFER_MAX_SIZE 0x200 + +struct interleaved_rgb565_pixels { uint16_t bottom_first; uint16_t top_first; uint16_t bottom_second; @@ -18,13 +20,74 @@ struct interleaved_ds_pixels { uint16_t top_fourth; }; -struct deinterleaved_ds_pixels_le { +struct ALIGNED(8) interleaved_3d_rgb565_pixels { + uint16_t bottom_first; + uint16_t top_l_first; + uint16_t top_r_first; + uint16_t bottom_second; + uint16_t top_l_second; + uint16_t top_r_second; + uint16_t bottom_third; + uint16_t top_l_third; + uint16_t top_r_third; + uint16_t bottom_fourth; + uint16_t top_l_fourth; + uint16_t top_r_fourth; +}; + +struct deinterleaved_rgb565_pixels { uint64_t first : 16; uint64_t second : 16; uint64_t third : 16; uint64_t fourth : 16; }; +struct ALIGNED(8) interleaved_rgb888_u16_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; + uint16_t bottom_fifth; + uint16_t top_fifth; + uint16_t bottom_sixth; + uint16_t top_sixth; +}; + +struct ALIGNED(4) interleaved_3d_rgb888_u16_pixels { + uint16_t bottom_first; + uint16_t top_l_first; + uint16_t top_r_first; + uint16_t bottom_second; + uint16_t top_l_second; + uint16_t top_r_second; + uint16_t bottom_third; + uint16_t top_l_third; + uint16_t top_r_third; + uint16_t bottom_fourth; + uint16_t top_l_fourth; + uint16_t top_r_fourth; + uint16_t bottom_fifth; + uint16_t top_l_fifth; + uint16_t top_r_fifth; + uint16_t bottom_sixth; + uint16_t top_l_sixth; + uint16_t top_r_sixth; +}; + +struct ALIGNED(4) deinterleaved_rgb888_u16_pixels { + // 4 pixels + uint16_t first; + uint16_t second; + uint16_t third; + uint16_t fourth; + uint16_t fifth; + uint16_t sixth; +}; + struct twl_16bit_pixels { uint16_t first_r : 5; uint16_t first_g : 6; @@ -51,6 +114,325 @@ struct twl_2bit_pixels { uint8_t fourth_b : 1; }; +static void usb_new_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d, const bool is_big_endian, bool interleaved_3d, bool requested_3d, bool is_rgb888); + +// Optimized de-interleave methods... + +static inline uint16_t _reverse_endianness(uint16_t data) { + return (data >> 8) | ((data << 8) & 0xFF00); +} + +static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptLE(deinterleaved_rgb565_pixels* out_ptr_top, deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel = (output_halfline * num_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 inline void usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(deinterleaved_rgb565_pixels* out_ptr_top, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel = (output_halfline * num_iters) + i; + 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 inline void usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel = (output_halfline * num_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; + } +} + +static inline void usb_rgb565convertInterleave3DVideoToOutputDirectOptLE(deinterleaved_rgb565_pixels* out_ptr_top_l, deinterleaved_rgb565_pixels* out_ptr_top_r, deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_3d_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline, int multiplier_top) { + //de-interleave pixels + const size_t output_halfline_pos = output_halfline * num_iters; + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel_bottom = output_halfline_pos + i; + size_t output_halfline_pixel_top = (output_halfline_pos * multiplier_top) + i; + out_ptr_bottom[output_halfline_pixel_bottom].first = in_ptr[input_halfline_pixel].bottom_first; + out_ptr_bottom[output_halfline_pixel_bottom].second = in_ptr[input_halfline_pixel].bottom_second; + out_ptr_bottom[output_halfline_pixel_bottom].third = in_ptr[input_halfline_pixel].bottom_third; + out_ptr_bottom[output_halfline_pixel_bottom].fourth = in_ptr[input_halfline_pixel].bottom_fourth; + out_ptr_top_l[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_l_first; + out_ptr_top_l[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_l_second; + out_ptr_top_l[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_l_third; + out_ptr_top_l[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_l_fourth; + out_ptr_top_r[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_r_first; + out_ptr_top_r[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_r_second; + out_ptr_top_r[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_r_third; + out_ptr_top_r[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_r_fourth; + } +} + +static inline void usb_rgb565convertInterleave3DVideoToOutputDirectOptLEMonoTop(deinterleaved_rgb565_pixels* out_ptr_top_l, deinterleaved_rgb565_pixels* out_ptr_top_r, interleaved_3d_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline, int multiplier_top) { + //de-interleave pixels + const size_t output_halfline_pos = output_halfline * num_iters; + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel_top = (output_halfline_pos * multiplier_top) + i; + out_ptr_top_l[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_l_first; + out_ptr_top_l[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_l_second; + out_ptr_top_l[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_l_third; + out_ptr_top_l[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_l_fourth; + out_ptr_top_r[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_r_first; + out_ptr_top_r[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_r_second; + out_ptr_top_r[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_r_third; + out_ptr_top_r[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_r_fourth; + } +} + +static inline void usb_rgb565convertInterleave3DVideoToOutputDirectOptLEMonoBottom(deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_3d_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel = (output_halfline * num_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; + } +} + +static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptBE(deinterleaved_rgb565_pixels* out_ptr_top, deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel = (output_halfline * num_iters) + i; + out_ptr_bottom[output_halfline_pixel].first = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_first); + out_ptr_bottom[output_halfline_pixel].second = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_second); + out_ptr_bottom[output_halfline_pixel].third = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_third); + out_ptr_bottom[output_halfline_pixel].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_fourth); + out_ptr_top[output_halfline_pixel].first = _reverse_endianness(in_ptr[input_halfline_pixel].top_first); + out_ptr_top[output_halfline_pixel].second = _reverse_endianness(in_ptr[input_halfline_pixel].top_second); + out_ptr_top[output_halfline_pixel].third = _reverse_endianness(in_ptr[input_halfline_pixel].top_third); + out_ptr_top[output_halfline_pixel].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].top_fourth); + } +} + +static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(deinterleaved_rgb565_pixels* out_ptr_top, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel = (output_halfline * num_iters) + i; + out_ptr_top[output_halfline_pixel].first = _reverse_endianness(in_ptr[input_halfline_pixel].top_first); + out_ptr_top[output_halfline_pixel].second = _reverse_endianness(in_ptr[input_halfline_pixel].top_second); + out_ptr_top[output_halfline_pixel].third = _reverse_endianness(in_ptr[input_halfline_pixel].top_third); + out_ptr_top[output_halfline_pixel].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].top_fourth); + } +} + +static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline, const int num_screens = 2) { + //de-interleave pixels + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel = (output_halfline * num_iters) + i; + out_ptr_bottom[output_halfline_pixel].first = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_first); + out_ptr_bottom[output_halfline_pixel].second = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_second); + out_ptr_bottom[output_halfline_pixel].third = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_third); + out_ptr_bottom[output_halfline_pixel].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_fourth); + } +} + +static inline void usb_rgb565convertInterleave3DVideoToOutputDirectOptBE(deinterleaved_rgb565_pixels* out_ptr_top_l, deinterleaved_rgb565_pixels* out_ptr_top_r, deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_3d_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline, int multiplier_top) { + //de-interleave pixels + const size_t output_halfline_pos = output_halfline * num_iters; + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel_bottom = output_halfline_pos + i; + size_t output_halfline_pixel_top = (output_halfline_pos * multiplier_top) + i; + out_ptr_bottom[output_halfline_pixel_bottom].first = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_first); + out_ptr_bottom[output_halfline_pixel_bottom].second = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_second); + out_ptr_bottom[output_halfline_pixel_bottom].third = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_third); + out_ptr_bottom[output_halfline_pixel_bottom].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_fourth); + out_ptr_top_l[output_halfline_pixel_top].first = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_first); + out_ptr_top_l[output_halfline_pixel_top].second = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_second); + out_ptr_top_l[output_halfline_pixel_top].third = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_third); + out_ptr_top_l[output_halfline_pixel_top].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_fourth); + out_ptr_top_r[output_halfline_pixel_top].first = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_first); + out_ptr_top_r[output_halfline_pixel_top].second = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_second); + out_ptr_top_r[output_halfline_pixel_top].third = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_third); + out_ptr_top_r[output_halfline_pixel_top].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_fourth); + } +} + +static inline void usb_rgb565convertInterleave3DVideoToOutputDirectOptBEMonoTop(deinterleaved_rgb565_pixels* out_ptr_top_l, deinterleaved_rgb565_pixels* out_ptr_top_r, interleaved_3d_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline, int multiplier_top) { + //de-interleave pixels + const size_t output_halfline_pos = output_halfline * num_iters; + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel_top = (output_halfline_pos * multiplier_top) + i; + out_ptr_top_l[output_halfline_pixel_top].first = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_first); + out_ptr_top_l[output_halfline_pixel_top].second = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_second); + out_ptr_top_l[output_halfline_pixel_top].third = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_third); + out_ptr_top_l[output_halfline_pixel_top].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].top_l_fourth); + out_ptr_top_r[output_halfline_pixel_top].first = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_first); + out_ptr_top_r[output_halfline_pixel_top].second = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_second); + out_ptr_top_r[output_halfline_pixel_top].third = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_third); + out_ptr_top_r[output_halfline_pixel_top].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].top_r_fourth); + } +} + +static inline void usb_rgb565convertInterleave3DVideoToOutputDirectOptBEMonoBottom(deinterleaved_rgb565_pixels* out_ptr_bottom, interleaved_3d_rgb565_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + const size_t output_halfline_pos = output_halfline * num_iters; + for(size_t i = 0; i < num_iters; i++) { + size_t input_halfline_pixel = (input_halfline * num_iters) + i; + size_t output_halfline_pixel_bottom = output_halfline_pos + i; + out_ptr_bottom[output_halfline_pixel_bottom].first = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_first); + out_ptr_bottom[output_halfline_pixel_bottom].second = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_second); + out_ptr_bottom[output_halfline_pixel_bottom].third = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_third); + out_ptr_bottom[output_halfline_pixel_bottom].fourth = _reverse_endianness(in_ptr[input_halfline_pixel].bottom_fourth); + } +} + +static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOpt(deinterleaved_rgb888_u16_pixels* out_ptr_top, deinterleaved_rgb888_u16_pixels* out_ptr_bottom, interleaved_rgb888_u16_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + const int pixel_size = 3; + const int num_pixels_processed = sizeof(deinterleaved_rgb888_u16_pixels) / pixel_size; + const size_t real_num_iters = num_iters / num_pixels_processed; + 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; + 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_bottom[output_halfline_pixel].fifth = in_ptr[input_halfline_pixel].bottom_fifth; + out_ptr_bottom[output_halfline_pixel].sixth = in_ptr[input_halfline_pixel].bottom_sixth; + 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; + out_ptr_top[output_halfline_pixel].fifth = in_ptr[input_halfline_pixel].top_fifth; + out_ptr_top[output_halfline_pixel].sixth = in_ptr[input_halfline_pixel].top_sixth; + } +} + +static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoTop(deinterleaved_rgb888_u16_pixels* out_ptr_top, interleaved_rgb888_u16_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + const int pixel_size = 3; + const int num_pixels_processed = sizeof(deinterleaved_rgb888_u16_pixels) / pixel_size; + const size_t real_num_iters = num_iters / num_pixels_processed; + 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; + 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; + out_ptr_top[output_halfline_pixel].fifth = in_ptr[input_halfline_pixel].top_fifth; + out_ptr_top[output_halfline_pixel].sixth = in_ptr[input_halfline_pixel].top_sixth; + } +} + +static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoBottom(deinterleaved_rgb888_u16_pixels* out_ptr_bottom, interleaved_rgb888_u16_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + //de-interleave pixels + const int pixel_size = 3; + const int num_pixels_processed = sizeof(deinterleaved_rgb888_u16_pixels) / pixel_size; + const size_t real_num_iters = num_iters / num_pixels_processed; + 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; + 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_bottom[output_halfline_pixel].fifth = in_ptr[input_halfline_pixel].bottom_fifth; + out_ptr_bottom[output_halfline_pixel].sixth = in_ptr[input_halfline_pixel].bottom_sixth; + } +} + +static inline void usb_rgb888convertInterleaveU163DVideoToOutputDirectOpt(deinterleaved_rgb888_u16_pixels* out_ptr_top_l, deinterleaved_rgb888_u16_pixels* out_ptr_top_r, deinterleaved_rgb888_u16_pixels* out_ptr_bottom, interleaved_3d_rgb888_u16_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline, int multiplier_top) { + //de-interleave pixels + const int pixel_size = 3; + const int num_pixels_processed = sizeof(deinterleaved_rgb888_u16_pixels) / pixel_size; + const size_t real_num_iters = num_iters / num_pixels_processed; + const size_t output_halfline_pos = output_halfline * num_iters; + 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_pos + i; + size_t output_halfline_pixel_top = (output_halfline_pos * multiplier_top) + i; + out_ptr_bottom[output_halfline_pixel_bottom].first = in_ptr[input_halfline_pixel].bottom_first; + out_ptr_bottom[output_halfline_pixel_bottom].second = in_ptr[input_halfline_pixel].bottom_second; + out_ptr_bottom[output_halfline_pixel_bottom].third = in_ptr[input_halfline_pixel].bottom_third; + out_ptr_bottom[output_halfline_pixel_bottom].fourth = in_ptr[input_halfline_pixel].bottom_fourth; + out_ptr_bottom[output_halfline_pixel_bottom].fifth = in_ptr[input_halfline_pixel].bottom_fifth; + out_ptr_bottom[output_halfline_pixel_bottom].sixth = in_ptr[input_halfline_pixel].bottom_sixth; + out_ptr_top_l[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_l_first; + out_ptr_top_l[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_l_second; + out_ptr_top_l[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_l_third; + out_ptr_top_l[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_l_fourth; + out_ptr_top_l[output_halfline_pixel_top].fifth = in_ptr[input_halfline_pixel].top_l_fifth; + out_ptr_top_l[output_halfline_pixel_top].sixth = in_ptr[input_halfline_pixel].top_l_sixth; + out_ptr_top_r[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_r_first; + out_ptr_top_r[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_r_second; + out_ptr_top_r[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_r_third; + out_ptr_top_r[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_r_fourth; + out_ptr_top_r[output_halfline_pixel_top].fifth = in_ptr[input_halfline_pixel].top_r_fifth; + out_ptr_top_r[output_halfline_pixel_top].sixth = in_ptr[input_halfline_pixel].top_r_sixth; + } +} + +static inline void usb_rgb888convertInterleaveU163DVideoToOutputDirectOptMonoTop(deinterleaved_rgb888_u16_pixels* out_ptr_top_l, deinterleaved_rgb888_u16_pixels* out_ptr_top_r, interleaved_3d_rgb888_u16_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline, int multiplier_top) { + const int pixel_size = 3; + const int num_pixels_processed = sizeof(deinterleaved_rgb888_u16_pixels) / pixel_size; + const size_t real_num_iters = num_iters / num_pixels_processed; + const size_t output_halfline_pos = output_halfline * num_iters; + 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_top = (output_halfline_pos * multiplier_top) + i; + out_ptr_top_l[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_l_first; + out_ptr_top_l[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_l_second; + out_ptr_top_l[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_l_third; + out_ptr_top_l[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_l_fourth; + out_ptr_top_l[output_halfline_pixel_top].fifth = in_ptr[input_halfline_pixel].top_l_fifth; + out_ptr_top_l[output_halfline_pixel_top].sixth = in_ptr[input_halfline_pixel].top_l_sixth; + out_ptr_top_r[output_halfline_pixel_top].first = in_ptr[input_halfline_pixel].top_r_first; + out_ptr_top_r[output_halfline_pixel_top].second = in_ptr[input_halfline_pixel].top_r_second; + out_ptr_top_r[output_halfline_pixel_top].third = in_ptr[input_halfline_pixel].top_r_third; + out_ptr_top_r[output_halfline_pixel_top].fourth = in_ptr[input_halfline_pixel].top_r_fourth; + out_ptr_top_r[output_halfline_pixel_top].fifth = in_ptr[input_halfline_pixel].top_r_fifth; + out_ptr_top_r[output_halfline_pixel_top].sixth = in_ptr[input_halfline_pixel].top_r_sixth; + } +} + +static inline void usb_rgb888convertInterleaveU163DVideoToOutputDirectOptMonoBottom(deinterleaved_rgb888_u16_pixels* out_ptr_bottom, interleaved_3d_rgb888_u16_pixels* in_ptr, uint32_t num_iters, int input_halfline, int output_halfline) { + const int pixel_size = 3; + const int num_pixels_processed = sizeof(deinterleaved_rgb888_u16_pixels) / pixel_size; + const size_t real_num_iters = num_iters / num_pixels_processed; + const size_t output_halfline_pos = output_halfline * num_iters; + 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_pos + i; + out_ptr_bottom[output_halfline_pixel_bottom].first = in_ptr[input_halfline_pixel].bottom_first; + out_ptr_bottom[output_halfline_pixel_bottom].second = in_ptr[input_halfline_pixel].bottom_second; + out_ptr_bottom[output_halfline_pixel_bottom].third = in_ptr[input_halfline_pixel].bottom_third; + out_ptr_bottom[output_halfline_pixel_bottom].fourth = in_ptr[input_halfline_pixel].bottom_fourth; + out_ptr_bottom[output_halfline_pixel_bottom].fifth = in_ptr[input_halfline_pixel].bottom_fifth; + out_ptr_bottom[output_halfline_pixel_bottom].sixth = in_ptr[input_halfline_pixel].bottom_sixth; + } +} + + 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); } @@ -59,6 +441,19 @@ static inline void convertVideoToOutputChunk_3D(RGB83DSVideoInputData_3D *p_in, memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3); } +static void expand_2d_to_3d_convertVideoToOutput(uint8_t *out_screen_data, size_t pixels_size, bool interleaved_3d, bool requested_3d) { + if(requested_3d && interleaved_3d) { + for(int i = TOP_WIDTH_3DS - 1; i >= 0; i--) { + memcpy(&out_screen_data[(BOT_SIZE_3DS + (((2 * i) + 1) * HEIGHT_3DS)) * pixels_size], &out_screen_data[(BOT_SIZE_3DS + (i * HEIGHT_3DS)) * pixels_size], HEIGHT_3DS * pixels_size); + memcpy(&out_screen_data[(BOT_SIZE_3DS + ((2 * i) * HEIGHT_3DS)) * pixels_size], &out_screen_data[(BOT_SIZE_3DS + (i * HEIGHT_3DS)) * pixels_size], HEIGHT_3DS * pixels_size); + } + } + else if(requested_3d) { + memcpy(&out_screen_data[(BOT_SIZE_3DS + TOP_SIZE_3DS) * pixels_size], &out_screen_data[BOT_SIZE_3DS * pixels_size], TOP_SIZE_3DS * pixels_size); + } +} + +// Logical conversions static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d, bool interleaved_3d, bool requested_3d) { if(!enabled_3d) { convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_NO_BOTTOM_SIZE_3DS, 0, BOT_SIZE_3DS); @@ -67,15 +462,7 @@ static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_ convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, (((i * 2) + 0) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_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, BOT_SIZE_3DS + IN_VIDEO_NO_BOTTOM_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS)); } - if(requested_3d && interleaved_3d) { - for(int i = TOP_WIDTH_3DS - 1; i >= 0; i--) { - memcpy(&p_out->screen_data[BOT_SIZE_3DS + (((2 * i) + 1) * HEIGHT_3DS)], &p_out->screen_data[BOT_SIZE_3DS + (i * HEIGHT_3DS)], HEIGHT_3DS * 3); - memcpy(&p_out->screen_data[BOT_SIZE_3DS + ((2 * i) * HEIGHT_3DS)], &p_out->screen_data[BOT_SIZE_3DS + (i * HEIGHT_3DS)], HEIGHT_3DS * 3); - } - } - else if(requested_3d) { - memcpy(&p_out->screen_data[BOT_SIZE_3DS + TOP_SIZE_3DS], &p_out->screen_data[BOT_SIZE_3DS], TOP_SIZE_3DS * 3); - } + expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->screen_data, 3, interleaved_3d, requested_3d); } else { size_t last_line_index = ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)) - 1; @@ -117,37 +504,220 @@ static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_ static inline void usb_oldDSconvertVideoToOutputHalfLineDirectOptLE(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) { //de-interleave pixels - deinterleaved_ds_pixels_le* out_ptr_top = (deinterleaved_ds_pixels_le*)p_out->screen_data; - deinterleaved_ds_pixels_le* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS / (sizeof(deinterleaved_ds_pixels_le) / 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; - } + const int pixels_size = 2; + const int num_screens = 2; + const int num_halflines = 2; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + const size_t ptr_in_size = sizeof(interleaved_rgb565_pixels); + deinterleaved_rgb565_pixels* out_ptr_top = (deinterleaved_rgb565_pixels*)p_out->screen_data; + deinterleaved_rgb565_pixels* out_ptr_bottom = out_ptr_top + ((WIDTH_DS * HEIGHT_DS * pixels_size) / ptr_out_size); + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->video_in.screen_data; + const uint32_t halfline_iters = (WIDTH_DS * num_screens * pixels_size) / (ptr_in_size * num_halflines); + usb_rgb565convertInterleaveVideoToOutputDirectOptLE(out_ptr_top, out_ptr_bottom, in_ptr, halfline_iters, input_halfline, output_halfline); } static inline void usb_oldDSconvertVideoToOutputHalfLineDirectOptBE(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 / (sizeof(uint16_t) / 2)); - uint32_t* in_ptr = (uint32_t*)p_in->video_in.screen_data; - const uint32_t halfline_iters = WIDTH_DS / (sizeof(uint32_t) / 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; - uint16_t bottom_pixel_rev = in_ptr[input_halfline_pixel] >> 16; - uint16_t top_pixel_rev = in_ptr[input_halfline_pixel] & 0xFFFF; - out_ptr_bottom[output_halfline_pixel] = (bottom_pixel_rev >> 8) | ((bottom_pixel_rev << 8) & 0xFF00); - out_ptr_top[output_halfline_pixel] = (top_pixel_rev >> 8) | ((top_pixel_rev << 8) & 0xFF00); + const int pixels_size = 2; + const int num_screens = 2; + const int num_halflines = 2; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + const size_t ptr_in_size = sizeof(interleaved_rgb565_pixels); + deinterleaved_rgb565_pixels* out_ptr_top = (deinterleaved_rgb565_pixels*)p_out->screen_data; + deinterleaved_rgb565_pixels* out_ptr_bottom = out_ptr_top + ((WIDTH_DS * HEIGHT_DS * pixels_size) / ptr_out_size); + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->video_in.screen_data; + const uint32_t halfline_iters = (WIDTH_DS * num_screens * pixels_size) / (ptr_in_size * num_halflines); + usb_rgb565convertInterleaveVideoToOutputDirectOptBE(out_ptr_top, out_ptr_bottom, in_ptr, halfline_iters, input_halfline, output_halfline); +} + +static inline void usb_new3DS565OptimizeconvertVideoToOutputLineDirectOptLE(USB565New3DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, int column) { + //de-interleave pixels + const int pixels_size = 2; + const int num_screens = 2; + const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + const size_t ptr_in_size = sizeof(interleaved_rgb565_pixels); + deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data; + deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column; + if(column < column_last_bot_pos) + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].pixel; + const uint32_t num_iters = (HEIGHT_3DS * pixels_size * num_screens) / ptr_in_size; + if(column == column_last_bot_pos) + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); + else if(column == column_pre_last_bot_pos) { + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(out_ptr_top, in_ptr, num_iters, 0, column); + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 2); + } + else if(column < column_start_bot_pos) + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(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_rgb565convertInterleaveVideoToOutputDirectOptLE(out_ptr_top, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos); + } +} + +static inline void usb_new3DS565OptimizeconvertVideoToOutputLineDirectOptBE(USB565New3DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, int column) { + //de-interleave pixels + const int pixels_size = 2; + const int num_screens = 2; + const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + const size_t ptr_in_size = sizeof(interleaved_rgb565_pixels); + deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data; + deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column; + if(column < column_last_bot_pos) + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].pixel; + const uint32_t num_iters = (HEIGHT_3DS * pixels_size * num_screens) / ptr_in_size; + if(column == column_last_bot_pos) + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); + else if(column == column_pre_last_bot_pos) { + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(out_ptr_top, in_ptr, num_iters, 0, column); + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 2); + } + else if(column < column_start_bot_pos) + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(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_rgb565convertInterleaveVideoToOutputDirectOptBE(out_ptr_top, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos); + } +} + +static inline void usb_new3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB565New3DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, int column, bool interleaved_3d) { + //de-interleave pixels + const int pixels_size = 2; + const int num_screens = 3; + const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + const size_t ptr_in_size = sizeof(interleaved_3d_rgb565_pixels); + deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data; + deinterleaved_rgb565_pixels* out_ptr_top_l = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); + deinterleaved_rgb565_pixels* out_ptr_top_r = out_ptr_bottom + (((TOP_SIZE_3DS + BOT_SIZE_3DS) * pixels_size) / ptr_out_size); + interleaved_3d_rgb565_pixels* in_ptr = (interleaved_3d_rgb565_pixels*)p_in->bottom_only_column; + if(column < column_last_bot_pos) + in_ptr = (interleaved_3d_rgb565_pixels*)p_in->columns_data[column].pixel; + int multiplier_top = 1; + if(interleaved_3d) { + multiplier_top = 2; + out_ptr_top_r = out_ptr_top_l + ((HEIGHT_3DS * pixels_size) / ptr_out_size); + } + const uint32_t num_iters = (HEIGHT_3DS * pixels_size * num_screens) / ptr_in_size; + if(column == column_last_bot_pos) + usb_rgb565convertInterleave3DVideoToOutputDirectOptLEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); + else if(column == column_pre_last_bot_pos) { + usb_rgb565convertInterleave3DVideoToOutputDirectOptLEMonoTop(out_ptr_top_l, out_ptr_top_r, in_ptr, num_iters, 0, column, multiplier_top); + usb_rgb565convertInterleave3DVideoToOutputDirectOptLEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 2); + } + else if(column < column_start_bot_pos) + usb_rgb565convertInterleave3DVideoToOutputDirectOptLEMonoTop(out_ptr_top_l, out_ptr_top_r, in_ptr, num_iters, 0, column, multiplier_top); + else { + out_ptr_top_l += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + out_ptr_top_r += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + usb_rgb565convertInterleave3DVideoToOutputDirectOptLE(out_ptr_top_l, out_ptr_top_r, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos, multiplier_top); + } +} + +static inline void usb_new3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB565New3DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, int column, bool interleaved_3d) { + //de-interleave pixels + const int pixels_size = 2; + const int num_screens = 3; + const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels); + const size_t ptr_in_size = sizeof(interleaved_3d_rgb565_pixels); + deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data; + deinterleaved_rgb565_pixels* out_ptr_top_l = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); + deinterleaved_rgb565_pixels* out_ptr_top_r = out_ptr_bottom + (((TOP_SIZE_3DS + BOT_SIZE_3DS) * pixels_size) / ptr_out_size); + interleaved_3d_rgb565_pixels* in_ptr = (interleaved_3d_rgb565_pixels*)p_in->bottom_only_column; + if(column < column_last_bot_pos) + in_ptr = (interleaved_3d_rgb565_pixels*)p_in->columns_data[column].pixel; + int multiplier_top = 1; + if(interleaved_3d) { + multiplier_top = 2; + out_ptr_top_r = out_ptr_top_l + ((HEIGHT_3DS * pixels_size) / ptr_out_size); + } + const uint32_t num_iters = (HEIGHT_3DS * pixels_size * num_screens) / ptr_in_size; + if(column == column_last_bot_pos) + usb_rgb565convertInterleave3DVideoToOutputDirectOptBEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); + else if(column == column_pre_last_bot_pos) { + usb_rgb565convertInterleave3DVideoToOutputDirectOptBEMonoTop(out_ptr_top_l, out_ptr_top_r, in_ptr, num_iters, 0, column, multiplier_top); + usb_rgb565convertInterleave3DVideoToOutputDirectOptBEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 2); + } + else if(column < column_start_bot_pos) + usb_rgb565convertInterleave3DVideoToOutputDirectOptBEMonoTop(out_ptr_top_l, out_ptr_top_r, in_ptr, num_iters, 0, column, multiplier_top); + else { + out_ptr_top_l += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + out_ptr_top_r += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + usb_rgb565convertInterleave3DVideoToOutputDirectOptBE(out_ptr_top_l, out_ptr_top_r, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos, multiplier_top); + } +} + +static inline void usb_new3DS888OptimizeconvertVideoToOutputLineDirectOpt(USB888New3DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, int column) { + //de-interleave pixels + const int pixels_size = 3; + const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb888_u16_pixels); + deinterleaved_rgb888_u16_pixels* out_ptr_bottom = (deinterleaved_rgb888_u16_pixels*)p_out->screen_data; + deinterleaved_rgb888_u16_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); + interleaved_rgb888_u16_pixels* in_ptr = (interleaved_rgb888_u16_pixels*)p_in->bottom_only_column; + if(column < column_last_bot_pos) + in_ptr = (interleaved_rgb888_u16_pixels*)p_in->columns_data[column].pixel; + const uint32_t num_iters = HEIGHT_3DS; + if(column == column_last_bot_pos) + usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); + else if(column == column_pre_last_bot_pos) { + usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoTop(out_ptr_top, in_ptr, num_iters, 0, column); + usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 2); + } + else if(column < column_start_bot_pos) + usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoTop(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_rgb888convertInterleaveU16VideoToOutputDirectOpt(out_ptr_top, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos); + } +} + +static inline void usb_new3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(USB888New3DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, int column, bool interleaved_3d) { + //de-interleave pixels + const int pixels_size = 3; + const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + const size_t column_last_bot_pos = TOP_WIDTH_3DS; + const size_t ptr_out_size = sizeof(deinterleaved_rgb888_u16_pixels); + deinterleaved_rgb888_u16_pixels* out_ptr_bottom = (deinterleaved_rgb888_u16_pixels*)p_out->screen_data; + deinterleaved_rgb888_u16_pixels* out_ptr_top_l = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); + deinterleaved_rgb888_u16_pixels* out_ptr_top_r = out_ptr_bottom + (((TOP_SIZE_3DS + BOT_SIZE_3DS) * pixels_size) / ptr_out_size); + interleaved_3d_rgb888_u16_pixels* in_ptr = (interleaved_3d_rgb888_u16_pixels*)p_in->bottom_only_column; + if(column < column_last_bot_pos) + in_ptr = (interleaved_3d_rgb888_u16_pixels*)p_in->columns_data[column].pixel; + int multiplier_top = 1; + if(interleaved_3d) { + multiplier_top = 2; + out_ptr_top_r = out_ptr_top_l + (HEIGHT_3DS / ptr_out_size); + } + const uint32_t num_iters = HEIGHT_3DS; + if(column == column_last_bot_pos) + usb_rgb888convertInterleaveU163DVideoToOutputDirectOptMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); + else if(column == column_pre_last_bot_pos) { + usb_rgb888convertInterleaveU163DVideoToOutputDirectOptMonoTop(out_ptr_top_l, out_ptr_top_r, in_ptr, num_iters, 0, column, multiplier_top); + usb_rgb888convertInterleaveU163DVideoToOutputDirectOptMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 2); + } + else if(column < column_start_bot_pos) + usb_rgb888convertInterleaveU163DVideoToOutputDirectOptMonoTop(out_ptr_top_l, out_ptr_top_r, in_ptr, num_iters, 0, column, multiplier_top); + else { + out_ptr_top_l += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + out_ptr_top_r += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + usb_rgb888convertInterleaveU163DVideoToOutputDirectOpt(out_ptr_top_l, out_ptr_top_r, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos, multiplier_top); } } @@ -248,6 +818,39 @@ static void usb_cypress_nisetro_ds_convertVideoToOutput(CaptureReceived *p_in, V } } +static void usb_new_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d, const bool is_big_endian, bool interleaved_3d, bool requested_3d, bool is_rgb888) { + if(!is_rgb888) { + if(!enabled_3d) { + if(!is_big_endian) + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_new3DS565OptimizeconvertVideoToOutputLineDirectOptLE(&p_in->cypress_new_optimize_received_565, p_out, i); + else + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_new3DS565OptimizeconvertVideoToOutputLineDirectOptBE(&p_in->cypress_new_optimize_received_565, p_out, i); + expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->screen_data, 2, interleaved_3d, requested_3d); + } + else { + if(!is_big_endian) + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_new3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(&p_in->cypress_new_optimize_received_565_3d, p_out, i, interleaved_3d); + else + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_new3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(&p_in->cypress_new_optimize_received_565_3d, p_out, i, interleaved_3d); + } + } + else { + if(!enabled_3d) { + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_new3DS888OptimizeconvertVideoToOutputLineDirectOpt(&p_in->cypress_new_optimize_received_888, p_out, i); + expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->screen_data, 3, interleaved_3d, requested_3d); + } + else { + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_new3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(&p_in->cypress_new_optimize_received_888_3d, p_out, i, interleaved_3d); + } + } +} + 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 @@ -332,10 +935,90 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt converted = true; } #endif + #ifdef USE_CYPRESS_NEW_OPTIMIZE + if(status->device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE) { + bool is_rgb888 = true; + usb_new_3ds_optimize_convertVideoToOutput(p_in, p_out, is_data_3d, is_big_endian, interleaved_3d, requested_3d, is_rgb888); + converted = true; + } + #endif return converted; } -bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool is_data_3d) { +static USBNew3DSOptimizeHeaderSoundData* getAudioHeaderPtrNewOptimize3DS(CaptureReceived* buffer, bool is_rgb888, bool is_data_3d, int column) { + if(!is_rgb888) { + if(!is_data_3d) + return &buffer->cypress_new_optimize_received_565.columns_data[column].header_sound; + return &buffer->cypress_new_optimize_received_565_3d.columns_data[column].header_sound; + } + if(!is_data_3d) + return &buffer->cypress_new_optimize_received_888.columns_data[column].header_sound; + return &buffer->cypress_new_optimize_received_888_3d.columns_data[column].header_sound; +} + +static inline uint16_t read_sample_indexLE(USBNew3DSOptimizeSingleSoundData* sample) { + return sample->sample_index % OPTIMIZE_AUDIO_BUFFER_MAX_SIZE; +} + +static inline uint16_t read_sample_indexBE(USBNew3DSOptimizeSingleSoundData* sample) { + return _reverse_endianness(sample->sample_index) % OPTIMIZE_AUDIO_BUFFER_MAX_SIZE; +} + +static inline void copyAudioFromSoundDataNewOptimize3DSLE(std::int16_t *p_out, uint16_t start, USBNew3DSOptimizeSingleSoundData* sample) { + int32_t position = (read_sample_indexLE(sample) + OPTIMIZE_AUDIO_BUFFER_MAX_SIZE - start) % OPTIMIZE_AUDIO_BUFFER_MAX_SIZE; + p_out[position * 2] = sample->sample_l; + p_out[(position * 2) + 1] = sample->sample_r; +} + +static inline void copyAudioFromSoundDataNewOptimize3DSBE(std::int16_t *p_out, uint16_t start, USBNew3DSOptimizeSingleSoundData* sample) { + int32_t position = (read_sample_indexBE(sample) + OPTIMIZE_AUDIO_BUFFER_MAX_SIZE - start) % OPTIMIZE_AUDIO_BUFFER_MAX_SIZE; + p_out[position * 2] = _reverse_endianness(sample->sample_l); + p_out[(position * 2) + 1] = _reverse_endianness(sample->sample_r); +} + +static void copyAudioNewOptimize3DSLE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888, bool is_data_3d) { + USBNew3DSOptimizeHeaderSoundData* first_column_data = getAudioHeaderPtrNewOptimize3DS(buffer, is_rgb888, is_data_3d, 0); + uint16_t start = read_sample_indexLE(&first_column_data->samples[0]); + if(start == last_buffer_index) { + start = read_sample_indexLE(&first_column_data->samples[1]); + copyAudioFromSoundDataNewOptimize3DSLE(p_out, start, &first_column_data->samples[1]); + } + else { + copyAudioFromSoundDataNewOptimize3DSLE(p_out, start, &first_column_data->samples[0]); + copyAudioFromSoundDataNewOptimize3DSLE(p_out, start, &first_column_data->samples[1]); + } + for(int i = 1; i < TOP_WIDTH_3DS; i++) { + USBNew3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrNewOptimize3DS(buffer, is_rgb888, is_data_3d, i); + copyAudioFromSoundDataNewOptimize3DSLE(p_out, start, &curr_column_data->samples[0]); + copyAudioFromSoundDataNewOptimize3DSLE(p_out, start, &curr_column_data->samples[1]); + } + USBNew3DSOptimizeHeaderSoundData* last_column_data = getAudioHeaderPtrNewOptimize3DS(buffer, is_rgb888, is_data_3d, TOP_WIDTH_3DS - 1); + last_buffer_index = read_sample_indexLE(&last_column_data->samples[1]); + n_samples = ((last_buffer_index + 1 + OPTIMIZE_AUDIO_BUFFER_MAX_SIZE - start) % OPTIMIZE_AUDIO_BUFFER_MAX_SIZE) * 2; +} + +static void copyAudioNewOptimize3DSBE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888, bool is_data_3d) { + USBNew3DSOptimizeHeaderSoundData* first_column_data = getAudioHeaderPtrNewOptimize3DS(buffer, is_rgb888, is_data_3d, 0); + uint16_t start = read_sample_indexBE(&first_column_data->samples[0]); + if(start == last_buffer_index) { + start = read_sample_indexBE(&first_column_data->samples[1]); + copyAudioFromSoundDataNewOptimize3DSBE(p_out, start, &first_column_data->samples[1]); + } + else { + copyAudioFromSoundDataNewOptimize3DSBE(p_out, start, &first_column_data->samples[0]); + copyAudioFromSoundDataNewOptimize3DSBE(p_out, start, &first_column_data->samples[1]); + } + for(int i = 1; i < TOP_WIDTH_3DS; i++) { + USBNew3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrNewOptimize3DS(buffer, is_rgb888, is_data_3d, i); + copyAudioFromSoundDataNewOptimize3DSBE(p_out, start, &curr_column_data->samples[0]); + copyAudioFromSoundDataNewOptimize3DSBE(p_out, start, &curr_column_data->samples[1]); + } + USBNew3DSOptimizeHeaderSoundData* last_column_data = getAudioHeaderPtrNewOptimize3DS(buffer, is_rgb888, is_data_3d, TOP_WIDTH_3DS - 1); + last_buffer_index = read_sample_indexBE(&last_column_data->samples[1]); + n_samples = ((last_buffer_index + 1 + OPTIMIZE_AUDIO_BUFFER_MAX_SIZE - start) % OPTIMIZE_AUDIO_BUFFER_MAX_SIZE) * 2; +} + +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, bool is_data_3d) { if(!status->device.has_audio) return true; CaptureReceived* p_in = (CaptureReceived*)(((uint8_t*)&data_buffer->capture_buf) + data_buffer->unused_offset); @@ -378,6 +1061,16 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, const bool i } #endif + #ifdef USE_CYPRESS_NEW_OPTIMIZE + if(status->device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE) { + bool is_rgb888 = true; + if(is_big_endian) + copyAudioNewOptimize3DSBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888, is_data_3d); + else + copyAudioNewOptimize3DSLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888, is_data_3d); + return true; + } + #endif if(base_ptr == NULL) return false; if(!is_big_endian) diff --git a/source/devicecapture.cpp b/source/devicecapture.cpp index 6f2f631..29b51aa 100755 --- a/source/devicecapture.cpp +++ b/source/devicecapture.cpp @@ -222,10 +222,14 @@ void captureCall(CaptureData* capture_data) { } } -uint64_t get_audio_n_samples(CaptureData* capture_data, uint64_t read, bool is_3d) { +uint64_t get_audio_n_samples(CaptureData* capture_data, CaptureDataSingleBuffer* data_buffer) { if(!capture_data->status.device.has_audio) return 0; - uint64_t n_samples = (read - get_video_in_size(capture_data, is_3d)) / 2; + #ifdef USE_CYPRESS_NEW_OPTIMIZE + if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE) + return -1; + #endif + uint64_t n_samples = (data_buffer->read - get_video_in_size(capture_data, data_buffer->is_3d)) / 2; if(n_samples > capture_data->status.device.max_samples_in) n_samples = capture_data->status.device.max_samples_in; // Avoid entering a glitched state due to a partial packet or something