Optimize DS and N3DS CC conversions
Some checks are pending
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux32 flags:32 name:Linux GCC 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linux64 flags:64 name:Linux GCC x64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm32 flags:arm32 name:Linux GCC ARM 32 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:linuxarm64 flags:arm64 name:Linux GCC ARM 64 os:ubuntu-latest]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:macos name:macOS Apple Silicon os:macos-14]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win32 flags:-A Win32 name:Windows VS2022 Win32 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:win64 flags:-A x64 name:Windows VS2022 x64 os:windows-2022]) (push) Waiting to run
CD / ${{ matrix.platform.name }} ${{ matrix.config.name }} (map[flags:-DBUILD_SHARED_LIBS=FALSE name:Static], map[artifact_name:winarm64 flags:-A ARM64 name:Windows VS2022 ARM os:windows-2022]) (push) Waiting to run
CD / Create Pi Mono Setup (push) Blocked by required conditions
CD / Publishing (push) Blocked by required conditions

This commit is contained in:
Lorenzooone
2024-11-10 16:53:17 +01:00
parent d9df617d51
commit 5d85fd3cb4
13 changed files with 166 additions and 119 deletions

View File

@@ -394,7 +394,14 @@ execute_process(COMMAND ${CMAKE_COMMAND} --build ${TOOLS_DATA_DIR})
set(OUTPUT_NAME cc3dsfs)
if(MSVC)
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "/O2")
else()
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "-O3")
endif()
add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/CaptureDataBuffers.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${SOURCE_CPP_EXTRA_FILES})
if(NOT ("${EXTRA_DEPENDENCIES}" STREQUAL ""))
add_dependencies(${OUTPUT_NAME} ${EXTRA_DEPENDENCIES})
endif()

View File

