From efac5ce6b98e409afa109b444a3188d580938676 Mon Sep 17 00:00:00 2001 From: Lorenzooone Date: Mon, 17 Nov 2025 03:37:32 +0100 Subject: [PATCH] Fix graphical issues with Optimize CCs --- .../cypress_optimize_3ds_acquisition.hpp | 4 +- include/capture_structs.hpp | 16 +- include/devicecapture.hpp | 2 +- source/CaptureDataBuffers.cpp | 15 +- .../cypress_optimize_3ds_acquisition.cpp | 146 ++++++++++-- source/cc3dsfs.cpp | 4 +- source/conversions.cpp | 210 ++++++++++++++---- source/devicecapture.cpp | 6 +- 8 files changed, 312 insertions(+), 91 deletions(-) diff --git a/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp b/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp index f21ed91..6e07c3e 100644 --- a/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp +++ b/include/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.hpp @@ -16,8 +16,8 @@ void list_devices_cyop_device(std::vector &devices_list, std::vector &no_access_list, bool* devices_allowed_scan); bool cyop_device_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device); -uint64_t cyop_device_get_video_in_size(CaptureStatus* status, bool is_3d, InputVideoDataType video_data_type); -uint64_t cyop_device_get_video_in_size(CaptureData* capture_data, bool is_3d, InputVideoDataType video_data_type); +uint64_t cyop_device_get_video_in_size(CaptureStatus* status, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type); +uint64_t cyop_device_get_video_in_size(CaptureData* capture_data, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type); void cyop_device_acquisition_main_loop(CaptureData* capture_data); void usb_cyop_device_acquisition_cleanup(CaptureData* capture_data); bool is_device_optimize_3ds(CaptureDevice* device); diff --git a/include/capture_structs.hpp b/include/capture_structs.hpp index ee2ff58..b10aa09 100755 --- a/include/capture_structs.hpp +++ b/include/capture_structs.hpp @@ -91,7 +91,7 @@ struct PACKED USB3DSOptimizeColumnInfo { uint16_t column_index : 10; uint16_t unk : 4; uint16_t buffer_num : 1; - uint16_t has_extra_header_data : 1; + uint16_t has_extra_header_data_2d_only : 1; }; struct PACKED USB3DSOptimizeHeaderData { @@ -242,6 +242,10 @@ struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived_3D { USB8883DSOptimizeInputColumnData3D bottom_only_column; }; +struct ALIGNED(16) PACKED USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen { + USB8883DSOptimizeInputColumnData3D columns_data[TOP_WIDTH_3DS + 1]; +}; + struct ALIGNED(16) PACKED USB5653DSOptimizeCaptureReceivedExtraHeader { USB5653DSOptimizeInputColumnData columns_data[TOP_WIDTH_3DS + 1]; }; @@ -272,6 +276,7 @@ union CaptureReceived { USB5653DSOptimizeCaptureReceived_3D cypress_optimize_received_565_3d; USB8883DSOptimizeCaptureReceived cypress_optimize_received_888; USB8883DSOptimizeCaptureReceived_3D cypress_optimize_received_888_3d; + USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen cypress_optimize_received_888_3d_2d; USB5653DSOptimizeCaptureReceivedExtraHeader cypress_optimize_received_565_extra_header; USB8883DSOptimizeCaptureReceivedExtraHeader cypress_optimize_received_888_extra_header; }; @@ -347,6 +352,7 @@ struct CaptureDataSingleBuffer { double time_in_buf; uint32_t inner_index; bool is_3d; + bool should_be_3d; InputVideoDataType buffer_video_data_type; }; @@ -355,10 +361,10 @@ public: CaptureDataBuffers(); CaptureDataSingleBuffer* GetReaderBuffer(CaptureReaderType reader_type); void ReleaseReaderBuffer(CaptureReaderType reader_type); - void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, size_t offset, int index, bool is_3d = false); - void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, int index, bool is_3d = false); - void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset, int index, bool is_3d = false); - void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, int index, bool is_3d = false); + void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, size_t offset, int index, bool is_3d = false, bool should_be_3d = false); + void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, int index, bool is_3d = false, bool should_be_3d = false); + void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset, int index, bool is_3d = false, bool should_be_3d = false); + void WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, int index, bool is_3d = false, bool should_be_3d = false); CaptureDataSingleBuffer* GetWriterBuffer(int index = 0); void ReleaseWriterBuffer(int index = 0, bool update_last_curr_in = true); private: diff --git a/include/devicecapture.hpp b/include/devicecapture.hpp index 47c7d0a..d2786e7 100755 --- a/include/devicecapture.hpp +++ b/include/devicecapture.hpp @@ -26,7 +26,7 @@ void capture_error_print(bool print_failed, CaptureData* capture_data, std::stri void capture_warning_print(CaptureData* capture_data, std::string warning_string); void capture_warning_print(CaptureData* capture_data, std::string graphical_string, std::string detailed_string); uint64_t get_audio_n_samples(CaptureData* capture_data, CaptureDataSingleBuffer* data_buffer); -uint64_t get_video_in_size(CaptureData* capture_data, bool is_3d, InputVideoDataType video_data_type); +uint64_t get_video_in_size(CaptureData* capture_data, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type); std::string get_device_id_string(CaptureStatus* capture_status); std::string get_device_serial_key_string(CaptureStatus* capture_status); std::string get_name_of_device(CaptureStatus* capture_status, bool use_long = false, bool want_real_serial = false); diff --git a/source/CaptureDataBuffers.cpp b/source/CaptureDataBuffers.cpp index 099e679..249f520 100644 --- a/source/CaptureDataBuffers.cpp +++ b/source/CaptureDataBuffers.cpp @@ -95,7 +95,7 @@ void CaptureDataBuffers::ReleaseWriterBuffer(int index, bool update_last_curr_in access_mutex.unlock(); } -void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, size_t offset, int index, bool is_3d) { +void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, size_t offset, int index, bool is_3d, bool should_be_3d) { if(offset >= read) return; if(!is_writer_index_valid(index)) @@ -117,18 +117,19 @@ void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, d target->time_in_buf = time_in_buf; target->capture_type = capture_type; target->is_3d = is_3d; + target->should_be_3d = should_be_3d; target->buffer_video_data_type = device->video_data_type; this->ReleaseWriterBuffer(index); } -void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, int index, bool is_3d) { - return this->WriteToBuffer(buffer, read, time_in_buf, device, capture_type, 0, index, is_3d); +void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, CaptureScreensType capture_type, int index, bool is_3d, bool should_be_3d) { + return this->WriteToBuffer(buffer, read, time_in_buf, device, capture_type, 0, index, is_3d, should_be_3d); } -void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset, int index, bool is_3d) { - return this->WriteToBuffer(buffer, read, time_in_buf, device, CAPTURE_SCREENS_BOTH, offset, index, is_3d); +void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, size_t offset, int index, bool is_3d, bool should_be_3d) { + return this->WriteToBuffer(buffer, read, time_in_buf, device, CAPTURE_SCREENS_BOTH, offset, index, is_3d, should_be_3d); } -void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, int index, bool is_3d) { - return this->WriteToBuffer(buffer, read, time_in_buf, device, CAPTURE_SCREENS_BOTH, 0, index, is_3d); +void CaptureDataBuffers::WriteToBuffer(CaptureReceived* buffer, uint64_t read, double time_in_buf, CaptureDevice* device, int index, bool is_3d, bool should_be_3d) { + return this->WriteToBuffer(buffer, read, time_in_buf, device, CAPTURE_SCREENS_BOTH, 0, index, is_3d, should_be_3d); } diff --git a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp index 5a5a5d3..c74167e 100644 --- a/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp +++ b/source/CaptureDeviceSpecific/Optimize_3DS/cypress_optimize_3ds_acquisition.cpp @@ -212,11 +212,14 @@ bool cyop_device_connect_usb(bool print_failed, CaptureData* capture_data, Captu return true; } -uint64_t cyop_device_get_video_in_size(bool is_3d, InputVideoDataType video_data_type) { +uint64_t cyop_device_get_video_in_size(bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; if(is_rgb888) { - if(is_3d) - return sizeof(USB8883DSOptimizeCaptureReceived_3D); + if(should_be_3d) { + if(is_3d) + return sizeof(USB8883DSOptimizeCaptureReceived_3D); + return sizeof(USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen); + } return sizeof(USB8883DSOptimizeCaptureReceived); } if(is_3d) @@ -224,11 +227,14 @@ uint64_t cyop_device_get_video_in_size(bool is_3d, InputVideoDataType video_data return sizeof(USB5653DSOptimizeCaptureReceived); } -uint64_t cyop_device_get_video_in_size_extra_header(bool is_3d, InputVideoDataType video_data_type) { +uint64_t cyop_device_get_video_in_size_extra_header(bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; if(is_rgb888) { - if(is_3d) - return sizeof(USB8883DSOptimizeCaptureReceived_3D); + if(should_be_3d) { + if(is_3d) + return sizeof(USB8883DSOptimizeCaptureReceived_3D); + return sizeof(USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen); + } return sizeof(USB8883DSOptimizeCaptureReceivedExtraHeader); } if(is_3d) @@ -237,13 +243,13 @@ uint64_t cyop_device_get_video_in_size_extra_header(bool is_3d, InputVideoDataTy } -uint64_t cyop_device_get_video_in_size(CaptureStatus* status, bool is_3d, InputVideoDataType video_data_type) { - return cyop_device_get_video_in_size(is_3d, video_data_type); +uint64_t cyop_device_get_video_in_size(CaptureStatus* status, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { + return cyop_device_get_video_in_size(is_3d, should_be_3d, video_data_type); } -uint64_t cyop_device_get_video_in_size(CaptureData* capture_data, bool is_3d, InputVideoDataType video_data_type) { - return cyop_device_get_video_in_size(&capture_data->status, is_3d, video_data_type); +uint64_t cyop_device_get_video_in_size(CaptureData* capture_data, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { + return cyop_device_get_video_in_size(&capture_data->status, is_3d, should_be_3d, video_data_type); } bool is_device_optimize_3ds(CaptureDevice* device) { @@ -293,7 +299,7 @@ static int cypress_device_read_frame_request(CaptureData* capture_data, CypressO const cyop_device_usb_device* usb_device_info = (const cyop_device_usb_device*)capture_data->status.device.descriptor; cypress_device_capture_recv_data->index = index; cypress_device_capture_recv_data->cb_data.function = cypress_device_read_frame_cb; - //size_t read_size = cyop_device_get_video_in_size(is_3d, video_data_type); + //size_t read_size = cyop_device_get_video_in_size(is_3d, is_3d, video_data_type); size_t read_size = SINGLE_RING_BUFFER_SLICE_SIZE; int new_buffer_slice_index = ((*cypress_device_capture_recv_data->last_ring_buffer_slice_allocated) + 1) % NUM_TOTAL_OPTIMIZE_3DS_CYPRESS_BUFFERS; uint8_t* buffer = &cypress_device_capture_recv_data->ring_slice_buffer_arr[new_buffer_slice_index * SINGLE_RING_BUFFER_SLICE_SIZE]; @@ -343,7 +349,7 @@ static void end_cypress_device_read_frame_cb(CypressOptimize3DSDeviceCaptureRece static USB3DSOptimizeColumnInfo convert_to_column_info(uint16_t value) { // The macos compiler requires this... :/ USB3DSOptimizeColumnInfo column_info; - column_info.has_extra_header_data = (value >> 15) & 1; + column_info.has_extra_header_data_2d_only = (value >> 15) & 1; column_info.buffer_num = (value >> 14) & 1; column_info.unk = (value >> 10) & 0xF; column_info.column_index = value & 0x3FF; @@ -351,13 +357,98 @@ static USB3DSOptimizeColumnInfo convert_to_column_info(uint16_t value) { } static bool get_expect_extra_header_in_buffer(uint16_t value) { - return convert_to_column_info(value).has_extra_header_data; + return convert_to_column_info(value).has_extra_header_data_2d_only; +} + +static bool get_is_data_2d_only(uint16_t value) { + return convert_to_column_info(value).has_extra_header_data_2d_only; +} + +static bool get_is_pos_column_synch_in_buffer(uint8_t* buffer, size_t pos_to_check, uint16_t column_index) { + if(read_le16(buffer + pos_to_check) != SYNCH_VALUE_OPTIMIZE) + return false; + return convert_to_column_info(read_le16(buffer + pos_to_check + 2)).column_index == column_index; +} + +static bool get_is_pos_column_synch_in_buffer(USB3DSOptimizeHeaderSoundData* in_ptr, uint16_t column_index) { + return get_is_pos_column_synch_in_buffer((uint8_t*)&in_ptr->header_info, 0, column_index); } static bool get_is_pos_first_synch_in_buffer(uint8_t* buffer, size_t pos_to_check) { - if(read_le16(buffer + pos_to_check) != SYNCH_VALUE_OPTIMIZE) + return get_is_pos_column_synch_in_buffer(buffer, pos_to_check, 0); +} + +static bool get_is_buffer_rgb565_fully_synced(CaptureReceived* buffer) { + USB5653DSOptimizeCaptureReceived* real_buffer = &buffer->cypress_optimize_received_565; + USB5653DSOptimizeCaptureReceivedExtraHeader* real_buffer_special = &buffer->cypress_optimize_received_565_extra_header; + bool is_special = get_expect_extra_header_in_buffer(read_le16((uint8_t*)&real_buffer->columns_data[0].header_sound.header_info.column_info)); + for(int i = 0; i < TOP_WIDTH_3DS; i++) + if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].header_sound, i)) + return false; + if(is_special && (!get_is_pos_column_synch_in_buffer(&real_buffer_special->columns_data[TOP_WIDTH_3DS].header_sound, TOP_WIDTH_3DS))) return false; - return convert_to_column_info(read_le16(buffer + pos_to_check + 2)).column_index == 0; + return true; +} + +static bool get_is_buffer_rgb565_3d_fully_synced(CaptureReceived* buffer) { + USB5653DSOptimizeCaptureReceived_3D* real_buffer = &buffer->cypress_optimize_received_565_3d; + for(int i = 0; i < TOP_WIDTH_3DS; i++) { + if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].top_r_screen_column.header_sound, i * 2)) + return false; + if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].bot_top_l_screens_column.header_sound, (i * 2) + 1)) + return false; + } + if(!get_is_pos_column_synch_in_buffer(&real_buffer->bottom_only_column.header_sound, TOP_WIDTH_3DS * 2)) + return false; + return true; +} + +static bool get_is_buffer_rgb888_fully_synced(CaptureReceived* buffer) { + USB8883DSOptimizeCaptureReceived* real_buffer = &buffer->cypress_optimize_received_888; + USB8883DSOptimizeCaptureReceivedExtraHeader* real_buffer_special = &buffer->cypress_optimize_received_888_extra_header; + bool is_special = get_expect_extra_header_in_buffer(read_le16((uint8_t*)&real_buffer->columns_data[0].header_sound.header_info.column_info)); + for(int i = 0; i < TOP_WIDTH_3DS; i++) + if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].header_sound, i)) + return false; + if(is_special && (!get_is_pos_column_synch_in_buffer(&real_buffer_special->columns_data[TOP_WIDTH_3DS].header_sound, TOP_WIDTH_3DS))) + return false; + return true; +} + +static bool get_is_buffer_rgb888_3d_fully_synced(CaptureReceived* buffer) { + USB8883DSOptimizeCaptureReceived_3D* real_buffer = &buffer->cypress_optimize_received_888_3d; + for(int i = 0; i < TOP_WIDTH_3DS; i++) { + if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i][0].header_sound, i * 2)) + return false; + if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i][1].header_sound, (i * 2) + 1)) + return false; + } + if(!get_is_pos_column_synch_in_buffer(&real_buffer->bottom_only_column.header_sound, TOP_WIDTH_3DS * 2)) + return false; + return true; +} + +static bool get_is_buffer_rgb888_3d_2d_fully_synced(CaptureReceived* buffer) { + USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen* real_buffer = &buffer->cypress_optimize_received_888_3d_2d; + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) { + if(!get_is_pos_column_synch_in_buffer(&real_buffer->columns_data[i].header_sound, i)) + return false; + } + return true; +} + +static bool get_is_buffer_fully_synched(CaptureReceived* buffer, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { + bool is_rgb888 = video_data_type == OPTIMIZE_RGB888_FORMAT; + if(!is_rgb888) { + if(!is_3d) + return get_is_buffer_rgb565_fully_synced(buffer); + return get_is_buffer_rgb565_3d_fully_synced(buffer); + } + if(is_3d) + return get_is_buffer_rgb888_3d_fully_synced(buffer); + if(should_be_3d) + return get_is_buffer_rgb888_3d_2d_fully_synced(buffer); + return get_is_buffer_rgb888_fully_synced(buffer); } static size_t get_pos_first_synch_in_buffer(uint8_t* buffer) { @@ -395,14 +486,18 @@ 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, bool is_3d) { +static void cypress_output_to_thread(CaptureData* capture_data, uint8_t *buffer_arr, size_t start_slice_index, size_t start_slice_pos, int internal_index, std::chrono::time_point* clock_start, size_t read_size, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { // Output to the other threads... CaptureDataSingleBuffer* data_buf = capture_data->data_buffers.GetWriterBuffer(internal_index); copy_slice_data_to_buffer((uint8_t*)&data_buf->capture_buf, buffer_arr, start_slice_index, start_slice_pos, read_size); + if(!get_is_buffer_fully_synched(&data_buf->capture_buf, is_3d, should_be_3d, video_data_type)) { + capture_data->data_buffers.ReleaseWriterBuffer(internal_index, false); + return; + } 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, is_3d); + capture_data->data_buffers.WriteToBuffer(NULL, read_size, diff.count(), &capture_data->status.device, internal_index, is_3d, should_be_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(); @@ -453,7 +548,10 @@ static void cypress_device_read_frame_synchronized(CypressOptimize3DSDeviceCaptu volatile int read_slice_index = *cypress_device_capture_recv_data->first_usable_ring_buffer_slice_index; volatile size_t read_slice_pos = *cypress_device_capture_recv_data->last_used_ring_buffer_slice_pos; int num_consecutive_ready_buffers = get_num_consecutive_ready_ring_buffer_slices(cypress_device_capture_recv_data, read_slice_index); - size_t video_in_size = (size_t)cyop_device_get_video_in_size(*cypress_device_capture_recv_data->stored_is_3d, *cypress_device_capture_recv_data->stored_video_data_type); + bool should_be_3d_data = *cypress_device_capture_recv_data->stored_is_3d; + bool is_3d_data = should_be_3d_data; + InputVideoDataType video_data_type = *cypress_device_capture_recv_data->stored_video_data_type; + size_t video_in_size = (size_t)cyop_device_get_video_in_size(is_3d_data, should_be_3d_data, video_data_type); size_t curr_consecutive_available_bytes = (num_consecutive_ready_buffers * SINGLE_RING_BUFFER_SLICE_SIZE) - read_slice_pos; if(curr_consecutive_available_bytes >= sizeof(USB3DSOptimizeHeaderData)) { uint8_t tmp_buffer[sizeof(USB3DSOptimizeHeaderData)]; @@ -464,12 +562,16 @@ static void cypress_device_read_frame_synchronized(CypressOptimize3DSDeviceCaptu } else { if(get_expect_extra_header_in_buffer(read_le16(tmp_buffer, 1))) - video_in_size = (size_t)cyop_device_get_video_in_size_extra_header(*cypress_device_capture_recv_data->stored_is_3d, *cypress_device_capture_recv_data->stored_video_data_type); + video_in_size = (size_t)cyop_device_get_video_in_size_extra_header(is_3d_data, should_be_3d_data, video_data_type); + if(get_is_data_2d_only(read_le16(tmp_buffer, 1))) { + is_3d_data = false; + video_in_size = (size_t)cyop_device_get_video_in_size_extra_header(is_3d_data, should_be_3d_data, video_data_type); + } } } 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_device_capture_recv_data->stored_is_3d); + 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, is_3d_data, should_be_3d_data, video_data_type); // 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)); @@ -705,7 +807,7 @@ static int restart_captures_cc_reads(CaptureData* capture_data, CypressOptimize3 } if(set_max_again) - CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(stored_is_3d, stored_video_data_type)); + CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(stored_is_3d, stored_is_3d, stored_video_data_type)); index = 0; reset_buffer_processing_data(cypress_device_capture_recv_data); @@ -761,7 +863,7 @@ static bool cyop_device_acquisition_loop(CaptureData* capture_data, CypressOptim capture_error_print(true, capture_data, "Capture Start: Failed"); return false; } - CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(stored_is_3d, stored_video_data_type)); + CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), (size_t)cyop_device_get_video_in_size_extra_header(stored_is_3d, stored_is_3d, stored_video_data_type)); if(!schedule_all_reads(capture_data, cypress_device_capture_recv_data, index, stored_video_data_type, stored_is_3d, "Initial Reads: Failed")) return false; diff --git a/source/cc3dsfs.cpp b/source/cc3dsfs.cpp index 87f4b07..515c4d9 100755 --- a/source/cc3dsfs.cpp +++ b/source/cc3dsfs.cpp @@ -457,7 +457,7 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data, volatile 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, data_buffer->buffer_video_data_type)) && (loaded_samples < MAX_MAX_AUDIO_LATENCY) && capture_data->status.connected) { + if((data_buffer->read >= get_video_in_size(capture_data, data_buffer->is_3d, data_buffer->should_be_3d, data_buffer->buffer_video_data_type)) && (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, last_buffer_index, endianness, data_buffer, &capture_data->status); @@ -645,7 +645,7 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data, CaptureDataSingleBuffer* data_buffer = capture_data->data_buffers.GetReaderBuffer(CAPTURE_READER_VIDEO); if(data_buffer != NULL) { last_frame_time = data_buffer->time_in_buf; - if(data_buffer->read >= get_video_in_size(capture_data, data_buffer->is_3d, data_buffer->buffer_video_data_type)) { + if(data_buffer->read >= get_video_in_size(capture_data, data_buffer->is_3d, data_buffer->should_be_3d, data_buffer->buffer_video_data_type)) { if(capture_data->status.cooldown_curr_in || (!capture_data->status.connected)) blank_out = true; else { diff --git a/source/conversions.cpp b/source/conversions.cpp index 54814f0..225368d 100755 --- a/source/conversions.cpp +++ b/source/conversions.cpp @@ -293,30 +293,44 @@ static inline bool usb_OptimizeHasExtraHeaderSoundData(USB3DSOptimizeHeaderSound // The macos compiler requires this... :/ uint16_t base_data = read_le16((uint8_t*)&header_sound_data->header_info.column_info); USB3DSOptimizeColumnInfo column_info; - column_info.has_extra_header_data = (base_data >> 15) & 1; - return column_info.has_extra_header_data; + column_info.has_extra_header_data_2d_only = (base_data >> 15) & 1; + return column_info.has_extra_header_data_2d_only; +} + +static inline uint16_t usb_OptimizeGetDataBufferNumber(USB3DSOptimizeHeaderSoundData* header_sound_data) { + // The macos compiler requires this... :/ + uint16_t base_data = read_le16((uint8_t*)&header_sound_data->header_info.column_info); + USB3DSOptimizeColumnInfo column_info; + column_info.buffer_num = (base_data >> 14) & 1; + return column_info.buffer_num; } static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptLE(USB5653DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) { //de-interleave pixels const int pixels_size = sizeof(VideoPixelRGB16); - 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); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + bool is_special_header = usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound); deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data; deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); 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; - else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) - in_ptr = (interleaved_rgb565_pixels*)(((USB5653DSOptimizeCaptureReceivedExtraHeader*)p_in)->columns_data[column].pixel); + if(is_special_header) { + column_start_bot_pos -= 1; + column_pre_last_bot_pos -= 2; + target_bot_column_pre_last = BOT_WIDTH_3DS - 1; + if(column == column_last_bot_pos) + return; + } + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].pixel; const uint32_t num_iters = HEIGHT_3DS; if(column == column_last_bot_pos) usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_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); + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last); } else if(column < column_start_bot_pos) usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(out_ptr_top, in_ptr, num_iters, 0, column); @@ -329,23 +343,29 @@ static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptLE(USB5653 static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptBE(USB5653DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) { //de-interleave pixels const int pixels_size = sizeof(VideoPixelRGB16); - 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); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + bool is_special_header = usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound); deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data; deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size); 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; - else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) - in_ptr = (interleaved_rgb565_pixels*)(((USB5653DSOptimizeCaptureReceivedExtraHeader*)p_in)->columns_data[column].pixel); + if(is_special_header) { + column_start_bot_pos -= 1; + column_pre_last_bot_pos -= 2; + target_bot_column_pre_last = BOT_WIDTH_3DS - 1; + if(column == column_last_bot_pos) + return; + } + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].pixel; const uint32_t num_iters = HEIGHT_3DS; if(column == column_last_bot_pos) usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_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); + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last); } else if(column < column_start_bot_pos) usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(out_ptr_top, in_ptr, num_iters, 0, column); @@ -358,19 +378,24 @@ static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptBE(USB5653 static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB5653DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, uint16_t column, bool interleaved_3d) { //de-interleave pixels const int pixels_size = sizeof(VideoPixelRGB16); - 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); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + bool is_special_header = usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].bot_top_l_screens_column.header_sound); 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_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column.pixel; - if(column < column_last_bot_pos) - 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); - //} + if(is_special_header) { + column_start_bot_pos -= 1; + column_pre_last_bot_pos -= 2; + target_bot_column_pre_last = BOT_WIDTH_3DS - 1; + if(column == column_last_bot_pos) + return; + } + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].bot_top_l_screens_column.pixel; int multiplier_top = 1; if(interleaved_3d) { multiplier_top = 2; @@ -383,7 +408,7 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB56 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); + usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last); } else if(column < column_start_bot_pos) usb_rgb565convertInterleaveVideoToOutputDirectOptLEMonoTop(out_ptr_top_l, in_ptr, num_iters, 0, column, multiplier_top); @@ -397,19 +422,24 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB56 static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB5653DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, uint16_t column, bool interleaved_3d) { //de-interleave pixels const int pixels_size = sizeof(VideoPixelRGB16); - 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); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + bool is_special_header = usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].bot_top_l_screens_column.header_sound); 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_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column.pixel; - if(column < column_last_bot_pos) - 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); - //} + if(is_special_header) { + column_start_bot_pos -= 1; + column_pre_last_bot_pos -= 2; + target_bot_column_pre_last = BOT_WIDTH_3DS - 1; + if(column == column_last_bot_pos) + return; + } + in_ptr = (interleaved_rgb565_pixels*)p_in->columns_data[column].bot_top_l_screens_column.pixel; int multiplier_top = 1; if(interleaved_3d) { multiplier_top = 2; @@ -422,7 +452,7 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB56 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); + usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last); } else if(column < column_start_bot_pos) usb_rgb565convertInterleaveVideoToOutputDirectOptBEMonoTop(out_ptr_top_l, in_ptr, num_iters, 0, column, multiplier_top); @@ -436,23 +466,29 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB56 static inline void usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(USB8883DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) { //de-interleave pixels 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); + size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2; + size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2); + size_t target_bot_column_pre_last = BOT_WIDTH_3DS - 2; + bool is_special_header = usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound); 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 = 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; - else if(usb_OptimizeHasExtraHeaderSoundData(&p_in->columns_data[0].header_sound)) - in_ptr = (interleaved_rgb888_u16_pixels*)(((USB8883DSOptimizeCaptureReceivedExtraHeader*)p_in)->columns_data[column].pixel); + if(is_special_header) { + column_start_bot_pos -= 1; + column_pre_last_bot_pos -= 2; + target_bot_column_pre_last = BOT_WIDTH_3DS - 1; + if(column == column_last_bot_pos) + return; + } + 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); + usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoBottom(out_ptr_bottom, in_ptr, num_iters, 0, target_bot_column_pre_last); } else if(column < column_start_bot_pos) usb_rgb888convertInterleaveU16VideoToOutputDirectOptMonoTop(out_ptr_top, in_ptr, num_iters, 0, column); @@ -462,6 +498,37 @@ static inline void usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(USB8883DS } } +static inline void usb_3DS888Optimizeconvert3DForced2DVideoToOutputLineDirectOpt(USB8883DSOptimizeCaptureReceived_3D_Forced2DSingleScreen *p_in, VideoOutputData *p_out, uint16_t column, bool &do_expand) { + const int pixels_size = sizeof(VideoPixelRGB); + bool is_for_bottom = true; + uint8_t* out_ptr = (uint8_t*)p_out->rgb_video_output_data.screen_data; + if(usb_OptimizeGetDataBufferNumber(&p_in->columns_data[column].header_sound) == 1) { + out_ptr = out_ptr + (BOT_SIZE_3DS * pixels_size); + is_for_bottom = false; + } + size_t column_start = 0; + size_t column_end = TOP_WIDTH_3DS; + size_t special_column_index = 0xFFFF; + size_t special_column_target = 0xFFFF; + if(is_for_bottom) { + column_start = TOP_WIDTH_3DS - BOT_WIDTH_3DS + 1; + column_end = TOP_WIDTH_3DS; + special_column_index = TOP_WIDTH_3DS - BOT_WIDTH_3DS; + special_column_target = BOT_WIDTH_3DS - 1; + do_expand = false; + } + + if(column == special_column_index) { + memcpy(out_ptr + (special_column_target * HEIGHT_3DS * pixels_size), (uint8_t*)p_in->columns_data[special_column_index].pixel, HEIGHT_3DS * pixels_size); + return; + } + if(column < column_start) + return; + if(column >= column_end) + return; + memcpy(out_ptr + ((column - column_start) * HEIGHT_3DS * pixels_size), (uint8_t*)p_in->columns_data[column].pixel, HEIGHT_3DS * pixels_size); +} + 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; @@ -478,7 +545,6 @@ static inline void usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(USB8883 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) { @@ -603,7 +669,7 @@ static void usb_cypress_nisetro_ds_convertVideoToOutput(CaptureReceived *p_in, V } } -static void usb_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) { +static void usb_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d, bool should_be_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) @@ -625,9 +691,17 @@ static void usb_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOu } else { if(!enabled_3d) { - for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) - usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(&p_in->cypress_optimize_received_888, p_out, i); - expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->rgb_video_output_data.screen_data, sizeof(VideoPixelRGB), interleaved_3d, requested_3d); + bool do_expand = true; + if(should_be_3d) { + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_3DS888Optimizeconvert3DForced2DVideoToOutputLineDirectOpt(&p_in->cypress_optimize_received_888_3d_2d, p_out, i, do_expand); + } + else { + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) + usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(&p_in->cypress_optimize_received_888, p_out, i); + } + if(do_expand) + expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->rgb_video_output_data.screen_data, sizeof(VideoPixelRGB), interleaved_3d, requested_3d); } else { USB3DSOptimizeHeaderSoundData* first_column_header = getAudioHeaderPtrOptimize3DS3D(p_in, is_rgb888, 0); @@ -692,6 +766,7 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt bool converted = false; CaptureDevice* chosen_device = &status->device; bool is_data_3d = data_buffer->is_3d; + bool should_be_3d = data_buffer->should_be_3d; InputVideoDataType video_data_type = data_buffer->buffer_video_data_type; bool is_3d_requested = get_3d_enabled(status); #ifdef USE_FTD3 @@ -727,7 +802,7 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt #ifdef USE_CYPRESS_OPTIMIZE if(status->device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE) { bool is_rgb888 = video_data_type == VIDEO_DATA_RGB; - usb_3ds_optimize_convertVideoToOutput(p_in, p_out, is_data_3d, is_big_endian, interleaved_3d, is_3d_requested, is_rgb888); + usb_3ds_optimize_convertVideoToOutput(p_in, p_out, is_data_3d, should_be_3d, is_big_endian, interleaved_3d, is_3d_requested, is_rgb888); converted = true; } #endif @@ -756,6 +831,10 @@ static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DS3D(CaptureRece return &buffer->cypress_optimize_received_888_3d.columns_data[column / 2][column % 2].header_sound; } +static USB3DSOptimizeHeaderSoundData* getAudioHeaderPtrOptimize3DS3DForced2D(CaptureReceived* buffer, uint16_t column) { + return &buffer->cypress_optimize_received_888_3d_2d.columns_data[column].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; @@ -823,6 +902,18 @@ static void copyAudioOptimize3DS3DLE(std::int16_t *p_out, uint64_t &n_samples, u n_samples = num_inserted * 2; } +static void copyAudioOptimize3DS3DForced2DLE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer) { + uint64_t num_inserted = 0; + int last_inserted_index = last_buffer_index; + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) { + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS3DForced2D(buffer, 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); + } + 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; @@ -856,10 +947,23 @@ static void copyAudioOptimize3DS3DBE(std::int16_t *p_out, uint64_t &n_samples, u n_samples = num_inserted * 2; } +static void copyAudioOptimize3DS3DForced2DBE(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, CaptureReceived* buffer) { + uint64_t num_inserted = 0; + int last_inserted_index = last_buffer_index; + for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++) { + USB3DSOptimizeHeaderSoundData* curr_column_data = getAudioHeaderPtrOptimize3DS3DForced2D(buffer, 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); + } + 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; bool is_data_3d = data_buffer->is_3d; + bool should_be_3d = data_buffer->should_be_3d; InputVideoDataType video_data_type = data_buffer->buffer_video_data_type; CaptureReceived* p_in = (CaptureReceived*)(((uint8_t*)&data_buffer->capture_buf) + data_buffer->unused_offset); uint8_t* base_ptr = NULL; @@ -907,14 +1011,22 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &la 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(should_be_3d && is_rgb888) + copyAudioOptimize3DS3DForced2DBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf); + else + copyAudioOptimize3DSBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + } } 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); + else { + if(should_be_3d && is_rgb888) + copyAudioOptimize3DS3DForced2DLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf); + else + copyAudioOptimize3DSLE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888); + } } return true; } diff --git a/source/devicecapture.cpp b/source/devicecapture.cpp index 80640cf..a94efed 100755 --- a/source/devicecapture.cpp +++ b/source/devicecapture.cpp @@ -260,7 +260,7 @@ uint64_t get_audio_n_samples(CaptureData* capture_data, CaptureDataSingleBuffer* if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE) return -1; #endif - uint64_t n_samples = (data_buffer->read - get_video_in_size(capture_data, data_buffer->is_3d, data_buffer->buffer_video_data_type)) / 2; + uint64_t n_samples = (data_buffer->read - get_video_in_size(capture_data, data_buffer->is_3d, data_buffer->should_be_3d, data_buffer->buffer_video_data_type)) / 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 @@ -269,14 +269,14 @@ uint64_t get_audio_n_samples(CaptureData* capture_data, CaptureDataSingleBuffer* return n_samples; } -uint64_t get_video_in_size(CaptureData* capture_data, bool is_3d, InputVideoDataType video_data_type) { +uint64_t get_video_in_size(CaptureData* capture_data, bool is_3d, bool should_be_3d, InputVideoDataType video_data_type) { #ifdef USE_CYNI_USB if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NISETRO) return cyni_device_get_video_in_size(capture_data); #endif #ifdef USE_CYPRESS_OPTIMIZE if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_OPTIMIZE) - return cyop_device_get_video_in_size(capture_data, is_3d, video_data_type); + return cyop_device_get_video_in_size(capture_data, is_3d, should_be_3d, video_data_type); #endif #ifdef USE_FTD3 if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD3)