From 5d0c49a8eec7240ea83f1ae2bfc9c77a95bb3f6e Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Sat, 3 May 2025 04:14:02 +0200 Subject: [PATCH] Implement basic Optimize 3D --- include/capture_structs.hpp | 27 +- include/devicecapture.hpp | 1 + .../cypress_optimize_3ds_acquisition.cpp | 10 +- source/Menus/StatusMenu.cpp | 4 +- source/conversions.cpp | 422 +++++++----------- source/devicecapture.cpp | 14 + 6 files changed, 199 insertions(+), 279 deletions(-) diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index f128abe..7f45c20 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -109,9 +109,14 @@ struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData { USB5653DSOptimizePixelData pixel[HEIGHT_3DS][2]; }; -struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData3D { +struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData3DTopRScreen { USB3DSOptimizeHeaderSoundData header_sound; - USB5653DSOptimizePixelData pixel[HEIGHT_3DS][3]; + USB5653DSOptimizePixelData pixel[HEIGHT_3DS]; +}; + +struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData3D { + USB5653DSOptimizeInputColumnData3DTopRScreen top_r_screen_column; + USB5653DSOptimizeInputColumnData bot_top_l_screens_column; }; struct PACKED ALIGNED(16) USB8883DSOptimizeInputColumnData { @@ -121,7 +126,7 @@ struct PACKED ALIGNED(16) USB8883DSOptimizeInputColumnData { struct PACKED ALIGNED(16) USB8883DSOptimizeInputColumnData3D { USB3DSOptimizeHeaderSoundData header_sound; - USB8883DSOptimizePixelData pixel[HEIGHT_3DS][3]; + USB8883DSOptimizePixelData pixel[HEIGHT_3DS]; }; struct PACKED ISNitroEmulatorVideoInputData { @@ -224,7 +229,7 @@ struct ALIGNED(16) PACKED USB5653DSOptimizeCaptureReceived { struct ALIGNED(16) PACKED USB5653DSOptimizeCaptureReceived_3D { USB5653DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS]; - USB5653DSOptimizePixelData bottom_only_column[HEIGHT_3DS][3]; + USB5653DSOptimizeInputColumnData bottom_only_column; }; struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived { @@ -233,26 +238,18 @@ struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived { }; struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived_3D { - USB8883DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS]; - USB8883DSOptimizePixelData bottom_only_column[HEIGHT_3DS][3]; + USB8883DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS][2]; + USB8883DSOptimizeInputColumnData3D bottom_only_column; }; struct ALIGNED(16) PACKED USB5653DSOptimizeCaptureReceivedExtraHeader { USB5653DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS + 1]; }; -struct ALIGNED(16) PACKED USB5653DSOptimizeCaptureReceived_3DExtraHeader { - USB5653DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS + 1]; -}; - struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceivedExtraHeader { USB8883DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS + 1]; }; -struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived_3DExtraHeader { - USB8883DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS + 1]; -}; - #pragma pack(pop) struct ALIGNED(16) FTD2OldDSCaptureReceivedNormalPlusRaw { @@ -276,9 +273,7 @@ union CaptureReceived { USB8883DSOptimizeCaptureReceived cypress_optimize_received_888; USB8883DSOptimizeCaptureReceived_3D cypress_optimize_received_888_3d; USB5653DSOptimizeCaptureReceivedExtraHeader cypress_optimize_received_565_extra_header; - USB5653DSOptimizeCaptureReceived_3DExtraHeader cypress_optimize_received_565_3d_extra_header; USB8883DSOptimizeCaptureReceivedExtraHeader cypress_optimize_received_888_extra_header; - USB8883DSOptimizeCaptureReceived_3DExtraHeader cypress_optimize_received_888_3d_extra_header; }; struct CaptureDevice { diff --git a/include/devicecapture.hpp b/include/devicecapture.hpp index f705562..758f7d3 100755 --- a/include/devicecapture.hpp +++ b/include/devicecapture.hpp @@ -31,4 +31,5 @@ bool is_usb_speed_of_device_enough_3d(CaptureStatus* capture_status); bool get_3d_enabled(CaptureStatus* capture_status, bool skip_requested_3d_check = false); bool update_3d_enabled(CaptureStatus* capture_status); bool set_3d_enabled(CaptureStatus* capture_status, bool new_value); +float get_framerate_multiplier(CaptureStatus* capture_status); #endif diff --git a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp index a786fb5..9a87cfc 100644 --- a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp +++ b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp @@ -210,11 +210,11 @@ uint64_t cyop_device_get_video_in_size_extra_header(bool is_3d, InputVideoDataTy bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; if(is_rgb888) { if(is_3d) - return sizeof(USB8883DSOptimizeCaptureReceived_3DExtraHeader); + return sizeof(USB8883DSOptimizeCaptureReceived_3D); return sizeof(USB8883DSOptimizeCaptureReceivedExtraHeader); } if(is_3d) - return sizeof(USB5653DSOptimizeCaptureReceived_3DExtraHeader); + return sizeof(USB5653DSOptimizeCaptureReceived_3D); return sizeof(USB5653DSOptimizeCaptureReceivedExtraHeader); } @@ -371,14 +371,14 @@ static void copy_slice_data_to_buffer(uint8_t* dst, uint8_t *src, size_t start_s } } -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) { +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) { // Output to the other threads... 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); 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(NULL, read_size, diff.count(), &capture_data->status.device, internal_index); + capture_data->data_buffers.WriteToBuffer(NULL, read_size, diff.count(), &capture_data->status.device, internal_index, is_3d); if (capture_data->status.cooldown_curr_in) capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1; capture_data->status.video_wait.unlock(); @@ -445,7 +445,7 @@ static void cypress_device_read_frame_synchronized(CypressOptimize3DSDeviceCaptu } if(curr_consecutive_available_bytes >= video_in_size) { // Enough data. Time to do output... - cypress_output_to_thread(cypress_device_capture_recv_data->capture_data, cypress_device_capture_recv_data->ring_slice_buffer_arr, read_slice_index, read_slice_pos, 0, cypress_device_capture_recv_data->clock_start, video_in_size); + cypress_output_to_thread(cypress_device_capture_recv_data->capture_data, cypress_device_capture_recv_data->ring_slice_buffer_arr, read_slice_index, read_slice_pos, 0, cypress_device_capture_recv_data->clock_start, video_in_size, *cypress_device_capture_recv_data->stored_is_3d); // Keep the ring buffer going. size_t raw_new_pos = read_slice_pos + video_in_size; int new_slice_index = (int)(read_slice_index + (raw_new_pos / SINGLE_RING_BUFFER_SLICE_SIZE)); diff --git a/source/Menus/StatusMenu.cpp b/source/Menus/StatusMenu.cpp index e58530d..a693c05 100755 --- a/source/Menus/StatusMenu.cpp +++ b/source/Menus/StatusMenu.cpp @@ -161,13 +161,13 @@ void StatusMenu::prepare(float menu_scaling_factor, int view_size_x, int view_si this->labels[index]->setText(get_usb_speed_text(get_usb_speed_of_device(capture_status))); break; case STATUS_MENU_FPS_IN: - this->labels[index + INC_ACTION]->setText(get_float_str_decimals((float)in_fps, 2)); + this->labels[index + INC_ACTION]->setText(get_float_str_decimals((float)in_fps * get_framerate_multiplier(capture_status), 2)); break; case STATUS_MENU_FPS_POLL: this->labels[index + INC_ACTION]->setText(get_float_str_decimals((float)poll_fps, 2)); break; case STATUS_MENU_FPS_DRAW: - this->labels[index + INC_ACTION]->setText(get_float_str_decimals((float)draw_fps, 2)); + this->labels[index + INC_ACTION]->setText(get_float_str_decimals((float)draw_fps * get_framerate_multiplier(capture_status), 2)); break; default: break; diff --git a/source/conversions.cpp b/source/conversions.cpp index 125a60b..54814f0 100755 --- a/source/conversions.cpp +++ b/source/conversions.cpp @@ -17,14 +17,12 @@ #define INTERLEAVED_RGB888_DATA_SIZE sizeof(uint16_t) #define INTERLEAVED_RGB888_TOTAL_SIZE (INTERLEAVED_RGB888_PIXEL_SIZE * INTERLEAVED_RGB888_PIXEL_NUM / INTERLEAVED_RGB888_DATA_SIZE) +static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DS3D(CaptureReceived* buffer, bool is_rgb888, uint16_t column); + struct interleaved_rgb565_pixels { uint16_t pixels[INTERLEAVED_RGB565_TOTAL_SIZE][2]; }; -struct ALIGNED(INTERLEAVED_RGB565_PIXEL_NUM * INTERLEAVED_RGB565_PIXEL_SIZE) interleaved_3d_rgb565_pixels { - uint16_t pixels[INTERLEAVED_RGB565_TOTAL_SIZE][3]; -}; - struct deinterleaved_rgb565_pixels { uint16_t pixels[INTERLEAVED_RGB565_TOTAL_SIZE]; }; @@ -33,10 +31,6 @@ struct ALIGNED(INTERLEAVED_RGB888_PIXEL_NUM * 2) interleaved_rgb888_u16_pixels { uint16_t pixels[INTERLEAVED_RGB888_TOTAL_SIZE][2]; }; -struct ALIGNED(INTERLEAVED_RGB888_PIXEL_NUM) interleaved_3d_rgb888_u16_pixels { - uint16_t pixels[INTERLEAVED_RGB888_TOTAL_SIZE][3]; -}; - struct ALIGNED(INTERLEAVED_RGB888_PIXEL_NUM) deinterleaved_rgb888_u16_pixels { // 4 pixels uint16_t pixels[INTERLEAVED_RGB888_TOTAL_SIZE]; @@ -74,28 +68,37 @@ 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) { +static inline void memcpy_data_u16le_origin(uint16_t* dst, uint8_t* src, size_t num_iters, bool is_big_endian) { + if(!is_big_endian) + memcpy(dst, src, num_iters * 2); + else + for(size_t i = 0; i < num_iters; i++) + dst[i] = (src[(i * 2) + 1] << 8) | src[i * 2]; +} + +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, int multiplier_top = 1) { //de-interleave pixels const int bottom_pos = 0; const int top_pos = 1; 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 = (output_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].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][bottom_pos]; + 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].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_pos]; + 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, int input_halfline, int output_halfline) { +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, int multiplier_top = 1) { //de-interleave pixels const int top_pos = 1; 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 = (output_halfline * real_num_iters) + i; + size_t output_halfline_pixel = (output_halfline * real_num_iters * multiplier_top) + i; for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) out_ptr_top[output_halfline_pixel].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_pos]; } @@ -113,77 +116,29 @@ static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom } } -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 int bottom_pos = 0; - const int top_l_pos = 1; - const int top_r_pos = 2; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - 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_l[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_l_pos]; - for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) - out_ptr_top_r[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_r_pos]; - } -} - -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 int top_l_pos = 1; - const int top_r_pos = 2; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) - out_ptr_top_l[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_l_pos]; - for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) - out_ptr_top_r[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_r_pos]; - } -} - -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 - const int bottom_pos = 0; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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 = output_halfline_pos + i; - for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) - out_ptr_bottom[output_halfline_pixel].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][bottom_pos]; - } -} - -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) { +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, int multiplier_top = 1) { //de-interleave pixels const int bottom_pos = 0; const int top_pos = 1; 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 = (output_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].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][bottom_pos]); + 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].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][top_pos]); + 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, int input_halfline, int output_halfline) { +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, int multiplier_top = 1) { //de-interleave pixels const int top_pos = 1; 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 = (output_halfline * real_num_iters) + i; + size_t output_halfline_pixel = (output_halfline * real_num_iters * multiplier_top) + i; for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) out_ptr_top[output_halfline_pixel].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][top_pos]); } @@ -201,55 +156,6 @@ static inline void usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom } } -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 int bottom_pos = 0; - const int top_l_pos = 1; - const int top_r_pos = 2; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - 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_l[output_halfline_pixel_top].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][top_l_pos]); - for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) - out_ptr_top_r[output_halfline_pixel_top].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][top_r_pos]); - } -} - -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 int top_l_pos = 1; - const int top_r_pos = 2; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) - out_ptr_top_l[output_halfline_pixel_top].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][top_l_pos]); - for(size_t j = 0; j < INTERLEAVED_RGB565_TOTAL_SIZE; j++) - out_ptr_top_r[output_halfline_pixel_top].pixels[j] = _reverse_endianness(in_ptr[input_halfline_pixel].pixels[j][top_r_pos]); - } -} - -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) { - //de-interleave pixels - const int bottom_pos = 0; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB565_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - 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]); - } -} - 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 bottom_pos = 0; @@ -289,55 +195,6 @@ static inline void usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoBotto } } -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 bottom_pos = 0; - const int top_l_pos = 1; - const int top_r_pos = 2; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB888_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - for(size_t j = 0; j < INTERLEAVED_RGB888_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_RGB888_TOTAL_SIZE; j++) - out_ptr_top_l[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_l_pos]; - for(size_t j = 0; j < INTERLEAVED_RGB888_TOTAL_SIZE; j++) - out_ptr_top_r[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_r_pos]; - } -} - -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) { - //de-interleave pixels - const int top_l_pos = 1; - const int top_r_pos = 2; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB888_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - for(size_t j = 0; j < INTERLEAVED_RGB888_TOTAL_SIZE; j++) - out_ptr_top_l[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_l_pos]; - for(size_t j = 0; j < INTERLEAVED_RGB888_TOTAL_SIZE; j++) - out_ptr_top_r[output_halfline_pixel_top].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][top_r_pos]; - } -} - -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) { - //de-interleave pixels - const int bottom_pos = 0; - const size_t real_num_iters = num_iters / INTERLEAVED_RGB888_PIXEL_NUM; - const size_t output_halfline_pos = output_halfline * real_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; - for(size_t j = 0; j < INTERLEAVED_RGB888_TOTAL_SIZE; j++) - out_ptr_bottom[output_halfline_pixel_bottom].pixels[j] = in_ptr[input_halfline_pixel].pixels[j][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)); @@ -508,11 +365,12 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB56 deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.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; + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column.pixel; if(column < column_last_bot_pos) - in_ptr = (interleaved_3d_rgb565_pixels*)p_in->columns_data[column].pixel; - else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) - in_ptr = (interleaved_3d_rgb565_pixels*)(((USB5653DSOptimizeCaptureReceived_3DExtraHeader*)p_in)->columns_data[column].pixel); + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].bot_top_l_screens_column.pixel; + //else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) { + //in_ptr = (interleaved_rgb565_pixels*)(((USB5653DSOptimizeCaptureReceived_3DExtraHeader*)p_in)->columns_data[column].pixel); + //} int multiplier_top = 1; if(interleaved_3d) { multiplier_top = 2; @@ -520,17 +378,19 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB56 } const uint32_t num_iters = HEIGHT_3DS; 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); + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); 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); + memcpy_data_u16le_origin((uint16_t*)(out_ptr_top_r + ((column * HEIGHT_3DS * multiplier_top * pixels_size) / ptr_out_size)), (uint8_t*)p_in->columns_data[column].top_r_screen_column.pixel, HEIGHT_3DS, false); + if(column == column_pre_last_bot_pos) { + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(out_ptr_top_l, in_ptr, num_iters, 0, column, multiplier_top); + 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_l, in_ptr, num_iters, 0, column, multiplier_top); + else { + out_ptr_top_l += (column_start_bot_pos * HEIGHT_3DS * multiplier_top * pixels_size) / ptr_out_size; + usb_rgb565convertInterleaveVideoToOutputDirectOptLE(out_ptr_top_l, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos, multiplier_top); + } } } @@ -544,11 +404,12 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB56 deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.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; + interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column.pixel; if(column < column_last_bot_pos) - in_ptr = (interleaved_3d_rgb565_pixels*)p_in->columns_data[column].pixel; - else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) - in_ptr = (interleaved_3d_rgb565_pixels*)(((USB5653DSOptimizeCaptureReceived_3DExtraHeader*)p_in)->columns_data[column].pixel); + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].bot_top_l_screens_column.pixel; + //else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) { + //in_ptr = (interleaved_rgb565_pixels*)(((USB5653DSOptimizeCaptureReceived_3DExtraHeader*)p_in)->columns_data[column].pixel); + //} int multiplier_top = 1; if(interleaved_3d) { multiplier_top = 2; @@ -556,17 +417,19 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB56 } const uint32_t num_iters = HEIGHT_3DS; 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); + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, BOT_WIDTH_3DS - 1); 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); + memcpy_data_u16le_origin((uint16_t*)(out_ptr_top_r + ((column * HEIGHT_3DS * multiplier_top * pixels_size) / ptr_out_size)), (uint8_t*)p_in->columns_data[column].top_r_screen_column.pixel, HEIGHT_3DS, true); + if(column == column_pre_last_bot_pos) { + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(out_ptr_top_l, in_ptr, num_iters, 0, column, multiplier_top); + 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_l, in_ptr, num_iters, 0, column, multiplier_top); + else { + out_ptr_top_l += (column_start_bot_pos * HEIGHT_3DS * pixels_size) / ptr_out_size; + usb_rgb565convertInterleaveVideoToOutputDirectOptBE(out_ptr_top_l, out_ptr_bottom, in_ptr, num_iters, 0, column - column_start_bot_pos, multiplier_top); + } } } @@ -599,40 +462,44 @@ static inline void usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(USB8883DS } } -static inline void usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(USB8883DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, uint16_t column, bool interleaved_3d) { - //de-interleave pixels +static inline void usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(USB8883DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, uint16_t column, bool interleaved_3d, bool is_bottom_data) { const int pixels_size = sizeof(VideoPixelRGB); 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->rgb_video_output_data.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; - else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) - in_ptr = (interleaved_3d_rgb888_u16_pixels*)(((USB8883DSOptimizeCaptureReceived_3DExtraHeader*)p_in)->columns_data[column].pixel); + uint8_t* out_ptr_bottom = (uint8_t*)p_out->rgb_video_output_data.screen_data; + uint8_t* out_ptr_top_l = out_ptr_bottom + (BOT_SIZE_3DS * pixels_size); + uint8_t* out_ptr_top_r = out_ptr_top_l + (TOP_SIZE_3DS * pixels_size); int multiplier_top = 1; if(interleaved_3d) { multiplier_top = 2; - out_ptr_top_r = out_ptr_top_l + (HEIGHT_3DS / ptr_out_size); + out_ptr_top_r = out_ptr_top_l + (HEIGHT_3DS * pixels_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); + + if((!is_bottom_data) && (column >= TOP_WIDTH_3DS)) + return; + + uint8_t* src_ptr = (uint8_t*)p_in->bottom_only_column.pixel; + uint8_t* dst_ptr_first = out_ptr_bottom; + uint8_t* dst_ptr_second = out_ptr_bottom; + if(is_bottom_data) { + if(column >= TOP_WIDTH_3DS) { + memcpy(out_ptr_bottom + ((BOT_WIDTH_3DS - 1) * HEIGHT_3DS * pixels_size), (uint8_t*)p_in->bottom_only_column.pixel, HEIGHT_3DS * pixels_size); + } + else { + int out_column_pos = -1; + if(column == column_pre_last_bot_pos) + out_column_pos = BOT_WIDTH_3DS - 2; + else if(column >= column_start_bot_pos) + out_column_pos = column - column_start_bot_pos; + if(out_column_pos == -1) + return; + memcpy(out_ptr_bottom + (out_column_pos * HEIGHT_3DS * pixels_size), (uint8_t*)p_in->columns_data[column][1].pixel, HEIGHT_3DS * pixels_size); + } + return; } + + memcpy(out_ptr_top_l + (column * HEIGHT_3DS * pixels_size * multiplier_top), (uint8_t*)p_in->columns_data[column][0].pixel, HEIGHT_3DS * pixels_size); + 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 void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, const bool is_big_endian) { @@ -763,8 +630,11 @@ static void usb_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOu expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->rgb_video_output_data.screen_data, sizeof(VideoPixelRGB), interleaved_3d, requested_3d); } else { - for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) - usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(&p_in->cypress_optimize_received_888_3d, p_out, i, interleaved_3d); + USB3DSOptimizeHeaderSoundData* first_column_header = getAudioHeaderPtrOptimize3DS3D(p_in, is_rgb888, 0); + bool is_bottom_data = (((uint8_t*)&first_column_header->header_info.column_info)[1] & 0x40) == 0; + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) { + usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(&p_in->cypress_optimize_received_888_3d, p_out, i, interleaved_3d, is_bottom_data); + } } } } @@ -864,26 +734,32 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt return converted; } -static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DS(CaptureReceived* buffer, bool is_rgb888, bool is_data_3d, uint16_t column) { - if(!is_rgb888) { - if(!is_data_3d) - return &buffer->cypress_optimize_received_565.columns_data[column].header_sound; - return &buffer->cypress_optimize_received_565_3d.columns_data[column].header_sound; - } - if(!is_data_3d) - return &buffer->cypress_optimize_received_888.columns_data[column].header_sound; - return &buffer->cypress_optimize_received_888_3d.columns_data[column].header_sound; +static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DS(CaptureReceived* buffer, bool is_rgb888, uint16_t column) { + if(!is_rgb888) + return &buffer->cypress_optimize_received_565.columns_data[column].header_sound; + return &buffer->cypress_optimize_received_888.columns_data[column].header_sound; } -static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DSExtraHeader(CaptureReceived* buffer, bool is_rgb888, bool is_data_3d, uint16_t column) { +static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DSExtraHeader(CaptureReceived* buffer, bool is_rgb888, uint16_t column) { + if(!is_rgb888) + return &buffer->cypress_optimize_received_565_extra_header.columns_data[column].header_sound; + return &buffer->cypress_optimize_received_888_extra_header.columns_data[column].header_sound; +} + +static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DS3D(CaptureReceived* buffer, bool is_rgb888, uint16_t column) { if(!is_rgb888) { - if(!is_data_3d) - return &buffer->cypress_optimize_received_565_extra_header.columns_data[column].header_sound; - return &buffer->cypress_optimize_received_565_3d_extra_header.columns_data[column].header_sound; + int target_column = column / 2; + if((column % 2) == 0) + return &buffer->cypress_optimize_received_565_3d.columns_data[target_column].top_r_screen_column.header_sound; + return &buffer->cypress_optimize_received_565_3d.columns_data[target_column].bot_top_l_screens_column.header_sound; } - if(!is_data_3d) - return &buffer->cypress_optimize_received_888_extra_header.columns_data[column].header_sound; - return &buffer->cypress_optimize_received_888_3d_extra_header.columns_data[column].header_sound; + return &buffer->cypress_optimize_received_888_3d.columns_data[column / 2][column % 2].header_sound; +} + +static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DS3DExtraHeader(CaptureReceived* buffer, bool is_rgb888) { + if(!is_rgb888) + return &buffer->cypress_optimize_received_565_3d.bottom_only_column.header_sound; + return &buffer->cypress_optimize_received_888_3d.bottom_only_column.header_sound; } static inline uint16_t read_sample_indexLE(USB3DSOptimizeSingleSoundData* sample) { @@ -914,17 +790,17 @@ 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, bool is_data_3d) { +static void copyAudioOptimize3DSLE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888) { uint64_t num_inserted = 0; int last_inserted_index = last_buffer_index; for(int i = 0; i < TOP_WIDTH_3DS; i++) { - USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, is_data_3d, i); + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, i); 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); } - USB3DSOptimizeHeaderSoundData* initial_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, is_data_3d, 0); + USB3DSOptimizeHeaderSoundData* initial_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, 0); if(usb_OptimizeHasExtraHeaderSoundData(initial_column_data)) { - USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DSExtraHeader(buffer, is_rgb888, is_data_3d, TOP_WIDTH_3DS); + 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); } @@ -932,17 +808,32 @@ static void copyAudioOptimize3DSLE(std::int16_t *p_out, uint64_t &n_samples, uin 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, bool is_data_3d) { +static void copyAudioOptimize3DS3DLE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888) { + uint64_t num_inserted = 0; + int last_inserted_index = last_buffer_index; + for(int i = 0; i < TOP_WIDTH_3DS * 2; i++) { + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS3D(buffer, is_rgb888, i); + 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); + } + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS3DExtraHeader(buffer, is_rgb888); + 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); + last_buffer_index = last_inserted_index; + 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) { uint64_t num_inserted = 0; int last_inserted_index = last_buffer_index; for(int i = 0; i < TOP_WIDTH_3DS; i++) { - USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, is_data_3d, i); + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, i); 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); } - USB3DSOptimizeHeaderSoundData* initial_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, is_data_3d, 0); + USB3DSOptimizeHeaderSoundData* initial_column_data = getAudioHeaderPtrOptimize3DS(buffer, is_rgb888, 0); if(usb_OptimizeHasExtraHeaderSoundData(initial_column_data)) { - USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DSExtraHeader(buffer, is_rgb888, is_data_3d, TOP_WIDTH_3DS); + 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); } @@ -950,6 +841,21 @@ static void copyAudioOptimize3DSBE(std::int16_t *p_out, uint64_t &n_samples, uin n_samples = num_inserted * 2; } +static void copyAudioOptimize3DS3DBE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer, bool is_rgb888) { + uint64_t num_inserted = 0; + int last_inserted_index = last_buffer_index; + for(int i = 0; i < TOP_WIDTH_3DS * 2; i++) { + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS3D(buffer, is_rgb888, i); + 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); + } + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS3DExtraHeader(buffer, is_rgb888); + 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); + last_buffer_index = last_inserted_index; + n_samples = num_inserted * 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) { if(!status->device.has_audio) return true; @@ -998,20 +904,24 @@ 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; - if(is_big_endian) - copyAudioOptimize3DSBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888, is_data_3d); - else - copyAudioOptimize3DSLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888, is_data_3d); + if(is_big_endian) { + if(is_data_3d) + copyAudioOptimize3DS3DBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + else + copyAudioOptimize3DSBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + } + else { + if(is_data_3d) + copyAudioOptimize3DS3DLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + else + copyAudioOptimize3DSLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + } return true; } #endif if(base_ptr == NULL) return false; - if(!is_big_endian) - memcpy(p_out, base_ptr, (size_t)(n_samples * 2)); - else - for(uint64_t i = 0; i < n_samples; i++) - p_out[i] = (base_ptr[(i * 2) + 1] << 8) | base_ptr[i * 2]; + memcpy_data_u16le_origin((uint16_t*)p_out, base_ptr, (size_t)n_samples, is_big_endian); return true; } diff --git a/source/devicecapture.cpp b/source/devicecapture.cpp index 75306a7..88b4726 100755 --- a/source/devicecapture.cpp +++ b/source/devicecapture.cpp @@ -326,6 +326,8 @@ bool get_device_3d_implemented(CaptureStatus* capture_status) { switch(capture_status->device.cc_type) { case CAPTURE_CONN_FTD3: return true; + case CAPTURE_CONN_CYPRESS_OPTIMIZE: + return true; default: return false; } @@ -357,6 +359,18 @@ bool update_3d_enabled(CaptureStatus* capture_status) { return set_3d_enabled(capture_status, !capture_status->requested_3d); } +float get_framerate_multiplier(CaptureStatus* capture_status) { + if(!capture_status->connected) + return 1; + if(capture_status->device.cc_type != CAPTURE_CONN_CYPRESS_OPTIMIZE) + return 1; + if(!get_3d_enabled(capture_status)) + return 1; + if(capture_status->request_low_bw_format) + return 1; + return 0.5; +} + void capture_init() { #ifdef USE_DS_3DS_USB usb_ds_3ds_init();