@@ -12,7 +12,6 @@ void list_devices_ftd3(std::vector<CaptureDevice> &devices_list, std::vector<no_
bool connect_ftd3(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
void ftd3_capture_main_loop(CaptureData* capture_data);
void ftd3_capture_cleanup(CaptureData* capture_data);
void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d);
uint64_t ftd3_get_video_in_size(CaptureData* capture_data);
#endif

View File

@@ -12,8 +12,8 @@ void list_devices_is_nitro(std::vector<CaptureDevice> &devices_list, std::vector
bool is_nitro_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
void is_nitro_acquisition_main_loop(CaptureData* capture_data);
void usb_is_nitro_acquisition_cleanup(CaptureData* capture_data);
void usb_is_nitro_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureScreensType capture_type);
uint64_t usb_is_nitro_get_video_in_size(CaptureData* capture_data);
uint64_t usb_is_nitro_get_video_in_size(CaptureScreensType capture_type);
bool is_nitro_is_capture(CaptureDevice* device);
void usb_is_nitro_init();
void usb_is_nitro_close();

View File

@@ -21,7 +21,6 @@ struct ISNitroCaptureReceivedData {
isn_async_callback_data cb_data;
};
uint64_t _is_nitro_get_video_in_size(CaptureScreensType capture_type);
int set_acquisition_mode(is_nitro_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_nitro_usb_device* usb_device_desc);
int EndAcquisition(CaptureData* capture_data, ISNitroCaptureReceivedData* is_nitro_capture_recv_data, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);
int EndAcquisition(const is_nitro_usb_device* usb_device_desc, is_nitro_device_handlers* handlers, bool do_drain_frames, int start_frames, CaptureScreensType capture_type);

View File

@@ -12,7 +12,6 @@ void list_devices_ftd2(std::vector<CaptureDevice> &devices_list, std::vector<no_
bool connect_ftd2(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
void ftd2_capture_main_loop(CaptureData* capture_data);
void ftd2_capture_cleanup(CaptureData* capture_data);
void ftd2_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d);
uint64_t ftd2_get_video_in_size(CaptureData* capture_data);
#endif

View File

@@ -8,11 +8,12 @@
#include "display_structs.hpp"
#include "devicecapture.hpp"
#define SIMPLE_DS_FRAME_SKIP
void list_devices_usb_ds_3ds(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
bool connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
void usb_capture_main_loop(CaptureData* capture_data);
void usb_capture_cleanup(CaptureData* capture_data);
void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureDevice* capture_device, bool enabled_3d);
uint64_t usb_get_video_in_size(CaptureData* capture_data);
void usb_ds_3ds_init();
void usb_ds_3ds_close();

View File

@@ -40,6 +40,7 @@
#define HEIGHT_NES 240
#define TOP_SIZE_3DS (TOP_WIDTH_3DS * HEIGHT_3DS)
#define BOT_SIZE_3DS (BOT_WIDTH_3DS * HEIGHT_3DS)
#define TOP_SIZE_DS (WIDTH_DS * HEIGHT_DS)
#define IN_VIDEO_WIDTH_3DS HEIGHT_3DS
@@ -49,7 +50,8 @@
#define IN_VIDEO_BPP_SIZE_3DS 24
#define IN_VIDEO_WIDTH_3DS_3D HEIGHT_3DS
#define IN_VIDEO_HEIGHT_3DS_3D (TOP_WIDTH_3DS + TOP_WIDTH_3DS + BOT_WIDTH_3DS)
#define IN_VIDEO_HEIGHT_3DS_3D (TOP_WIDTH_3DS + BOT_WIDTH_3DS + TOP_WIDTH_3DS)
#define IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D (((TOP_WIDTH_3DS - BOT_WIDTH_3DS) * HEIGHT_3DS) * 2)
#define IN_VIDEO_SIZE_3DS_3D (IN_VIDEO_WIDTH_3DS_3D * IN_VIDEO_HEIGHT_3DS_3D)
#define IN_VIDEO_BPP_SIZE_3DS_3D 24

View File

@@ -312,23 +312,3 @@ void ftd3_capture_cleanup(CaptureData* capture_data) {
capture_error_print(true, capture_data, "Disconnected: Close failed");
}
}
static inline void convertVideoToOutputChunk(RGB83DSVideoInputData *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) {
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
}
static inline void convertVideoToOutputChunk_3D(RGB83DSVideoInputData_3D *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) {
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
}
void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d) {
if(!enabled_3d) {
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_NO_BOTTOM_SIZE_3DS, 0, 0);
for(int i = 0; i < ((IN_VIDEO_SIZE_3DS - IN_VIDEO_NO_BOTTOM_SIZE_3DS) / (IN_VIDEO_WIDTH_3DS * 2)); i++) {
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, ((i * 2) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, TOP_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS));
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, (((i * 2) + 1) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, IN_VIDEO_NO_BOTTOM_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS));
}
}
}

View File

