Implement Optimize New 3DS Firmware loading
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 2025-04-01 23:21:42 +02:00
parent 7c4640b3dc
commit 6b040e4d36
24 changed files with 592 additions and 91 deletions

View File

@ -11,12 +11,13 @@ set(NEW_DS_LOOPY_SUPPORT 1)
set(IS_DEVICES_SUPPORT 1)
set(OLD_DS_3DS_LOOPY_SUPPORT 1)
set(CYPRESS_NISETRO_SUPPORT 1)
set(OPTIMIZE_NEW3DS_SUPPORT 1)
set(USE_FTD2XX_FOR_NEW_DS_LOOPY ${NEW_DS_LOOPY_SUPPORT})
set(USE_LIBUSB_FOR_NEW_DS_LOOPY ${NEW_DS_LOOPY_SUPPORT})
set(USE_FTD3XX_FOR_N3DSXL_LOOPY ${N3DSXL_LOOPY_SUPPORT})
set(USE_LIBUSB_FOR_N3DSXL_LOOPY ${N3DSXL_LOOPY_SUPPORT})
set(USE_CYPRESS_USB_SUPPORT ${CYPRESS_NISETRO_SUPPORT})
set(USE_CYPRESS_USB_SUPPORT ${CYPRESS_NISETRO_SUPPORT} OR ${OPTIMIZE_NEW3DS_SUPPORT})
set(USE_LIBUSB_SUPPORT ${IS_DEVICES_SUPPORT} OR ${OLD_DS_3DS_LOOPY_SUPPORT} OR ${USE_LIBUSB_FOR_NEW_DS_LOOPY} OR ${USE_LIBUSB_FOR_N3DSXL_LOOPY} OR ${USE_CYPRESS_USB_SUPPORT})
if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Windows"))
#Performance outside of Windows is very bad for the official drivers...
@ -306,6 +307,7 @@ set(SOURCE_CPP_FTD2_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/DSCapt
set(SOURCE_CPP_FTD3_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/3DSCapture_FTD3")
set(SOURCE_CPP_CYPRESS_USB_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/CypressShared")
set(SOURCE_CPP_CYPRESS_NISETRO_DEVICES_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/Nisetro")
set(SOURCE_CPP_CYPRESS_NEW_OPTIMIZE_3DS_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/Optimize_New_3DS")
if(N3DSXL_LOOPY_SUPPORT)
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_FTD3_FILES_BASE_PATH}/3dscapture_ftd3_shared.cpp ${SOURCE_CPP_FTD3_FILES_BASE_PATH}/3dscapture_ftd3_compatibility.cpp)
if(MSVC)
@ -368,6 +370,14 @@ if(CYPRESS_NISETRO_SUPPORT)
list(APPEND EXTRA_CXX_FLAGS "-DUSE_CYNI_USB")
endif()
endif()
if(OPTIMIZE_NEW3DS_SUPPORT)
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_CYPRESS_NEW_OPTIMIZE_3DS_FILES_BASE_PATH}/cypress_optimize_new_3ds_communications.cpp ${SOURCE_CPP_CYPRESS_NEW_OPTIMIZE_3DS_FILES_BASE_PATH}/cypress_optimize_new_3ds_acquisition.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_fw.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_565_fpga_pl.cpp ${TOOLS_DATA_DIR}/optimize_new_3ds_888_fpga_pl.cpp)
if(MSVC)
list(APPEND EXTRA_CXX_FLAGS "/DUSE_CYPRESS_NEW_OPTIMIZE")
else()
list(APPEND EXTRA_CXX_FLAGS "-DUSE_CYPRESS_NEW_OPTIMIZE")
endif()
endif()
if(NEW_DS_LOOPY_SUPPORT)
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_FTD2_FILES_BASE_PATH}/dscapture_ftd2_shared.cpp ${SOURCE_CPP_FTD2_FILES_BASE_PATH}/dscapture_ftd2_compatibility.cpp ${TOOLS_DATA_DIR}/ftd2_ds2_fw_1.cpp ${TOOLS_DATA_DIR}/ftd2_ds2_fw_2.cpp)
if(MSVC)
@ -527,7 +537,7 @@ endif()
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
target_link_libraries(${OUTPUT_NAME} PRIVATE ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER}/${FTD2XX_LIB})
endif()
target_include_directories(${OUTPUT_NAME} PRIVATE ${EXTRA_INCLUDE_DIRECTORIES} ${TOOLS_DATA_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/Menus ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/ISDevices ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/Nisetro ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/CypressShared ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/3DSCapture_FTD3 ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/DSCapture_FTD2)
target_include_directories(${OUTPUT_NAME} PRIVATE ${EXTRA_INCLUDE_DIRECTORIES} ${TOOLS_DATA_DIR} ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/include/Menus ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/ISDevices ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/Nisetro ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/Optimize_New_3DS ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/CypressShared ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/3DSCapture_FTD3 ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/DSCapture_FTD2)
target_compile_features(${OUTPUT_NAME} PRIVATE cxx_std_20)
target_compile_options(${OUTPUT_NAME} PRIVATE ${EXTRA_CXX_FLAGS})
@ -573,6 +583,27 @@ add_custom_command(
DEPENDS ${CMAKE_SOURCE_DIR}/bin/nisetro_ds_fw.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
)
add_custom_command(
OUTPUT ${TOOLS_DATA_DIR}/optimize_new_3ds_fw.cpp
COMMENT "Convert fw binary to C - Optimize New 3DS"
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/optimize_new_3ds_fw.bin ${TOOLS_DATA_DIR} optimize_new_3ds_fw optimize_new_3ds_fw
DEPENDS ${CMAKE_SOURCE_DIR}/bin/optimize_new_3ds_fw.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
)
add_custom_command(
OUTPUT ${TOOLS_DATA_DIR}/optimize_new_3ds_565_fpga_pl.cpp
COMMENT "Convert FPGA 565 PL binary to C - Optimize New 3DS"
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/optimize_new_3ds_565_fpga_pl.bin ${TOOLS_DATA_DIR} optimize_new_3ds_565_fpga_pl optimize_new_3ds_565_fpga_pl
DEPENDS ${CMAKE_SOURCE_DIR}/bin/optimize_new_3ds_565_fpga_pl.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
)
add_custom_command(
OUTPUT ${TOOLS_DATA_DIR}/optimize_new_3ds_888_fpga_pl.cpp
COMMENT "Convert FPGA 888 PL binary to C - Optimize New 3DS"
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/optimize_new_3ds_888_fpga_pl.bin ${TOOLS_DATA_DIR} optimize_new_3ds_888_fpga_pl optimize_new_3ds_888_fpga_pl
DEPENDS ${CMAKE_SOURCE_DIR}/bin/optimize_new_3ds_888_fpga_pl.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
)
set(SHADERS_LIST "")
list(APPEND SHADERS_LIST ${CMAKE_SOURCE_DIR}/shaders/bit_crusher_fragment_shader.2_to_x_1_7.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_crusher_fragment_shader.2_to_x_1_6.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_crusher_fragment_shader_7.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_fragment_shader.2_to_x_0_6.frag ${CMAKE_SOURCE_DIR}/shaders/bit_merger_fragment_shader_7.frag ${CMAKE_SOURCE_DIR}/shaders/frame_blending_bit_crusher_fragment_shader.2_to_x_1_7.frag ${CMAKE_SOURCE_DIR}/shaders/frame_blending_fragment_shader.frag ${CMAKE_SOURCE_DIR}/shaders/no_effect_fragment_shader.frag ${CMAKE_SOURCE_DIR}/shaders/color_emulation_fragment_shader.frag)
@ -647,6 +678,7 @@ else()
install(FILES ${USB_RULES_DIR}/50-ftd2xx.rules DESTINATION .)
install(FILES ${USB_RULES_DIR}/51-ftd2xx.rules DESTINATION .)
install(FILES ${USB_RULES_DIR}/51-nisetro.rules DESTINATION .)
install(FILES ${USB_RULES_DIR}/51-optimize.rules DESTINATION .)
install(FILES ${SETUP_SCRIPTS_DIR}/install_usb_rules${SCRIPT_EXTENSION} DESTINATION .)
endif()

Binary file not shown.

Binary file not shown.

BIN
bin/optimize_new_3ds_fw.bin Normal file

Binary file not shown.

View File

@ -1,18 +1,18 @@
#ifndef __CYPRESS_NISETRO_DRIVER_COMMS_HPP
#define __CYPRESS_NISETRO_DRIVER_COMMS_HPP
#ifndef __CYPRESS_SHARED_DRIVER_COMMS_HPP
#define __CYPRESS_SHARED_DRIVER_COMMS_HPP
#include <vector>
#include "capture_structs.hpp"
#include "utils.hpp"
#include "cypress_shared_communications.hpp"
enum CypressWindowsDriversEnum { CYPRESS_WINDOWS_DEFAULT_USB_DRIVER };
enum CypressWindowsDriversEnum { CYPRESS_WINDOWS_DEFAULT_USB_DRIVER, CYPRESS_WINDOWS_OPTIMIZE_NEW_USB_DRIVER };
void cypress_driver_list_devices(std::vector<CaptureDevice>& devices_list, bool* not_supported_elems, int* curr_serial_extra_id_cypress, std::vector<const cy_device_usb_device*> &device_descriptions, CypressWindowsDriversEnum driver);
void cypress_driver_find_used_serial(const cy_device_usb_device* usb_device_desc, bool* found, size_t num_free_fw_ids, int &curr_serial_extra_id, CypressWindowsDriversEnum driver);
cy_device_device_handlers* cypress_driver_find_by_serial_number(const cy_device_usb_device* usb_device_desc, std::string wanted_serial_number, int &curr_serial_extra_id, CaptureDevice* new_device, CypressWindowsDriversEnum driver);
cy_device_device_handlers* cypress_driver_serial_reconnection(CaptureDevice* device);
void cypress_nisetro_driver_end_connection(cy_device_device_handlers* handlers);
void cypress_driver_end_connection(cy_device_device_handlers* handlers);
int cypress_driver_ctrl_transfer_in(cy_device_device_handlers* handlers, uint8_t* buffer, size_t inner_size, uint16_t value, uint16_t index, uint16_t request_code, int* num_read);
int cypress_driver_ctrl_transfer_out(cy_device_device_handlers* handlers, uint8_t* buffer, size_t inner_size, uint16_t value, uint16_t index, uint16_t request_code, int* num_read);
int cypress_driver_bulk_in(cy_device_device_handlers* handlers, const cy_device_usb_device* usb_device_desc, uint8_t* buf, int length, int* transferred);

View File

@ -1,5 +1,5 @@
#ifndef __CYPRESS_NISETRO_DEVICE_LIBUSB_HPP
#define __CYPRESS_NISETRO_DEVICE_LIBUSB_HPP
#ifndef __CYPRESS_SHARED_DEVICE_LIBUSB_HPP
#define __CYPRESS_SHARED_DEVICE_LIBUSB_HPP
#include <vector>
#include "capture_structs.hpp"

View File

@ -4,25 +4,6 @@
#include "cypress_shared_communications.hpp"
#include "cypress_nisetro_communications.hpp"
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS NUM_CONCURRENT_DATA_BUFFER_WRITERS
struct CypressDeviceCaptureReceivedData {
volatile bool in_use;
uint32_t index;
SharedConsumerMutex* is_buffer_free_shared_mutex;
size_t* scheduled_special_read;
uint32_t* active_special_read_index;
bool* is_active_special_read;
bool* recalibration_request;
int* status;
uint32_t* last_index;
int* errors_since_last_output;
int* consecutive_output_to_thread;
CaptureData* capture_data;
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
cy_async_callback_data cb_data;
};
std::string cypress_nisetro_get_serial(const void* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id);
CaptureDevice cypress_nisetro_create_device(const void* usb_device_desc, std::string serial, std::string path);

View File

@ -0,0 +1,20 @@
#ifndef __CYPRESS_OPTIMIZE_NEW_3DS_ACQUISITION_HPP
#define __CYPRESS_OPTIMIZE_NEW_3DS_ACQUISITION_HPP
#include <vector>
#include "utils.hpp"
#include "hw_defs.hpp"
#include "capture_structs.hpp"
#include "display_structs.hpp"
#include "devicecapture.hpp"
void list_devices_cyopn_device(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
bool cyopn_device_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
uint64_t cyopn_device_get_video_in_size(CaptureStatus* status, bool is_3d, InputVideoDataType video_data_type);
uint64_t cyopn_device_get_video_in_size(CaptureData* capture_data, bool is_3d, InputVideoDataType video_data_type);
void cyopn_device_acquisition_main_loop(CaptureData* capture_data);
void usb_cyopn_device_acquisition_cleanup(CaptureData* capture_data);
void usb_cyopn_device_init();
void usb_cyopn_device_close();
#endif

View File

@ -0,0 +1,10 @@
#ifndef __CYPRESS_OPTIMIZE_NEW_3DS_ACQUISITION_GENERAL_HPP
#define __CYPRESS_OPTIMIZE_NEW_3DS_ACQUISITION_GENERAL_HPP
#include "cypress_shared_communications.hpp"
#include "cypress_optimize_new_3ds_communications.hpp"
std::string cypress_optimize_new_3ds_get_serial(const void* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id);
CaptureDevice cypress_optimize_new_3ds_create_device(const void* usb_device_desc, std::string serial, std::string path);
#endif

View File

@ -0,0 +1,40 @@
#ifndef __CYPRESS_OPTIMIZE_NEW_3DS_DEVICE_COMMUNICATIONS_HPP
#define __CYPRESS_OPTIMIZE_NEW_3DS_DEVICE_COMMUNICATIONS_HPP
#include <libusb.h>
#include <vector>
#include <fstream>
#include <thread>
#include "utils.hpp"
#include "capture_structs.hpp"
#include "cypress_shared_communications.hpp"
enum cypress_optimize_new_device_type {
CYPRESS_OPTIMIZE_NEW_3DS_BLANK_DEVICE,
};
struct cyopn_device_usb_device {
std::string name;
std::string long_name;
cypress_optimize_new_device_type device_type;
uint8_t* firmware_to_load;
size_t firmware_size;
cypress_optimize_new_device_type next_device;
bool has_bcd_device_serial;
cy_device_usb_device usb_device_info;
};
int GetNumCyOpNDeviceDesc(void);
const cyopn_device_usb_device* GetCyOpNDeviceDesc(int index);
const cyopn_device_usb_device* GetNextDeviceDesc(const cyopn_device_usb_device* device);
const cy_device_usb_device* get_cy_usb_info(const cyopn_device_usb_device* usb_device_desc);
bool has_to_load_firmware(const cyopn_device_usb_device* device);
bool load_firmware(cy_device_device_handlers* handlers, const cyopn_device_usb_device* device, uint8_t patch_id);
int capture_start(cy_device_device_handlers* handlers, const cyopn_device_usb_device* device);
int StartCaptureDma(cy_device_device_handlers* handlers, const cyopn_device_usb_device* device);
int capture_end(cy_device_device_handlers* handlers, const cyopn_device_usb_device* device);
int ReadFrame(cy_device_device_handlers* handlers, uint8_t* buf, int length, const cyopn_device_usb_device* device_desc);
int ReadFrameAsync(cy_device_device_handlers* handlers, uint8_t* buf, int length, const cyopn_device_usb_device* device_desc, cy_async_callback_data* cb_data);
#endif

View File

@ -308,6 +308,7 @@ struct CaptureDataSingleBuffer {
double time_in_buf;
uint32_t inner_index;
bool is_3d;
InputVideoDataType buffer_video_data_type;
};
class CaptureDataBuffers {

View File

@ -4,6 +4,6 @@
#include "capture_structs.hpp"
#include "display_structs.hpp"
bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool interleaved_3d, bool is_data_3d);
bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool is_data_3d);
bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool interleaved_3d);
bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status);
#endif