@@ -129,14 +129,15 @@ bool is_nitro_connect_usb(bool print_failed, CaptureData* capture_data, CaptureD
return true;
}
uint64_t _is_nitro_get_video_in_size(CaptureScreensType capture_type) {
uint64_t usb_is_nitro_get_video_in_size(CaptureScreensType capture_type) {
if((capture_type == CAPTURE_SCREENS_TOP) || (capture_type == CAPTURE_SCREENS_BOTTOM))
return sizeof(ISNitroEmulatorVideoInputData) / 2;
return sizeof(ISNitroEmulatorVideoInputData);
}
uint64_t usb_is_nitro_get_video_in_size(CaptureData* capture_data) {
return _is_nitro_get_video_in_size(capture_data->status.capture_type);
return usb_is_nitro_get_video_in_size(capture_data->status.capture_type);
}
int set_acquisition_mode(is_nitro_device_handlers* handlers, CaptureScreensType capture_type, CaptureSpeedsType capture_speed, const is_nitro_usb_device* usb_device_desc) {
@@ -185,7 +186,7 @@ static void output_to_thread(CaptureData* capture_data, CaptureReceived* capture
const auto curr_time = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double> diff = curr_time - (*clock_start);
*clock_start = curr_time;
capture_data->data_buffers.WriteToBuffer(capture_buf, _is_nitro_get_video_in_size(curr_capture_type), diff.count(), &capture_data->status.device, curr_capture_type);
capture_data->data_buffers.WriteToBuffer(capture_buf, usb_is_nitro_get_video_in_size(curr_capture_type), diff.count(), &capture_data->status.device, curr_capture_type);
if (capture_data->status.cooldown_curr_in)
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
@@ -194,7 +195,7 @@ static void output_to_thread(CaptureData* capture_data, CaptureReceived* capture
}
int is_nitro_read_frame_and_output(CaptureData* capture_data, CaptureReceived* capture_buf, CaptureScreensType curr_capture_type, std::chrono::time_point<std::chrono::high_resolution_clock> &clock_start) {
int ret = ReadFrame((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, _is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor);
int ret = ReadFrame((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)capture_buf, usb_is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor);
if (ret < 0)
return ret;
output_to_thread(capture_data, capture_buf, curr_capture_type, &clock_start);
@@ -207,7 +208,7 @@ void is_nitro_read_frame_request(CaptureData* capture_data, ISNitroCaptureReceiv
is_nitro_capture_recv_data->index = index;
is_nitro_capture_recv_data->curr_capture_type = curr_capture_type;
is_nitro_capture_recv_data->cb_data.function = is_nitro_read_frame_cb;
ReadFrameAsync((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)&is_nitro_capture_recv_data->buffer, _is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor, &is_nitro_capture_recv_data->cb_data);
ReadFrameAsync((is_nitro_device_handlers*)capture_data->handle, (uint8_t*)&is_nitro_capture_recv_data->buffer, usb_is_nitro_get_video_in_size(curr_capture_type), (const is_nitro_usb_device*)capture_data->status.device.descriptor, &is_nitro_capture_recv_data->cb_data);
}
static void end_is_nitro_read_frame_cb(ISNitroCaptureReceivedData* is_nitro_capture_recv_data) {
@@ -364,21 +365,6 @@ void usb_is_nitro_acquisition_cleanup(CaptureData* capture_data) {
capture_data->handle = NULL;
}
void usb_is_nitro_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureScreensType capture_type) {
if(!usb_is_initialized())
return;
int num_pixels = _is_nitro_get_video_in_size(capture_type) / 3;
int out_start_pos = 0;
int out_clear_pos = num_pixels;
if(capture_type == CAPTURE_SCREENS_BOTTOM) {
out_start_pos = num_pixels;
out_clear_pos = 0;
}
if((capture_type == CAPTURE_SCREENS_BOTTOM) || (capture_type == CAPTURE_SCREENS_TOP))
memset(p_out->screen_data[out_clear_pos], 0, num_pixels * 3);
memcpy(p_out->screen_data[out_start_pos], p_in->is_nitro_capture_received.video_in.screen_data, num_pixels * 3);
}
bool is_nitro_is_capture(CaptureDevice* device) {
const is_nitro_usb_device* usb_device_info = (const is_nitro_usb_device*)device->descriptor;
return usb_device_info->is_capture;

View File

@@ -1,5 +1,6 @@
#include "devicecapture.hpp"
#include "usb_is_nitro_communications.hpp"
#include "usb_is_nitro_acquisition.hpp"
#include "usb_is_nitro_acquisition_general.hpp"
#include "usb_is_nitro_acquisition_emulator.hpp"
@@ -35,7 +36,7 @@
static int drain_frames(is_nitro_device_handlers* handlers, int num_frames, int start_frames, CaptureScreensType capture_type, const is_nitro_usb_device* usb_device_desc) {
ISNitroEmulatorVideoInputData* video_in_buffer = new ISNitroEmulatorVideoInputData;
for (int i = start_frames; i < num_frames; i++) {
int ret = ReadFrame(handlers, (uint8_t*)video_in_buffer, _is_nitro_get_video_in_size(capture_type), usb_device_desc);
int ret = ReadFrame(handlers, (uint8_t*)video_in_buffer, usb_is_nitro_get_video_in_size(capture_type), usb_device_desc);
if(ret < 0) {
delete video_in_buffer;
return ret;

View File

@@ -29,7 +29,3 @@ void ftd2_capture_main_loop(CaptureData* capture_data) {
void ftd2_capture_cleanup(CaptureData* capture_data) {
}
void ftd2_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d) {
}

View File

@@ -16,8 +16,6 @@
#define FIRST_3D_VERSION 6
#define CAPTURE_SKIP_TIMEOUT_SECONDS 1.0
#define SIMPLE_DS_FRAME_SKIP
#define NUM_DS_3DS_CONCURRENT_DATA_BUFFERS 4
#define NUM_DS_3DS_CONCURRENT_REQUESTS 4
@@ -331,55 +329,6 @@ static usb_capture_status capture_read_oldds_3ds(usb_ds_3ds_general_data* chosen
return USB_CAPTURE_SUCCESS;
}
static inline void usb_oldDSconvertVideoToOutputHalfLine(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) {
//de-interleave pixels
uint16_t* out_ptr_top = (uint16_t*)p_out->screen_data;
uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS);
uint16_t* in_ptr = (uint16_t*)p_in->video_in.screen_data;
for(int i = 0; i < WIDTH_DS / 2 ; i++) {
uint32_t input_halfline_pixel = (input_halfline * (WIDTH_DS / 2)) + i;
uint32_t output_halfline_pixel = (output_halfline * (WIDTH_DS / 2)) + i;
out_ptr_bottom[output_halfline_pixel] = in_ptr[input_halfline_pixel * 2];
out_ptr_top[output_halfline_pixel] = in_ptr[(input_halfline_pixel * 2) + 1];
}
}
static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out) {
#ifndef SIMPLE_DS_FRAME_SKIP
if(!p_in->frameinfo.valid) { //LCD was off
memset(p_out->screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * sizeof(uint16_t));
return;
}
// Handle first line being off, if needed
memset(p_out->screen_data, 0, WIDTH_DS * sizeof(uint16_t));
int input_halfline = 0;
for(int i = 0; i < 2; i++) {
if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7)))
usb_oldDSconvertVideoToOutputHalfLine(p_in, p_out, input_halfline++, i);
}
for(int i = 2; i < HEIGHT_DS * 2; i++) {
if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7)))
usb_oldDSconvertVideoToOutputHalfLine(p_in, p_out, input_halfline++, i);
else { // deal with missing half-line
uint16_t* out_ptr_top = (uint16_t*)&p_out->screen_data;
uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS);
memcpy(&out_ptr_top[i * (WIDTH_DS / 2)], &out_ptr_top[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
memcpy(&out_ptr_bottom[i * (WIDTH_DS / 2)], &out_ptr_bottom[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
}
}
#else
for(int i = 0; i < HEIGHT_DS * 2; i++)
usb_oldDSconvertVideoToOutputHalfLine(p_in, p_out, i, i);
#endif
}
static void usb_3DSconvertVideoToOutput(USB3DSCaptureReceived *p_in, VideoOutputData *p_out) {
memcpy(p_out->screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3);
}
static void process_usb_capture_result(usb_capture_status result, std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start, bool* done, usb_ds_3ds_general_data* chosen_buffer) {
const auto curr_time = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double> diff = curr_time - (*clock_start);
@@ -556,17 +505,6 @@ void usb_capture_cleanup(CaptureData* capture_data) {
capture_end((libusb_device_handle*)capture_data->handle, usb_device_desc);
}
void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureDevice* capture_device, bool enabled_3d) {
if(!usb_is_initialized())
return;
if(capture_device->is_3ds) {
if(!enabled_3d)
usb_3DSconvertVideoToOutput(&p_in->usb_received_3ds, p_out);
}
else
usb_oldDSconvertVideoToOutput(&p_in->usb_received_old_ds, p_out);
}
void usb_ds_3ds_init() {
return usb_init();
}

View File

@@ -7,29 +7,168 @@
#include <cstring>
struct interleaved_ds_pixels {
uint16_t bottom_first;
uint16_t top_first;
uint16_t bottom_second;
uint16_t top_second;
uint16_t bottom_third;
uint16_t top_third;
uint16_t bottom_fourth;
uint16_t top_fourth;
};
struct deinterleaved_ds_pixels {
uint32_t first : 16;
uint32_t second : 16;
uint32_t third : 16;
uint32_t fourth : 16;
};
#ifdef USE_FTD3
static inline void convertVideoToOutputChunk(RGB83DSVideoInputData *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) {
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
}
static inline void convertVideoToOutputChunk_3D(RGB83DSVideoInputData_3D *p_in, VideoOutputData *p_out, int iters, int start_in, int start_out) {
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
}
static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, bool enabled_3d) {
if(!enabled_3d) {
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_NO_BOTTOM_SIZE_3DS, 0, 0);
for(int i = 0; i < ((IN_VIDEO_SIZE_3DS - IN_VIDEO_NO_BOTTOM_SIZE_3DS) / (IN_VIDEO_WIDTH_3DS * 2)); i++) {
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, ((i * 2) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, TOP_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS));
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, (((i * 2) + 1) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, IN_VIDEO_NO_BOTTOM_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS));
}
}
else {
for(int i = 0; i < (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / (IN_VIDEO_WIDTH_3DS_3D * 2)); i++) {
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (i * 2) * IN_VIDEO_WIDTH_3DS_3D, i * IN_VIDEO_WIDTH_3DS_3D);
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, ((i * 2) + 1) * IN_VIDEO_WIDTH_3DS_3D, TOP_SIZE_3DS + BOT_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS_3D));
}
for(int i = 0; i < ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)); i++) {
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, ((i * 3) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, TOP_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS_3D));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D));
convertVideoToOutputChunk_3D(&p_in->ftd3_received_3d.video_in, p_out, IN_VIDEO_WIDTH_3DS_3D, (((i * 3) + 1) * IN_VIDEO_WIDTH_3DS_3D) + IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D, TOP_SIZE_3DS + BOT_SIZE_3DS + (IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D / 2) + (i * IN_VIDEO_WIDTH_3DS_3D));
}
}
}
#endif
#ifdef USE_FTD2
static void ftd2_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out) {
}
#endif
#ifdef USE_DS_3DS_USB
static inline void usb_oldDSconvertVideoToOutputHalfLineDirectOpt(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) {
//de-interleave pixels
deinterleaved_ds_pixels* out_ptr_top = (deinterleaved_ds_pixels*)p_out->screen_data;
deinterleaved_ds_pixels* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS / (sizeof(deinterleaved_ds_pixels) / 2));
interleaved_ds_pixels* in_ptr = (interleaved_ds_pixels*)p_in->video_in.screen_data;
const uint32_t halfline_iters = WIDTH_DS / (sizeof(interleaved_ds_pixels) / 2);
for(int i = 0; i < halfline_iters; i++) {
uint32_t input_halfline_pixel = (input_halfline * halfline_iters) + i;
uint32_t output_halfline_pixel = (output_halfline * halfline_iters) + i;
out_ptr_bottom[output_halfline_pixel].first = in_ptr[input_halfline_pixel].bottom_first;
out_ptr_bottom[output_halfline_pixel].second = in_ptr[input_halfline_pixel].bottom_second;
out_ptr_bottom[output_halfline_pixel].third = in_ptr[input_halfline_pixel].bottom_third;
out_ptr_bottom[output_halfline_pixel].fourth = in_ptr[input_halfline_pixel].bottom_fourth;
out_ptr_top[output_halfline_pixel].first = in_ptr[input_halfline_pixel].top_first;
out_ptr_top[output_halfline_pixel].second = in_ptr[input_halfline_pixel].top_second;
out_ptr_top[output_halfline_pixel].third = in_ptr[input_halfline_pixel].top_third;
out_ptr_top[output_halfline_pixel].fourth = in_ptr[input_halfline_pixel].top_fourth;
}
}
static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out) {
#ifndef SIMPLE_DS_FRAME_SKIP
if(!p_in->frameinfo.valid) { //LCD was off
memset(p_out->screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * sizeof(uint16_t));
return;
}
// Handle first line being off, if needed
memset(p_out->screen_data, 0, WIDTH_DS * sizeof(uint16_t));
int input_halfline = 0;
for(int i = 0; i < 2; i++) {
if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7)))
usb_oldDSconvertVideoToOutputHalfLineDirectOpt(p_in, p_out, input_halfline++, i);
}
for(int i = 2; i < HEIGHT_DS * 2; i++) {
if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7)))
usb_oldDSconvertVideoToOutputHalfLineDirectOpt(p_in, p_out, input_halfline++, i);
else { // deal with missing half-line
uint16_t* out_ptr_top = (uint16_t*)&p_out->screen_data;
uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS);
memcpy(&out_ptr_top[i * (WIDTH_DS / 2)], &out_ptr_top[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
memcpy(&out_ptr_bottom[i * (WIDTH_DS / 2)], &out_ptr_bottom[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
}
}
#else
for(int i = 0; i < HEIGHT_DS * 2; i++)
usb_oldDSconvertVideoToOutputHalfLineDirectOpt(p_in, p_out, i, i);
#endif
}
static void usb_3DSconvertVideoToOutput(USB3DSCaptureReceived *p_in, VideoOutputData *p_out) {
memcpy(p_out->screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3);
}
static void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureDevice* capture_device, bool enabled_3d) {
if(capture_device->is_3ds) {
if(!enabled_3d)
usb_3DSconvertVideoToOutput(&p_in->usb_received_3ds, p_out);
}
else
usb_oldDSconvertVideoToOutput(&p_in->usb_received_old_ds, p_out);
}
#endif
#ifdef USE_IS_NITRO_USB
static void usb_is_nitro_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureScreensType capture_type) {
int num_pixels = usb_is_nitro_get_video_in_size(capture_type) / 3;
int out_start_pos = 0;
int out_clear_pos = num_pixels;
if(capture_type == CAPTURE_SCREENS_BOTTOM) {
out_start_pos = num_pixels;
out_clear_pos = 0;
}
if((capture_type == CAPTURE_SCREENS_BOTTOM) || (capture_type == CAPTURE_SCREENS_TOP))
memset(p_out->screen_data[out_clear_pos], 0, num_pixels * 3);
memcpy(p_out->screen_data[out_start_pos], p_in->is_nitro_capture_received.video_in.screen_data, num_pixels * 3);
}
#endif
bool convertVideoToOutput(VideoOutputData *p_out, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status) {
CaptureReceived *p_in = &data_buffer->capture_buf;
bool converted = false;
CaptureDevice* chosen_device = &status->device;
#ifdef USE_FTD3
if(status->device.cc_type == CAPTURE_CONN_FTD3) {
if(chosen_device->cc_type == CAPTURE_CONN_FTD3) {
ftd3_convertVideoToOutput(p_in, p_out, status->enabled_3d);
converted = true;
}
#endif
#ifdef USE_FTD2
if(status->device.cc_type == CAPTURE_CONN_FTD2) {
ftd2_convertVideoToOutput(p_in, p_out, status->enabled_3d);
if(chosen_device->cc_type == CAPTURE_CONN_FTD2) {
ftd2_convertVideoToOutput(p_in, p_out);
converted = true;
}
#endif
#ifdef USE_DS_3DS_USB
if(status->device.cc_type == CAPTURE_CONN_USB) {
usb_convertVideoToOutput(p_in, p_out, &status->device, status->enabled_3d);
if(chosen_device->cc_type == CAPTURE_CONN_USB) {
usb_convertVideoToOutput(p_in, p_out, chosen_device, status->enabled_3d);
converted = true;
}
#endif
#ifdef USE_IS_NITRO_USB
if(status->device.cc_type == CAPTURE_CONN_IS_NITRO) {
if(chosen_device->cc_type == CAPTURE_CONN_IS_NITRO) {
usb_is_nitro_convertVideoToOutput(p_in, p_out, data_buffer->capture_type);
converted = true;
}