View File

@ -22,7 +22,7 @@ void captureCall(CaptureData* capture_data);
void capture_error_print(bool print_failed, CaptureData* capture_data, std::string error_string);
void capture_error_print(bool print_failed, CaptureData* capture_data, std::string graphical_string, std::string detailed_string);
uint64_t get_audio_n_samples(CaptureData* capture_data, CaptureDataSingleBuffer* data_buffer);
uint64_t get_video_in_size(CaptureData* capture_data, bool is_3d);
uint64_t get_video_in_size(CaptureData* capture_data, bool is_3d, InputVideoDataType video_data_type);
std::string get_name_of_device(CaptureStatus* capture_status, bool use_long = false);
int get_usb_speed_of_device(CaptureStatus* capture_status);
bool get_device_can_do_3d(CaptureStatus* capture_status);

View File

@ -117,6 +117,7 @@ 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->buffer_video_data_type = device->video_data_type;
this->ReleaseWriterBuffer(index);
}

View File

@ -138,11 +138,14 @@ struct PACKED CYPRESS_SET_TRANSFER_SIZE_INFO {
#pragma pack(pop)
static GUID cypress_driver_guid = {.Data1 = 0xae18aa60, .Data2 = 0x7f6a, .Data3 = 0x11d4, .Data4 = {0x97, 0xdd, 0x0, 0x1, 0x2, 0x29, 0xb9, 0x59}};
static GUID cypress_optimize_new_driver_guid = {.Data1 = 0xae18aa60, .Data2 = 0x7f6a, .Data3 = 0x11d4, .Data4 = {0x97, 0xdd, 0x0, 0x1, 0x2, 0x29, 0xb9, 0x59}};
static GUID* get_driver_guid(CypressWindowsDriversEnum driver) {
switch(driver) {
case CYPRESS_WINDOWS_DEFAULT_USB_DRIVER:
return &cypress_driver_guid;
case CYPRESS_WINDOWS_OPTIMIZE_NEW_USB_DRIVER:
return &cypress_optimize_new_driver_guid;
default:
return NULL;
}
@ -365,7 +368,7 @@ static bool cypress_driver_get_device_pid_vid_manufacturer_serial_number(std::st
return true;
}
static bool cypress_nisetro_driver_setup_connection(cy_device_device_handlers* handlers, std::string path, bool do_pipe_clear_reset) {
static bool cypress_driver_setup_connection(cy_device_device_handlers* handlers, std::string path, bool do_pipe_clear_reset) {
handlers->usb_handle = NULL;
handlers->mutex = NULL;
handlers->write_handle = INVALID_HANDLE_VALUE;
@ -397,7 +400,7 @@ static bool cypress_nisetro_driver_setup_connection(cy_device_device_handlers* h
return true;
}
static void cypress_nisetro_driver_close_handle(void** handle, void* default_value = INVALID_HANDLE_VALUE) {
static void cypress_driver_close_handle(void** handle, void* default_value = INVALID_HANDLE_VALUE) {
#ifdef _WIN32
if ((*handle) == default_value)
return;
@ -419,7 +422,7 @@ cy_device_device_handlers* cypress_driver_serial_reconnection(CaptureDevice* dev
if(device->path != "") {
cy_device_device_handlers handlers;
const cy_device_usb_device* usb_device_info = (const cy_device_usb_device*)device->descriptor;
if(cypress_nisetro_driver_setup_connection(&handlers, device->path, usb_device_info->do_pipe_clear_reset)) {
if(cypress_driver_setup_connection(&handlers, device->path, usb_device_info->do_pipe_clear_reset)) {
final_handlers = new cy_device_device_handlers;
final_handlers->usb_handle = NULL;
final_handlers->mutex = handlers.mutex;
@ -428,7 +431,7 @@ cy_device_device_handlers* cypress_driver_serial_reconnection(CaptureDevice* dev
final_handlers->path = device->path;
}
else
cypress_nisetro_driver_end_connection(&handlers);
cypress_driver_end_connection(&handlers);
}
#endif
return final_handlers;
@ -464,8 +467,8 @@ void cypress_driver_list_devices(std::vector<CaptureDevice> &devices_list, bool*
const cy_device_usb_device* usb_device_desc = device_descriptions[j];
if(not_supported_elems[j] && (usb_device_desc->vid == vid) && (usb_device_desc->pid == pid)) {
cy_device_device_handlers handlers;
bool result_conn_check = cypress_nisetro_driver_setup_connection(&handlers, path, usb_device_desc->do_pipe_clear_reset);
cypress_nisetro_driver_end_connection(&handlers);
bool result_conn_check = cypress_driver_setup_connection(&handlers, path, usb_device_desc->do_pipe_clear_reset);
cypress_driver_end_connection(&handlers);
if(result_conn_check)
cypress_insert_device(devices_list, usb_device_desc, serial, bcd_device, curr_serial_extra_id_cypress[j], path);
break;
@ -508,7 +511,7 @@ cy_device_device_handlers* cypress_driver_find_by_serial_number(const cy_device_
std::string read_serial = cypress_get_serial(usb_device_desc, serial, bcd_device, curr_serial_extra_id);
if((usb_device_desc->vid == vid) && (usb_device_desc->pid == pid) && (wanted_serial_number == read_serial)) {
cy_device_device_handlers handlers;
if(cypress_nisetro_driver_setup_connection(&handlers, path, usb_device_desc->do_pipe_clear_reset)) {
if(cypress_driver_setup_connection(&handlers, path, usb_device_desc->do_pipe_clear_reset)) {
final_handlers = new cy_device_device_handlers;
final_handlers->usb_handle = NULL;
final_handlers->mutex = handlers.mutex;
@ -519,7 +522,7 @@ cy_device_device_handlers* cypress_driver_find_by_serial_number(const cy_device_
*new_device = cypress_create_device(usb_device_desc, wanted_serial_number, path);
}
else
cypress_nisetro_driver_end_connection(&handlers);
cypress_driver_end_connection(&handlers);
break;
}
}
@ -552,11 +555,11 @@ int cypress_driver_ctrl_transfer_out(cy_device_device_handlers* handlers, uint8_
#endif
}
void cypress_nisetro_driver_end_connection(cy_device_device_handlers* handlers) {
void cypress_driver_end_connection(cy_device_device_handlers* handlers) {
#ifdef _WIN32
cypress_nisetro_driver_close_handle(&handlers->write_handle);
cypress_driver_close_handle(&handlers->write_handle);
handlers->read_handle = handlers->write_handle;
cypress_nisetro_driver_close_handle(&handlers->mutex, NULL);
cypress_driver_close_handle(&handlers->mutex, NULL);
#endif
}

View File

@ -11,6 +11,8 @@
#include <chrono>
#include <cstring>
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS NUM_CONCURRENT_DATA_BUFFER_WRITERS
// The driver only seems to support up to 4 concurrent reads. Not more...
#ifdef NUM_CAPTURE_RECEIVED_DATA_BUFFERS
#if NUM_CAPTURE_RECEIVED_DATA_BUFFERS > 4
@ -20,16 +22,32 @@
#endif
#endif
#define SERIAL_NUMBER_SIZE (0x100 + 1)
#define MAX_TIME_WAIT 1.0
#define MAX_ERRORS_ALLOWED 100
#define NUM_CONSECUTIVE_NEEDED_OUTPUT 6
#define NISETRO_CYPRESS_USB_WINDOWS_DRIVER CYPRESS_WINDOWS_DEFAULT_USB_DRIVER
struct CypressNisetroDeviceCaptureReceivedData {
volatile bool in_use;
uint32_t index;
SharedConsumerMutex* is_buffer_free_shared_mutex;
size_t* scheduled_special_read;
uint32_t* active_special_read_index;
bool* is_active_special_read;
bool* recalibration_request;
int* status;
uint32_t* last_index;
int* errors_since_last_output;
int* consecutive_output_to_thread;
CaptureData* capture_data;
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
cy_async_callback_data cb_data;
};
static void cypress_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status);
static int get_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data);
static void error_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val);
static int get_cypress_device_status(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data);
static void error_cypress_device_status(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val);
static cy_device_device_handlers* usb_find_by_serial_number(const cyni_device_usb_device* usb_device_desc, std::string wanted_serial_number, CaptureDevice* new_device) {
cy_device_device_handlers* final_handlers = NULL;
@ -96,7 +114,7 @@ static void cypress_nisetro_connection_end(cy_device_device_handlers* handlers,
if (handlers->usb_handle)
cypress_libusb_end_connection(handlers, get_cy_usb_info(device_desc), interface_claimed);
else
cypress_nisetro_driver_end_connection(handlers);
cypress_driver_end_connection(handlers);
delete handlers;
}
@ -231,7 +249,7 @@ static int cypress_device_read_frame_and_output(CaptureData* capture_data, int i
return ret;
}
static int cypress_device_read_frame_request(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, uint32_t index) {
static int cypress_device_read_frame_request(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data, uint32_t index) {
if(cypress_device_capture_recv_data == NULL)
return LIBUSB_SUCCESS;
if((*cypress_device_capture_recv_data->status) < 0) {
@ -253,7 +271,7 @@ static int cypress_device_read_frame_request(CaptureData* capture_data, CypressD
return ReadFrameAsync((cy_device_device_handlers*)capture_data->handle, buffer, read_size, usb_device_info, &cypress_device_capture_recv_data->cb_data);
}
static void end_cypress_device_read_frame_cb(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool early_release) {
static void end_cypress_device_read_frame_cb(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool early_release) {
if(early_release)
cypress_device_capture_recv_data->capture_data->data_buffers.ReleaseWriterBuffer(cypress_device_capture_recv_data->cb_data.internal_index, false);
cypress_device_capture_recv_data->in_use = false;
@ -261,7 +279,7 @@ static void end_cypress_device_read_frame_cb(CypressDeviceCaptureReceivedData* c
}
static void cypress_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status) {
CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data = (CypressDeviceCaptureReceivedData*)user_data;
CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data = (CypressNisetroDeviceCaptureReceivedData*)user_data;
if((*cypress_device_capture_recv_data->status) < 0)
return end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, true);
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
@ -298,7 +316,7 @@ static void cypress_device_read_frame_cb(void* user_data, int transfer_length, i
end_cypress_device_read_frame_cb(cypress_device_capture_recv_data, false);
}
static int cypress_device_get_num_free_buffers(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static int cypress_device_get_num_free_buffers(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
int num_free = 0;
for(int i = 0; i < NUM_NISETRO_CYPRESS_BUFFERS; i++)
if(!cypress_device_capture_recv_data[i].in_use)
@ -306,7 +324,7 @@ static int cypress_device_get_num_free_buffers(CypressDeviceCaptureReceivedData*
return num_free;
}
static void close_all_reads_error(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool &async_read_closed) {
static void close_all_reads_error(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool &async_read_closed) {
cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle;
const cyni_device_usb_device* usb_device_desc = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0) {
@ -328,14 +346,14 @@ static bool has_too_much_time_passed(const std::chrono::time_point<std::chrono::
return diff.count() > MAX_TIME_WAIT;
}
static void error_too_much_time_passed(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool &async_read_closed, const std::chrono::time_point<std::chrono::high_resolution_clock> &start_time) {
static void error_too_much_time_passed(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data, bool &async_read_closed, const std::chrono::time_point<std::chrono::high_resolution_clock> &start_time) {
if(has_too_much_time_passed(start_time)) {
error_cypress_device_status(cypress_device_capture_recv_data, -1);
close_all_reads_error(capture_data, cypress_device_capture_recv_data, async_read_closed);
}
}
static void wait_all_cypress_device_buffers_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static void wait_all_cypress_device_buffers_free(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
if(cypress_device_capture_recv_data == NULL)
return;
cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle;
@ -349,7 +367,7 @@ static void wait_all_cypress_device_buffers_free(CaptureData* capture_data, Cypr
}
}
static void wait_one_cypress_device_buffer_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static void wait_one_cypress_device_buffer_free(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle;
bool done = false;
const auto start_time = std::chrono::high_resolution_clock::now();
@ -369,7 +387,7 @@ static void wait_one_cypress_device_buffer_free(CaptureData* capture_data, Cypre
}
}
static void wait_specific_cypress_device_buffer_free(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static void wait_specific_cypress_device_buffer_free(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle;
bool done = false;
const auto start_time = std::chrono::high_resolution_clock::now();
@ -387,11 +405,11 @@ static void wait_specific_cypress_device_buffer_free(CaptureData* capture_data,
}
}
static bool cypress_device_are_buffers_all_free(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static bool cypress_device_are_buffers_all_free(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
return cypress_device_get_num_free_buffers(cypress_device_capture_recv_data) == NUM_NISETRO_CYPRESS_BUFFERS;
}
static CypressDeviceCaptureReceivedData* cypress_device_get_free_buffer(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static CypressNisetroDeviceCaptureReceivedData* cypress_device_get_free_buffer(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
wait_one_cypress_device_buffer_free(capture_data, cypress_device_capture_recv_data);
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
return NULL;
@ -404,11 +422,11 @@ static CypressDeviceCaptureReceivedData* cypress_device_get_free_buffer(CaptureD
return NULL;
}
static int get_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static int get_cypress_device_status(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
return *cypress_device_capture_recv_data[0].status;
}
static void error_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val) {
static void error_cypress_device_status(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val) {
if((error_val == 0) || (get_cypress_device_status(cypress_device_capture_recv_data) == 0))
*cypress_device_capture_recv_data[0].status = error_val;
}
@ -416,14 +434,14 @@ static void error_cypress_device_status(CypressDeviceCaptureReceivedData* cypres
static void exported_error_cypress_device_status(void* data, int error_val) {
if(data == NULL)
return;
return error_cypress_device_status((CypressDeviceCaptureReceivedData*)data, error_val);
return error_cypress_device_status((CypressNisetroDeviceCaptureReceivedData*)data, error_val);
}
static void reset_cypress_device_status(CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static void reset_cypress_device_status(CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
error_cypress_device_status(cypress_device_capture_recv_data, 0);
}
static void recalibration_reads(cy_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data, CypressDeviceCaptureReceivedData* chosen_buffer, uint32_t &index) {
static void recalibration_reads(cy_device_device_handlers* handlers, const cyni_device_usb_device* usb_device_desc, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data, CypressNisetroDeviceCaptureReceivedData* chosen_buffer, uint32_t &index) {
// Enforce properly synchronized reads.
// Reduces complexity and latency, at the cost of some extra
// time between lid reopening and visible video output.
@ -439,7 +457,7 @@ static void recalibration_reads(cy_device_device_handlers* handlers, const cyni_
chosen_buffer->in_use = true;
if(get_cypress_device_status(cypress_device_capture_recv_data) < 0)
return;
CypressDeviceCaptureReceivedData* next_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
CypressNisetroDeviceCaptureReceivedData* next_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
default_sleep();
*chosen_buffer->recalibration_request = false;
chosen_buffer->in_use = true;
@ -461,7 +479,7 @@ static void recalibration_reads(cy_device_device_handlers* handlers, const cyni_
chosen_buffer->in_use = true;
}
static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data) {
cy_device_device_handlers* handlers = (cy_device_device_handlers*)capture_data->handle;
const cyni_device_usb_device* usb_device_desc = (const cyni_device_usb_device*)capture_data->status.device.descriptor;
uint32_t index = 0;
@ -473,7 +491,7 @@ static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressDevic
CypressSetMaxTransferSize(handlers, get_cy_usb_info(usb_device_desc), cyni_device_get_video_in_size(usb_device_desc->device_type));
auto clock_last_reset = std::chrono::high_resolution_clock::now();
for(int i = 0; i < NUM_NISETRO_CYPRESS_BUFFERS; i++) {
CypressDeviceCaptureReceivedData* chosen_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
CypressNisetroDeviceCaptureReceivedData* chosen_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
ret = cypress_device_read_frame_request(capture_data, chosen_buffer, index++);
if(ret < 0) {
chosen_buffer->in_use = false;
@ -499,7 +517,7 @@ static bool cyni_device_acquisition_loop(CaptureData* capture_data, CypressDevic
reset_cypress_device_status(cypress_device_capture_recv_data);
default_sleep(100);
}
CypressDeviceCaptureReceivedData* chosen_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
CypressNisetroDeviceCaptureReceivedData* chosen_buffer = cypress_device_get_free_buffer(capture_data, cypress_device_capture_recv_data);
if(chosen_buffer == NULL)
error_cypress_device_status(cypress_device_capture_recv_data, LIBUSB_ERROR_TIMEOUT);
if(chosen_buffer && (*chosen_buffer->recalibration_request)) {
@ -540,7 +558,7 @@ void cyni_device_acquisition_main_loop(CaptureData* capture_data) {
SharedConsumerMutex is_transfer_done_shared_mutex(NUM_NISETRO_CYPRESS_BUFFERS);
SharedConsumerMutex is_transfer_data_ready_shared_mutex(NUM_NISETRO_CYPRESS_BUFFERS);
std::chrono::time_point<std::chrono::high_resolution_clock> clock_start = std::chrono::high_resolution_clock::now();
CypressDeviceCaptureReceivedData* cypress_device_capture_recv_data = new CypressDeviceCaptureReceivedData[NUM_NISETRO_CYPRESS_BUFFERS];
CypressNisetroDeviceCaptureReceivedData* cypress_device_capture_recv_data = new CypressNisetroDeviceCaptureReceivedData[NUM_NISETRO_CYPRESS_BUFFERS];
for(int i = 0; i < NUM_NISETRO_CYPRESS_BUFFERS; i++) {
cypress_device_capture_recv_data[i].in_use = false;
cypress_device_capture_recv_data[i].index = i;

View File

@ -106,6 +106,11 @@ bool has_to_load_firmware(const cyni_device_usb_device* device) {
return !((device->firmware_to_load == NULL) || (device->firmware_size == 0));
}
static bool free_firmware_and_return(uint8_t* fw_data, bool retval) {
delete []fw_data;
return retval;
}
bool load_firmware(cy_device_device_handlers* handlers, const cyni_device_usb_device* device, uint8_t patch_id) {
if(!has_to_load_firmware(device))
return true;
@ -120,10 +125,8 @@ bool load_firmware(cy_device_device_handlers* handlers, const cyni_device_usb_de
uint8_t buffer[0x8000];
buffer[0] = 1;
int ret = cypress_ctrl_out_transfer(handlers, get_cy_usb_info(device), buffer, 1, 0xA0, 0xE600, 0, &transferred);
if(ret < 0) {
delete []fw_data;
return false;
}
if(ret < 0)
return free_firmware_and_return(fw_data, false);
bool done = false;
int fw_pos = read_le16(fw_data);
while(!done) {
@ -132,20 +135,15 @@ bool load_firmware(cy_device_device_handlers* handlers, const cyni_device_usb_de
done = (inside_len & 0x8000) != 0;
inside_len &= 0x7FFF;
fw_pos += 4;
if((inside_len + fw_pos) > device->firmware_size) {
delete []fw_data;
return false;
}
if((inside_len + fw_pos) > device->firmware_size)
return free_firmware_and_return(fw_data, false);
memcpy(buffer, fw_data + fw_pos, inside_len);
fw_pos += inside_len;
ret = cypress_ctrl_out_transfer(handlers, get_cy_usb_info(device), buffer, inside_len, 0xA0, offset, 0, &transferred);
if(ret < 0) {
delete []fw_data;
return false;
}
if(ret < 0)
return free_firmware_and_return(fw_data, false);
}
delete []fw_data;
return true;
return free_firmware_and_return(fw_data, true);
}
int capture_start(cy_device_device_handlers* handlers, const cyni_device_usb_device* device) {

View File

@ -0,0 +1,225 @@
#include "devicecapture.hpp"
#include "cypress_shared_driver_comms.hpp"
#include "cypress_shared_libusb_comms.hpp"
#include "cypress_shared_communications.hpp"
#include "cypress_optimize_new_3ds_communications.hpp"
#include "cypress_optimize_new_3ds_acquisition.hpp"
#include "cypress_optimize_new_3ds_acquisition_general.hpp"
#include "usb_generic.hpp"
#include <libusb.h>
#include <chrono>
#include <cstring>
// This code was developed by exclusively looking at Wireshark USB packet
// captures to learn the USB device's protocol.
// As such, it was developed in a clean room environment, to provide
// compatibility of the USB device with more (and more modern) hardware.
// Such an action is allowed under EU law.
// No reverse engineering of the original software was done to create this.
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS NUM_CONCURRENT_DATA_BUFFER_WRITERS
// The driver only seems to support up to 4 concurrent reads. Not more...
#ifdef NUM_CAPTURE_RECEIVED_DATA_BUFFERS
#if NUM_CAPTURE_RECEIVED_DATA_BUFFERS > 4
#define NUM_OPTIMIZE_NEW_3DS_CYPRESS_BUFFERS 4
#else
#define NUM_OPTIMIZE_NEW_3DS_CYPRESS_BUFFERS NUM_CAPTURE_RECEIVED_DATA_BUFFERS
#endif
#endif
#define MAX_TIME_WAIT 1.0
#define OPTIMIZE_NEW_3DS_CYPRESS_USB_WINDOWS_DRIVER CYPRESS_WINDOWS_OPTIMIZE_NEW_USB_DRIVER
struct CypressOptimizeNew3DSDeviceCaptureReceivedData {
volatile bool in_use;
uint32_t index;
SharedConsumerMutex* is_buffer_free_shared_mutex;
int* status;
uint32_t* last_index;
CaptureData* capture_data;
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
cy_async_callback_data cb_data;
};
static void cypress_device_read_frame_cb(void* user_data, int transfer_length, int transfer_status);
static int get_cypress_device_status(CypressOptimizeNew3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data);
static void error_cypress_device_status(CypressOptimizeNew3DSDeviceCaptureReceivedData* cypress_device_capture_recv_data, int error_val);
static cy_device_device_handlers* usb_find_by_serial_number(const cyopn_device_usb_device* usb_device_desc, std::string wanted_serial_number, CaptureDevice* new_device) {
cy_device_device_handlers* final_handlers = NULL;
int curr_serial_extra_id = 0;
final_handlers = cypress_libusb_serial_reconnection(get_cy_usb_info(usb_device_desc), wanted_serial_number, curr_serial_extra_id, new_device);
if(final_handlers == NULL)
final_handlers = cypress_driver_find_by_serial_number(get_cy_usb_info(usb_device_desc), wanted_serial_number, curr_serial_extra_id, new_device, OPTIMIZE_NEW_3DS_CYPRESS_USB_WINDOWS_DRIVER);
return final_handlers;
}
static int usb_find_free_fw_id(const cyopn_device_usb_device* usb_device_desc) {
int curr_serial_extra_id = 0;
const int num_free_fw_ids = 0x100;
bool found[num_free_fw_ids];
for(int i = 0; i < num_free_fw_ids; i++)
found[i] = false;
cypress_libusb_find_used_serial(get_cy_usb_info(usb_device_desc), found, num_free_fw_ids, curr_serial_extra_id);
cypress_driver_find_used_serial(get_cy_usb_info(usb_device_desc), found, num_free_fw_ids, curr_serial_extra_id, OPTIMIZE_NEW_3DS_CYPRESS_USB_WINDOWS_DRIVER);
for(int i = 0; i < num_free_fw_ids; i++)
if(!found[i])
return i;
return 0;
}
static cy_device_device_handlers* usb_reconnect(const cyopn_device_usb_device* usb_device_desc, CaptureDevice* device) {
cy_device_device_handlers* final_handlers = NULL;
int curr_serial_extra_id = 0;
final_handlers = cypress_libusb_serial_reconnection(get_cy_usb_info(usb_device_desc), device->serial_number, curr_serial_extra_id, NULL);
if (final_handlers == NULL)
final_handlers = cypress_driver_serial_reconnection(device);
return final_handlers;
}
static std::string _cypress_optimize_new_3ds_get_serial(const cyopn_device_usb_device* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id) {
if((!usb_device_desc->has_bcd_device_serial) && (serial != ""))
return serial;
if(usb_device_desc->has_bcd_device_serial)
return std::to_string(bcd_device & 0xFF);
return std::to_string((curr_serial_extra_id++) + 1);
}
std::string cypress_optimize_new_3ds_get_serial(const void* usb_device_desc, std::string serial, uint16_t bcd_device, int& curr_serial_extra_id) {
if(usb_device_desc == NULL)
return "";
return _cypress_optimize_new_3ds_get_serial((const cyopn_device_usb_device*)usb_device_desc, serial, bcd_device, curr_serial_extra_id);
}
static CaptureDevice _cypress_optimize_new_3ds_create_device(const cyopn_device_usb_device* usb_device_desc, std::string serial, std::string path) {
return CaptureDevice(serial, usb_device_desc->name, usb_device_desc->long_name, CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_RGB, path);
}
CaptureDevice cypress_optimize_new_3ds_create_device(const void* usb_device_desc, std::string serial, std::string path) {
if(usb_device_desc == NULL)
return CaptureDevice();
return _cypress_optimize_new_3ds_create_device((const cyopn_device_usb_device*)usb_device_desc, serial, path);
}
static void cypress_optimize_new_3ds_connection_end(cy_device_device_handlers* handlers, const cyopn_device_usb_device *device_desc, bool interface_claimed = true) {
if (handlers == NULL)
return;
if (handlers->usb_handle)
cypress_libusb_end_connection(handlers, get_cy_usb_info(device_desc), interface_claimed);
else
cypress_driver_end_connection(handlers);
delete handlers;
}
void list_devices_cyopn_device(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
const size_t num_cyopn_device_desc = GetNumCyOpNDeviceDesc();
int* curr_serial_extra_id_cyopn_device = new int[num_cyopn_device_desc];
bool* no_access_elems = new bool[num_cyopn_device_desc];
bool* not_supported_elems = new bool[num_cyopn_device_desc];
std::vector<const cy_device_usb_device*> usb_devices_to_check;
for (int i = 0; i < num_cyopn_device_desc; i++) {
no_access_elems[i] = false;
not_supported_elems[i] = false;
curr_serial_extra_id_cyopn_device[i] = 0;
const cyopn_device_usb_device* curr_device_desc = GetCyOpNDeviceDesc(i);
usb_devices_to_check.push_back(get_cy_usb_info(curr_device_desc));
}
cypress_libusb_list_devices(devices_list, no_access_elems, not_supported_elems, curr_serial_extra_id_cyopn_device, usb_devices_to_check);
bool any_not_supported = false;
for(int i = 0; i < num_cyopn_device_desc; i++)
any_not_supported |= not_supported_elems[i];
for(int i = 0; i < num_cyopn_device_desc; i++)
if(no_access_elems[i])
no_access_list.emplace_back(usb_devices_to_check[i]->vid, usb_devices_to_check[i]->pid);
if(any_not_supported)
cypress_driver_list_devices(devices_list, not_supported_elems, curr_serial_extra_id_cyopn_device, usb_devices_to_check, OPTIMIZE_NEW_3DS_CYPRESS_USB_WINDOWS_DRIVER);
delete[] curr_serial_extra_id_cyopn_device;
delete[] no_access_elems;
delete[] not_supported_elems;
}
bool cyopn_device_connect_usb(bool print_failed, CaptureData* capture_data, CaptureDevice* device) {
const cyopn_device_usb_device* usb_device_info = (const cyopn_device_usb_device*)device->descriptor;
cy_device_device_handlers* handlers = usb_reconnect(usb_device_info, device);
if(handlers == NULL) {
capture_error_print(true, capture_data, "Device not found");
return false;
}
if(has_to_load_firmware(usb_device_info)) {
const cyopn_device_usb_device* next_usb_device_info = GetNextDeviceDesc(usb_device_info);
int free_fw_id = usb_find_free_fw_id(next_usb_device_info);
int ret = load_firmware(handlers, usb_device_info, free_fw_id);
if(!ret) {
capture_error_print(true, capture_data, "Firmware load error");
return false;
}
cypress_optimize_new_3ds_connection_end(handlers, usb_device_info);
std::string new_serial_number = std::to_string(free_fw_id);
CaptureDevice new_device;
for(int i = 0; i < 20; i++) {
default_sleep(500);
handlers = usb_find_by_serial_number(next_usb_device_info, new_serial_number, &new_device);
if(handlers != NULL)
break;
}
if(handlers == NULL) {
capture_error_print(true, capture_data, "Device reconnection error");
return false;
}
*device = new_device;
}
capture_data->handle = (void*)handlers;
return true;
}
uint64_t cyopn_device_get_video_in_size(bool is_3d, InputVideoDataType video_data_type) {
bool is_rgb888 = video_data_type == VIDEO_DATA_RGB;
if(is_rgb888) {
if(is_3d)
return sizeof(USB888New3DSOptimizeCaptureReceived_3D);
return sizeof(USB888New3DSOptimizeCaptureReceived);
}
if(is_3d)
return sizeof(USB565New3DSOptimizeCaptureReceived_3D);
return sizeof(USB565New3DSOptimizeCaptureReceived);
}
uint64_t cyopn_device_get_video_in_size(CaptureStatus* status, bool is_3d, InputVideoDataType video_data_type) {
return cyopn_device_get_video_in_size(is_3d, video_data_type);
}
uint64_t cyopn_device_get_video_in_size(CaptureData* capture_data, bool is_3d, InputVideoDataType video_data_type) {
return cyopn_device_get_video_in_size(&capture_data->status, is_3d, video_data_type);
}
void cyopn_device_acquisition_main_loop(CaptureData* capture_data) {
if(!usb_is_initialized())
return;
}
void usb_cyopn_device_acquisition_cleanup(CaptureData* capture_data) {
if(!usb_is_initialized())
return;
cypress_optimize_new_3ds_connection_end((cy_device_device_handlers*)capture_data->handle, (const cyopn_device_usb_device*)capture_data->status.device.descriptor);
capture_data->handle = NULL;
}
void usb_cyopn_device_init() {
return usb_init();
}
void usb_cyopn_device_close() {
usb_close();
}

View File

@ -0,0 +1,122 @@
#include "frontend.hpp"
#include "cypress_optimize_new_3ds_communications.hpp"
#include "cypress_shared_communications.hpp"
#include "cypress_optimize_new_3ds_acquisition_general.hpp"
#include "usb_generic.hpp"
#include "optimize_new_3ds_fw.h"
#include "optimize_new_3ds_565_fpga_pl.h"
#include "optimize_new_3ds_888_fpga_pl.h"
#include <libusb.h>
#include <cstring>
#include <thread>
#include <chrono>
#include <iostream>
// This code was developed by exclusively looking at Wireshark USB packet
// captures to learn the USB device's protocol.
// As such, it was developed in a clean room environment, to provide
// compatibility of the USB device with more (and more modern) hardware.
// Such an action is allowed under EU law.
// No reverse engineering of the original software was done to create this.
#define CYPRESS_BASE_USB_PACKET_LIMIT 64
#define CYPRESS_OPTIMIZE_NEW_3DS_USB_PACKET_LIMIT 512
static const cyopn_device_usb_device cypress_optimize_new_3ds_generic_device = {
.name = "EZ-USB Optimize New 3DS", .long_name = "EZ-USB Optimize New 3DS",
.device_type = CYPRESS_OPTIMIZE_NEW_3DS_BLANK_DEVICE,
.firmware_to_load = optimize_new_3ds_fw, .firmware_size = optimize_new_3ds_fw_len,
.next_device = CYPRESS_OPTIMIZE_NEW_3DS_BLANK_DEVICE,
.has_bcd_device_serial = false,
.usb_device_info = {
.vid = 0x0752, .pid = 0x8613,
.default_config = 1, .default_interface = 0,
.bulk_timeout = 500,
.ep_ctrl_bulk_in = 0, .ep_ctrl_bulk_out = 0,
.ep_bulk_in = 0,
.max_usb_packet_size = CYPRESS_BASE_USB_PACKET_LIMIT,
.do_pipe_clear_reset = false,
.alt_interface = 1,
.full_data = &cypress_optimize_new_3ds_generic_device,
.get_serial_fn = cypress_optimize_new_3ds_get_serial,
.create_device_fn = cypress_optimize_new_3ds_create_device
}
};
static const cyopn_device_usb_device* all_usb_cyopn_device_devices_desc[] = {
&cypress_optimize_new_3ds_generic_device,
};
const cy_device_usb_device* get_cy_usb_info(const cyopn_device_usb_device* usb_device_desc) {
return &usb_device_desc->usb_device_info;
}
int GetNumCyOpNDeviceDesc() {
return sizeof(all_usb_cyopn_device_devices_desc) / sizeof(all_usb_cyopn_device_devices_desc[0]);
}
const cyopn_device_usb_device* GetCyOpNDeviceDesc(int index) {
if((index < 0) || (index >= GetNumCyOpNDeviceDesc()))
index = 0;
return all_usb_cyopn_device_devices_desc[index];
}
const cyopn_device_usb_device* GetNextDeviceDesc(const cyopn_device_usb_device* device) {
for(int i = 0; i < GetNumCyOpNDeviceDesc(); i++) {
const cyopn_device_usb_device* examined_device = GetCyOpNDeviceDesc(i);
if(examined_device->device_type == device->next_device)
return examined_device;
}
return NULL;
}
bool has_to_load_firmware(const cyopn_device_usb_device* device) {
return !((device->firmware_to_load == NULL) || (device->firmware_size == 0));
}
static bool free_firmware_and_return(uint8_t* fw_data, bool retval) {
delete []fw_data;
return retval;
}
bool load_firmware(cy_device_device_handlers* handlers, const cyopn_device_usb_device* device, uint8_t patch_id) {
if(!has_to_load_firmware(device))
return true;
int transferred = 0;
uint8_t* fw_data = new uint8_t[device->firmware_size];
memcpy(fw_data, device->firmware_to_load, device->firmware_size);
int num_patches = read_le16(fw_data, 1);
for(int i = 0; i < num_patches; i++) {
int pos_patch = read_le16(fw_data, 2 + i);
write_le16(fw_data + pos_patch, patch_id | 0xFF00);
}
uint8_t buffer[0x8000];
buffer[0] = 1;
int ret = cypress_ctrl_out_transfer(handlers, get_cy_usb_info(device), buffer, 1, 0xA0, 0xE600, 0, &transferred);
if(ret < 0)
return free_firmware_and_return(fw_data, false);
bool done = false;
int fw_pos = read_le16(fw_data);
while(!done) {
int offset = read_le16(fw_data + fw_pos);
int index = read_le16(fw_data + fw_pos, 1);
int inside_len = read_le16(fw_data + fw_pos, 2);
done = (inside_len & 0x8000) != 0;
inside_len &= 0x7FFF;
fw_pos += 6;
if((inside_len + fw_pos) > device->firmware_size)
return free_firmware_and_return(fw_data, false);
memcpy(buffer, fw_data + fw_pos, inside_len);
fw_pos += inside_len;
ret = cypress_ctrl_out_transfer(handlers, get_cy_usb_info(device), buffer, inside_len, 0xA0, offset, index, &transferred);
if(ret < 0)
return free_firmware_and_return(fw_data, false);
}
buffer[0] = 0;
ret = cypress_ctrl_out_transfer(handlers, get_cy_usb_info(device), buffer, 1, 0xA0, 0xE600, 0, &transferred);
if(ret < 0)
return free_firmware_and_return(fw_data, false);
return free_firmware_and_return(fw_data, true);
}

View File

@ -9,6 +9,7 @@
// Adapted from sample code provided by Loopy
#define PRODUCT_SIZE 32
#define REAL_SERIAL_NUMBER_SIZE 32
#define SERIAL_NUMBER_SIZE (REAL_SERIAL_NUMBER_SIZE+1)
@ -131,6 +132,16 @@ static std::string get_serial(libusb_device_handle *handle, libusb_device_descri
return serial_str;
}
static bool check_product_usable(libusb_device_handle *handle, libusb_device_descriptor *usb_descriptor) {
uint8_t data[PRODUCT_SIZE + 1];
std::string product_str = "";
if(libusb_get_string_descriptor_ascii(handle, usb_descriptor->iProduct, data, PRODUCT_SIZE-1) >= 0) {
data[PRODUCT_SIZE] = '\0';
product_str = std::string((const char*)data);
}
return product_str != "N3DSCC";
}
static int do_usb_config_device(libusb_device_handle *handle, const usb_device* usb_device_desc) {
libusb_check_and_detach_kernel_driver(handle, usb_device_desc->capture_interface);
int result = libusb_check_and_set_configuration(handle, usb_device_desc->default_config);
@ -160,6 +171,10 @@ static int insert_device(std::vector<CaptureDevice> &devices_list, const usb_dev
libusb_close(handle);
return result;
}
if(!check_product_usable(handle, usb_descriptor)) {
libusb_close(handle);
return LIBUSB_ERROR_NOT_FOUND;
}
std::string serial_str = get_serial(handle, usb_descriptor, curr_serial_extra_id);
if(usb_device_desc->is_3ds)
devices_list.emplace_back(serial_str, "3DS", CAPTURE_CONN_USB, (void*)usb_device_desc, true, capture_get_has_3d(handle, usb_device_desc), true, HEIGHT_3DS, TOP_WIDTH_3DS + BOT_WIDTH_3DS, O3DS_SAMPLES_IN, 90, 0, 0, TOP_WIDTH_3DS, 0, VIDEO_DATA_RGB);
@ -189,6 +204,10 @@ static libusb_device_handle* usb_find_by_serial_number(const usb_device* usb_dev
result = libusb_open(usb_devices[i], &handle);
if(result || (handle == NULL))
continue;
if(!check_product_usable(handle, &usb_descriptor)) {
libusb_close(handle);
continue;
}
std::string device_serial_number = get_serial(handle, &usb_descriptor, curr_serial_extra_id);
if(serial_number == device_serial_number) {
final_handle = handle;

View File

@ -420,10 +420,10 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data) {
CaptureDataSingleBuffer* data_buffer = capture_data->data_buffers.GetReaderBuffer(CAPTURE_READER_AUDIO);
if(data_buffer != NULL) {
loaded_samples = audio.samples.size();
if((data_buffer->read >= get_video_in_size(capture_data, data_buffer->is_3d)) && (loaded_samples < MAX_MAX_AUDIO_LATENCY) && capture_data->status.connected) {
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) {
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, data_buffer->is_3d);
bool conversion_success = convertAudioToOutput(out_buf[audio_buf_counter], n_samples, last_buffer_index, endianness, data_buffer, &capture_data->status);
if(!conversion_success)
audio_data->signal_conversion_error();
audio.samples.emplace(out_buf[audio_buf_counter], n_samples, out_time);
@ -604,11 +604,11 @@ 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)) {
if(data_buffer->read >= get_video_in_size(capture_data, data_buffer->is_3d, data_buffer->buffer_video_data_type)) {
if(capture_data->status.cooldown_curr_in || (!capture_data->status.connected))
blank_out = true;
else {
bool conversion_success = convertVideoToOutput(out_buf, endianness, data_buffer, &capture_data->status, frontend_data.display_data.interleaved_3d, data_buffer->is_3d);
bool conversion_success = convertVideoToOutput(out_buf, endianness, data_buffer, &capture_data->status, frontend_data.display_data.interleaved_3d);
if(!conversion_success)
UpdateOutText(out_text_data, "", "Video conversion failed...", TEXT_KIND_NORMAL);
}

View File

@ -804,10 +804,12 @@ static void usb_is_device_convertVideoToOutput(CaptureReceived *p_in, VideoOutpu
}
}
bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool interleaved_3d, bool is_data_3d) {
bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool interleaved_3d) {
CaptureReceived* p_in = (CaptureReceived*)(((uint8_t*)&data_buffer->capture_buf) + data_buffer->unused_offset);
bool converted = false;
CaptureDevice* chosen_device = &status->device;
bool is_data_3d = data_buffer->is_3d;
InputVideoDataType video_data_type = data_buffer->buffer_video_data_type;
bool is_3d_requested = get_3d_enabled(status);
#ifdef USE_FTD3
if(chosen_device->cc_type == CAPTURE_CONN_FTD3) {
@ -841,8 +843,8 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
if(status->device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE) {
bool is_rgb888 = true;
usb_new_3ds_optimize_convertVideoToOutput(p_in, p_out, is_data_3d, is_big_endian, interleaved_3d, requested_3d, is_rgb888);
bool is_rgb888 = video_data_type == VIDEO_DATA_RGB;
usb_new_3ds_optimize_convertVideoToOutput(p_in, p_out, is_data_3d, is_big_endian, interleaved_3d, is_3d_requested, is_rgb888);
converted = true;
}
#endif
@ -922,9 +924,11 @@ static void copyAudioNewOptimize3DSBE(std::int16_t *p_out, uint64_t &n_samples,
n_samples = ((last_buffer_index + 1 + OPTIMIZE_AUDIO_BUFFER_MAX_SIZE - start) % OPTIMIZE_AUDIO_BUFFER_MAX_SIZE) * 2;
}
bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool is_data_3d) {
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;
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;
#ifdef USE_FTD3
@ -967,7 +971,7 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &la
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
if(status->device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE) {
bool is_rgb888 = true;
bool is_rgb888 = video_data_type == VIDEO_DATA_RGB;
if(is_big_endian)
copyAudioNewOptimize3DSBE(p_out, n_samples, last_buffer_index, &data_buffer->capture_buf, is_rgb888, is_data_3d);
else

View File

@ -4,6 +4,7 @@
#include "usb_ds_3ds_capture.hpp"
#include "usb_is_device_acquisition.hpp"
#include "cypress_nisetro_acquisition.hpp"
#include "cypress_optimize_new_3ds_acquisition.hpp"
#include <vector>
#include <thread>
@ -87,6 +88,9 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
#ifdef USE_CYNI_USB
list_devices_cyni_device(devices_list, no_access_list);
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
list_devices_cyopn_device(devices_list, no_access_list);
#endif
#ifdef USE_FTD3
list_devices_ftd3(devices_list, no_access_list);
#endif
@ -128,6 +132,10 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_CYPRESS_NISETRO) && (!cyni_device_connect_usb(print_failed, capture_data, &devices_list[chosen_device])))
return false;
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE) && (!cyopn_device_connect_usb(print_failed, capture_data, &devices_list[chosen_device])))
return false;
#endif
#ifdef USE_FTD3
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_FTD3) && (!connect_ftd3(print_failed, capture_data, &devices_list[chosen_device])))
return false;
@ -168,6 +176,10 @@ void captureCall(CaptureData* capture_data) {
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NISETRO)
cyni_device_acquisition_main_loop(capture_data);
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE)
cyopn_device_acquisition_main_loop(capture_data);
#endif
#ifdef USE_FTD3
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD3)
ftd3_capture_main_loop(capture_data);
@ -198,6 +210,10 @@ void captureCall(CaptureData* capture_data) {
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NISETRO)
usb_cyni_device_acquisition_cleanup(capture_data);
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE)
usb_cyopn_device_acquisition_cleanup(capture_data);
#endif
#ifdef USE_FTD3
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD3)
ftd3_capture_cleanup(capture_data);
@ -229,7 +245,7 @@ uint64_t get_audio_n_samples(CaptureData* capture_data, CaptureDataSingleBuffer*
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE)
return -1;
#endif
uint64_t n_samples = (data_buffer->read - get_video_in_size(capture_data, data_buffer->is_3d)) / 2;
uint64_t n_samples = (data_buffer->read - get_video_in_size(capture_data, data_buffer->is_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
@ -238,11 +254,15 @@ 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) {
uint64_t get_video_in_size(CaptureData* capture_data, bool is_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_NEW_OPTIMIZE
if(capture_data->status.device.cc_type == CAPTURE_CONN_CYPRESS_NEW_OPTIMIZE)
return cyopn_device_get_video_in_size(capture_data, is_3d, video_data_type);
#endif
#ifdef USE_FTD3
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD3)
return ftd3_get_video_in_size(capture_data, is_3d);
@ -344,6 +364,9 @@ void capture_init() {
#ifdef USE_CYNI_USB
usb_cyni_device_init();
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
usb_cyopn_device_init();
#endif
}
void capture_close() {
@ -359,4 +382,7 @@ void capture_close() {
#ifdef USE_CYNI_USB
usb_cyni_device_close();
#endif
#ifdef USE_CYPRESS_NEW_OPTIMIZE
usb_cyopn_device_close();
#endif
}

View File

@ -0,0 +1 @@
SUBSYSTEM=="usb", ATTRS{idVendor}=="0752", ATTRS{idProduct}=="8613", MODE="0666"