mirror of
https://github.com/Lorenzooone/cc3dsfs.git
synced 2025-06-18 08:35:33 -04:00
Attempt using libftdi
This commit is contained in:
parent
e89798b6ec
commit
8da1172b70
525
CMakeLists.txt
525
CMakeLists.txt
@ -1,15 +1,24 @@
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64" CACHE STRING "Build archs for Mac OS X" FORCE)
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
set(TARGET_LANGUAGES CXX C)
|
||||
project(cc3dsfs VERSION 1.0.0 LANGUAGES ${TARGET_LANGUAGES})
|
||||
include(ExternalProject)
|
||||
|
||||
set(N3DSXL_LOOPY_SUPPORT 0)
|
||||
set(N3DSXL_LOOPY_SUPPORT 1)
|
||||
set(NEW_DS_LOOPY_SUPPORT 1)
|
||||
set(IS_NITRO_SUPPORT 1)
|
||||
set(OLD_DS_3DS_LOOPY_SUPPORT 1)
|
||||
|
||||
set(USE_FTD2XX_FOR_NEW_DS_LOOPY ${NEW_DS_LOOPY_SUPPORT})
|
||||
set(USE_LIBFTDI_FOR_NEW_DS_LOOPY ${NEW_DS_LOOPY_SUPPORT})
|
||||
set(USE_LIBUSB_SUPPORT ${IS_NITRO_SUPPORT} OR ${OLD_DS_3DS_LOOPY_SUPPORT} OR ${USE_LIBFTDI_FOR_NEW_DS_LOOPY})
|
||||
if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Windows"))
|
||||
#Performance outside of Windows is very bad for the official drivers...
|
||||
set(USE_FTD2XX_FOR_NEW_DS_LOOPY 0)
|
||||
endif()
|
||||
set(FTDI_EEPROM OFF)
|
||||
set(WINDOWS_ARM64 0)
|
||||
set(WINDOWS_x86_32 0)
|
||||
set(FETCHCONTENT_UPDATES_DISCONNECTED ON)
|
||||
@ -19,14 +28,14 @@ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
set(SFML_USE_STATIC_STD_LIBS TRUE)
|
||||
set(CMAKE_HOST_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE STRING "Host Compiler")
|
||||
if(FORCE_WINDOWS_FTD3XX_SHARED_LIB)
|
||||
set(WINDOWS_FTD3XX_USE_SHARED_LIB 1)
|
||||
set(WINDOWS_FTD3XX_USE_SHARED_LIB 1)
|
||||
else()
|
||||
set(WINDOWS_FTD3XX_USE_SHARED_LIB 0)
|
||||
set(WINDOWS_FTD3XX_USE_SHARED_LIB 0)
|
||||
endif()
|
||||
if(FORCE_WINDOWS_FTD2XX_SHARED_LIB)
|
||||
set(WINDOWS_FTD2XX_USE_SHARED_LIB 1)
|
||||
set(WINDOWS_FTD2XX_USE_SHARED_LIB 1)
|
||||
else()
|
||||
set(WINDOWS_FTD2XX_USE_SHARED_LIB 0)
|
||||
set(WINDOWS_FTD2XX_USE_SHARED_LIB 0)
|
||||
endif()
|
||||
set(FETCHCONTENT_QUIET FALSE)
|
||||
set(EXTRA_CXX_FLAGS "")
|
||||
@ -52,27 +61,34 @@ if (RASPBERRY_PI_COMPILATION)
|
||||
endif()
|
||||
|
||||
if((${CMAKE_SYSTEM_NAME} STREQUAL "Windows") AND ((${CMAKE_GENERATOR_PLATFORM} MATCHES "ARM64") OR (("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "") AND (${CMAKE_SYSTEM_PROCESSOR} MATCHES "ARM64"))))
|
||||
set(WINDOWS_ARM64 1)
|
||||
set(WINDOWS_ARM64 1)
|
||||
endif()
|
||||
|
||||
if((${CMAKE_SYSTEM_NAME} STREQUAL "Windows") AND ((${CMAKE_GENERATOR_PLATFORM} MATCHES "Win32") OR (("${CMAKE_GENERATOR_PLATFORM}" STREQUAL "") AND ((${CMAKE_SYSTEM_PROCESSOR} MATCHES "Win32") OR (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86") OR (${CMAKE_SYSTEM_PROCESSOR} MATCHES "X86")))))
|
||||
set(WINDOWS_x86_32 1)
|
||||
set(WINDOWS_x86_32 1)
|
||||
endif()
|
||||
|
||||
# Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24:
|
||||
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(SFML
|
||||
GIT_REPOSITORY https://github.com/SFML/SFML.git
|
||||
GIT_TAG master)
|
||||
GIT_REPOSITORY https://github.com/SFML/SFML.git
|
||||
GIT_TAG master)
|
||||
|
||||
if(IS_NITRO_SUPPORT OR OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
FetchContent_Declare(libusb1
|
||||
if(USE_LIBUSB_SUPPORT)
|
||||
FetchContent_Declare(LibUSB
|
||||
GIT_REPOSITORY https://github.com/libusb/libusb-cmake.git
|
||||
GIT_TAG main)
|
||||
GIT_TAG main
|
||||
OVERRIDE_FIND_PACKAGE)
|
||||
endif()
|
||||
|
||||
if(USE_LIBFTDI_FOR_NEW_DS_LOOPY)
|
||||
FetchContent_Declare(libftdi1
|
||||
GIT_REPOSITORY git://developer.intra2net.com/libftdi
|
||||
)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_HOST_SYSTEM_NAME} STREQUAL "Windows")
|
||||
@ -104,32 +120,32 @@ if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
set(FTD3XX_LIB FTD3XX.lib)
|
||||
set(FTD3XX_DLL FTD3XX.dll)
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD3XX_LIB FTD3XXWU.lib)
|
||||
set(FTD3XX_LIB FTD3XXWU.lib)
|
||||
set(FTD3XX_DLL FTD3XXWU.dll)
|
||||
set(FTD3XX_URL_TIME 2024/06)
|
||||
set(FTD3XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/windows_setup_ftd3xx_winusb)
|
||||
set(FTD3XX_ARCHIVE FTD3XX_WinUSB_Package.zip)
|
||||
set(FTD3XX_PATH_WINDOWS_ARCH ARM64)
|
||||
set(FTD3XX_URL_TIME 2024/06)
|
||||
set(FTD3XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/windows_setup_ftd3xx_winusb)
|
||||
set(FTD3XX_ARCHIVE FTD3XX_WinUSB_Package.zip)
|
||||
set(FTD3XX_PATH_WINDOWS_ARCH ARM64)
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD3XX_PATH_WINDOWS_ARCH Win32)
|
||||
set(FTD3XX_PATH_WINDOWS_ARCH Win32)
|
||||
else ()
|
||||
set(FTD3XX_PATH_WINDOWS_ARCH x64)
|
||||
set(FTD3XX_PATH_WINDOWS_ARCH x64)
|
||||
endif()
|
||||
if(${WINDOWS_FTD3XX_USE_SHARED_LIB})
|
||||
set(FTD3XX_BUILD_COMMAND ${FTD3XX_BUILD_COMMAND}_dll)
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER DLL)
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER Dynamic)
|
||||
endif()
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER DLL)
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER Dynamic)
|
||||
endif()
|
||||
else()
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER Static_Lib)
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER Static)
|
||||
endif()
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER Static_Lib)
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD3XX_WINDOWS_PATH_SPECIFIER Static)
|
||||
endif()
|
||||
endif()
|
||||
set(FTD3XX_PRE_WINDOWS_PATH ${FTD3XX_PATH_WINDOWS_ARCH}/${FTD3XX_WINDOWS_PATH_SPECIFIER})
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD3XX_PRE_WINDOWS_PATH ${FTD3XX_WINDOWS_PATH_SPECIFIER}/${FTD3XX_PATH_WINDOWS_ARCH})
|
||||
set(FTD3XX_PRE_WINDOWS_PATH ${FTD3XX_WINDOWS_PATH_SPECIFIER}/${FTD3XX_PATH_WINDOWS_ARCH})
|
||||
endif()
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
set(FTD3XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/macos_setup_ftd3xx)
|
||||
@ -145,17 +161,17 @@ else()
|
||||
set(FTD3XX_URL_TIME 2023/03)
|
||||
set(FTD3XX_VER 1.0.5)
|
||||
if((${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch") OR (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm"))
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD3XX_VOL libftd3xx-linux-arm-v8-${FTD3XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD3XX_VOL libftd3xx-linux-arm-v7_32-${FTD3XX_VER})
|
||||
endif()
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD3XX_VOL libftd3xx-linux-arm-v8-${FTD3XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD3XX_VOL libftd3xx-linux-arm-v7_32-${FTD3XX_VER})
|
||||
endif()
|
||||
else()
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD3XX_VOL libftd3xx-linux-x86_64-${FTD3XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD3XX_VOL libftd3xx-linux-x86_32-${FTD3XX_VER})
|
||||
endif()
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD3XX_VOL libftd3xx-linux-x86_64-${FTD3XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD3XX_VOL libftd3xx-linux-x86_32-${FTD3XX_VER})
|
||||
endif()
|
||||
endif()
|
||||
set(FTD3XX_ARCHIVE ${FTD3XX_VOL}.tgz)
|
||||
set(FTD3XX_LIB libftd3xx-static.a)
|
||||
@ -164,80 +180,80 @@ endif()
|
||||
|
||||
set(FTD2XX_BASE_URL https://ftdichip.com/wp-content/uploads/)
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
set(FTD2XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/windows_setup_ftd2xx)
|
||||
set(FTD2XX_URL_TIME 2023/09)
|
||||
set(FTD2XX_VER 2.12.36.4-WHQL-Certified)
|
||||
set(FTD2XX_VOL CDM-v${FTD2XX_VER})
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.zip)
|
||||
set(FTD2XX_SUBFOLDER win)
|
||||
set(FTD2XX_HEADER_PATH ftd2xx.h)
|
||||
if(${WINDOWS_FTD2XX_USE_SHARED_LIB})
|
||||
set(FTD2XX_BUILD_COMMAND ${FTD2XX_BUILD_COMMAND}_dll)
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER "")
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER Release)
|
||||
set(FTD2XX_LIB FTD2XX.lib)
|
||||
set(FTD2XX_DLL FTD2XX.dll)
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_LIB ftd2xx.lib)
|
||||
set(FTD2XX_DLL ftd2xx.dll)
|
||||
else()
|
||||
set(FTD2XX_LIB ftd2xx.lib)
|
||||
set(FTD2XX_DLL ftd2xx64.lib)
|
||||
endif()
|
||||
else()
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER Static)
|
||||
set(FTD2XX_LIB ftd2xx.lib)
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER Release)
|
||||
set(FTD2XX_LIB FTD2XXstatic.lib)
|
||||
endif()
|
||||
endif()
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_URL_TIME 2022/02)
|
||||
set(FTD2XX_VER 2.12.36.4-for-ARM64-Signed-Distributable)
|
||||
set(FTD2XX_VOL CDM-v${FTD2XX_VER})
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.zip)
|
||||
set(FTD2XX_PATH_WINDOWS_ARCH ARM64)
|
||||
set(FTD2XX_HEADER_PATH x86/FTD2XX.H)
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_PATH_WINDOWS_ARCH i386)
|
||||
else ()
|
||||
set(FTD2XX_PATH_WINDOWS_ARCH amd64)
|
||||
endif()
|
||||
set(FTD2XX_PRE_WINDOWS_PATH ${FTD2XX_WINDOWS_PATH_SPECIFIER}/${FTD2XX_PATH_WINDOWS_ARCH})
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_PRE_WINDOWS_PATH ${FTD2XX_PATH_WINDOWS_ARCH}/${FTD2XX_WINDOWS_PATH_SPECIFIER})
|
||||
endif()
|
||||
set(FTD2XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/windows_setup_ftd2xx)
|
||||
set(FTD2XX_URL_TIME 2023/09)
|
||||
set(FTD2XX_VER 2.12.36.4-WHQL-Certified)
|
||||
set(FTD2XX_VOL CDM-v${FTD2XX_VER})
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.zip)
|
||||
set(FTD2XX_SUBFOLDER win)
|
||||
set(FTD2XX_HEADER_PATH ftd2xx.h)
|
||||
if(${WINDOWS_FTD2XX_USE_SHARED_LIB})
|
||||
set(FTD2XX_BUILD_COMMAND ${FTD2XX_BUILD_COMMAND}_dll)
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER "")
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER Release)
|
||||
set(FTD2XX_LIB FTD2XX.lib)
|
||||
set(FTD2XX_DLL FTD2XX.dll)
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_LIB ftd2xx.lib)
|
||||
set(FTD2XX_DLL ftd2xx.dll)
|
||||
else()
|
||||
set(FTD2XX_LIB ftd2xx.lib)
|
||||
set(FTD2XX_DLL ftd2xx64.lib)
|
||||
endif()
|
||||
else()
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER Static)
|
||||
set(FTD2XX_LIB ftd2xx.lib)
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_WINDOWS_PATH_SPECIFIER Release)
|
||||
set(FTD2XX_LIB FTD2XXstatic.lib)
|
||||
endif()
|
||||
endif()
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_URL_TIME 2022/02)
|
||||
set(FTD2XX_VER 2.12.36.4-for-ARM64-Signed-Distributable)
|
||||
set(FTD2XX_VOL CDM-v${FTD2XX_VER})
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.zip)
|
||||
set(FTD2XX_PATH_WINDOWS_ARCH ARM64)
|
||||
set(FTD2XX_HEADER_PATH x86/FTD2XX.H)
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_PATH_WINDOWS_ARCH i386)
|
||||
else ()
|
||||
set(FTD2XX_PATH_WINDOWS_ARCH amd64)
|
||||
endif()
|
||||
set(FTD2XX_PRE_WINDOWS_PATH ${FTD2XX_WINDOWS_PATH_SPECIFIER}/${FTD2XX_PATH_WINDOWS_ARCH})
|
||||
if(WINDOWS_ARM64)
|
||||
set(FTD2XX_PRE_WINDOWS_PATH ${FTD2XX_PATH_WINDOWS_ARCH}/${FTD2XX_WINDOWS_PATH_SPECIFIER})
|
||||
endif()
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
set(FTD2XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/macos_setup_ftd2xx)
|
||||
set(FTD2XX_URL_TIME 2024/04)
|
||||
set(FTD2XX_VER 1.4.30)
|
||||
set(FTD2XX_VOL D2XX${FTD2XX_VER})
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.dmg)
|
||||
set(FTD2XX_LIB libftd2xx.a)
|
||||
set(FTD2XX_MOUNTED_FOLDER /Volumes/dmg)
|
||||
set(FTD2XX_SUBFOLDER macos)
|
||||
set(FTD2XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/macos_setup_ftd2xx)
|
||||
set(FTD2XX_URL_TIME 2024/04)
|
||||
set(FTD2XX_VER 1.4.30)
|
||||
set(FTD2XX_VOL D2XX${FTD2XX_VER})
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.dmg)
|
||||
set(FTD2XX_LIB libftd2xx.a)
|
||||
set(FTD2XX_MOUNTED_FOLDER /Volumes/dmg)
|
||||
set(FTD2XX_SUBFOLDER macos)
|
||||
else()
|
||||
set(FTD2XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/linux_setup_ftd3xx)
|
||||
set(FTD2XX_URL_TIME 2022/07)
|
||||
set(FTD2XX_VER 1.4.27)
|
||||
if((${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch") OR (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm"))
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD2XX_VOL libftd2xx-arm-v8-${FTD2XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_VOL libftd2xx-arm-v7-hf-${FTD2XX_VER})
|
||||
endif()
|
||||
else()
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD2XX_VOL libftd2xx-x86_64-${FTD2XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_VOL libftd2xx-x86_32-${FTD2XX_VER})
|
||||
endif()
|
||||
endif()
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.tgz)
|
||||
set(FTD2XX_LIB libftd2xx.a)
|
||||
set(FTD2XX_SUBFOLDER linux)
|
||||
set(FTD2XX_BUILD_COMMAND ${SETUP_SCRIPTS_DIR}/linux_setup_ftd3xx)
|
||||
set(FTD2XX_URL_TIME 2022/07)
|
||||
set(FTD2XX_VER 1.4.27)
|
||||
if((${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch") OR (${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm"))
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD2XX_VOL libftd2xx-arm-v8-${FTD2XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_VOL libftd2xx-arm-v7-hf-${FTD2XX_VER})
|
||||
endif()
|
||||
else()
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(FTD2XX_VOL libftd2xx-x86_64-${FTD2XX_VER})
|
||||
elseif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(FTD2XX_VOL libftd2xx-x86_32-${FTD2XX_VER})
|
||||
endif()
|
||||
endif()
|
||||
set(FTD2XX_ARCHIVE ${FTD2XX_VOL}.tgz)
|
||||
set(FTD2XX_LIB libftd2xx.a)
|
||||
set(FTD2XX_SUBFOLDER linux)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
@ -247,7 +263,7 @@ if(N3DSXL_LOOPY_SUPPORT)
|
||||
DOWNLOAD_NO_EXTRACT TRUE
|
||||
)
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
|
||||
FetchContent_Declare(FTD2XX
|
||||
URL ${FTD2XX_BASE_URL}${FTD2XX_URL_TIME}/${FTD2XX_ARCHIVE}
|
||||
DOWNLOAD_NO_EXTRACT TRUE
|
||||
@ -259,7 +275,7 @@ if(N3DSXL_LOOPY_SUPPORT)
|
||||
URL ${FTD3XX_BASE_URL}${FTD3XX_URL_TIME}/${FTD3XX_ARCHIVE}
|
||||
)
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
|
||||
FetchContent_Declare(FTD2XX
|
||||
URL ${FTD2XX_BASE_URL}${FTD2XX_URL_TIME}/${FTD2XX_ARCHIVE}
|
||||
)
|
||||
@ -270,10 +286,12 @@ set(TOOLS_DATA_DIR ${CMAKE_BINARY_DIR}/tools_and_data)
|
||||
file(MAKE_DIRECTORY ${TOOLS_DATA_DIR})
|
||||
|
||||
set(FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES "")
|
||||
set(FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES_SEPARATE "")
|
||||
set(SOURCE_CPP_EXTRA_FILES "")
|
||||
set(EXTRA_DEPENDENCIES "")
|
||||
set(SOURCE_CPP_DEVICE_FILES_BASE_PATH "source/CaptureDeviceSpecific")
|
||||
set(SOURCE_CPP_IS_NITRO_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/ISNitro")
|
||||
set(SOURCE_CPP_FTD2_FILES_BASE_PATH "${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/DSCapture_FTD2")
|
||||
if(N3DSXL_LOOPY_SUPPORT)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES FTD3XX)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/3dscapture_ftd3.cpp)
|
||||
@ -284,54 +302,88 @@ if(N3DSXL_LOOPY_SUPPORT)
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_FTD3")
|
||||
endif()
|
||||
endif()
|
||||
if(USE_LIBUSB_SUPPORT)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES LibUSB)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/usb_generic.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_LIBUSB")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_LIBUSB")
|
||||
endif()
|
||||
endif()
|
||||
if(IS_NITRO_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_communications.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition_capture.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition_emulator.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_is_driver.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_libusb.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_IS_NITRO_USB")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_IS_NITRO_USB")
|
||||
endif()
|
||||
endif()
|
||||
if(OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/usb_ds_3ds_capture.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_DS_3DS_USB")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_DS_3DS_USB")
|
||||
endif()
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES FTD2XX)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/dscapture_ftd2.cpp ${TOOLS_DATA_DIR}/ftd2_ds2_fw_1.cpp ${TOOLS_DATA_DIR}/ftd2_ds2_fw_2.cpp)
|
||||
list(APPEND EXTRA_DEPENDENCIES FTD2XX_BUILD_PROJECT)
|
||||
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)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_FTD2")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_FTD2")
|
||||
endif()
|
||||
endif()
|
||||
if(IS_NITRO_SUPPORT OR OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES libusb1)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/usb_generic.cpp)
|
||||
if(IS_NITRO_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_communications.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition_capture.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_acquisition_emulator.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_is_driver.cpp ${SOURCE_CPP_IS_NITRO_FILES_BASE_PATH}/usb_is_nitro_libusb.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_IS_NITRO_USB")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_IS_NITRO_USB")
|
||||
endif()
|
||||
if(USE_LIBFTDI_FOR_NEW_DS_LOOPY)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES_SEPARATE libftdi1)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_FTD2_FILES_BASE_PATH}/dscapture_libftdi2.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_FTD2_LIBFTDI")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_FTD2_LIBFTDI")
|
||||
endif()
|
||||
if(OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_DEVICE_FILES_BASE_PATH}/usb_ds_3ds_capture.cpp)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_DS_3DS_USB")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_DS_3DS_USB")
|
||||
endif()
|
||||
endif()
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
|
||||
list(APPEND FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES FTD2XX)
|
||||
list(APPEND SOURCE_CPP_EXTRA_FILES ${SOURCE_CPP_FTD2_FILES_BASE_PATH}/dscapture_ftd2_driver.cpp)
|
||||
list(APPEND EXTRA_DEPENDENCIES FTD2XX_BUILD_PROJECT)
|
||||
if(MSVC)
|
||||
list(APPEND EXTRA_CXX_FLAGS "/DUSE_FTD2_DRIVER")
|
||||
else()
|
||||
list(APPEND EXTRA_CXX_FLAGS "-DUSE_FTD2_DRIVER")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
FetchContent_MakeAvailable(SFML ${FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES})
|
||||
# Find libusb
|
||||
set(LIBUSB_INCLUDE_DIR ${libusb_SOURCE_DIR}/libusb/libusb)
|
||||
FetchContent_MakeAvailable(${FETCH_CONTENT_MAKE_AVAILABLE_LIBRARIES_SEPARATE})
|
||||
|
||||
set(EXTRA_INCLUDE_DIRECTORIES "")
|
||||
if(N3DSXL_LOOPY_SUPPORT)
|
||||
list(APPEND EXTRA_INCLUDE_DIRECTORIES ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER})
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
|
||||
list(APPEND EXTRA_INCLUDE_DIRECTORIES ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER})
|
||||
endif()
|
||||
if(USE_LIBUSB_SUPPORT)
|
||||
list(APPEND EXTRA_INCLUDE_DIRECTORIES ${libusb_SOURCE_DIR}/libusb/libusb)
|
||||
endif()
|
||||
|
||||
if(IS_DIRECTORY "${sfml_SOURCE_DIR}")
|
||||
set_property(DIRECTORY ${sfml_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL YES)
|
||||
set_property(DIRECTORY ${sfml_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL YES)
|
||||
endif()
|
||||
|
||||
if(IS_NITRO_SUPPORT OR OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
if(IS_DIRECTORY "${libusb1_SOURCE_DIR}")
|
||||
set_property(DIRECTORY ${libusb1_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL YES)
|
||||
if(USE_LIBUSB_SUPPORT)
|
||||
if(IS_DIRECTORY "${libusb_SOURCE_DIR}")
|
||||
set_property(DIRECTORY ${libusb_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL YES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_LIBFTDI_FOR_NEW_DS_LOOPY)
|
||||
if(IS_DIRECTORY "${libftdi1_SOURCE_DIR}")
|
||||
set_property(DIRECTORY ${libftdi1_SOURCE_DIR} PROPERTY EXCLUDE_FROM_ALL YES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@ -341,27 +393,27 @@ if(N3DSXL_LOOPY_SUPPORT)
|
||||
file(MAKE_DIRECTORY ${ftd3xx_BINARY_DIR}/linux)
|
||||
endif()
|
||||
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
|
||||
file(MAKE_DIRECTORY ${ftd2xx_BINARY_DIR}/win)
|
||||
file(MAKE_DIRECTORY ${ftd2xx_BINARY_DIR}/macos)
|
||||
file(MAKE_DIRECTORY ${ftd2xx_BINARY_DIR}/linux)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
set(FTD3XX_BUILD_COMMAND_PARAMETERS ${ftd3xx_SOURCE_DIR}/${FTD3XX_ARCHIVE} ${FTD3XX_MOUNTED_FOLDER} ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER} ${FTD3XX_LIB})
|
||||
set(FTD2XX_BUILD_COMMAND_PARAMETERS ${ftd2xx_SOURCE_DIR}/${FTD2XX_ARCHIVE} ${FTD2XX_MOUNTED_FOLDER} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER} ${FTD2XX_LIB})
|
||||
set(FTD3XX_BUILD_COMMAND_PARAMETERS ${ftd3xx_SOURCE_DIR}/${FTD3XX_ARCHIVE} ${FTD3XX_MOUNTED_FOLDER} ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER} ${FTD3XX_LIB})
|
||||
set(FTD2XX_BUILD_COMMAND_PARAMETERS ${ftd2xx_SOURCE_DIR}/${FTD2XX_ARCHIVE} ${FTD2XX_MOUNTED_FOLDER} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER} ${FTD2XX_LIB})
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
set(FTD3XX_BUILD_COMMAND_PARAMETERS ${ftd3xx_SOURCE_DIR} ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER} ${FTD3XX_PRE_WINDOWS_PATH}/${FTD3XX_LIB})
|
||||
set(FTD3XX_BUILD_COMMAND_PARAMETERS ${ftd3xx_SOURCE_DIR} ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER} ${FTD3XX_PRE_WINDOWS_PATH}/${FTD3XX_LIB})
|
||||
if(WINDOWS_FTD3XX_USE_SHARED_LIB)
|
||||
set(FTD3XX_BUILD_COMMAND_PARAMETERS ${FTD3XX_BUILD_COMMAND_PARAMETERS} ${FTD3XX_PRE_WINDOWS_PATH}/${FTD3XX_DLL})
|
||||
endif()
|
||||
set(FTD2XX_BUILD_COMMAND_PARAMETERS ${ftd2xx_SOURCE_DIR} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER} ${FTD2XX_PRE_WINDOWS_PATH}/${FTD2XX_LIB} ${FTD2XX_HEADER_PATH})
|
||||
set(FTD2XX_BUILD_COMMAND_PARAMETERS ${ftd2xx_SOURCE_DIR} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER} ${FTD2XX_PRE_WINDOWS_PATH}/${FTD2XX_LIB} ${FTD2XX_HEADER_PATH})
|
||||
if(WINDOWS_FTD2XX_USE_SHARED_LIB)
|
||||
set(FTD2XX_BUILD_COMMAND_PARAMETERS ${FTD2XX_BUILD_COMMAND_PARAMETERS} ${FTD2XX_PRE_WINDOWS_PATH}/${FTD2XX_DLL})
|
||||
endif()
|
||||
else()
|
||||
set(FTD3XX_BUILD_COMMAND_PARAMETERS ${ftd3xx_SOURCE_DIR} ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER} ${FTD3XX_LIB})
|
||||
set(FTD2XX_BUILD_COMMAND_PARAMETERS ${ftd2xx_SOURCE_DIR} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER} build/${FTD2XX_LIB})
|
||||
set(FTD3XX_BUILD_COMMAND_PARAMETERS ${ftd3xx_SOURCE_DIR} ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER} ${FTD3XX_LIB})
|
||||
set(FTD2XX_BUILD_COMMAND_PARAMETERS ${ftd2xx_SOURCE_DIR} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER} build/${FTD2XX_LIB})
|
||||
endif()
|
||||
|
||||
if(N3DSXL_LOOPY_SUPPORT)
|
||||
@ -369,20 +421,41 @@ if(N3DSXL_LOOPY_SUPPORT)
|
||||
SOURCE_DIR ${ftd3xx_SOURCE_DIR}
|
||||
BINARY_DIR ${ftd3xx_BINARY_DIR}
|
||||
BUILD_COMMAND ${FTD3XX_BUILD_COMMAND}${SCRIPT_EXTENSION} ${FTD3XX_BUILD_COMMAND_PARAMETERS}
|
||||
#COMMAND ${TOOLS_DATA_DIR}/CMakePrepareRenameSymbols${HOST_FINAL_EXTENSION} ${SETUP_SCRIPTS_DIR}/ftd_shared_symbols.txt ftd3_ ${TOOLS_DATA_DIR}/bad_ftd3_symbols_list.txt ${TOOLS_DATA_DIR}/ftd3xx_symbols_renames.h
|
||||
#COMMAND ${CMAKE_OBJCOPY} ARGS --redefine-syms=${TOOLS_DATA_DIR}/bad_ftd3_symbols_list.txt ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER}/${FTD3XX_LIB}
|
||||
UPDATE_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
)
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
set(BASE_REPLACEMENT_FTD2XX_SYMBOL F2)
|
||||
set(BASE_REPLACEMENT_FTD2XX_SYMBOLS_LIST ${SETUP_SCRIPTS_DIR}/ftd_shared_symbols.txt)
|
||||
set(REPLACEMENT_FTD2XX_SYMBOL ${BASE_REPLACEMENT_FTD2XX_SYMBOL})
|
||||
set(REPLACEMENT_FTD2XX_SYMBOLS_LIST ${BASE_REPLACEMENT_FTD2XX_SYMBOLS_LIST})
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
set(REPLACEMENT_FTD2XX_SYMBOL _F2)
|
||||
set(REPLACEMENT_FTD2XX_SYMBOLS_LIST ${SETUP_SCRIPTS_DIR}/ftd_shared_symbols_macos.txt)
|
||||
endif()
|
||||
if((${CMAKE_SYSTEM_NAME} STREQUAL "Windows") AND ("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4"))
|
||||
set(REPLACEMENT_FTD2XX_SYMBOL _F2)
|
||||
set(REPLACEMENT_FTD2XX_SYMBOLS_LIST ${SETUP_SCRIPTS_DIR}/ftd_shared_symbols_macos.txt)
|
||||
endif()
|
||||
set(REPLACEMENT_FTD2XX_SYMBOL_EXTRA ${REPLACEMENT_FTD2XX_SYMBOL})
|
||||
set(REPLACEMENT_FTD2XX_SYMBOLS_LIST_EXTRA ${REPLACEMENT_FTD2XX_SYMBOLS_LIST})
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
set(REPLACEMENT_FTD2XX_SYMBOL_EXTRA ?F2)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||
set(REPLACEMENT_FTD2XX_SYMBOLS_LIST_EXTRA ${SETUP_SCRIPTS_DIR}/ftd_shared_symbols_special_windows32.txt)
|
||||
else()
|
||||
set(REPLACEMENT_FTD2XX_SYMBOLS_LIST_EXTRA ${SETUP_SCRIPTS_DIR}/ftd_shared_symbols_special_windows.txt)
|
||||
endif()
|
||||
endif()
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY)
|
||||
ExternalProject_Add(FTD2XX_BUILD_PROJECT
|
||||
SOURCE_DIR ${ftd2xx_SOURCE_DIR}
|
||||
BINARY_DIR ${ftd2xx_BINARY_DIR}
|
||||
BUILD_COMMAND ${FTD2XX_BUILD_COMMAND}${SCRIPT_EXTENSION} ${FTD2XX_BUILD_COMMAND_PARAMETERS}
|
||||
#COMMAND ${TOOLS_DATA_DIR}/CMakePrepareRenameSymbols${HOST_FINAL_EXTENSION} ${SETUP_SCRIPTS_DIR}/ftd_shared_symbols.txt ftd2_ ${TOOLS_DATA_DIR}/bad_ftd2_symbols_list.txt ${TOOLS_DATA_DIR}/ftd2xx_symbols_renames.h
|
||||
#COMMAND ${CMAKE_OBJCOPY} ARGS --redefine-syms=${TOOLS_DATA_DIR}/bad_ftd2_symbols_list.txt ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER}/${FTD2XX_LIB}
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeRenameLibFunctions${HOST_FINAL_EXTENSION} ${REPLACEMENT_FTD2XX_SYMBOLS_LIST} ${REPLACEMENT_FTD2XX_SYMBOL} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER}/${FTD2XX_LIB}
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeRenameLibFunctions${HOST_FINAL_EXTENSION} ${REPLACEMENT_FTD2XX_SYMBOLS_LIST_EXTRA} ${REPLACEMENT_FTD2XX_SYMBOL_EXTRA} ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER}/${FTD2XX_LIB}
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeRenameSymbols${HOST_FINAL_EXTENSION} ${BASE_REPLACEMENT_FTD2XX_SYMBOLS_LIST} ${BASE_REPLACEMENT_FTD2XX_SYMBOL} ${TOOLS_DATA_DIR}/ftd2xx_symbols_renames.h
|
||||
UPDATE_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
@ -412,38 +485,41 @@ if(NOT ("${EXTRA_DEPENDENCIES}" STREQUAL ""))
|
||||
add_dependencies(${OUTPUT_NAME} ${EXTRA_DEPENDENCIES})
|
||||
endif()
|
||||
target_link_libraries(${OUTPUT_NAME} PRIVATE SFML::Graphics SFML::Audio SFML::Window SFML::System ${EXTRA_LIBRARIES})
|
||||
if(IS_NITRO_SUPPORT OR OLD_DS_3DS_LOOPY_SUPPORT)
|
||||
if(USE_LIBUSB_SUPPORT)
|
||||
target_link_libraries(${OUTPUT_NAME} PRIVATE usb-1.0)
|
||||
endif()
|
||||
if(N3DSXL_LOOPY_SUPPORT)
|
||||
target_link_libraries(${OUTPUT_NAME} PRIVATE ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER}/${FTD3XX_LIB})
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT)
|
||||
if(USE_LIBFTDI_FOR_NEW_DS_LOOPY)
|
||||
target_link_libraries(${OUTPUT_NAME} PRIVATE ftdi1-static)
|
||||
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/ISNitro)
|
||||
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/ISNitro ${CMAKE_SOURCE_DIR}/include/CaptureDeviceSpecific/DSCapture_FTD2 ${libftdi1_SOURCE_DIR}/src)
|
||||
target_compile_features(${OUTPUT_NAME} PRIVATE cxx_std_20)
|
||||
target_compile_options(${OUTPUT_NAME} PRIVATE ${EXTRA_CXX_FLAGS})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${TOOLS_DATA_DIR}/font_ttf.cpp
|
||||
COMMENT "Convert font to binary"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/data/font.ttf ${TOOLS_DATA_DIR} font_ttf font_ttf
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/data/font.ttf ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
OUTPUT ${TOOLS_DATA_DIR}/font_ttf.cpp
|
||||
COMMENT "Convert font to binary"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/data/font.ttf ${TOOLS_DATA_DIR} font_ttf font_ttf
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/data/font.ttf ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${TOOLS_DATA_DIR}/ftd2_ds2_fw_1.cpp
|
||||
COMMENT "Convert fw binary to C - FTD2 NDS 1"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_1.bin ${TOOLS_DATA_DIR} ftd2_ds2_fw_1 ftd2_ds2_fw_1
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_1.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
OUTPUT ${TOOLS_DATA_DIR}/ftd2_ds2_fw_1.cpp
|
||||
COMMENT "Convert fw binary to C - FTD2 NDS 1"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_1.bin ${TOOLS_DATA_DIR} ftd2_ds2_fw_1 ftd2_ds2_fw_1
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_1.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${TOOLS_DATA_DIR}/ftd2_ds2_fw_2.cpp
|
||||
COMMENT "Convert fw binary to C - FTD2 NDS 2"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_2.bin ${TOOLS_DATA_DIR} ftd2_ds2_fw_2 ftd2_ds2_fw_2
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_2.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
OUTPUT ${TOOLS_DATA_DIR}/ftd2_ds2_fw_2.cpp
|
||||
COMMENT "Convert fw binary to C - FTD2 NDS 2"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_2.bin ${TOOLS_DATA_DIR} ftd2_ds2_fw_2 ftd2_ds2_fw_2
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/bin/ftd2_ds2_fw_2.bin ${TOOLS_DATA_DIR}/CMakeBin2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
set(SHADERS_LIST "")
|
||||
@ -451,35 +527,35 @@ list(APPEND SHADERS_LIST ${CMAKE_SOURCE_DIR}/shaders/bit_crusher_fragment_shader
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${TOOLS_DATA_DIR}/shaders_list.cpp
|
||||
COMMENT "Prepare shaders list"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeShader2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/shaders ${CMAKE_SOURCE_DIR}/source/shaders_list_template.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/source/shaders_list_template.cpp ${SHADERS_LIST} ${TOOLS_DATA_DIR}/CMakeShader2C${HOST_FINAL_EXTENSION}
|
||||
COMMENT "Prepare shaders list"
|
||||
COMMAND ${TOOLS_DATA_DIR}/CMakeShader2C${HOST_FINAL_EXTENSION} ${CMAKE_SOURCE_DIR}/shaders ${CMAKE_SOURCE_DIR}/source/shaders_list_template.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp
|
||||
DEPENDS ${CMAKE_SOURCE_DIR}/source/shaders_list_template.cpp ${SHADERS_LIST} ${TOOLS_DATA_DIR}/CMakeShader2C${HOST_FINAL_EXTENSION}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
if(N3DSXL_LOOPY_SUPPORT AND WINDOWS_FTD3XX_USE_SHARED_LIB)
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy FTD3XX DLL"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER}/${FTD3XX_DLL} ${CMAKE_SOURCE_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT AND WINDOWS_FTD2XX_USE_SHARED_LIB)
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy FTD2XX DLL"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER}/${FTD2XX_DLL} ${CMAKE_SOURCE_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy FTD3XX DLL"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${ftd3xx_BINARY_DIR}/${FTD3XX_SUBFOLDER}/${FTD3XX_DLL} ${CMAKE_SOURCE_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY AND WINDOWS_FTD2XX_USE_SHARED_LIB)
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy FTD2XX DLL"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${ftd2xx_BINARY_DIR}/${FTD2XX_SUBFOLDER}/${FTD2XX_DLL} ${CMAKE_SOURCE_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy Output"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${OUTPUT_NAME}> ${CMAKE_SOURCE_DIR}
|
||||
VERBATIM
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy Output"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${OUTPUT_NAME}> ${CMAKE_SOURCE_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
@ -491,37 +567,38 @@ install(FILES LICENSE README.md DESTINATION .)
|
||||
install(DIRECTORY "other licenses" DESTINATION .)
|
||||
if(WIN32)
|
||||
if(N3DSXL_LOOPY_SUPPORT AND WINDOWS_FTD3XX_USE_SHARED_LIB)
|
||||
install(FILES ${FTD3XX_DLL} DESTINATION .)
|
||||
install(FILES ${FTD3XX_DLL} DESTINATION .)
|
||||
endif()
|
||||
if(NEW_DS_LOOPY_SUPPORT AND WINDOWS_FTD2XX_USE_SHARED_LIB)
|
||||
install(FILES ${FTD2XX_DLL} DESTINATION .)
|
||||
if(USE_FTD2XX_FOR_NEW_DS_LOOPY AND WINDOWS_FTD2XX_USE_SHARED_LIB)
|
||||
install(FILES ${FTD2XX_DLL} DESTINATION .)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
set(FW_APP ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OUTPUT_NAME}.app)
|
||||
set(FW_DIRS ${sfml_SOURCE_DIR}/extlibs/libs-macos/Frameworks)
|
||||
set_target_properties(${OUTPUT_NAME} PROPERTIES
|
||||
MACOSX_BUNDLE TRUE
|
||||
MACOSX_BUNDLE_BUNDLE_NAME ${OUTPUT_NAME}
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER ${OUTPUT_NAME}
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/data/MacOSXBundleInfo.plist.in)
|
||||
set(CMAKE_MACOSX_RPATH TRUE)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Prepare bundle"
|
||||
POST_BUILD COMMAND ${SETUP_SCRIPTS_DIR}/macos_bundle_setup${SCRIPT_EXTENSION} ${FW_APP}/Contents/MacOS/${OUTPUT_NAME} ${FW_DIRS} ${FW_APP}/Contents/Frameworks
|
||||
VERBATIM
|
||||
)
|
||||
set(FW_APP ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${OUTPUT_NAME}.app)
|
||||
set(FW_DIRS ${sfml_SOURCE_DIR}/extlibs/libs-macos/Frameworks)
|
||||
set_target_properties(${OUTPUT_NAME} PROPERTIES
|
||||
MACOSX_BUNDLE TRUE
|
||||
MACOSX_BUNDLE_BUNDLE_NAME ${OUTPUT_NAME}
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER ${OUTPUT_NAME}
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_SOURCE_DIR}/data/MacOSXBundleInfo.plist.in)
|
||||
set(CMAKE_MACOSX_RPATH TRUE)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Prepare bundle"
|
||||
POST_BUILD COMMAND ${SETUP_SCRIPTS_DIR}/macos_bundle_setup${SCRIPT_EXTENSION} ${FW_APP}/Contents/MacOS/${OUTPUT_NAME} ${FW_DIRS} ${FW_APP}/Contents/Frameworks
|
||||
VERBATIM
|
||||
)
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
else()
|
||||
install(FILES ${USB_RULES_DIR}/51-ftd3xx.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/95-usb3dscapture.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/95-usbdscapture.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/51-isnitro.rules DESTINATION .)
|
||||
install(FILES ${SETUP_SCRIPTS_DIR}/install_usb_rules${SCRIPT_EXTENSION} DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/51-ftd3xx.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/95-usb3dscapture.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/95-usbdscapture.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/51-isnitro.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/50-ftd2xx.rules DESTINATION .)
|
||||
install(FILES ${USB_RULES_DIR}/51-ftd2xx.rules DESTINATION .)
|
||||
install(FILES ${SETUP_SCRIPTS_DIR}/install_usb_rules${SCRIPT_EXTENSION} DESTINATION .)
|
||||
endif()
|
||||
|
||||
|
||||
@ -533,25 +610,25 @@ set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
||||
set(CPACK_VERBATIM_VARIABLES TRUE)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "Darwin")
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_macos)
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_macos)
|
||||
elseif(${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||
if(WINDOWS_ARM64)
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_windows_arm64)
|
||||
elseif(WINDOWS_x86_32)
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_windows_x86_32)
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_windows_x86_64)
|
||||
endif()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_windows_arm64)
|
||||
elseif(WINDOWS_x86_32)
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_windows_x86_32)
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_windows_x86_64)
|
||||
endif()
|
||||
else()
|
||||
if(RASPBERRY_PI_COMPILATION)
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_linux_pi64)
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_linux_pi32)
|
||||
endif()
|
||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_linux_pi64)
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_linux_pi32)
|
||||
endif()
|
||||
else()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_linux_${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
set(CPACK_PACKAGE_FILE_NAME ${CPACK_PACKAGE_NAME}_linux_${CMAKE_SYSTEM_PROCESSOR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(CPack)
|
||||
|
@ -12,6 +12,7 @@ IS Nitro Emulator (newer revisions) and IS Nitro Capture support is also present
|
||||
- Make your game run in fullscreen mode. If you own multiple displays, you can even use one per-window.
|
||||
- Many builtin crop options for the screens.
|
||||
- Many other settings, explained in [Controls](#Controls).
|
||||
- Prebuilt executables available in the [Releases](https://github.com/Lorenzooone/cc3dsfs/releases/latest) page for ease of use.
|
||||
|
||||
_Note: On 3DS, DS, GBA, GBC and GB games boot in scaled resolution mode by default. Holding START or SELECT while launching these games will boot in native resolution mode._
|
||||
|
||||
@ -23,10 +24,10 @@ cc3dsfs has three build dependencies: CMake, g++ and git.
|
||||
Make sure all are installed.
|
||||
On MacOS, [Homebrew](https://brew.sh/) can be used to install both CMake and git. An automatic popup should appear to install g++ at Compile time.
|
||||
|
||||
cc3dsfs has four library dependencies: [FTDI's D3XX driver](https://ftdichip.com/drivers/d3xx-drivers/), [FTDI's D2XX driver](https://ftdichip.com/drivers/d2xx-drivers/), [libusb](https://libusb.info/) and [SFML](https://www.sfml-dev.org/).
|
||||
cc3dsfs has five library dependencies: [FTDI's D3XX driver](https://ftdichip.com/drivers/d3xx-drivers/), [FTDI's D2XX driver](https://ftdichip.com/drivers/d2xx-drivers/) (on Windows), [libusb](https://libusb.info/), [libftdi](https://www.intra2net.com/en/developer/libftdi/) and [SFML](https://www.sfml-dev.org/).
|
||||
All of them should get downloaded automatically via CMake during the building process.
|
||||
|
||||
Linux users will also need to install the SFML dependencies. Different distributions will require slightly different processes.
|
||||
Linux users who wish to compile this, will also need to install the SFML dependencies. Different distributions will require slightly different processes.
|
||||
Below, the command for Debian-based distributions, which also lists the required libraries.
|
||||
|
||||
```
|
||||
@ -135,7 +136,7 @@ On Linux and MacOS, the profiles can be found at the "${HOME}/.config/cc3dsfs" f
|
||||
On Windows, the profiles can be found in the ".config/cc3dsfs" folder inside the directory in which the program runs from.
|
||||
|
||||
## Notes
|
||||
- On Linux, you may need to include the udev USB access rules. You can use the .rules files available in the repository's usb\_rules directory, or define your own. For ease of use, releases come bundled with a script to do it named install\_usb\_rules.sh. It may require elevated permissions to execute properly.
|
||||
- On Linux, you may need to include the udev USB access rules. You can use the .rules files available in the repository's usb\_rules directory, or define your own. For ease of use, releases come bundled with a script to do it named install\_usb\_rules.sh. It may require elevated permissions to execute properly. You may get a permission error if the rules are not installed.
|
||||
- At startup, the audio may be unstable. It should fix itself, if you give it enough time.
|
||||
- If, at first, the connection to the 3DS/DS fails, reconnect the 3DS/DS and then try again. If that also doesn't work, try restarting the program. If that also doesn't work, try restarting the computer.
|
||||
- USB Hubs can be the cause of connection issues. If you're having problems, try checking whether the 3DS/DS connects fine or not without any other devices connected.
|
||||
|
@ -0,0 +1,28 @@
|
||||
#ifndef __DSCAPTURE_FTD2_COMPATIBILITY_HPP
|
||||
#define __DSCAPTURE_FTD2_COMPATIBILITY_HPP
|
||||
|
||||
#include "devicecapture.hpp"
|
||||
|
||||
void list_devices_ftd2_compatibility(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
void ftd2_capture_main_loop(CaptureData* capture_data);
|
||||
int ftd2_get_queue_status(void* handle, bool is_libftdi, size_t* bytes_in);
|
||||
bool ftd2_is_error(int value, bool is_libftdi);
|
||||
int ftd2_write(void* handle, bool is_libftdi, const uint8_t* data, size_t size, size_t *sent);
|
||||
int ftd2_read(void* handle, bool is_libftdi, uint8_t* data, size_t size, size_t *bytesIn);
|
||||
int ftd2_set_timeouts(void* handle, bool is_libftdi, int timeout_read, int timeout_write);
|
||||
int ftd2_reset_device(void* handle, bool is_libftdi);
|
||||
int ftd2_set_usb_parameters(void* handle, bool is_libftdi, size_t size_in, size_t size_out);
|
||||
int ftd2_set_chars(void* handle, bool is_libftdi, unsigned char eventch, unsigned char event_enable, unsigned char errorch, unsigned char error_enable);
|
||||
int ftd2_set_latency_timer(void* handle, bool is_libftdi, unsigned char latency);
|
||||
int ftd2_set_flow_ctrl_rts_cts(void* handle, bool is_libftdi);
|
||||
int ftd2_reset_bitmode(void* handle, bool is_libftdi);
|
||||
int ftd2_set_mpsse_bitmode(void* handle, bool is_libftdi);
|
||||
int ftd2_set_fifo_bitmode(void* handle, bool is_libftdi);
|
||||
int ftd2_purge_all(void* handle, bool is_libftdi);
|
||||
int ftd2_read_ee(void* handle, bool is_libftdi, int eeprom_addr, int *eeprom_val);
|
||||
int ftd2_close(void* handle, bool is_libftdi);
|
||||
int ftd2_open(CaptureDevice* device, void** handle, bool is_libftdi);
|
||||
void ftd2_init();
|
||||
void ftd2_end();
|
||||
|
||||
#endif
|
@ -0,0 +1,17 @@
|
||||
#ifndef __DSCAPTURE_FTD2_DRIVER_HPP
|
||||
#define __DSCAPTURE_FTD2_DRIVER_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "utils.hpp"
|
||||
#include "hw_defs.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
|
||||
#define FTD2_OLDDS_SYNCH_VALUES 0x4321
|
||||
|
||||
void list_devices_ftd2_driver(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
int ftd2_driver_open_serial(CaptureDevice* device, void** handle);
|
||||
void ftd2_capture_main_loop_driver(CaptureData* capture_data);
|
||||
|
||||
#endif
|
@ -0,0 +1,52 @@
|
||||
#ifndef __DSCAPTURE_FTD2_GENERAL_HPP
|
||||
#define __DSCAPTURE_FTD2_GENERAL_HPP
|
||||
|
||||
#include "utils.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
// Sometimes the CC returns a 2 length packet, if you're too fast
|
||||
#define BASE_NUM_CAPTURE_RECEIVED_DATA_BUFFERS 4
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_0_MULTIPLIER 2
|
||||
#define NUM_CAPTURE_RECEIVED_DATA_BUFFERS (BASE_NUM_CAPTURE_RECEIVED_DATA_BUFFERS * NUM_CAPTURE_RECEIVED_DATA_0_MULTIPLIER)
|
||||
|
||||
typedef void (*fdt2_async_callback_function)(void* user_data, int transfer_length, int transfer_status);
|
||||
|
||||
struct ftd2_async_callback_data {
|
||||
FTD2OldDSCaptureReceivedRaw buffer_raw;
|
||||
fdt2_async_callback_function function;
|
||||
void* actual_user_data;
|
||||
void* transfer_data;
|
||||
void* handle;
|
||||
std::mutex transfer_data_access;
|
||||
SharedConsumerMutex* is_transfer_done_mutex;
|
||||
size_t requested_length;
|
||||
int internal_index;
|
||||
};
|
||||
|
||||
struct FTD2CaptureReceivedData {
|
||||
size_t actual_length;
|
||||
volatile bool in_use;
|
||||
volatile bool is_data_ready;
|
||||
SharedConsumerMutex* is_buffer_free_shared_mutex;
|
||||
int* status;
|
||||
uint32_t index;
|
||||
uint32_t* last_used_index;
|
||||
size_t* curr_offset;
|
||||
CaptureData* capture_data;
|
||||
std::chrono::time_point<std::chrono::high_resolution_clock>* clock_start;
|
||||
ftd2_async_callback_data cb_data;
|
||||
};
|
||||
|
||||
int get_num_ftd2_device_types();
|
||||
const std::string get_ftd2_fw_desc(int index);
|
||||
const int get_ftd2_fw_index(int index);
|
||||
uint64_t get_max_samples(bool is_rgb888);
|
||||
uint64_t get_capture_size(bool is_rgb888);
|
||||
size_t remove_synch_from_final_length(uint32_t* out_buffer, size_t real_length);
|
||||
bool enable_capture(void* handle, bool is_libftdi);
|
||||
bool synchronization_check(uint16_t* data_buffer, size_t size, uint16_t* next_data_buffer, size_t* next_size, bool special_check = false);
|
||||
|
||||
#endif
|
@ -0,0 +1,21 @@
|
||||
#ifndef __DSCAPTURE_FTD2_SHARED_HPP
|
||||
#define __DSCAPTURE_FTD2_SHARED_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "utils.hpp"
|
||||
#include "hw_defs.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
|
||||
#define FTD2_OLDDS_SYNCH_VALUES 0x4321
|
||||
|
||||
void list_devices_ftd2_shared(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
bool connect_ftd2_shared(bool print_failed, CaptureData* capture_data, CaptureDevice* device);
|
||||
void ftd2_capture_main_loop_shared(CaptureData* capture_data);
|
||||
void ftd2_capture_cleanup_shared(CaptureData* capture_data);
|
||||
uint64_t ftd2_get_video_in_size(CaptureData* capture_data);
|
||||
void ftd2_init_shared();
|
||||
void ftd2_end_shared();
|
||||
|
||||
#endif
|
@ -0,0 +1,27 @@
|
||||
#ifndef __DSCAPTURE_LIBFTDI2_HPP
|
||||
#define __DSCAPTURE_LIBFTDI2_HPP
|
||||
|
||||
#include "dscapture_ftd2_shared.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
|
||||
void libftdi_init();
|
||||
void libftdi_end();
|
||||
|
||||
void list_devices_libftdi(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
void ftd2_capture_main_loop_libftdi(CaptureData* capture_data);
|
||||
int libftdi_reset(void* handle);
|
||||
int libftdi_set_latency_timer(void* handle, unsigned char latency);
|
||||
int libftdi_setflowctrl(void* handle, int flowctrl, unsigned char xon, unsigned char xoff);
|
||||
int libftdi_set_bitmode(void* handle, unsigned char bitmask, unsigned char mode);
|
||||
int libftdi_purge(void* handle, bool do_read, bool do_write);
|
||||
int libftdi_read_eeprom(void* handle, int eeprom_addr, int *eeprom_val);
|
||||
int libftdi_set_chars(void* handle, unsigned char eventch, unsigned char event_enable, unsigned char errorch, unsigned char error_enable);
|
||||
int libftdi_set_usb_chunksizes(void* handle, unsigned int chunksize_in, unsigned int chunksize_out);
|
||||
void libftdi_set_timeouts(void* handle, int timeout_in_ms, int timeout_out_ms);
|
||||
int libftdi_write(void* handle, const uint8_t* data, size_t size, size_t* bytesOut);
|
||||
int libftdi_read(void* handle, uint8_t* data, size_t size, size_t* bytesIn);
|
||||
int get_libftdi_read_queue_size(void* handle, size_t* bytesIn);
|
||||
int libftdi_open_serial(CaptureDevice* device, void** handle);
|
||||
int libftdi_close(void* handle);
|
||||
|
||||
#endif
|
@ -47,6 +47,7 @@ struct isn_async_callback_data {
|
||||
|
||||
struct is_nitro_usb_device {
|
||||
std::string name;
|
||||
std::string long_name;
|
||||
int vid;
|
||||
int pid;
|
||||
int default_config;
|
||||
|
@ -1,19 +0,0 @@
|
||||
#ifndef __DSCAPTURE_FTD2_HPP
|
||||
#define __DSCAPTURE_FTD2_HPP
|
||||
|
||||
#include <vector>
|
||||
#include "utils.hpp"
|
||||
#include "hw_defs.hpp"
|
||||
#include "capture_structs.hpp"
|
||||
#include "display_structs.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
|
||||
#define FTD2_OLDDS_SYNCH_VALUES 0x4321
|
||||
|
||||
void list_devices_ftd2(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list);
|
||||
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);
|
||||
uint64_t ftd2_get_video_in_size(CaptureData* capture_data);
|
||||
|
||||
#endif
|
@ -13,9 +13,13 @@
|
||||
|
||||
#define FIX_PARTIAL_FIRST_FRAME_NUM 3
|
||||
|
||||
#define EXTRA_DATA_BUFFER_USB_SIZE (1 << 9)
|
||||
#define MAX_PACKET_SIZE_USB2 (1 << 9)
|
||||
#define EXTRA_DATA_BUFFER_USB_SIZE MAX_PACKET_SIZE_USB2
|
||||
#define EXTRA_DATA_BUFFER_FTD3XX_SIZE (1 << 10)
|
||||
|
||||
#define FTD2_INTRA_PACKET_HEADER_SIZE 2
|
||||
#define MAX_PACKET_SIZE_FTD2 (MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE)
|
||||
|
||||
enum CaptureConnectionType { CAPTURE_CONN_FTD3, CAPTURE_CONN_USB, CAPTURE_CONN_FTD2, CAPTURE_CONN_IS_NITRO };
|
||||
enum InputVideoDataType { VIDEO_DATA_RGB, VIDEO_DATA_BGR, VIDEO_DATA_RGB16, VIDEO_DATA_BGR16 };
|
||||
enum CaptureScreensType { CAPTURE_SCREENS_BOTH, CAPTURE_SCREENS_TOP, CAPTURE_SCREENS_BOTTOM, CAPTURE_SCREENS_ENUM_END };
|
||||
@ -100,6 +104,11 @@ struct ALIGNED(16) PACKED FTD2OldDSCaptureReceived {
|
||||
uint8_t unused_buffer[EXTRA_DATA_BUFFER_USB_SIZE];
|
||||
};
|
||||
|
||||
struct ALIGNED(16) PACKED FTD2OldDSCaptureReceivedRaw {
|
||||
FTD2OldDSCaptureReceived data;
|
||||
uint8_t extra_ftd2_buffer[((sizeof(FTD2OldDSCaptureReceived) + MAX_PACKET_SIZE_FTD2 - 1) / MAX_PACKET_SIZE_FTD2) * FTD2_INTRA_PACKET_HEADER_SIZE];
|
||||
};
|
||||
|
||||
struct ALIGNED(16) PACKED ISNitroCaptureReceived {
|
||||
ISNitroEmulatorVideoInputData video_in;
|
||||
};
|
||||
@ -113,17 +122,21 @@ union CaptureReceived {
|
||||
USB3DSCaptureReceived_3D usb_received_3ds_3d;
|
||||
USBOldDSCaptureReceived usb_received_old_ds;
|
||||
FTD2OldDSCaptureReceived ftd2_received_old_ds;
|
||||
FTD2OldDSCaptureReceivedRaw ftd2_received_old_ds_raw;
|
||||
ISNitroCaptureReceived is_nitro_capture_received;
|
||||
};
|
||||
|
||||
struct CaptureDevice {
|
||||
CaptureDevice(std::string serial_number, std::string name, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(""), video_data_type(video_data_type), firmware_id(0), is_rgb_888(false) {}
|
||||
CaptureDevice(std::string serial_number, std::string name, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type, int firmware_id, bool is_rgb_888) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(""), video_data_type(video_data_type), firmware_id(firmware_id), is_rgb_888(is_rgb_888) {}
|
||||
CaptureDevice(std::string serial_number, std::string name, std::string path, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(path), video_data_type(video_data_type), firmware_id(0), is_rgb_888(false) {}
|
||||
CaptureDevice(): serial_number(""), name(""), cc_type(CAPTURE_CONN_USB), descriptor(NULL), is_3ds(false), has_3d(false), has_audio(false), width(0), height(0), max_samples_in(0), base_rotation(0), top_screen_x(0), top_screen_y(0), bot_screen_x(0), bot_screen_y(0), path(""), firmware_id(0), video_data_type(VIDEO_DATA_RGB), is_rgb_888(false) {}
|
||||
CaptureDevice(std::string serial_number, std::string name, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(""), video_data_type(video_data_type), firmware_id(0), is_rgb_888(false), long_name(name) {}
|
||||
CaptureDevice(std::string serial_number, std::string name, std::string long_name, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(""), video_data_type(video_data_type), firmware_id(0), is_rgb_888(false), long_name(long_name) {}
|
||||
CaptureDevice(std::string serial_number, std::string name, std::string long_name, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type, int firmware_id, bool is_rgb_888) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(""), video_data_type(video_data_type), firmware_id(firmware_id), is_rgb_888(is_rgb_888), long_name(name) {}
|
||||
CaptureDevice(std::string serial_number, std::string name, std::string long_name, std::string path, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type, int firmware_id, bool is_rgb_888) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(path), video_data_type(video_data_type), firmware_id(firmware_id), is_rgb_888(is_rgb_888), long_name(long_name) {}
|
||||
CaptureDevice(std::string serial_number, std::string name, std::string long_name, std::string path, CaptureConnectionType cc_type, const void* descriptor, bool is_3ds, bool has_3d, bool has_audio, int width, int height, int max_samples_in, int base_rotation, int top_screen_x, int top_screen_y, int bot_screen_x, int bot_screen_y, InputVideoDataType video_data_type) : serial_number(serial_number), name(name), cc_type(cc_type), descriptor(descriptor), is_3ds(is_3ds), has_3d(has_3d), has_audio(has_audio), width(width), height(height), max_samples_in(max_samples_in), base_rotation(base_rotation), top_screen_x(top_screen_x), top_screen_y(top_screen_y), bot_screen_x(bot_screen_x), bot_screen_y(bot_screen_y), path(path), video_data_type(video_data_type), firmware_id(0), is_rgb_888(false), long_name(long_name) {}
|
||||
CaptureDevice(): serial_number(""), name(""), cc_type(CAPTURE_CONN_USB), descriptor(NULL), is_3ds(false), has_3d(false), has_audio(false), width(0), height(0), max_samples_in(0), base_rotation(0), top_screen_x(0), top_screen_y(0), bot_screen_x(0), bot_screen_y(0), path(""), firmware_id(0), video_data_type(VIDEO_DATA_RGB), is_rgb_888(false), long_name("") {}
|
||||
|
||||
std::string serial_number;
|
||||
std::string name;
|
||||
std::string long_name;
|
||||
std::string path;
|
||||
CaptureConnectionType cc_type;
|
||||
InputVideoDataType video_data_type;
|
||||
@ -166,6 +179,7 @@ struct CaptureDataSingleBuffer {
|
||||
uint64_t read;
|
||||
CaptureReceived capture_buf;
|
||||
double time_in_buf;
|
||||
uint32_t inner_index;
|
||||
};
|
||||
|
||||
class CaptureDataBuffers {
|
||||
@ -174,7 +188,10 @@ public:
|
||||
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 = CAPTURE_SCREENS_BOTH);
|
||||
CaptureDataSingleBuffer* GetWriterBuffer();
|
||||
void ReleaseWriterBuffer();
|
||||
private:
|
||||
uint32_t inner_index = 0;
|
||||
std::mutex access_mutex;
|
||||
int last_curr_in;
|
||||
int curr_writer_pos;
|
||||
@ -182,9 +199,6 @@ private:
|
||||
int num_readers[NUM_CONCURRENT_DATA_BUFFERS];
|
||||
bool has_read_data[NUM_CONCURRENT_DATA_BUFFERS][NUM_CONCURRENT_DATA_BUFFER_READERS];
|
||||
CaptureDataSingleBuffer buffers[NUM_CONCURRENT_DATA_BUFFERS];
|
||||
|
||||
CaptureDataSingleBuffer* GetWriterBuffer();
|
||||
void ReleaseWriterBuffer();
|
||||
};
|
||||
|
||||
struct CaptureData {
|
||||
|
@ -5,5 +5,5 @@
|
||||
#include "display_structs.hpp"
|
||||
|
||||
bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status);
|
||||
bool convertAudioToOutput(std::int16_t *p_out, uint64_t n_samples, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status);
|
||||
bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status);
|
||||
#endif
|
||||
|
@ -23,5 +23,5 @@ void capture_error_print(bool print_failed, CaptureData* capture_data, std::stri
|
||||
void capture_error_print(bool print_failed, CaptureData* capture_data, std::string graphical_string, std::string detailed_string);
|
||||
uint64_t get_audio_n_samples(CaptureData* capture_data, uint64_t read);
|
||||
uint64_t get_video_in_size(CaptureData* capture_data);
|
||||
std::string get_name_of_device(CaptureStatus* capture_status);
|
||||
std::string get_name_of_device(CaptureStatus* capture_status, bool use_long = false);
|
||||
#endif
|
||||
|
26
other licenses/libftdi.txt
Normal file
26
other licenses/libftdi.txt
Normal file
@ -0,0 +1,26 @@
|
||||
The C library "libftdi1" is distributed under the
|
||||
GNU Library General Public License version 2.
|
||||
|
||||
A copy of the GNU Library General Public License (LGPL) is included
|
||||
in this distribution, in the file COPYING.LIB.
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
The C++ wrapper "ftdipp1" is distributed under the GNU General
|
||||
Public License version 2 (with a special exception described below).
|
||||
|
||||
A copy of the GNU General Public License (GPL) is included
|
||||
in this distribution, in the file COPYING.GPL.
|
||||
|
||||
As a special exception, if other files instantiate templates or use macros
|
||||
or inline functions from this file, or you compile this file and link it
|
||||
with other works to produce a work based on this file, this file
|
||||
does not by itself cause the resulting work to be covered
|
||||
by the GNU General Public License.
|
||||
|
||||
However the source code for this file must still be made available
|
||||
in accordance with section (3) of the GNU General Public License.
|
||||
|
||||
This exception does not invalidate any other reasons why a work based
|
||||
on this file might be covered by the GNU General Public License.
|
||||
|
8
setup_scripts/ftd_shared_symbols_macos.txt
Normal file
8
setup_scripts/ftd_shared_symbols_macos.txt
Normal file
@ -0,0 +1,8 @@
|
||||
_FT_ListDevices
|
||||
_FT_GetVIDPID
|
||||
_FT_Close
|
||||
_FT_CreateDeviceInfoList
|
||||
_FT_GetDeviceInfoList
|
||||
_FT_GetDeviceInfoDetail
|
||||
_FT_GetDriverVersion
|
||||
_FT_GetLibraryVersion
|
15
setup_scripts/ftd_shared_symbols_special_windows.txt
Normal file
15
setup_scripts/ftd_shared_symbols_special_windows.txt
Normal file
@ -0,0 +1,15 @@
|
||||
?AddDevice@@YAPEAUft_private_vars@@XZ
|
||||
?CreateDeviceInfoList@@YAKPEAK@Z
|
||||
?FT_GetPacketSize@@YAKPEAXPEAG@Z
|
||||
?FindDevice@@YAPEAUft_private_vars@@K@Z
|
||||
?IsDeviceValid@@YAEPEAUft_private_vars@@@Z
|
||||
?RemoveDevice@@YAKPEAUft_private_vars@@@Z
|
||||
?ResetAttachedList@@YAKXZ
|
||||
?dwNumberOfAttachedDevices@@3KA
|
||||
?ghFtOpenLock@@3PEAXEA
|
||||
?ghFtDevListLock@@3PEAXEA
|
||||
?gCS@@3U_RTL_CRITICAL_SECTION@@A
|
||||
?gInitialised@@3HA
|
||||
?pgDeviceList@@3PEAUft_private_vars@@EA
|
||||
?Set1Ioctls@@3PAKA
|
||||
?Set2Ioctls@@3PAKA
|
15
setup_scripts/ftd_shared_symbols_special_windows32.txt
Normal file
15
setup_scripts/ftd_shared_symbols_special_windows32.txt
Normal file
@ -0,0 +1,15 @@
|
||||
?AddDevice@@YAPAUft_private_vars@@XZ
|
||||
?CreateDeviceInfoList@@YAKPAK@Z
|
||||
?FT_GetPacketSize@@YAKPAXPAG@Z
|
||||
?FindDevice@@YAPAUft_private_vars@@K@Z
|
||||
?IsDeviceValid@@YAEPAUft_private_vars@@@Z
|
||||
?RemoveDevice@@YAKPAUft_private_vars@@@Z
|
||||
?ghFtOpenLock@@3PAXA
|
||||
?ghFtDevListLock@@3PAXA
|
||||
?pgDeviceList@@3PAUft_private_vars@@A
|
||||
?ResetAttachedList@@YAKXZ
|
||||
?dwNumberOfAttachedDevices@@3KA
|
||||
?gCS@@3U_RTL_CRITICAL_SECTION@@A
|
||||
?gInitialised@@3HA
|
||||
?Set1Ioctls@@3PAKA
|
||||
?Set2Ioctls@@3PAKA
|
@ -1,69 +0,0 @@
|
||||
usbi_hotplug_notification
|
||||
usbi_default_context
|
||||
usbi_log
|
||||
usbi_alloc_device
|
||||
usbi_connect_device
|
||||
usbi_disconnect_device
|
||||
usbi_sanitize_device
|
||||
usbi_get_device_by_session_id
|
||||
usbi_signal_event
|
||||
usbi_clear_event
|
||||
active_contexts_lock
|
||||
discovered_devs_append
|
||||
libusb_get_version
|
||||
libusb_error_name
|
||||
libusb_exit
|
||||
libusb_init
|
||||
libusb_set_option
|
||||
libusb_set_debug
|
||||
libusb_set_auto_detach_kernel_driver
|
||||
libusb_attach_kernel_driver
|
||||
libusb_detach_kernel_driver
|
||||
libusb_kernel_driver_active
|
||||
libusb_dev_mem_free
|
||||
libusb_dev_mem_alloc
|
||||
libusb_free_streams
|
||||
libusb_alloc_streams
|
||||
libusb_reset_device
|
||||
libusb_clear_halt
|
||||
libusb_unref_device
|
||||
libusb_ref_device
|
||||
libusb_has_capability
|
||||
libusb_get_device_list
|
||||
libusb_free_device_list
|
||||
libusb_get_bus_number
|
||||
libusb_get_port_number
|
||||
libusb_get_port_numbers
|
||||
libusb_get_port_path
|
||||
libusb_get_parent
|
||||
libusb_get_device_address
|
||||
libusb_get_device_speed
|
||||
libusb_get_max_packet_size
|
||||
libusb_get_max_iso_packet_size
|
||||
libusb_open
|
||||
libusb_open_device_with_vid_pid
|
||||
libusb_close
|
||||
libusb_get_device
|
||||
libusb_get_configuration
|
||||
libusb_set_configuration
|
||||
libusb_claim_interface
|
||||
libusb_release_interface
|
||||
libusb_set_interface_alt_setting
|
||||
libusb_hotplug_register_callback
|
||||
libusb_hotplug_deregister_callback
|
||||
libusb_get_device_descriptor
|
||||
libusb_get_active_config_descriptor
|
||||
libusb_get_config_descriptor
|
||||
libusb_get_config_descriptor_by_value
|
||||
libusb_free_config_descriptor
|
||||
libusb_get_ss_endpoint_companion_descriptor
|
||||
libusb_free_ss_endpoint_companion_descriptor
|
||||
libusb_free_bos_descriptor
|
||||
libusb_get_bos_descriptor
|
||||
libusb_get_usb_2_0_extension_descriptor
|
||||
libusb_free_usb_2_0_extension_descriptor
|
||||
libusb_get_ss_usb_device_capability_descriptor
|
||||
libusb_free_ss_usb_device_capability_descriptor
|
||||
libusb_get_container_id_descriptor
|
||||
libusb_free_container_id_descriptor
|
||||
libusb_get_string_descriptor_ascii
|
@ -6,4 +6,4 @@ const float normalizer = inner_divisor * (255.0 / (256.0 - inner_divisor)) / 255
|
||||
|
||||
void main() {
|
||||
gl_FragColor = clamp(floor(texture2D(Texture0, gl_TexCoord[0].xy) * bit_crusher) * normalizer, 0.0, 1.0);
|
||||
};
|
||||
}
|
||||
|
@ -16,4 +16,4 @@ void main() {
|
||||
vec4 actual_nth_bit_component = get_nth_bit_component(gl_FragColor);
|
||||
vec4 old_nth_bit_component = get_nth_bit_component(OldFragColor);
|
||||
gl_FragColor = clamp((((floor(gl_FragColor * bit_crusher_greater) * inner_divisor_greater) + ((actual_nth_bit_component + old_nth_bit_component) / 2.0)) / inner_divisor) * normalizer, 0.0, 1.0);
|
||||
};
|
||||
}
|
||||
|
@ -14,4 +14,4 @@ void main() {
|
||||
vec4 actual_nth_bit_component = get_nth_bit_component(gl_FragColor);
|
||||
vec4 old_nth_bit_component = get_nth_bit_component(OldFragColor);
|
||||
gl_FragColor = clamp(((((actual_nth_bit_component + old_nth_bit_component) / 2.0)) / inner_divisor) * normalizer, 0.0, 1.0);
|
||||
};
|
||||
}
|
||||
|
@ -16,4 +16,4 @@ void main() {
|
||||
vec4 actual_nth_bit_component = get_nth_bit_component(gl_FragColor);
|
||||
vec4 old_nth_bit_component = get_nth_bit_component(OldFragColor);
|
||||
gl_FragColor = clamp((floor(gl_FragColor * 255.0) - actual_nth_bit_component + ((actual_nth_bit_component + old_nth_bit_component) / 2.0)) / 255.0, 0.0, 1.0);
|
||||
};
|
||||
}
|
||||
|
@ -13,4 +13,4 @@ void main() {
|
||||
vec4 actual_nth_bit_component = get_nth_bit_component(gl_FragColor);
|
||||
vec4 old_nth_bit_component = get_nth_bit_component(OldFragColor);
|
||||
gl_FragColor = clamp((floor(gl_FragColor * 255.0) - actual_nth_bit_component + ((actual_nth_bit_component + old_nth_bit_component) / 2.0)) / 255.0, 0.0, 1.0);
|
||||
};
|
||||
}
|
||||
|
@ -11,4 +11,4 @@ void main() {
|
||||
vec4 OldFragColor = texture2D(Texture0, gl_TexCoord[0].xy + old_frame_offset);
|
||||
OldFragColor = clamp(floor(OldFragColor * bit_crusher) * normalizer, 0.0, 1.0);
|
||||
gl_FragColor = (gl_FragColor + OldFragColor) / 2.0;
|
||||
};
|
||||
}
|
||||
|
@ -5,4 +5,4 @@ void main() {
|
||||
gl_FragColor = texture2D(Texture0, gl_TexCoord[0].xy);
|
||||
vec4 OldFragColor = texture2D(Texture0, gl_TexCoord[0].xy + old_frame_offset);
|
||||
gl_FragColor = (gl_FragColor + OldFragColor) / 2.0;
|
||||
};
|
||||
}
|
||||
|
@ -2,4 +2,4 @@ uniform sampler2D Texture0;
|
||||
|
||||
void main() {
|
||||
gl_FragColor = texture2D(Texture0, gl_TexCoord[0].xy);
|
||||
};
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ void CaptureDataBuffers::ReleaseReaderBuffer(CaptureReaderType reader_type) {
|
||||
void CaptureDataBuffers::ReleaseWriterBuffer() {
|
||||
access_mutex.lock();
|
||||
if(curr_writer_pos != -1) {
|
||||
buffers[curr_writer_pos].inner_index = inner_index++;
|
||||
last_curr_in = curr_writer_pos;
|
||||
curr_writer_pos = -1;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@
|
||||
#define FT_ASYNC_CALL FT_ReadPipeAsync
|
||||
#endif
|
||||
#include <ftd3xx.h>
|
||||
#if defined(USE_IS_NITRO_USB) || defined(USE_DS_3DS_USB)
|
||||
#ifdef USE_LIBUSB
|
||||
#include "usb_generic.hpp"
|
||||
#endif
|
||||
|
||||
@ -122,7 +122,7 @@ void list_devices_ftd3(std::vector<CaptureDevice> &devices_list, std::vector<no_
|
||||
}
|
||||
}
|
||||
if(num_inserted == 0) {
|
||||
#if defined(USE_IS_NITRO_USB) || defined(USE_DS_3DS_USB)
|
||||
#ifdef USE_LIBUSB
|
||||
if(get_usb_total_filtered_devices(ftd3xx_valid_vids, sizeof(ftd3xx_valid_vids) / sizeof(ftd3xx_valid_vids[0]), ftd3xx_valid_pids, sizeof(ftd3xx_valid_pids) / sizeof(ftd3xx_valid_pids[0])) != numDevs)
|
||||
no_access_list.emplace_back("FTD3XX");
|
||||
#endif
|
||||
|
@ -0,0 +1,273 @@
|
||||
#include "dscapture_libftdi2.hpp"
|
||||
#include "dscapture_ftd2_driver.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
#include "dscapture_ftd2_compatibility.hpp"
|
||||
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
#include <ftdi.h>
|
||||
#endif
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
#define FTD2XX_STATIC
|
||||
#include "ftd2xx_symbols_renames.h"
|
||||
#include <ftd2xx.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#define FT_FAILED(x) ((x) != FT_OK)
|
||||
|
||||
void list_devices_ftd2_compatibility(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
list_devices_ftd2_driver(devices_list, no_access_list);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
list_devices_libftdi(devices_list, no_access_list);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ftd2_capture_main_loop(CaptureData* capture_data) {
|
||||
bool is_libftdi = capture_data->status.device.descriptor != NULL;
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return ftd2_capture_main_loop_driver(capture_data);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return ftd2_capture_main_loop_libftdi(capture_data);
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_get_queue_status(void* handle, bool is_libftdi, size_t* bytes_in) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi) {
|
||||
DWORD bytesIn = 0;
|
||||
FT_STATUS ftStatus = FT_GetQueueStatus(handle, &bytesIn);
|
||||
*bytes_in = bytesIn;
|
||||
return ftStatus;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return get_libftdi_read_queue_size(handle, bytes_in);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ftd2_is_error(int value, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_FAILED(value);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return value < 0;
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_write(void* handle, bool is_libftdi, const uint8_t* data, size_t size, size_t *sent) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi) {
|
||||
DWORD inner_sent = 0;
|
||||
FT_STATUS ftStatus = FT_Write(handle, (void*)data, size, &inner_sent);
|
||||
*sent = inner_sent;
|
||||
return ftStatus;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_write(handle, data, size, sent);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_read(void* handle, bool is_libftdi, uint8_t* data, size_t size, size_t *bytesIn) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi) {
|
||||
DWORD inner_bytes_in = 0;
|
||||
FT_STATUS ftStatus = FT_Read(handle, (void*)data, size, &inner_bytes_in);
|
||||
*bytesIn = inner_bytes_in;
|
||||
return ftStatus;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_read(handle, data, size, bytesIn);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_set_timeouts(void* handle, bool is_libftdi, int timeout_read, int timeout_write) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetTimeouts(handle, timeout_read, timeout_write);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
libftdi_set_timeouts(handle, timeout_read, timeout_write);
|
||||
return 0;
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_reset_device(void* handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_ResetDevice(handle);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_reset(handle);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_set_usb_parameters(void* handle, bool is_libftdi, size_t size_in, size_t size_out) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetUSBParameters(handle, size_in, size_out);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_set_usb_chunksizes(handle, size_in, size_out);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_set_chars(void* handle, bool is_libftdi, unsigned char eventch, unsigned char event_enable, unsigned char errorch, unsigned char error_enable) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetChars(handle, eventch, event_enable, errorch, error_enable);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_set_chars(handle, eventch, event_enable, errorch, error_enable);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_set_latency_timer(void* handle, bool is_libftdi, unsigned char latency) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetLatencyTimer(handle, latency);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_set_latency_timer(handle, latency);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_set_flow_ctrl_rts_cts(void* handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetFlowControl(handle, FT_FLOW_RTS_CTS, 0, 0);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_setflowctrl(handle, SIO_RTS_CTS_HS, 0, 0);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_reset_bitmode(void* handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetBitMode(handle, 0x00, FT_BITMODE_RESET);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_set_bitmode(handle, 0x00, BITMODE_RESET);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_set_mpsse_bitmode(void* handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetBitMode(handle, 0x00, FT_BITMODE_MPSSE);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_set_bitmode(handle, 0x00, BITMODE_MPSSE);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_set_fifo_bitmode(void* handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_SetBitMode(handle, 0x00, FT_BITMODE_SYNC_FIFO);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_set_bitmode(handle, 0x00, BITMODE_SYNCFF);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_purge_all(void* handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_Purge(handle, FT_PURGE_RX | FT_PURGE_TX);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_purge(handle, true, true);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_read_ee(void* handle, bool is_libftdi, int eeprom_addr, int *eeprom_val) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi) {
|
||||
WORD val = 0;
|
||||
int retval = FT_ReadEE(handle, eeprom_addr, &val);
|
||||
*eeprom_val = val;
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_read_eeprom(handle, eeprom_addr, eeprom_val);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_close(void* handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return FT_Close(handle);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_close(handle);
|
||||
#else
|
||||
return FT_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
int ftd2_open(CaptureDevice* device, void** handle, bool is_libftdi) {
|
||||
#ifdef USE_FTD2_DRIVER
|
||||
if(!is_libftdi)
|
||||
return ftd2_driver_open_serial(device, handle);
|
||||
#endif
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
return libftdi_open_serial(device, handle);
|
||||
#else
|
||||
return FT_OTHER_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ftd2_init() {
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
libftdi_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
void ftd2_end() {
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
libftdi_end();
|
||||
#endif
|
||||
}
|
@ -0,0 +1,110 @@
|
||||
#include "dscapture_ftd2_driver.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
#include "dscapture_ftd2_general.hpp"
|
||||
#include "dscapture_ftd2_compatibility.hpp"
|
||||
|
||||
#include "ftd2xx_symbols_renames.h"
|
||||
#define FTD2XX_STATIC
|
||||
#include <ftd2xx.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#define FT_FAILED(x) ((x) != FT_OK)
|
||||
|
||||
#define REAL_SERIAL_NUMBER_SIZE 16
|
||||
#define SERIAL_NUMBER_SIZE (REAL_SERIAL_NUMBER_SIZE+1)
|
||||
|
||||
#define ENABLE_AUDIO true
|
||||
|
||||
// Code based on sample provided by Loopy.
|
||||
|
||||
void list_devices_ftd2_driver(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
FT_STATUS ftStatus;
|
||||
DWORD numDevs = 0;
|
||||
ftStatus = FT_CreateDeviceInfoList(&numDevs);
|
||||
size_t num_inserted = 0;
|
||||
if (!FT_FAILED(ftStatus) && numDevs > 0)
|
||||
{
|
||||
const int debug_multiplier = 1;
|
||||
FT_HANDLE ftHandle = NULL;
|
||||
DWORD Flags = 0;
|
||||
DWORD Type = 0;
|
||||
DWORD ID = 0;
|
||||
char SerialNumber[SERIAL_NUMBER_SIZE] = { 0 };
|
||||
char Description[65] = { 0 };
|
||||
for (DWORD i = 0; i < numDevs; i++)
|
||||
{
|
||||
ftStatus = FT_GetDeviceInfoDetail(i, &Flags, &Type, &ID, NULL,
|
||||
SerialNumber, Description, &ftHandle);
|
||||
if((!FT_FAILED(ftStatus)) && (Flags & FT_FLAGS_HISPEED) && (Type == FT_DEVICE_232H))
|
||||
{
|
||||
for(int j = 0; j < get_num_ftd2_device_types(); j++) {
|
||||
if(Description == get_ftd2_fw_desc(j)) {
|
||||
for(int u = 0; u < debug_multiplier; u++)
|
||||
devices_list.emplace_back(std::string(SerialNumber), "DS.2", "DS.2.d565", CAPTURE_CONN_FTD2, (void*)NULL, false, false, ENABLE_AUDIO, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, get_max_samples(false), 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_RGB16, get_ftd2_fw_index(j), false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ftd2_driver_open_serial(CaptureDevice* device, void** handle) {
|
||||
char SerialNumber[SERIAL_NUMBER_SIZE] = { 0 };
|
||||
strncpy(SerialNumber, device->serial_number.c_str(), SERIAL_NUMBER_SIZE);
|
||||
SerialNumber[REAL_SERIAL_NUMBER_SIZE] = 0;
|
||||
return FT_OpenEx(SerialNumber, FT_OPEN_BY_SERIAL_NUMBER, handle);
|
||||
}
|
||||
|
||||
static void data_output_update(CaptureReceived* buffer, CaptureData* capture_data, int read_amount, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time) {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - base_time;
|
||||
base_time = curr_time;
|
||||
capture_data->data_buffers.WriteToBuffer(buffer, remove_synch_from_final_length((uint32_t*)buffer, read_amount), diff.count(), &capture_data->status.device);
|
||||
|
||||
if(capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
// Signal that there is data available
|
||||
capture_data->status.video_wait.unlock();
|
||||
capture_data->status.audio_wait.unlock();
|
||||
}
|
||||
|
||||
void ftd2_capture_main_loop_driver(CaptureData* capture_data) {
|
||||
bool is_libftdi = false;
|
||||
// Separate Capture Enable and put it here, for better control
|
||||
if(!enable_capture(capture_data->handle, is_libftdi)) {
|
||||
capture_error_print(true, capture_data, "Capture enable error");
|
||||
return;
|
||||
}
|
||||
int inner_curr_in = 0;
|
||||
int retval = 0;
|
||||
auto clock_start = std::chrono::high_resolution_clock::now();
|
||||
CaptureReceived* data_buffer = new CaptureReceived[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
int curr_data_buffer = 0;
|
||||
int next_data_buffer = 0;
|
||||
const size_t full_size = get_capture_size(capture_data->status.device.is_rgb_888);
|
||||
size_t next_size = full_size;
|
||||
size_t bytesIn;
|
||||
|
||||
while (capture_data->status.connected && capture_data->status.running) {
|
||||
curr_data_buffer = next_data_buffer;
|
||||
retval = ftd2_read(capture_data->handle, is_libftdi, ((uint8_t*)(&data_buffer[curr_data_buffer]) + (full_size - next_size)), next_size, &bytesIn);
|
||||
if(ftd2_is_error(retval, is_libftdi)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read failed");
|
||||
break;
|
||||
}
|
||||
if(bytesIn < next_size)
|
||||
continue;
|
||||
next_data_buffer = (curr_data_buffer + 1) % NUM_CAPTURE_RECEIVED_DATA_BUFFERS;
|
||||
bool has_synch_failed = !synchronization_check((uint16_t*)(&data_buffer[curr_data_buffer]), full_size, (uint16_t*)(&data_buffer[next_data_buffer]), &next_size);
|
||||
if(has_synch_failed)
|
||||
continue;
|
||||
data_output_update(&data_buffer[curr_data_buffer], capture_data, bytesIn, clock_start);
|
||||
}
|
||||
delete []data_buffer;
|
||||
}
|
@ -0,0 +1,399 @@
|
||||
#include "dscapture_ftd2_shared.hpp"
|
||||
#include "dscapture_ftd2_driver.hpp"
|
||||
#include "dscapture_ftd2_general.hpp"
|
||||
#include "dscapture_libftdi2.hpp"
|
||||
#include "dscapture_ftd2_compatibility.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
|
||||
#include "ftd2_ds2_fw_1.h"
|
||||
#include "ftd2_ds2_fw_2.h"
|
||||
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#define LE16(x) ((x) & 0xff), (((x) >> 8) & 0xff)
|
||||
|
||||
#define FTD2XX_IN_SIZE 0x10000
|
||||
#define FTD2XX_OUT_SIZE 0x10000
|
||||
|
||||
#define CLKRATE 6 // 1 - 25MHz
|
||||
#define CLKDIV ((30 / CLKRATE) - 1)
|
||||
#define RESETDELAY ((1 * CLKRATE) / 8) //1uS in bytes (clks/8)
|
||||
#define INITDELAY ((1200 * CLKRATE) / 8) //1200uS
|
||||
|
||||
#define TX_SPI_SIZE (1 << 16)
|
||||
#define TX_SPI_OFFSET 3
|
||||
|
||||
const uint8_t* ftd2_ds2_fws[] = {
|
||||
ftd2_ds2_fw_1,
|
||||
ftd2_ds2_fw_2,
|
||||
};
|
||||
|
||||
const size_t ftd2_ds2_sizes[] = {
|
||||
ftd2_ds2_fw_1_len,
|
||||
ftd2_ds2_fw_2_len,
|
||||
};
|
||||
|
||||
const std::string valid_descriptions[] = {"NDS.1", "NDS.2"};
|
||||
const int descriptions_firmware_ids[] = {1, 2};
|
||||
|
||||
// Code based on sample provided by Loopy.
|
||||
|
||||
int get_num_ftd2_device_types() {
|
||||
return sizeof(descriptions_firmware_ids) / sizeof(descriptions_firmware_ids[0]);
|
||||
}
|
||||
|
||||
const std::string get_ftd2_fw_desc(int index) {
|
||||
if((index < 0) || (index >= get_num_ftd2_device_types()))
|
||||
return "";
|
||||
return valid_descriptions[index];
|
||||
}
|
||||
|
||||
const int get_ftd2_fw_index(int index) {
|
||||
if((index < 0) || (index >= get_num_ftd2_device_types()))
|
||||
return 0;
|
||||
return descriptions_firmware_ids[index];
|
||||
}
|
||||
|
||||
void list_devices_ftd2_shared(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
list_devices_ftd2_compatibility(devices_list, no_access_list);
|
||||
}
|
||||
|
||||
static uint64_t _ftd2_get_video_in_size(bool is_rgb888) {
|
||||
return sizeof(USBOldDSVideoInputData);
|
||||
}
|
||||
|
||||
uint64_t ftd2_get_video_in_size(CaptureData* capture_data) {
|
||||
return _ftd2_get_video_in_size(capture_data->status.device.is_rgb_888);
|
||||
}
|
||||
|
||||
uint64_t get_capture_size(bool is_rgb888) {
|
||||
return (((sizeof(FTD2OldDSCaptureReceived) - EXTRA_DATA_BUFFER_USB_SIZE) + (MAX_PACKET_SIZE_FTD2 - 1)) / MAX_PACKET_SIZE_FTD2) * MAX_PACKET_SIZE_FTD2; // multiple of maxPacketSize
|
||||
}
|
||||
|
||||
uint64_t get_max_samples(bool is_rgb888) {
|
||||
return ((get_capture_size(is_rgb888) - _ftd2_get_video_in_size(is_rgb888)) / 2) - 4; // The last 4 bytes should never be different from 0x43214321
|
||||
}
|
||||
|
||||
static bool pass_if_FT_queue_empty(void* handle, bool is_libftdi) {
|
||||
size_t bytesIn = 0;
|
||||
int retval = ftd2_get_queue_status(handle, is_libftdi, &bytesIn);
|
||||
if(ftd2_is_error(retval, is_libftdi) || (bytesIn != 0)) //should be empty
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ftd2_write_all_check(void* handle, bool is_libftdi, const uint8_t* data, size_t size) {
|
||||
size_t sent = 0;
|
||||
int retval = ftd2_write(handle, is_libftdi, data, size, &sent);
|
||||
if(ftd2_is_error(retval, is_libftdi) || (sent != size))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool full_ftd2_write(void* handle, bool is_libftdi, const uint8_t* data, size_t size) {
|
||||
if(!pass_if_FT_queue_empty(handle, is_libftdi)) // maybe MPSSE error?
|
||||
return false;
|
||||
return ftd2_write_all_check(handle, is_libftdi, data, size);
|
||||
}
|
||||
|
||||
//verify CDONE==val
|
||||
static bool check_cdone(void* handle, bool is_libftdi, bool want_active) {
|
||||
static const uint8_t cmd[] = {
|
||||
0x81, //read D
|
||||
0x83, //read C
|
||||
};
|
||||
uint8_t buf[2];
|
||||
|
||||
if(!full_ftd2_write(handle, is_libftdi, cmd, sizeof(cmd)))
|
||||
return false;
|
||||
|
||||
size_t bytesIn = 0;
|
||||
int retval = ftd2_read(handle, is_libftdi, buf, 2, &bytesIn);
|
||||
if(ftd2_is_error(retval, is_libftdi) || (bytesIn != 2) || (buf[0] == 0xFA))
|
||||
return false;
|
||||
|
||||
if(want_active)
|
||||
return (buf[0] & 0x40);
|
||||
return !(buf[0] & 0x40);
|
||||
}
|
||||
|
||||
static int end_spi_tx(uint8_t *txBuf, int retval) {
|
||||
delete []txBuf;
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int ftd2_spi_tx(void* handle, bool is_libftdi, const uint8_t* buf, int size) {
|
||||
uint8_t *txBuf = new uint8_t[TX_SPI_SIZE + TX_SPI_OFFSET];
|
||||
int retval = 0;
|
||||
int len;
|
||||
size_t sent;
|
||||
size_t bytesIn;
|
||||
size_t wrote = 0;
|
||||
|
||||
if(!pass_if_FT_queue_empty(handle, is_libftdi))
|
||||
return end_spi_tx(txBuf, -1);
|
||||
|
||||
while(size > 0) {
|
||||
len = size;
|
||||
if(len > TX_SPI_SIZE)
|
||||
len = TX_SPI_SIZE;
|
||||
memcpy(&txBuf[TX_SPI_OFFSET], &buf[wrote], len);
|
||||
|
||||
txBuf[0] = 0x11;
|
||||
txBuf[1] = (len - 1) & 0xFF;
|
||||
txBuf[2] = ((len - 1) >> 8) & 0xFF;
|
||||
|
||||
retval = ftd2_write(handle, is_libftdi, txBuf, len + TX_SPI_OFFSET, &sent);
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return end_spi_tx(txBuf, retval);
|
||||
if(sent != (len + TX_SPI_OFFSET))
|
||||
return end_spi_tx(txBuf, -2);
|
||||
|
||||
if(!pass_if_FT_queue_empty(handle, is_libftdi))
|
||||
return end_spi_tx(txBuf, -1);
|
||||
|
||||
wrote += sent - TX_SPI_OFFSET;
|
||||
size -= len;
|
||||
}
|
||||
return end_spi_tx(txBuf, 0);
|
||||
}
|
||||
|
||||
static bool fpga_config(void* handle, bool is_libftdi, const uint8_t* bitstream, int size) {
|
||||
//D6=CDONE (in)
|
||||
//D3=SS (out)
|
||||
//D2=TDO (in)
|
||||
//D1=TDI (out)
|
||||
//D0=TCK (out)
|
||||
//C7=reset (out)
|
||||
|
||||
//Lattice programming:
|
||||
// hold SS low
|
||||
// pulse reset 200ns
|
||||
// wait 1200us
|
||||
// release SS
|
||||
// send 8 clocks
|
||||
// hold SS low
|
||||
// send configuration MSB first, sampled on +clk
|
||||
// release SS
|
||||
// CDONE should go high within 100 clocks
|
||||
// send >49 clocks after CDONE=1
|
||||
|
||||
static const uint8_t cmd0[] = { //configure for lattice SPI:
|
||||
0x82, 0x7f, 0x80, //set Cx pins {val,dir:1=out}: reset=0
|
||||
0x80, 0xf0, 0x0b, //set Dx pins {val,dir:1=out}: SS=0, clk idle low, TDI out, TCK out
|
||||
0x8f, LE16(RESETDELAY), //reset delay
|
||||
0x82, 0xff, 0x00, //set Cx pins: reset=PU (does val=1 enable pullups? seems to...)
|
||||
0x8f, LE16(INITDELAY), //init delay
|
||||
0x80, 0xf8, 0x0b, //set Dx pins: SS=1
|
||||
0x8f, LE16(1), //16 dummy clocks
|
||||
0x80, 0xf0, 0x0b, //set Dx pins: SS=0
|
||||
};
|
||||
|
||||
int retval = 0;
|
||||
retval = ftd2_set_timeouts(handle, is_libftdi, 300, 300);
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
if(!full_ftd2_write(handle, is_libftdi, cmd0, sizeof(cmd0)))
|
||||
return false;
|
||||
|
||||
//verify CDONE=0
|
||||
if(!check_cdone(handle, is_libftdi, false))
|
||||
return false;
|
||||
|
||||
//send configuration
|
||||
retval = ftd2_spi_tx(handle, is_libftdi, bitstream, size);
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
|
||||
//finish up
|
||||
static const uint8_t cmd1[] = {
|
||||
0x80, 0xf8, 0x0b, //set Dx pins: SS=1
|
||||
0x8f, LE16(20), //>150 dummy clocks
|
||||
0x80, 0x00, 0x00, //float Dx
|
||||
0x82, 0x00, 0x00, //float Cx
|
||||
};
|
||||
if(!full_ftd2_write(handle, is_libftdi, cmd1, sizeof(cmd1)))
|
||||
return false;
|
||||
|
||||
//verify CDONE=1
|
||||
if(!check_cdone(handle, is_libftdi, true))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool init_MPSSE(void* handle, bool is_libftdi) {
|
||||
static const uint8_t cmd[] = {
|
||||
0x85, //no loopback
|
||||
0x8d, //disable 3-phase clocking
|
||||
0x8a, //disable clk divide-by-5
|
||||
0x97, //disable adaptive clocking
|
||||
0x86, LE16(CLKDIV), //set clock rate
|
||||
};
|
||||
|
||||
int retval = 0;
|
||||
retval = ftd2_reset_device(handle, is_libftdi);
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
retval = ftd2_set_usb_parameters(handle, is_libftdi, FTD2XX_IN_SIZE, FTD2XX_OUT_SIZE); //Multiple of 64 bytes up to 64k
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
retval = ftd2_set_chars(handle, is_libftdi, 0, 0, 0, 0);
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
retval = ftd2_set_timeouts(handle, is_libftdi, 300, 300); //read,write timeout (ms)
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
retval = ftd2_set_latency_timer(handle, is_libftdi, 3); //time to wait before incomplete packet is sent (default=16ms). MPSSE read seems to fail on 2 sometimes, too fast?
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
retval = ftd2_set_flow_ctrl_rts_cts(handle, is_libftdi); //turn on flow control to synchronize IN requests
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
retval = ftd2_reset_bitmode(handle, is_libftdi); //performs a general reset on MPSSE
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
retval = ftd2_set_mpsse_bitmode(handle, is_libftdi); //enable MPSSE mode
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
|
||||
//MPSSE seems to choke on first write sometimes :/ Send, purge, resend.
|
||||
size_t sent = 0;
|
||||
retval = ftd2_write(handle, is_libftdi, cmd, 1, &sent); //enable MPSSE mode
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
default_sleep();
|
||||
retval = ftd2_purge_all(handle, is_libftdi);
|
||||
if(ftd2_is_error(retval, is_libftdi))
|
||||
return false;
|
||||
return full_ftd2_write(handle, is_libftdi, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static bool preemptive_close_connection(CaptureData* capture_data, bool is_libftdi) {
|
||||
ftd2_reset_device(capture_data->handle, is_libftdi);
|
||||
ftd2_close(capture_data->handle, is_libftdi);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool connect_ftd2_shared(bool print_failed, CaptureData* capture_data, CaptureDevice* device) {
|
||||
bool is_libftdi = device->descriptor != NULL;
|
||||
if(ftd2_open(device, &capture_data->handle, is_libftdi)) {
|
||||
capture_error_print(print_failed, capture_data, "Create failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!init_MPSSE(capture_data->handle, is_libftdi)) {
|
||||
capture_error_print(print_failed, capture_data, "MPSSE init failed");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
|
||||
if(!fpga_config(capture_data->handle, is_libftdi, ftd2_ds2_fws[device->firmware_id - 1], ftd2_ds2_sizes[device->firmware_id - 1])) {
|
||||
capture_error_print(print_failed, capture_data, "FPGA config failed");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
|
||||
int retval = 0;
|
||||
int val = 0;
|
||||
retval = ftd2_read_ee(capture_data->handle, is_libftdi, 1, &val);
|
||||
if(ftd2_is_error(retval, is_libftdi) || (val != 0x0403)) { //=85A8: something went wrong (fpga is configured but FT chip detected wrong eeprom size)
|
||||
capture_error_print(print_failed, capture_data, "EEPROM read error");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
|
||||
/*
|
||||
int Firmware = 0;
|
||||
int Hardware = 0;
|
||||
retval = ftd2_read_ee(capture_data->handle, is_libftdi, 0x10, &Firmware);
|
||||
if(ftd2_is_error(retval, is_libftdi)) {
|
||||
capture_error_print(print_failed, capture_data, "Firmware ID read error");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
retval = ftd2_read_ee(capture_data->handle, is_libftdi, 0x11, &Hardware);
|
||||
if(ftd2_is_error(retval, is_libftdi)) {
|
||||
capture_error_print(print_failed, capture_data, "Hardware ID read error");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
*/
|
||||
|
||||
retval = ftd2_set_fifo_bitmode(capture_data->handle, is_libftdi); //to FIFO mode. This takes over port B, pins shouldn't get modified though
|
||||
if(ftd2_is_error(retval, is_libftdi)) {
|
||||
capture_error_print(print_failed, capture_data, "Bitmode setup error");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
|
||||
retval = ftd2_set_timeouts(capture_data->handle, is_libftdi, 50, 50);
|
||||
if(ftd2_is_error(retval, is_libftdi)) {
|
||||
capture_error_print(print_failed, capture_data, "Timeouts setup error");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
|
||||
if(!pass_if_FT_queue_empty(capture_data->handle, is_libftdi)) {// maybe MPSSE error?
|
||||
capture_error_print(print_failed, capture_data, "Intermediate error");
|
||||
return preemptive_close_connection(capture_data, is_libftdi);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool synchronization_check(uint16_t* data_buffer, size_t size, uint16_t* next_data_buffer, size_t* next_size, bool special_check) {
|
||||
size_t size_words = size / 2;
|
||||
*next_size = size;
|
||||
if((data_buffer[0] != FTD2_OLDDS_SYNCH_VALUES) && (data_buffer[size_words - 1] == FTD2_OLDDS_SYNCH_VALUES))
|
||||
return true;
|
||||
if(special_check && (data_buffer[0] == FTD2_OLDDS_SYNCH_VALUES) && (data_buffer[size_words - 1] == FTD2_OLDDS_SYNCH_VALUES))
|
||||
return true;
|
||||
|
||||
//check sync
|
||||
size_t samples = 0;
|
||||
|
||||
// Find the first spot the padding is present
|
||||
while((samples < size_words) && (data_buffer[samples] != FTD2_OLDDS_SYNCH_VALUES))
|
||||
samples++;
|
||||
while((samples < size_words) && (data_buffer[samples] == FTD2_OLDDS_SYNCH_VALUES))
|
||||
samples++;
|
||||
|
||||
// Schedule a read to re-synchronize
|
||||
if(next_data_buffer != NULL)
|
||||
memcpy(&data_buffer[samples], next_data_buffer, (size_words - samples) * 2);
|
||||
*next_size = samples * 2;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t remove_synch_from_final_length(uint32_t* out_buffer, size_t real_length) {
|
||||
// Ignore synch for final length
|
||||
const uint32_t check_value = FTD2_OLDDS_SYNCH_VALUES | (FTD2_OLDDS_SYNCH_VALUES << 16);
|
||||
while((real_length >= 4) && ((out_buffer)[(real_length / 4) - 1] == check_value))
|
||||
real_length -= 4;
|
||||
if((real_length < 4) && (out_buffer[0] == check_value))
|
||||
real_length = 0;
|
||||
return real_length;
|
||||
}
|
||||
|
||||
bool enable_capture(void* handle, bool is_libftdi) {
|
||||
static const uint8_t cmd[]={ 0x80, 0x01 }; //enable capture
|
||||
return ftd2_write_all_check(handle, is_libftdi, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
void ftd2_capture_main_loop_shared(CaptureData* capture_data) {
|
||||
ftd2_capture_main_loop(capture_data);
|
||||
}
|
||||
|
||||
void ftd2_capture_cleanup_shared(CaptureData* capture_data) {
|
||||
bool is_libftdi = capture_data->status.device.descriptor != NULL;
|
||||
if(ftd2_close(capture_data->handle, is_libftdi)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Close failed");
|
||||
}
|
||||
}
|
||||
|
||||
void ftd2_init_shared() {
|
||||
ftd2_init();
|
||||
}
|
||||
|
||||
void ftd2_end_shared() {
|
||||
ftd2_end();
|
||||
}
|
@ -0,0 +1,704 @@
|
||||
#include "dscapture_libftdi2.hpp"
|
||||
#include "dscapture_ftd2_general.hpp"
|
||||
#include "dscapture_ftd2_compatibility.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
|
||||
#include <ftdi.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#define FT_FAILED(x) ((x) != FT_OK)
|
||||
|
||||
#define MANUFACTURER_SIZE 128
|
||||
#define DESCRIPTION_SIZE 128
|
||||
#define SERIAL_NUMBER_SIZE 128
|
||||
|
||||
#define ENABLE_AUDIO true
|
||||
|
||||
#define FTDI_VID 0x0403
|
||||
#define FT232H_PID 0x6014
|
||||
|
||||
#define EXPECTED_IGNORED_HALFWORDS 1
|
||||
|
||||
#define IGNORE_FIRST_FEW_FRAMES_SYNC (NUM_CAPTURE_RECEIVED_DATA_BUFFERS * 2)
|
||||
#define RESYNC_TIMEOUT 0.050
|
||||
|
||||
struct vid_pid_descriptor {
|
||||
int vid;
|
||||
int pid;
|
||||
};
|
||||
|
||||
static const vid_pid_descriptor base_device = {
|
||||
.vid = FTDI_VID, .pid = FT232H_PID
|
||||
};
|
||||
|
||||
static const vid_pid_descriptor* accepted_devices[] = {
|
||||
&base_device,
|
||||
};
|
||||
|
||||
static const vid_pid_descriptor* get_device_descriptor(int vid, int pid) {
|
||||
for(int i = 0; i < sizeof(accepted_devices) / sizeof(*accepted_devices); i++)
|
||||
if((vid == accepted_devices[i]->vid) && (pid == accepted_devices[i]->pid))
|
||||
return accepted_devices[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void libftdi_init() {
|
||||
}
|
||||
|
||||
void libftdi_end() {
|
||||
}
|
||||
|
||||
static void libftdi_usb_thread_function(bool* usb_thread_run, libusb_context *usb_ctx) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 300000;
|
||||
while(*usb_thread_run)
|
||||
libusb_handle_events_timeout_completed(usb_ctx, &tv, NULL);
|
||||
}
|
||||
|
||||
static void libftdi_start_thread(std::thread* thread_ptr, bool* usb_thread_run, libusb_context *usb_ctx) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = true;
|
||||
*thread_ptr = std::thread(libftdi_usb_thread_function, usb_thread_run, usb_ctx);
|
||||
}
|
||||
|
||||
static void libftdi_close_thread(std::thread* thread_ptr, bool* usb_thread_run) {
|
||||
if(!usb_is_initialized())
|
||||
return;
|
||||
*usb_thread_run = false;
|
||||
thread_ptr->join();
|
||||
}
|
||||
|
||||
static int check_single_device_valid_libftdi(ftdi_context *handle, libusb_device* dev, char* description, char* SerialNumber, const vid_pid_descriptor** curr_descriptor) {
|
||||
char manufacturer[MANUFACTURER_SIZE];
|
||||
libusb_device_handle *dev_handle = NULL;
|
||||
int retval = libusb_open(dev, &dev_handle);
|
||||
if(retval || (dev_handle == NULL))
|
||||
return retval;
|
||||
retval = libusb_claim_interface(dev_handle, handle->interface);
|
||||
if(retval == LIBUSB_SUCCESS)
|
||||
libusb_release_interface(dev_handle, handle->interface);
|
||||
libusb_close(dev_handle);
|
||||
if(retval < 0)
|
||||
return retval;
|
||||
libusb_device_descriptor desc = {0};
|
||||
retval = libusb_get_device_descriptor(dev, &desc);
|
||||
*curr_descriptor = NULL;
|
||||
if(retval >= 0)
|
||||
*curr_descriptor = get_device_descriptor(desc.idVendor, desc.idProduct);
|
||||
if((retval < 0) || ((retval = ftdi_usb_get_strings(handle, dev, manufacturer, MANUFACTURER_SIZE, description, DESCRIPTION_SIZE, SerialNumber, SERIAL_NUMBER_SIZE)) < 0))
|
||||
return retval;
|
||||
if((desc.bcdUSB < 0x0200) || ((*curr_descriptor) == NULL))
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
void list_devices_libftdi(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
ftdi_device_list *devlist, *curdev;
|
||||
ftdi_context *handle = ftdi_new();
|
||||
char description[DESCRIPTION_SIZE], SerialNumber[SERIAL_NUMBER_SIZE];
|
||||
int debug_multiplier = 1;
|
||||
bool insert_anyway = false;
|
||||
bool perm_error = false;
|
||||
const vid_pid_descriptor* curr_descriptor;
|
||||
|
||||
int num_devices = ftdi_usb_find_all(handle, &devlist, 0, 0);
|
||||
if(num_devices < 0) {
|
||||
ftdi_free(handle);
|
||||
return;
|
||||
}
|
||||
curdev = devlist;
|
||||
while(curdev != NULL)
|
||||
{
|
||||
int retval = check_single_device_valid_libftdi(handle, curdev->dev, description, SerialNumber, &curr_descriptor);
|
||||
if(retval < 0) {
|
||||
if(retval == LIBUSB_ERROR_ACCESS)
|
||||
perm_error = true;
|
||||
curdev = curdev->next;
|
||||
continue;
|
||||
}
|
||||
std::string serial_number = std::string(SerialNumber);
|
||||
bool is_already_inserted = false;
|
||||
for(int j = 0; j < devices_list.size(); j++) {
|
||||
if((devices_list[j].cc_type == CAPTURE_CONN_FTD2) && (devices_list[j].serial_number == serial_number)) {
|
||||
is_already_inserted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(is_already_inserted && (!insert_anyway)) {
|
||||
curdev = curdev->next;
|
||||
continue;
|
||||
}
|
||||
for(int j = 0; j < get_num_ftd2_device_types(); j++) {
|
||||
if(description == get_ftd2_fw_desc(j)) {
|
||||
for(int u = 0; u < debug_multiplier; u++)
|
||||
devices_list.emplace_back(serial_number, "DS.2", "DS.2.l565", std::string(description), CAPTURE_CONN_FTD2, (void*)curr_descriptor, false, false, ENABLE_AUDIO, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, get_max_samples(false), 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_RGB16, get_ftd2_fw_index(j), false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
curdev = curdev->next;
|
||||
}
|
||||
ftdi_list_free(&devlist);
|
||||
ftdi_free(handle);
|
||||
if(perm_error)
|
||||
no_access_list.emplace_back("libftdi");
|
||||
}
|
||||
|
||||
int libftdi_reset(void* handle) {
|
||||
return ftdi_usb_reset((ftdi_context*)handle);
|
||||
}
|
||||
|
||||
int libftdi_set_latency_timer(void* handle, unsigned char latency) {
|
||||
return ftdi_set_latency_timer((ftdi_context*)handle, latency);
|
||||
}
|
||||
|
||||
int libftdi_setflowctrl(void* handle, int flowctrl, unsigned char xon, unsigned char xoff) {
|
||||
if((flowctrl == SIO_DISABLE_FLOW_CTRL) || (flowctrl == SIO_RTS_CTS_HS) || (flowctrl == SIO_DTR_DSR_HS))
|
||||
return ftdi_setflowctrl((ftdi_context*)handle, flowctrl);
|
||||
return ftdi_setflowctrl_xonxoff((ftdi_context*)handle, xon, xoff);
|
||||
}
|
||||
|
||||
int libftdi_set_bitmode(void* handle, unsigned char bitmask, unsigned char mode) {
|
||||
return ftdi_set_bitmode((ftdi_context*)handle, bitmask, mode);
|
||||
}
|
||||
|
||||
int libftdi_purge(void* handle, bool do_read, bool do_write) {
|
||||
if(do_read && do_write)
|
||||
return ftdi_tcioflush((ftdi_context*)handle);
|
||||
if(do_read)
|
||||
return ftdi_tciflush((ftdi_context*)handle);
|
||||
if(do_write)
|
||||
return ftdi_tcoflush((ftdi_context*)handle);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int libftdi_read_eeprom(void* handle, int eeprom_addr, int *eeprom_val) {
|
||||
unsigned short val = 0;
|
||||
int ret = ftdi_read_eeprom_location((ftdi_context*)handle, eeprom_addr, &val);
|
||||
*eeprom_val = val;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int libftdi_set_chars(void* handle, unsigned char eventch, unsigned char event_enable, unsigned char errorch, unsigned char error_enable) {
|
||||
int ret = ftdi_set_event_char((ftdi_context*)handle, eventch, event_enable);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return ftdi_set_error_char((ftdi_context*)handle, errorch, error_enable);
|
||||
}
|
||||
|
||||
int libftdi_set_usb_chunksizes(void* handle, unsigned int chunksize_in, unsigned int chunksize_out) {
|
||||
int ret = ftdi_read_data_set_chunksize((ftdi_context*)handle, chunksize_in);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
return ftdi_write_data_set_chunksize((ftdi_context*)handle, chunksize_out);
|
||||
}
|
||||
|
||||
void libftdi_set_timeouts(void* handle, int timeout_in_ms, int timeout_out_ms) {
|
||||
ftdi_context* in_handle = (ftdi_context*)handle;
|
||||
in_handle->usb_read_timeout = timeout_in_ms;
|
||||
in_handle->usb_write_timeout = timeout_out_ms;
|
||||
}
|
||||
|
||||
int libftdi_write(void* handle, const uint8_t* data, size_t size, size_t* bytesOut) {
|
||||
*bytesOut = ftdi_write_data((ftdi_context*)handle, data, size);
|
||||
if((*bytesOut) >= 0)
|
||||
return 0;
|
||||
return *bytesOut;
|
||||
}
|
||||
|
||||
int libftdi_read(void* handle, uint8_t* data, size_t size, size_t* bytesIn) {
|
||||
*bytesIn = ftdi_read_data((ftdi_context*)handle, data, size);
|
||||
if((*bytesIn) >= 0)
|
||||
return 0;
|
||||
return *bytesIn;
|
||||
}
|
||||
|
||||
int get_libftdi_read_queue_size(void* handle, size_t* bytesIn) {
|
||||
uint8_t buffer[64];
|
||||
*bytesIn = 0;
|
||||
ftdi_context* in_handle = (ftdi_context*)handle;
|
||||
int timeout_in_ms = in_handle->usb_read_timeout;
|
||||
in_handle->usb_read_timeout = 0;
|
||||
size_t curr_bytes_in = 0;
|
||||
bool done = false;
|
||||
int retval = 0;
|
||||
while(!done) {
|
||||
retval = libftdi_read(handle, buffer, 64, &curr_bytes_in);
|
||||
if(retval <= 0)
|
||||
done = true;
|
||||
else
|
||||
*bytesIn += curr_bytes_in;
|
||||
}
|
||||
in_handle->usb_read_timeout = timeout_in_ms;
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
int libftdi_open_serial(CaptureDevice* device, void** handle) {
|
||||
ftdi_device_list *devlist, *curdev;
|
||||
ftdi_context *curr_handle = ftdi_new();
|
||||
char description[DESCRIPTION_SIZE], SerialNumber[SERIAL_NUMBER_SIZE];
|
||||
int debug_multiplier = 1;
|
||||
bool insert_anyway = false;
|
||||
bool perm_error = false;
|
||||
const vid_pid_descriptor* curr_descriptor;
|
||||
int ret = LIBUSB_ERROR_OTHER;
|
||||
|
||||
int num_devices = ftdi_usb_find_all(curr_handle, &devlist, 0, 0);
|
||||
if(num_devices < 0) {
|
||||
ftdi_free(curr_handle);
|
||||
return LIBUSB_ERROR_OTHER;
|
||||
}
|
||||
curdev = devlist;
|
||||
while(curdev != NULL)
|
||||
{
|
||||
int retval = check_single_device_valid_libftdi(curr_handle, curdev->dev, description, SerialNumber, &curr_descriptor);
|
||||
if(retval < 0) {
|
||||
curdev = curdev->next;
|
||||
continue;
|
||||
}
|
||||
if(curr_descriptor != ((const vid_pid_descriptor*)device->descriptor)) {
|
||||
curdev = curdev->next;
|
||||
continue;
|
||||
}
|
||||
std::string serial_number = std::string(SerialNumber);
|
||||
std::string desc = std::string(description);
|
||||
if((serial_number != device->serial_number) || (desc != device->path)) {
|
||||
curdev = curdev->next;
|
||||
continue;
|
||||
}
|
||||
ret = ftdi_usb_open_dev(curr_handle, curdev->dev);
|
||||
if(ret >= 0)
|
||||
*handle = (void*)curr_handle;
|
||||
curdev = NULL;
|
||||
}
|
||||
ftdi_list_free(&devlist);
|
||||
if(ret < 0)
|
||||
ftdi_free(curr_handle);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int libftdi_close(void* handle) {
|
||||
ftdi_usb_close((ftdi_context*)handle);
|
||||
ftdi_free((ftdi_context*)handle);
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
void libftdi_cancel_callback(ftd2_async_callback_data* cb_data) {
|
||||
cb_data->transfer_data_access.lock();
|
||||
if(cb_data->transfer_data)
|
||||
libusb_cancel_transfer((libusb_transfer*)cb_data->transfer_data);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
}
|
||||
|
||||
static void STDCALL libftdi_read_callback(libusb_transfer* transfer) {
|
||||
ftd2_async_callback_data* cb_data = (ftd2_async_callback_data*)transfer->user_data;
|
||||
FTD2CaptureReceivedData* user_data = (FTD2CaptureReceivedData*)cb_data->actual_user_data;
|
||||
cb_data->transfer_data_access.lock();
|
||||
cb_data->transfer_data = NULL;
|
||||
cb_data->is_transfer_done_mutex->specific_unlock(cb_data->internal_index);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
cb_data->function((void*)user_data, transfer->actual_length, transfer->status);
|
||||
}
|
||||
|
||||
// Read from bulk
|
||||
static void libftdi_schedule_read(ftd2_async_callback_data* cb_data, int length) {
|
||||
const int max_packet_size = MAX_PACKET_SIZE_USB2;
|
||||
libusb_transfer *transfer_in = libusb_alloc_transfer(0);
|
||||
if(!transfer_in)
|
||||
return;
|
||||
cb_data->transfer_data_access.lock();
|
||||
cb_data->transfer_data = transfer_in;
|
||||
cb_data->is_transfer_done_mutex->specific_try_lock(cb_data->internal_index);
|
||||
length += ((length + (max_packet_size - FTD2_INTRA_PACKET_HEADER_SIZE) - 1) / (max_packet_size - FTD2_INTRA_PACKET_HEADER_SIZE)) * FTD2_INTRA_PACKET_HEADER_SIZE;
|
||||
cb_data->requested_length = length;
|
||||
ftdi_context* in_handle = (ftdi_context*)cb_data->handle;
|
||||
libusb_fill_bulk_transfer(transfer_in, in_handle->usb_dev, in_handle->out_ep, (uint8_t*)&cb_data->buffer_raw, length, libftdi_read_callback, (void*)cb_data, in_handle->usb_read_timeout * NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
transfer_in->flags |= LIBUSB_TRANSFER_FREE_TRANSFER;
|
||||
libusb_submit_transfer(transfer_in);
|
||||
cb_data->transfer_data_access.unlock();
|
||||
}
|
||||
|
||||
static size_t libftdi_get_actual_length(const int max_packet_size, size_t length, size_t header_packet_size) {
|
||||
// Remove the small headers every 512 bytes...
|
||||
// The "- header_packet_size" instead of "-1" covers for partial header transfers...
|
||||
int num_iters = (length + max_packet_size - header_packet_size) / max_packet_size;
|
||||
if(num_iters > 0)
|
||||
length -= (num_iters * header_packet_size);
|
||||
else
|
||||
length = 0;
|
||||
return length;
|
||||
}
|
||||
|
||||
static void libftdi_copy_buffer_to_target(uint8_t* buffer_written, uint8_t* buffer_target, const int max_packet_size, size_t length, size_t header_packet_size) {
|
||||
// Remove the small headers every 512 bytes...
|
||||
// The "- header_packet_size" instead of "-1" covers for partial header transfers...
|
||||
int num_iters = (length + max_packet_size - header_packet_size) / max_packet_size;
|
||||
if(num_iters <= 0)
|
||||
return;
|
||||
|
||||
length -= (num_iters * header_packet_size);
|
||||
for(int i = 0; i < num_iters; i++) {
|
||||
int rem_size = length - ((max_packet_size - header_packet_size) * i);
|
||||
if(rem_size > ((int)(max_packet_size - header_packet_size)))
|
||||
rem_size = max_packet_size - header_packet_size;
|
||||
if(rem_size <= 0)
|
||||
break;
|
||||
memcpy(buffer_target + ((max_packet_size - header_packet_size) * i), buffer_written + header_packet_size + (max_packet_size * i), rem_size);
|
||||
}
|
||||
}
|
||||
|
||||
// Read from bulk
|
||||
static int libftdi_direct_read(void* handle, uint8_t* buffer_raw, uint8_t* buffer_normal, size_t length, size_t* transferred) {
|
||||
const int max_packet_size = MAX_PACKET_SIZE_USB2;
|
||||
length += ((length + (max_packet_size - FTD2_INTRA_PACKET_HEADER_SIZE) - 1) / (max_packet_size - FTD2_INTRA_PACKET_HEADER_SIZE)) * FTD2_INTRA_PACKET_HEADER_SIZE;
|
||||
ftdi_context* in_handle = (ftdi_context*)handle;
|
||||
*transferred = 0;
|
||||
int internal_transferred = 0;
|
||||
int retval = libusb_bulk_transfer(in_handle->usb_dev, in_handle->out_ep, buffer_raw, length, &internal_transferred, in_handle->usb_read_timeout);
|
||||
if(retval < 0)
|
||||
return retval;
|
||||
libftdi_copy_buffer_to_target(buffer_raw, buffer_normal, max_packet_size, internal_transferred, FTD2_INTRA_PACKET_HEADER_SIZE);
|
||||
*transferred = libftdi_get_actual_length(max_packet_size, internal_transferred, FTD2_INTRA_PACKET_HEADER_SIZE);
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static int libftdi_full_read(void* handle, uint8_t* buffer_raw, uint8_t* buffer_normal, size_t length, double timeout) {
|
||||
size_t total_transferred = 0;
|
||||
const auto start_time = std::chrono::high_resolution_clock::now();
|
||||
while(total_transferred < length) {
|
||||
size_t received = 0;
|
||||
int retval = libftdi_direct_read(handle, buffer_raw, buffer_normal, length - total_transferred, &received);
|
||||
if(ftd2_is_error(retval, true))
|
||||
return retval;
|
||||
total_transferred += received;
|
||||
if(received == 0)
|
||||
break;
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - start_time;
|
||||
if(diff.count() > timeout)
|
||||
return LIBUSB_ERROR_TIMEOUT;
|
||||
}
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
|
||||
static void libftdi_copy_buffer_to_target_and_skip(uint8_t* buffer_written, uint8_t* buffer_target, const int max_packet_size, size_t length, size_t header_packet_size, size_t ignored_bytes) {
|
||||
// This could be made faster for small "ignored_bytes", however this scales well...
|
||||
|
||||
// Remove the small headers every 512 bytes...
|
||||
// The "- header_packet_size" instead of "-1" covers for partial header transfers...
|
||||
int num_iters = (length + max_packet_size - header_packet_size) / max_packet_size;
|
||||
if(num_iters <= 0)
|
||||
return;
|
||||
|
||||
size_t inner_length = length - (num_iters * header_packet_size);
|
||||
size_t fully_ignored_iters = ignored_bytes / (max_packet_size - header_packet_size);
|
||||
size_t partially_ignored_iters = (ignored_bytes + (max_packet_size - header_packet_size) - 1) / (max_packet_size - header_packet_size);
|
||||
num_iters -= fully_ignored_iters;
|
||||
if(num_iters <= 0)
|
||||
return;
|
||||
|
||||
buffer_written += fully_ignored_iters * max_packet_size;
|
||||
// Skip inside a packet, since it's misaligned
|
||||
if(partially_ignored_iters != fully_ignored_iters) {
|
||||
size_t offset_bytes = ignored_bytes % (max_packet_size - header_packet_size);
|
||||
int rem_size = inner_length - ((max_packet_size - header_packet_size) * fully_ignored_iters);
|
||||
if(rem_size > ((int)((max_packet_size - header_packet_size))))
|
||||
rem_size = max_packet_size - header_packet_size;
|
||||
rem_size -= offset_bytes;
|
||||
if(rem_size > 0) {
|
||||
memcpy(buffer_target, buffer_written + header_packet_size + offset_bytes, rem_size);
|
||||
buffer_written += max_packet_size;
|
||||
buffer_target += rem_size;
|
||||
}
|
||||
}
|
||||
if(length <= (max_packet_size * partially_ignored_iters))
|
||||
return;
|
||||
libftdi_copy_buffer_to_target(buffer_written, buffer_target, max_packet_size, length - (max_packet_size * partially_ignored_iters), header_packet_size);
|
||||
}
|
||||
|
||||
static int get_libftdi_status(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
return *received_data_buffers[0].status;
|
||||
}
|
||||
|
||||
static void reset_libftdi_status(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
*received_data_buffers[0].status = 0;
|
||||
}
|
||||
|
||||
static void error_libftdi_status(FTD2CaptureReceivedData* received_data_buffers, int error) {
|
||||
*received_data_buffers[0].status = error;
|
||||
}
|
||||
|
||||
static int libftdi_get_num_free_buffers(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
int num_free = 0;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!received_data_buffers[i].in_use)
|
||||
num_free += 1;
|
||||
return num_free;
|
||||
}
|
||||
|
||||
static void wait_all_libftdi_transfers_done(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
if (received_data_buffers == NULL)
|
||||
return;
|
||||
if (*received_data_buffers[0].status < 0) {
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
libftdi_cancel_callback(&received_data_buffers[i].cb_data);
|
||||
}
|
||||
for (int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
void* transfer_data;
|
||||
do {
|
||||
received_data_buffers[i].cb_data.transfer_data_access.lock();
|
||||
transfer_data = received_data_buffers[i].cb_data.transfer_data;
|
||||
received_data_buffers[i].cb_data.transfer_data_access.unlock();
|
||||
if(transfer_data)
|
||||
received_data_buffers[i].cb_data.is_transfer_done_mutex->specific_timed_lock(i);
|
||||
} while(transfer_data);
|
||||
}
|
||||
}
|
||||
|
||||
static void wait_all_libftdi_buffers_free(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
if(received_data_buffers == NULL)
|
||||
return;
|
||||
if(*received_data_buffers[0].status < 0) {
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
libftdi_cancel_callback(&received_data_buffers[i].cb_data);
|
||||
}
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
while(received_data_buffers[i].in_use)
|
||||
received_data_buffers[i].is_buffer_free_shared_mutex->specific_timed_lock(i);
|
||||
}
|
||||
|
||||
static void wait_one_libftdi_buffer_free(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
bool done = false;
|
||||
while(!done) {
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
if(!received_data_buffers[i].in_use)
|
||||
done = true;
|
||||
}
|
||||
if(!done) {
|
||||
if(*received_data_buffers[0].status < 0)
|
||||
return;
|
||||
int dummy = 0;
|
||||
received_data_buffers[0].is_buffer_free_shared_mutex->general_timed_lock(&dummy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool libftdi_are_buffers_all_free(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
return libftdi_get_num_free_buffers(received_data_buffers) == NUM_CAPTURE_RECEIVED_DATA_BUFFERS;
|
||||
}
|
||||
|
||||
static FTD2CaptureReceivedData* libftdi_get_free_buffer(FTD2CaptureReceivedData* received_data_buffers) {
|
||||
wait_one_libftdi_buffer_free(received_data_buffers);
|
||||
if(*received_data_buffers[0].status < 0)
|
||||
return NULL;
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
if(!received_data_buffers[i].in_use) {
|
||||
received_data_buffers[i].is_buffer_free_shared_mutex->specific_try_lock(i);
|
||||
received_data_buffers[i].in_use = true;
|
||||
return &received_data_buffers[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void libftdi_start_read(FTD2CaptureReceivedData* received_data_buffer, int index, size_t size) {
|
||||
if(received_data_buffer == NULL)
|
||||
return;
|
||||
received_data_buffer->index = index;
|
||||
libftdi_schedule_read(&received_data_buffer->cb_data, size);
|
||||
}
|
||||
|
||||
static void end_libftdi_read_frame_cb(FTD2CaptureReceivedData* received_data_buffer) {
|
||||
received_data_buffer->in_use = false;
|
||||
received_data_buffer->is_buffer_free_shared_mutex->specific_unlock(received_data_buffer->cb_data.internal_index);
|
||||
}
|
||||
|
||||
static size_t libftdi_copy_buffer_to_target_and_skip_synch(uint8_t* in_buffer, uint32_t* out_buffer, int read_length, size_t* sync_offset) {
|
||||
// This is because the actual data seems to always start with a SYNCH
|
||||
size_t ignored_halfwords = 0;
|
||||
uint16_t* in_u16 = (uint16_t*)in_buffer;
|
||||
size_t real_length = libftdi_get_actual_length(MAX_PACKET_SIZE_USB2, read_length, FTD2_INTRA_PACKET_HEADER_SIZE);
|
||||
while((ignored_halfwords < (real_length / 2)) && (in_u16[ignored_halfwords + 1 + (ignored_halfwords / (MAX_PACKET_SIZE_USB2 / 2))] == FTD2_OLDDS_SYNCH_VALUES))
|
||||
ignored_halfwords++;
|
||||
size_t copy_offset = ignored_halfwords * 2;
|
||||
if(ignored_halfwords >= ((MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE) / 2))
|
||||
copy_offset = 0;
|
||||
libftdi_copy_buffer_to_target_and_skip(in_buffer, (uint8_t*)out_buffer, MAX_PACKET_SIZE_USB2, read_length, FTD2_INTRA_PACKET_HEADER_SIZE, copy_offset);
|
||||
if(copy_offset == 0) {
|
||||
size_t internal_sync_offset = 0;
|
||||
bool is_synced = synchronization_check((uint16_t*)out_buffer, real_length, NULL, &internal_sync_offset);
|
||||
if(!is_synced) {
|
||||
*sync_offset = (internal_sync_offset / (MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE)) * (MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
*sync_offset = 0;
|
||||
}
|
||||
else
|
||||
*sync_offset = 0;
|
||||
uint16_t* out_u16 = (uint16_t*)out_buffer;
|
||||
for(int i = 0; i < ignored_halfwords; i++)
|
||||
out_u16[(real_length / 2) - ignored_halfwords + i] = FTD2_OLDDS_SYNCH_VALUES;
|
||||
return remove_synch_from_final_length(out_buffer, real_length);
|
||||
}
|
||||
|
||||
static void output_to_thread(CaptureData* capture_data, uint8_t* buffer, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time, int read_length, size_t* sync_offset) {
|
||||
// For some reason, there is usually one.
|
||||
// Though make this generic enough
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - base_time;
|
||||
base_time = curr_time;
|
||||
CaptureDataSingleBuffer* target = capture_data->data_buffers.GetWriterBuffer();
|
||||
// Copy data to buffer, with special memcpy which accounts for ftd2 header data and skips synch bytes
|
||||
size_t real_length = libftdi_copy_buffer_to_target_and_skip_synch(buffer, (uint32_t*)&target->capture_buf, read_length, sync_offset);
|
||||
target->read = real_length;
|
||||
target->time_in_buf = diff.count();
|
||||
capture_data->data_buffers.ReleaseWriterBuffer();
|
||||
|
||||
if(capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
// Signal that there is data available
|
||||
capture_data->status.video_wait.unlock();
|
||||
capture_data->status.audio_wait.unlock();
|
||||
}
|
||||
|
||||
static void libftdi_capture_process_data(void* in_user_data, int transfer_length, int transfer_status) {
|
||||
// Note: sometimes the data returned has length 0...
|
||||
// It's because the code is too fast...
|
||||
FTD2CaptureReceivedData* user_data = (FTD2CaptureReceivedData*)in_user_data;
|
||||
if((*user_data->status) < 0)
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
if(transfer_status != LIBUSB_TRANSFER_COMPLETED) {
|
||||
*user_data->status = LIBUSB_ERROR_OTHER;
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
}
|
||||
if(transfer_length < user_data->cb_data.requested_length)
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
if(((int32_t)(user_data->index - (*user_data->last_used_index))) <= 0) {
|
||||
//*user_data->status = LIBUSB_ERROR_INTERRUPTED;
|
||||
return end_libftdi_read_frame_cb(user_data);
|
||||
}
|
||||
*user_data->last_used_index = user_data->index;
|
||||
|
||||
output_to_thread(user_data->capture_data, (uint8_t*)&user_data->cb_data.buffer_raw, *user_data->clock_start, transfer_length, user_data->curr_offset);
|
||||
end_libftdi_read_frame_cb(user_data);
|
||||
}
|
||||
|
||||
static void resync_offset(FTD2CaptureReceivedData* received_data_buffers, uint32_t &index, size_t full_size) {
|
||||
size_t wanted_offset = *received_data_buffers[0].curr_offset;
|
||||
if(wanted_offset == 0)
|
||||
return;
|
||||
wait_all_libftdi_buffers_free(received_data_buffers);
|
||||
if(get_libftdi_status(received_data_buffers) != 0)
|
||||
return;
|
||||
wanted_offset = *received_data_buffers[0].curr_offset;
|
||||
if(wanted_offset == 0)
|
||||
return;
|
||||
*received_data_buffers[0].curr_offset = 0;
|
||||
#if defined(__APPLE__) || defined(_WIN32)
|
||||
// Literally throw a die... Seems to work!
|
||||
default_sleep(1);
|
||||
return;
|
||||
#endif
|
||||
FTD2OldDSCaptureReceivedRaw* buffer_raw = new FTD2OldDSCaptureReceivedRaw;
|
||||
FTD2OldDSCaptureReceived* buffer = new FTD2OldDSCaptureReceived;
|
||||
CaptureData* capture_data = received_data_buffers[0].capture_data;
|
||||
bool is_synced = false;
|
||||
size_t chosen_transfer_size = (MAX_PACKET_SIZE_USB2 - FTD2_INTRA_PACKET_HEADER_SIZE) * 4;
|
||||
while((!is_synced) && (capture_data->status.connected && capture_data->status.running)) {
|
||||
int retval = libftdi_full_read(received_data_buffers[0].cb_data.handle, (uint8_t*)buffer_raw, (uint8_t*)buffer, chosen_transfer_size, RESYNC_TIMEOUT);
|
||||
if(ftd2_is_error(retval, true)) {
|
||||
//error_libftdi_status(received_data_buffers, retval);
|
||||
delete buffer_raw;
|
||||
delete buffer;
|
||||
return;
|
||||
}
|
||||
size_t internal_sync_offset = 0;
|
||||
is_synced = synchronization_check((uint16_t*)buffer, chosen_transfer_size, NULL, &internal_sync_offset, true);
|
||||
if((!is_synced) && (internal_sync_offset < chosen_transfer_size))
|
||||
is_synced = true;
|
||||
else
|
||||
is_synced = false;
|
||||
}
|
||||
int retval = libftdi_full_read(received_data_buffers[0].cb_data.handle, (uint8_t*)buffer_raw, (uint8_t*)buffer, full_size - chosen_transfer_size, RESYNC_TIMEOUT);
|
||||
if(ftd2_is_error(retval, true)) {
|
||||
error_libftdi_status(received_data_buffers, retval);
|
||||
delete buffer_raw;
|
||||
delete buffer;
|
||||
return;
|
||||
}
|
||||
capture_data->status.cooldown_curr_in = IGNORE_FIRST_FEW_FRAMES_SYNC;
|
||||
delete buffer_raw;
|
||||
delete buffer;
|
||||
}
|
||||
|
||||
void ftd2_capture_main_loop_libftdi(CaptureData* capture_data) {
|
||||
const bool is_libftdi = true;
|
||||
bool is_done = false;
|
||||
int inner_curr_in = 0;
|
||||
int retval = 0;
|
||||
auto clock_start = std::chrono::high_resolution_clock::now();
|
||||
FTD2CaptureReceivedData* received_data_buffers = new FTD2CaptureReceivedData[NUM_CAPTURE_RECEIVED_DATA_BUFFERS];
|
||||
int curr_data_buffer = 0;
|
||||
int next_data_buffer = 0;
|
||||
int status = 0;
|
||||
uint32_t last_used_index = -1;
|
||||
uint32_t index = 0;
|
||||
size_t curr_offset = 0;
|
||||
const size_t full_size = get_capture_size(capture_data->status.device.is_rgb_888);
|
||||
size_t bytesIn;
|
||||
bool usb_thread_run = false;
|
||||
std::thread processing_thread;
|
||||
libftdi_start_thread(&processing_thread, &usb_thread_run, ((ftdi_context*)capture_data->handle)->usb_ctx);
|
||||
|
||||
SharedConsumerMutex is_buffer_free_shared_mutex(NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
SharedConsumerMutex is_transfer_done_mutex(NUM_CAPTURE_RECEIVED_DATA_BUFFERS);
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++) {
|
||||
received_data_buffers[i].actual_length = 0;
|
||||
received_data_buffers[i].is_data_ready = false;
|
||||
received_data_buffers[i].in_use = false;
|
||||
received_data_buffers[i].is_buffer_free_shared_mutex = &is_buffer_free_shared_mutex;
|
||||
received_data_buffers[i].status = &status;
|
||||
received_data_buffers[i].index = 0;
|
||||
received_data_buffers[i].curr_offset = &curr_offset;
|
||||
received_data_buffers[i].last_used_index = &last_used_index;
|
||||
received_data_buffers[i].capture_data = capture_data;
|
||||
received_data_buffers[i].clock_start = &clock_start;
|
||||
received_data_buffers[i].cb_data.function = libftdi_capture_process_data;
|
||||
received_data_buffers[i].cb_data.actual_user_data = &received_data_buffers[i];
|
||||
received_data_buffers[i].cb_data.transfer_data = NULL;
|
||||
received_data_buffers[i].cb_data.handle = capture_data->handle;
|
||||
received_data_buffers[i].cb_data.is_transfer_done_mutex = &is_transfer_done_mutex;
|
||||
received_data_buffers[i].cb_data.requested_length = 0;
|
||||
}
|
||||
|
||||
if(!enable_capture(capture_data->handle, is_libftdi)) {
|
||||
capture_error_print(true, capture_data, "Capture enable error");
|
||||
is_done = true;
|
||||
}
|
||||
|
||||
for(int i = 0; i < NUM_CAPTURE_RECEIVED_DATA_BUFFERS; i++)
|
||||
libftdi_start_read(libftdi_get_free_buffer(received_data_buffers), index++, full_size);
|
||||
|
||||
|
||||
while(capture_data->status.connected && capture_data->status.running) {
|
||||
if(get_libftdi_status(received_data_buffers) != 0) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read error" + std::to_string(get_libftdi_status(received_data_buffers)));
|
||||
is_done = true;
|
||||
}
|
||||
if(is_done)
|
||||
break;
|
||||
libftdi_start_read(libftdi_get_free_buffer(received_data_buffers), index++, full_size);
|
||||
resync_offset(received_data_buffers, index, full_size);
|
||||
}
|
||||
wait_all_libftdi_buffers_free(received_data_buffers);
|
||||
libftdi_close_thread(&processing_thread, &usb_thread_run);
|
||||
delete []received_data_buffers;
|
||||
}
|
@ -62,11 +62,11 @@ std::string get_serial(const is_nitro_usb_device* usb_device_desc, is_nitro_devi
|
||||
}
|
||||
|
||||
void is_nitro_insert_device(std::vector<CaptureDevice>& devices_list, is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, int& curr_serial_extra_id_is_nitro, std::string path) {
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_nitro), usb_device_desc->name, path, CAPTURE_CONN_IS_NITRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_BGR);
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_nitro), usb_device_desc->name, usb_device_desc->long_name, path, CAPTURE_CONN_IS_NITRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_BGR);
|
||||
}
|
||||
|
||||
void is_nitro_insert_device(std::vector<CaptureDevice>& devices_list, is_nitro_device_handlers* handlers, const is_nitro_usb_device* usb_device_desc, int& curr_serial_extra_id_is_nitro) {
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_nitro), usb_device_desc->name, CAPTURE_CONN_IS_NITRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_BGR);
|
||||
devices_list.emplace_back(get_serial(usb_device_desc, handlers, curr_serial_extra_id_is_nitro), usb_device_desc->name, usb_device_desc->long_name, CAPTURE_CONN_IS_NITRO, (void*)usb_device_desc, false, false, false, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_BGR);
|
||||
}
|
||||
|
||||
static is_nitro_device_handlers* usb_find_by_serial_number(const is_nitro_usb_device* usb_device_desc, CaptureDevice* device) {
|
||||
|
@ -106,7 +106,7 @@ struct PACKED is_nitro_packet_header {
|
||||
#pragma pack(pop)
|
||||
|
||||
static const is_nitro_usb_device usb_is_nitro_emu_rare_desc = {
|
||||
.name = "IS Nitro Emulator(R)",
|
||||
.name = "ISNEr", .long_name = "IS Nitro Emulator(R)",
|
||||
.vid = 0x0f6e, .pid = 0x0400,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
@ -115,7 +115,7 @@ static const is_nitro_usb_device usb_is_nitro_emu_rare_desc = {
|
||||
};
|
||||
|
||||
static const is_nitro_usb_device usb_is_nitro_emu_common_desc = {
|
||||
.name = "IS Nitro Emulator",
|
||||
.name = "ISNE", .long_name = "IS Nitro Emulator",
|
||||
.vid = 0x0f6e, .pid = 0x0404,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
@ -124,7 +124,7 @@ static const is_nitro_usb_device usb_is_nitro_emu_common_desc = {
|
||||
};
|
||||
|
||||
static const is_nitro_usb_device usb_is_nitro_cap_desc = {
|
||||
.name = "IS Nitro Capture",
|
||||
.name = "ISNC", .long_name = "IS Nitro Capture",
|
||||
.vid = 0x0f6e, .pid = 0x0403,
|
||||
.default_config = 1, .default_interface = 0,
|
||||
.bulk_timeout = 500,
|
||||
@ -298,16 +298,16 @@ static int SendReadPacket(is_nitro_device_handlers* handlers, uint16_t command,
|
||||
}
|
||||
|
||||
int SendReadCommand(is_nitro_device_handlers* handlers, uint16_t command, uint8_t* buf, int length, const is_nitro_usb_device* device_desc) {
|
||||
return SendReadPacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
return SendReadPacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
}
|
||||
|
||||
int SendWriteCommand(is_nitro_device_handlers* handlers, uint16_t command, uint8_t* buf, int length, const is_nitro_usb_device* device_desc) {
|
||||
return SendWritePacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
return SendWritePacket(handlers, command, IS_NITRO_PACKET_TYPE_COMMAND, 0, buf, length, device_desc);
|
||||
}
|
||||
|
||||
int SendReadCommandU32(is_nitro_device_handlers* handlers, uint16_t command, uint32_t* out, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t buffer;
|
||||
int ret = SendReadCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
int ret = SendReadCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = from_le(buffer);
|
||||
@ -316,13 +316,13 @@ int SendReadCommandU32(is_nitro_device_handlers* handlers, uint16_t command, uin
|
||||
|
||||
int SendWriteCommandU32(is_nitro_device_handlers* handlers, uint16_t command, uint32_t value, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t buffer = to_le(value);
|
||||
return SendWriteCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
return SendWriteCommand(handlers, command, (uint8_t*)&buffer, sizeof(uint32_t), device_desc);
|
||||
}
|
||||
|
||||
int GetDeviceSerial(is_nitro_device_handlers* handlers, uint8_t* buf, const is_nitro_usb_device* device_desc) {
|
||||
if(device_desc->is_capture)
|
||||
return SendReadCommand(handlers, IS_NITRO_CAP_CMD_GET_SERIAL, buf, IS_NITRO_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
return SendReadCommand(handlers, IS_NITRO_EMU_CMD_GET_SERIAL, buf, IS_NITRO_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
return SendReadCommand(handlers, IS_NITRO_CAP_CMD_GET_SERIAL, buf, IS_NITRO_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
return SendReadCommand(handlers, IS_NITRO_EMU_CMD_GET_SERIAL, buf, IS_NITRO_REAL_SERIAL_NUMBER_SIZE, device_desc);
|
||||
}
|
||||
|
||||
int ReadNecMem(is_nitro_device_handlers* handlers, uint32_t address, uint8_t unit_size, uint8_t* buf, int count, const is_nitro_usb_device* device_desc) {
|
||||
@ -375,12 +375,12 @@ int WriteNecMem(is_nitro_device_handlers* handlers, uint32_t address, uint8_t un
|
||||
|
||||
int WriteNecMemU16(is_nitro_device_handlers* handlers, uint32_t address, uint16_t value, const is_nitro_usb_device* device_desc) {
|
||||
uint16_t buffer = to_le(value);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 1, device_desc);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 1, device_desc);
|
||||
}
|
||||
|
||||
int WriteNecMemU32(is_nitro_device_handlers* handlers, uint32_t address, uint32_t value, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t buffer = to_le(value);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 2, device_desc);
|
||||
return WriteNecMem(handlers, address, 2, (uint8_t*)&buffer, 2, device_desc);
|
||||
}
|
||||
|
||||
int DisableLca2(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
@ -403,7 +403,7 @@ int StartUsbCaptureDma(is_nitro_device_handlers* handlers, const is_nitro_usb_de
|
||||
return ret;
|
||||
return WriteNecMemU16(handlers, REG_USB_BIU_CONTROL_2, 1, device_desc);
|
||||
}
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 1, device_desc, false);
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 1, device_desc, false);
|
||||
}
|
||||
|
||||
int StopUsbCaptureDma(is_nitro_device_handlers* handlers, const is_nitro_usb_device* device_desc) {
|
||||
@ -413,7 +413,7 @@ int StopUsbCaptureDma(is_nitro_device_handlers* handlers, const is_nitro_usb_dev
|
||||
return ret;
|
||||
return WriteNecMemU16(handlers, REG_USB_BIU_CONTROL_2, 0, device_desc);
|
||||
}
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 0, device_desc);
|
||||
return SendReadPacket(handlers, IS_NITRO_CAP_CMD_ENABLE_CAP, IS_NITRO_CAPTURE_PACKET_TYPE_DMA_CONTROL, 0, NULL, 0, device_desc);
|
||||
}
|
||||
|
||||
int SetForwardFrameCount(is_nitro_device_handlers* handlers, uint16_t count, const is_nitro_usb_device* device_desc) {
|
||||
@ -434,12 +434,12 @@ int GetFrameCounter(is_nitro_device_handlers* handlers, uint16_t* out, const is_
|
||||
*out = 0;
|
||||
return LIBUSB_SUCCESS;
|
||||
}
|
||||
uint32_t counter = 0;
|
||||
int ret = ReadNecMemU32(handlers, 0x08000028, &counter, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (counter & 0xFF) | ((counter & 0xFF0000) >> 8);
|
||||
return ret;
|
||||
uint32_t counter = 0;
|
||||
int ret = ReadNecMemU32(handlers, 0x08000028, &counter, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (counter & 0xFF) | ((counter & 0xFF0000) >> 8);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int UpdateFrameForwardConfig(is_nitro_device_handlers* handlers, is_nitro_forward_config_values_colors colors, is_nitro_forward_config_values_screens screens, is_nitro_forward_config_values_rate rate, const is_nitro_usb_device* device_desc) {
|
||||
@ -469,31 +469,31 @@ int UpdateFrameForwardEnable(is_nitro_device_handlers* handlers, bool enable, bo
|
||||
}
|
||||
|
||||
int ReadLidState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t flags = 0;
|
||||
uint32_t flags = 0;
|
||||
if(device_desc->is_capture) {
|
||||
int ret = SendReadCommandU32(handlers, IS_NITRO_CAP_CMD_GET_LID_STATE, &flags, device_desc);
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
int ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 2) ? true : false;
|
||||
return ret;
|
||||
int ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 2) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ReadDebugButtonState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc) {
|
||||
uint32_t flags = 0;
|
||||
uint32_t flags = 0;
|
||||
if(device_desc->is_capture) {
|
||||
int ret = SendReadCommandU32(handlers, IS_NITRO_CAP_CMD_GET_DEBUG_STATE, &flags, device_desc);
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
int ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
int ret = ReadNecMemU32(handlers, 0x08000000, &flags, device_desc);
|
||||
if(ret < 0)
|
||||
return ret;
|
||||
*out = (flags & 1) ? true : false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ReadPowerButtonState(is_nitro_device_handlers* handlers, bool* out, const is_nitro_usb_device* device_desc) {
|
||||
@ -553,4 +553,4 @@ void EndISNitroAsyncThread(is_nitro_device_handlers* handlers, void* user_data,
|
||||
if(handlers->usb_handle)
|
||||
return is_nitro_libusb_close_thread(thread_ptr, keep_going);
|
||||
return is_nitro_is_driver_close_thread(thread_ptr, keep_going, (ISNitroCaptureReceivedData*)user_data);
|
||||
}
|
||||
}
|
||||
|
@ -1,505 +0,0 @@
|
||||
#include "dscapture_ftd2.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
#include "usb_generic.hpp"
|
||||
//#include "ftd2xx_symbols_renames.h"
|
||||
|
||||
#include "ftd2_ds2_fw_1.h"
|
||||
#include "ftd2_ds2_fw_2.h"
|
||||
|
||||
#define FTD2XX_STATIC
|
||||
#include <ftd2xx.h>
|
||||
|
||||
#include <cstring>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#define FT_FAILED(x) ((x) != FT_OK)
|
||||
|
||||
#define FTD2XX_VID 0x0403
|
||||
|
||||
#define REAL_SERIAL_NUMBER_SIZE 16
|
||||
#define SERIAL_NUMBER_SIZE (REAL_SERIAL_NUMBER_SIZE+1)
|
||||
|
||||
#define LE16(x) ((x) & 0xff), (((x) >> 8) & 0xff)
|
||||
|
||||
#define FTD2XX_IN_SIZE 0x10000
|
||||
#define FTD2XX_OUT_SIZE 0x10000
|
||||
|
||||
#define CLKRATE 6 // 1 - 25MHz
|
||||
#define CLKDIV ((30 / CLKRATE) - 1)
|
||||
#define RESETDELAY ((1 * CLKRATE) / 8) //1uS in bytes (clks/8)
|
||||
#define INITDELAY ((1200 * CLKRATE) / 8) //1200uS
|
||||
|
||||
#define TX_SPI_SIZE (1 << 16)
|
||||
#define TX_SPI_OFFSET 3
|
||||
|
||||
#define MAX_PACKET_SIZE_FTD2 510
|
||||
#define ENABLE_AUDIO true
|
||||
|
||||
const uint16_t ftd2xx_valid_vids[] = {FTD2XX_VID};
|
||||
const uint16_t ftd2xx_valid_pids[] = {0x6014};
|
||||
|
||||
const uint8_t* ftd2_ds2_fws[] = {
|
||||
ftd2_ds2_fw_1,
|
||||
ftd2_ds2_fw_2,
|
||||
};
|
||||
|
||||
const size_t ftd2_ds2_sizes[] = {
|
||||
ftd2_ds2_fw_1_len,
|
||||
ftd2_ds2_fw_2_len,
|
||||
};
|
||||
|
||||
void list_devices_ftd2(std::vector<CaptureDevice> &devices_list, std::vector<no_access_recap_data> &no_access_list) {
|
||||
FT_STATUS ftStatus;
|
||||
DWORD numDevs = 0;
|
||||
std::string valid_descriptions[] = {"NDS.1", "NDS.2"};
|
||||
int descriptions_firmware_ids[] = {1, 2};
|
||||
ftStatus = FT_CreateDeviceInfoList(&numDevs);
|
||||
size_t num_inserted = 0;
|
||||
if (!FT_FAILED(ftStatus) && numDevs > 0)
|
||||
{
|
||||
const int debug_multiplier = 1;
|
||||
FT_HANDLE ftHandle = NULL;
|
||||
DWORD Flags = 0;
|
||||
DWORD Type = 0;
|
||||
DWORD ID = 0;
|
||||
char SerialNumber[SERIAL_NUMBER_SIZE] = { 0 };
|
||||
char Description[65] = { 0 };
|
||||
for (DWORD i = 0; i < numDevs; i++)
|
||||
{
|
||||
ftStatus = FT_GetDeviceInfoDetail(i, &Flags, &Type, &ID, NULL,
|
||||
SerialNumber, Description, &ftHandle);
|
||||
if((!FT_FAILED(ftStatus)) && (Flags & FT_FLAGS_HISPEED) && (Type == FT_DEVICE_232H))
|
||||
{
|
||||
for(int j = 0; j < sizeof(valid_descriptions) / sizeof(*valid_descriptions); j++) {
|
||||
if(Description == valid_descriptions[j]) {
|
||||
for(int u = 0; u < debug_multiplier; u++)
|
||||
devices_list.emplace_back(std::string(SerialNumber), "DS.2", CAPTURE_CONN_FTD2, (void*)NULL, false, false, ENABLE_AUDIO, WIDTH_DS, HEIGHT_DS + HEIGHT_DS, 0, 0, 0, 0, 0, HEIGHT_DS, VIDEO_DATA_RGB16, descriptions_firmware_ids[j], false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(num_inserted == 0) {
|
||||
#if defined(USE_IS_NITRO_USB) || defined(USE_DS_3DS_USB)
|
||||
if(get_usb_total_filtered_devices(ftd2xx_valid_vids, sizeof(ftd2xx_valid_vids) / sizeof(ftd2xx_valid_vids[0]), ftd2xx_valid_pids, sizeof(ftd2xx_valid_pids) / sizeof(ftd2xx_valid_pids[0])) != numDevs)
|
||||
no_access_list.emplace_back("FTD2XX");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t ftd2_get_video_in_size(CaptureData* capture_data) {
|
||||
return sizeof(USBOldDSVideoInputData);
|
||||
}
|
||||
|
||||
static uint64_t get_capture_size(CaptureData* capture_data) {
|
||||
return (((sizeof(FTD2OldDSCaptureReceived) - EXTRA_DATA_BUFFER_USB_SIZE) + (MAX_PACKET_SIZE_FTD2 - 1)) / MAX_PACKET_SIZE_FTD2) * MAX_PACKET_SIZE_FTD2; // multiple of maxPacketSize
|
||||
}
|
||||
|
||||
static bool pass_if_FT_queue_empty(FT_HANDLE handle) {
|
||||
DWORD bytesIn = 0;
|
||||
FT_STATUS ftStatus;
|
||||
ftStatus = FT_GetQueueStatus(handle, &bytesIn);
|
||||
if(FT_FAILED(ftStatus) || (bytesIn != 0)) //should be empty
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool full_ftd2_write(FT_HANDLE handle, const uint8_t* data, size_t size) {
|
||||
FT_STATUS ftStatus;
|
||||
if(!pass_if_FT_queue_empty(handle)) // maybe MPSSE error?
|
||||
return false;
|
||||
|
||||
DWORD sent;
|
||||
ftStatus = FT_Write(handle, (void*)data, size, &sent);
|
||||
if(FT_FAILED(ftStatus) || (sent != size))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//verify CDONE==val
|
||||
static bool check_cdone(FT_HANDLE handle, bool want_active) {
|
||||
static const uint8_t cmd[] = {
|
||||
0x81, //read D
|
||||
0x83, //read C
|
||||
};
|
||||
uint8_t buf[2];
|
||||
|
||||
if(!full_ftd2_write(handle, cmd, sizeof(cmd)))
|
||||
return false;
|
||||
|
||||
DWORD bytesIn;
|
||||
FT_STATUS ftStatus = FT_Read(handle, buf, 2, &bytesIn);
|
||||
if(FT_FAILED(ftStatus) || (bytesIn != 2) || (buf[0] == 0xFA))
|
||||
return false;
|
||||
|
||||
if(want_active)
|
||||
return (buf[0] & 0x40);
|
||||
return !(buf[0] & 0x40);
|
||||
}
|
||||
|
||||
static FT_STATUS end_spi_tx(uint8_t *txBuf, FT_STATUS ftStatus) {
|
||||
delete []txBuf;
|
||||
return ftStatus;
|
||||
}
|
||||
|
||||
static FT_STATUS ftd2_spi_tx(FT_HANDLE handle, const uint8_t* buf, int size) {
|
||||
uint8_t *txBuf = new uint8_t[TX_SPI_SIZE + TX_SPI_OFFSET];
|
||||
FT_STATUS ftStatus;
|
||||
int len;
|
||||
DWORD sent;
|
||||
DWORD bytesIn;
|
||||
DWORD wrote = 0;
|
||||
|
||||
if(!pass_if_FT_queue_empty(handle))
|
||||
return end_spi_tx(txBuf, FT_OTHER_ERROR);
|
||||
|
||||
while(size > 0) {
|
||||
len = size;
|
||||
if(len > TX_SPI_SIZE)
|
||||
len = TX_SPI_SIZE;
|
||||
memcpy(&txBuf[TX_SPI_OFFSET], &buf[wrote], len);
|
||||
|
||||
txBuf[0] = 0x11;
|
||||
txBuf[1] = (len - 1) & 0xFF;
|
||||
txBuf[2] = ((len - 1) >> 8) & 0xFF;
|
||||
|
||||
ftStatus = FT_Write(handle, (void*)txBuf, len + TX_SPI_OFFSET, &sent);
|
||||
if(FT_FAILED(ftStatus))
|
||||
return end_spi_tx(txBuf, ftStatus);
|
||||
if(sent != (len + TX_SPI_OFFSET))
|
||||
return end_spi_tx(txBuf, FT_INSUFFICIENT_RESOURCES);
|
||||
|
||||
if(!pass_if_FT_queue_empty(handle))
|
||||
return end_spi_tx(txBuf, FT_OTHER_ERROR);
|
||||
|
||||
wrote += sent - TX_SPI_OFFSET;
|
||||
size -= len;
|
||||
}
|
||||
return end_spi_tx(txBuf, FT_OK);
|
||||
}
|
||||
|
||||
static bool fpga_config(FT_HANDLE handle, const uint8_t* bitstream, int size) {
|
||||
//D6=CDONE (in)
|
||||
//D3=SS (out)
|
||||
//D2=TDO (in)
|
||||
//D1=TDI (out)
|
||||
//D0=TCK (out)
|
||||
//C7=reset (out)
|
||||
|
||||
//Lattice programming:
|
||||
// hold SS low
|
||||
// pulse reset 200ns
|
||||
// wait 1200us
|
||||
// release SS
|
||||
// send 8 clocks
|
||||
// hold SS low
|
||||
// send configuration MSB first, sampled on +clk
|
||||
// release SS
|
||||
// CDONE should go high within 100 clocks
|
||||
// send >49 clocks after CDONE=1
|
||||
|
||||
static const uint8_t cmd0[] = { //configure for lattice SPI:
|
||||
0x82, 0x7f, 0x80, //set Cx pins {val,dir:1=out}: reset=0
|
||||
0x80, 0xf0, 0x0b, //set Dx pins {val,dir:1=out}: SS=0, clk idle low, TDI out, TCK out
|
||||
0x8f, LE16(RESETDELAY), //reset delay
|
||||
0x82, 0xff, 0x00, //set Cx pins: reset=PU (does val=1 enable pullups? seems to...)
|
||||
0x8f, LE16(INITDELAY), //init delay
|
||||
0x80, 0xf8, 0x0b, //set Dx pins: SS=1
|
||||
0x8f, LE16(1), //16 dummy clocks
|
||||
0x80, 0xf0, 0x0b, //set Dx pins: SS=0
|
||||
};
|
||||
|
||||
FT_STATUS ftStatus;
|
||||
ftStatus = FT_SetTimeouts(handle, 300, 300);
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
if(!full_ftd2_write(handle, cmd0, sizeof(cmd0)))
|
||||
return false;
|
||||
|
||||
//verify CDONE=0
|
||||
if(!check_cdone(handle, false))
|
||||
return false;
|
||||
|
||||
//send configuration
|
||||
ftStatus = ftd2_spi_tx(handle, bitstream, size);
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
|
||||
//finish up
|
||||
static const uint8_t cmd1[] = {
|
||||
0x80, 0xf8, 0x0b, //set Dx pins: SS=1
|
||||
0x8f, LE16(20), //>150 dummy clocks
|
||||
0x80, 0x00, 0x00, //float Dx
|
||||
0x82, 0x00, 0x00, //float Cx
|
||||
};
|
||||
if(!full_ftd2_write(handle, cmd1, sizeof(cmd1)))
|
||||
return false;
|
||||
|
||||
//verify CDONE=1
|
||||
if(!check_cdone(handle, true))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool init_MPSSE(FT_HANDLE handle) {
|
||||
static const uint8_t cmd[] = {
|
||||
0x85, //no loopback
|
||||
0x8d, //disable 3-phase clocking
|
||||
0x8a, //disable clk divide-by-5
|
||||
0x97, //disable adaptive clocking
|
||||
0x86, LE16(CLKDIV), //set clock rate
|
||||
};
|
||||
|
||||
FT_STATUS ftStatus;
|
||||
ftStatus = FT_ResetDevice(handle);
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
ftStatus = FT_SetUSBParameters(handle, FTD2XX_IN_SIZE, FTD2XX_OUT_SIZE); //Multiple of 64 bytes up to 64k
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
ftStatus = FT_SetChars(handle, 0, 0, 0, 0);
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
ftStatus = FT_SetTimeouts(handle, 300, 300); //read,write timeout (ms)
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
ftStatus = FT_SetLatencyTimer(handle, 3); //time to wait before incomplete packet is sent (default=16ms). MPSSE read seems to fail on 2 sometimes, too fast?
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
ftStatus = FT_SetFlowControl(handle, FT_FLOW_RTS_CTS, 0, 0); //turn on flow control to synchronize IN requests
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
ftStatus = FT_SetBitMode(handle, 0x00, FT_BITMODE_RESET); //performs a general reset on MPSSE
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
ftStatus = FT_SetBitMode(handle, 0x00, FT_BITMODE_MPSSE); //enable MPSSE mode
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
|
||||
//MPSSE seems to choke on first write sometimes :/ Send, purge, resend.
|
||||
DWORD sent;
|
||||
ftStatus = FT_Write(handle, (void*)cmd, 1, &sent); //enable MPSSE mode
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
default_sleep();
|
||||
ftStatus = FT_Purge(handle, FT_PURGE_RX | FT_PURGE_TX);
|
||||
if(FT_FAILED(ftStatus))
|
||||
return false;
|
||||
return full_ftd2_write(handle, cmd, sizeof(cmd));
|
||||
}
|
||||
|
||||
static void preemptive_close_connection(CaptureData* capture_data) {
|
||||
FT_ResetDevice(capture_data->handle);
|
||||
FT_Close(capture_data->handle);
|
||||
}
|
||||
|
||||
bool connect_ftd2(bool print_failed, CaptureData* capture_data, CaptureDevice* device) {
|
||||
char SerialNumber[SERIAL_NUMBER_SIZE] = { 0 };
|
||||
strncpy(SerialNumber, device->serial_number.c_str(), REAL_SERIAL_NUMBER_SIZE);
|
||||
SerialNumber[REAL_SERIAL_NUMBER_SIZE] = 0;
|
||||
if(FT_OpenEx(SerialNumber, FT_OPEN_BY_SERIAL_NUMBER, &capture_data->handle)) {
|
||||
capture_error_print(print_failed, capture_data, "Create failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!init_MPSSE(capture_data->handle)) {
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "MPSSE init failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!fpga_config(capture_data->handle, ftd2_ds2_fws[device->firmware_id - 1], ftd2_ds2_sizes[device->firmware_id - 1])) {
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "FPGA config failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
FT_STATUS ftStatus;
|
||||
WORD val=0;
|
||||
ftStatus = FT_ReadEE(capture_data->handle, 1, &val);
|
||||
if(FT_FAILED(ftStatus) || (val != 0x0403)) { //=85A8: something went wrong (fpga is configured but FT chip detected wrong eeprom size)
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "EEPROM read error");
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
WORD Firmware = 0;
|
||||
WORD Hardware = 0;
|
||||
ftStatus = FT_ReadEE(capture_data->handle, 0x10, &Firmware);
|
||||
if(FT_FAILED(ftStatus)) {
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "Firmware ID read error");
|
||||
return false;
|
||||
}
|
||||
ftStatus = FT_ReadEE(capture_data->handle, 0x11, &Hardware);
|
||||
if(FT_FAILED(ftStatus)) {
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "Hardware ID read error");
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
ftStatus = FT_SetBitMode(capture_data->handle, 0x00, FT_BITMODE_SYNC_FIFO); //to FIFO mode. This takes over port B, pins shouldn't get modified though
|
||||
if(FT_FAILED(ftStatus)) {
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "Bitmode setup error");
|
||||
return false;
|
||||
}
|
||||
|
||||
ftStatus = FT_SetTimeouts(capture_data->handle, 50, 50);
|
||||
if(FT_FAILED(ftStatus)) {
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "Timeouts setup error");
|
||||
return false;
|
||||
}
|
||||
|
||||
static const uint8_t cmd[]={ 0x80, 0x01 }; //enable capture
|
||||
if(!full_ftd2_write(capture_data->handle, cmd, sizeof(cmd))) {
|
||||
preemptive_close_connection(capture_data);
|
||||
capture_error_print(print_failed, capture_data, "Capture enable error");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
//DS frame:
|
||||
// video (top|bottom interleaved RGB16), 256*192*2*2 bytes
|
||||
// audio (16bit stereo, approx. 32729 Hz), 0x8F4 bytes
|
||||
// actual number of samples varies, audio is padded with 0x4321
|
||||
FrameResult DS2Device::getFrame(DSFrame *frame) {
|
||||
enum {
|
||||
FRAMESIZE = ndsWidth*ndsHeight*2*2,
|
||||
S_MAX = 0x47A/2, //#audiosamples(dword) aligns frame to 510 bytes..
|
||||
READSIZE = FRAMESIZE + S_MAX*4,
|
||||
MAX = READSIZE/2, //(usbFifoWords)
|
||||
};
|
||||
|
||||
FT_STATUS status;
|
||||
DWORD bytesIn;
|
||||
|
||||
status=FT_Read(handle, frame->raw, READSIZE, &bytesIn);
|
||||
if(status!=FT_OK) {
|
||||
DEBUG_TRACE("err %d\n",status); //disconnected = FT_IO_ERROR
|
||||
usb_close();
|
||||
return FRAME_ERROR;
|
||||
}
|
||||
if(bytesIn!=READSIZE) { //stream stopped (lid closed / DS is off)
|
||||
DEBUG_TRACE(".");
|
||||
return FRAME_SKIP;
|
||||
}
|
||||
|
||||
//check sync
|
||||
uint16_t *src=(uint16_t*)frame->raw;
|
||||
int samples;
|
||||
if(src[0]==0x4321) {
|
||||
samples=0;
|
||||
while(samples<MAX && src[samples]==0x4321)
|
||||
samples++;
|
||||
if(samples==MAX) //?? shouldn't happen
|
||||
DEBUG_TRACE("wut?");
|
||||
FT_Read(handle, frame->raw, samples*2, &bytesIn);
|
||||
DEBUG_TRACE("resync(%d)",samples);
|
||||
return FRAME_SKIP;
|
||||
} else if(src[MAX-1]!=0x4321) {
|
||||
samples=0;
|
||||
while(samples<MAX && src[samples]!=0x4321)
|
||||
samples++;
|
||||
while(samples<MAX && src[samples]==0x4321)
|
||||
samples++;
|
||||
if(samples==MAX) //?? shouldn't happen
|
||||
DEBUG_TRACE("wut?");
|
||||
FT_Read(handle, frame->raw, samples*2, &bytesIn);
|
||||
DEBUG_TRACE("resync(%d)",samples);
|
||||
return FRAME_SKIP;
|
||||
} else {
|
||||
//DEBUG_TRACE(".");
|
||||
}
|
||||
|
||||
//count audio samples
|
||||
samples=0;
|
||||
uint32_t *a=(uint32_t*)(frame->raw+FRAMESIZE);
|
||||
while(samples<S_MAX && a[samples]!=0x43214321)
|
||||
samples++;
|
||||
|
||||
//sanity check
|
||||
if(samples<547 || samples>548)
|
||||
DEBUG_TRACE("%d?",samples);
|
||||
|
||||
frame->audioBuf=a;
|
||||
frame->audioSamples=samples;
|
||||
|
||||
return FRAME_OK;
|
||||
}
|
||||
*/
|
||||
|
||||
static bool synchronization_check(CaptureData* capture_data, uint16_t* data_buffer) {
|
||||
//check sync
|
||||
DWORD bytesIn;
|
||||
int samples = 0;
|
||||
int size_words = get_capture_size(capture_data) / 2;
|
||||
if(data_buffer[0] == FTD2_OLDDS_SYNCH_VALUES) {
|
||||
while((samples < size_words) && (data_buffer[samples] == FTD2_OLDDS_SYNCH_VALUES))
|
||||
samples++;
|
||||
// Do a read to re-synchronize
|
||||
FT_Read(capture_data->handle, data_buffer, samples * 2, &bytesIn);
|
||||
return false;
|
||||
} else if(data_buffer[size_words - 1] != FTD2_OLDDS_SYNCH_VALUES) {
|
||||
// Find the first spot the padding is present
|
||||
while((samples < size_words) && (data_buffer[samples] != FTD2_OLDDS_SYNCH_VALUES))
|
||||
samples++;
|
||||
while((samples < size_words) && (data_buffer[samples] == FTD2_OLDDS_SYNCH_VALUES))
|
||||
samples++;
|
||||
// Do a read to re-synchronize
|
||||
FT_Read(capture_data->handle, data_buffer, samples * 2, &bytesIn);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void data_output_update(CaptureReceived* buffer, CaptureData* capture_data, int read_amount, std::chrono::time_point<std::chrono::high_resolution_clock> &base_time) {
|
||||
const auto curr_time = std::chrono::high_resolution_clock::now();
|
||||
const std::chrono::duration<double> diff = curr_time - base_time;
|
||||
base_time = curr_time;
|
||||
capture_data->data_buffers.WriteToBuffer(buffer, read_amount, diff.count(), &capture_data->status.device);
|
||||
|
||||
if(capture_data->status.cooldown_curr_in)
|
||||
capture_data->status.cooldown_curr_in = capture_data->status.cooldown_curr_in - 1;
|
||||
// Signal that there is data available
|
||||
capture_data->status.video_wait.unlock();
|
||||
capture_data->status.audio_wait.unlock();
|
||||
}
|
||||
|
||||
void ftd2_capture_main_loop(CaptureData* capture_data) {
|
||||
int inner_curr_in = 0;
|
||||
FT_STATUS ftStatus;
|
||||
auto clock_start = std::chrono::high_resolution_clock::now();
|
||||
CaptureReceived* data_buffer = new CaptureReceived[2];
|
||||
DWORD bytesIn;
|
||||
int read_size = get_capture_size(capture_data);
|
||||
|
||||
while (capture_data->status.connected && capture_data->status.running) {
|
||||
ftStatus = FT_Read(capture_data->handle, data_buffer, read_size, &bytesIn);
|
||||
if(FT_FAILED(ftStatus)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Read failed");
|
||||
return;
|
||||
}
|
||||
if(bytesIn < read_size)
|
||||
continue;
|
||||
if(!synchronization_check(capture_data, (uint16_t*)data_buffer))
|
||||
continue;
|
||||
data_output_update(data_buffer, capture_data, bytesIn, clock_start);
|
||||
}
|
||||
}
|
||||
|
||||
void ftd2_capture_cleanup(CaptureData* capture_data) {
|
||||
if(FT_Close(capture_data->handle)) {
|
||||
capture_error_print(true, capture_data, "Disconnected: Close failed");
|
||||
}
|
||||
}
|
@ -207,6 +207,13 @@ static int insert_device(std::vector<CaptureDevice> &devices_list, const usb_dev
|
||||
int result = libusb_open(usb_device, &handle);
|
||||
if(result || (handle == NULL))
|
||||
return result;
|
||||
result = libusb_claim_interface(handle, usb_device_desc->capture_interface);
|
||||
if(result == LIBUSB_SUCCESS)
|
||||
libusb_release_interface(handle, usb_device_desc->capture_interface);
|
||||
if(result < 0) {
|
||||
libusb_close(handle);
|
||||
return result;
|
||||
}
|
||||
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);
|
||||
|
@ -24,7 +24,7 @@ static const LicenseMenuOptionInfo sfml_license_4_option = {
|
||||
static const LicenseMenuOptionInfo ftd3xx_license_0_option = {
|
||||
.base_name = "This software makes use of"};
|
||||
|
||||
#if defined(USE_FTD3) && defined(USE_FTD2)
|
||||
#if defined(USE_FTD3) && defined(USE_FTD2_DRIVER)
|
||||
static const LicenseMenuOptionInfo ftd3xx_license_1_option = {
|
||||
.base_name = "FTD3XX and FTD2XX."};
|
||||
#else
|
||||
@ -46,6 +46,21 @@ static const LicenseMenuOptionInfo ftd3xx_license_3_option = {
|
||||
static const LicenseMenuOptionInfo ftd3xx_license_4_option = {
|
||||
.base_name = "driver-licence-terms-details/"};
|
||||
|
||||
static const LicenseMenuOptionInfo libftdi_license_0_option = {
|
||||
.base_name = "This software makes use of"};
|
||||
|
||||
static const LicenseMenuOptionInfo libftdi_license_1_option = {
|
||||
.base_name = "libftdi1."};
|
||||
|
||||
static const LicenseMenuOptionInfo libftdi_license_2_option = {
|
||||
.base_name = "For its license, check:"};
|
||||
|
||||
static const LicenseMenuOptionInfo libftdi_license_3_option = {
|
||||
.base_name = "http://developer.intra2net.com/git/?p="};
|
||||
|
||||
static const LicenseMenuOptionInfo libftdi_license_4_option = {
|
||||
.base_name = "libftdi;a=blob_plain;f=LICENSE;hb=HEAD/"};
|
||||
|
||||
static const LicenseMenuOptionInfo libusb_license_0_option = {
|
||||
.base_name = "This software makes use of"};
|
||||
|
||||
@ -127,14 +142,21 @@ static const LicenseMenuOptionInfo* pollable_options[] = {
|
||||
&sfml_license_2_option,
|
||||
&sfml_license_3_option,
|
||||
&sfml_license_4_option,
|
||||
#if defined(USE_FTD3) || defined(USE_FTD2)
|
||||
#if defined(USE_FTD3) || defined(USE_FTD2_DRIVER)
|
||||
&ftd3xx_license_0_option,
|
||||
&ftd3xx_license_1_option,
|
||||
&ftd3xx_license_2_option,
|
||||
&ftd3xx_license_3_option,
|
||||
&ftd3xx_license_4_option,
|
||||
#endif
|
||||
#if defined(USE_DS_3DS_USB) || defined(USE_IS_NITRO_USB) || defined(USE_FTD3) || defined(USE_FTD2)
|
||||
#ifdef USE_FTD2_LIBFTDI
|
||||
&libftdi_license_0_option,
|
||||
&libftdi_license_1_option,
|
||||
&libftdi_license_2_option,
|
||||
&libftdi_license_3_option,
|
||||
&libftdi_license_4_option,
|
||||
#endif
|
||||
#if defined(USE_LIBUSB) || defined(USE_FTD3) || defined(USE_FTD2_DRIVER)
|
||||
&libusb_license_0_option,
|
||||
&libusb_license_1_option,
|
||||
&libusb_license_2_option,
|
||||
|
@ -143,7 +143,7 @@ void StatusMenu::prepare(float menu_scaling_factor, int view_size_x, int view_si
|
||||
this->labels[index]->setText(this->get_string_option(real_index, DEFAULT_ACTION) + " - V." + get_version_string());
|
||||
break;
|
||||
case STATUS_MENU_CONNECTION:
|
||||
this->labels[index]->setText(get_name_of_device(capture_status));
|
||||
this->labels[index]->setText(get_name_of_device(capture_status, true));
|
||||
break;
|
||||
case STATUS_MENU_FPS_IN:
|
||||
this->labels[index + INC_ACTION]->setText(get_float_str_decimals(in_fps, 2));
|
||||
|
@ -51,7 +51,7 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp
|
||||
FPSArrayInit(&this->in_fps);
|
||||
FPSArrayInit(&this->draw_fps);
|
||||
FPSArrayInit(&this->poll_fps);
|
||||
(void)this->in_tex.resize({MAX_IN_VIDEO_WIDTH, MAX_IN_VIDEO_HEIGHT * NUM_FRAMES_BLENDED});
|
||||
(void)this->in_tex.resize({MAX_IN_VIDEO_WIDTH * NUM_FRAMES_BLENDED, MAX_IN_VIDEO_HEIGHT});
|
||||
this->m_in_rect_top.setTexture(&this->in_tex);
|
||||
this->m_in_rect_bot.setTexture(&this->in_tex);
|
||||
this->display_data = display_data;
|
||||
@ -83,11 +83,11 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp
|
||||
if(current_shader->shader.loadFromMemory(get_shader_string(current_shader->shader_enum), sf::Shader::Type::Fragment)) {
|
||||
current_shader->is_valid = true;
|
||||
auto* const defaultStreamBuffer = sf::err().rdbuf();
|
||||
sf::err().rdbuf(nullptr);
|
||||
sf::err().rdbuf(nullptr);
|
||||
sf::Glsl::Vec2 old_pos = {0.0, 0.0};
|
||||
current_shader->shader.setUniform("old_frame_offset", old_pos);
|
||||
sf::err().rdbuf(defaultStreamBuffer);
|
||||
}
|
||||
sf::err().rdbuf(defaultStreamBuffer);
|
||||
}
|
||||
}
|
||||
loaded_shaders = true;
|
||||
}
|
||||
@ -469,25 +469,25 @@ std::string WindowScreen::title_factory() {
|
||||
|
||||
void WindowScreen::update_texture() {
|
||||
unsigned int m_texture = this->in_tex.getNativeHandle();
|
||||
if (this->saved_buf && m_texture)
|
||||
{
|
||||
// Copy pixels from the given array to the texture
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
GLenum format = GL_RGB;
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
if(this->capture_status->device.video_data_type == VIDEO_DATA_BGR)
|
||||
format = GL_BGR;
|
||||
if(this->capture_status->device.video_data_type == VIDEO_DATA_RGB16)
|
||||
type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
if(this->capture_status->device.video_data_type == VIDEO_DATA_BGR16)
|
||||
type = GL_UNSIGNED_SHORT_5_6_5_REV;
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(0), static_cast<GLint>(this->curr_frame_texture_pos * MAX_IN_VIDEO_HEIGHT), static_cast<GLsizei>(this->capture_status->device.width), static_cast<GLsizei>(this->capture_status->device.height), format, type, this->saved_buf);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
if (this->saved_buf && m_texture)
|
||||
{
|
||||
// Copy pixels from the given array to the texture
|
||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||
GLenum format = GL_RGB;
|
||||
GLenum type = GL_UNSIGNED_BYTE;
|
||||
if(this->capture_status->device.video_data_type == VIDEO_DATA_BGR)
|
||||
format = GL_BGR;
|
||||
if(this->capture_status->device.video_data_type == VIDEO_DATA_RGB16)
|
||||
type = GL_UNSIGNED_SHORT_5_6_5;
|
||||
if(this->capture_status->device.video_data_type == VIDEO_DATA_BGR16)
|
||||
type = GL_UNSIGNED_SHORT_5_6_5_REV;
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(this->curr_frame_texture_pos * MAX_IN_VIDEO_WIDTH), static_cast<GLint>(0), static_cast<GLsizei>(this->capture_status->device.width), static_cast<GLsizei>(this->capture_status->device.height), format, type, this->saved_buf);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
// Force an OpenGL flush, so that the texture data will appear updated
|
||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||
glFlush();
|
||||
}
|
||||
// Force an OpenGL flush, so that the texture data will appear updated
|
||||
// in all contexts immediately (solves problems in multi-threaded apps)
|
||||
glFlush();
|
||||
}
|
||||
}
|
||||
|
||||
void WindowScreen::pre_texture_conversion_processing() {
|
||||
@ -572,17 +572,17 @@ void WindowScreen::post_texture_conversion_processing(out_rect_data &rect_data,
|
||||
rect_data.out_tex.clear();
|
||||
sf::RectangleShape final_in_rect = in_rect;
|
||||
sf::IntRect text_coords_rect = final_in_rect.getTextureRect();
|
||||
text_coords_rect.position.y += this->curr_frame_texture_pos * MAX_IN_VIDEO_HEIGHT;
|
||||
text_coords_rect.position.x += this->curr_frame_texture_pos * MAX_IN_VIDEO_WIDTH;
|
||||
final_in_rect.setTextureRect(text_coords_rect);
|
||||
if(this->capture_status->connected && actually_draw) {
|
||||
bool use_default_shader = true;
|
||||
if(sf::Shader::isAvailable()) {
|
||||
int chosen_shader = choose_shader(true, is_top);
|
||||
if(chosen_shader >= 0) {
|
||||
float old_frame_pos_y = 1.0 / NUM_FRAMES_BLENDED;
|
||||
if(this->curr_frame_texture_pos == 1)
|
||||
old_frame_pos_y = -1.0 / NUM_FRAMES_BLENDED;
|
||||
sf::Glsl::Vec2 old_pos = {0.0, old_frame_pos_y};
|
||||
float old_frame_pos_x = ((float)(NUM_FRAMES_BLENDED - 1)) / NUM_FRAMES_BLENDED;
|
||||
if(this->curr_frame_texture_pos > 0)
|
||||
old_frame_pos_x = -1.0 / NUM_FRAMES_BLENDED;
|
||||
sf::Glsl::Vec2 old_pos = {old_frame_pos_x, 0.0};
|
||||
usable_shaders[chosen_shader].shader.setUniform("old_frame_offset", old_pos);
|
||||
rect_data.out_tex.draw(final_in_rect, &usable_shaders[chosen_shader].shader);
|
||||
use_default_shader = false;
|
||||
|
@ -242,7 +242,7 @@ static void soundCall(AudioData *audio_data, CaptureData* capture_data) {
|
||||
if(data_buffer != NULL) {
|
||||
loaded_samples = audio.samples.size();
|
||||
if((data_buffer->read > get_video_in_size(capture_data)) && (loaded_samples < MAX_MAX_AUDIO_LATENCY)) {
|
||||
int n_samples = get_audio_n_samples(capture_data, data_buffer->read);
|
||||
uint64_t n_samples = get_audio_n_samples(capture_data, data_buffer->read);
|
||||
double out_time = data_buffer->time_in_buf;
|
||||
bool conversion_success = convertAudioToOutput(out_buf[audio_buf_counter], n_samples, endianness, data_buffer, &capture_data->status);
|
||||
if(!conversion_success)
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "conversions.hpp"
|
||||
#include "devicecapture.hpp"
|
||||
#include "3dscapture_ftd3.hpp"
|
||||
#include "dscapture_ftd2.hpp"
|
||||
#include "dscapture_ftd2_shared.hpp"
|
||||
#include "usb_ds_3ds_capture.hpp"
|
||||
#include "usb_is_nitro_acquisition.hpp"
|
||||
|
||||
@ -215,7 +215,7 @@ bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, Capt
|
||||
return converted;
|
||||
}
|
||||
|
||||
bool convertAudioToOutput(std::int16_t *p_out, uint64_t n_samples, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status) {
|
||||
bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status) {
|
||||
if(!status->device.has_audio)
|
||||
return true;
|
||||
CaptureReceived *p_in = &data_buffer->capture_buf;
|
||||
@ -229,13 +229,8 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t n_samples, const bool is
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
if(status->device.cc_type == CAPTURE_CONN_FTD2) {
|
||||
if(status->device.cc_type == CAPTURE_CONN_FTD2)
|
||||
base_ptr = (uint8_t*)p_in->ftd2_received_old_ds.audio_data;
|
||||
int real_samples = 0;
|
||||
while((real_samples < n_samples) && (((uint32_t*)base_ptr)[real_samples] != (FTD2_OLDDS_SYNCH_VALUES | (FTD2_OLDDS_SYNCH_VALUES << 16))))
|
||||
real_samples++;
|
||||
n_samples = real_samples;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_DS_3DS_USB
|
||||
if(status->device.cc_type == CAPTURE_CONN_USB) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
#include "devicecapture.hpp"
|
||||
#include "3dscapture_ftd3.hpp"
|
||||
#include "dscapture_ftd2.hpp"
|
||||
#include "dscapture_ftd2_shared.hpp"
|
||||
#include "usb_ds_3ds_capture.hpp"
|
||||
#include "usb_is_nitro_acquisition.hpp"
|
||||
|
||||
@ -80,7 +80,7 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
|
||||
list_devices_ftd3(devices_list, no_access_list);
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
list_devices_ftd2(devices_list, no_access_list);
|
||||
list_devices_ftd2_shared(devices_list, no_access_list);
|
||||
#endif
|
||||
#ifdef USE_DS_3DS_USB
|
||||
list_devices_usb_ds_3ds(devices_list, no_access_list);
|
||||
@ -118,7 +118,7 @@ bool connect(bool print_failed, CaptureData* capture_data, FrontendData* fronten
|
||||
return false;
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_FTD2) && (!connect_ftd2(print_failed, capture_data, &devices_list[chosen_device])))
|
||||
if((devices_list[chosen_device].cc_type == CAPTURE_CONN_FTD2) && (!connect_ftd2_shared(print_failed, capture_data, &devices_list[chosen_device])))
|
||||
return false;
|
||||
#endif
|
||||
#ifdef USE_DS_3DS_USB
|
||||
@ -155,7 +155,7 @@ void captureCall(CaptureData* capture_data) {
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD2)
|
||||
ftd2_capture_main_loop(capture_data);
|
||||
ftd2_capture_main_loop_shared(capture_data);
|
||||
#endif
|
||||
#ifdef USE_DS_3DS_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_USB)
|
||||
@ -181,7 +181,7 @@ void captureCall(CaptureData* capture_data) {
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_FTD2)
|
||||
ftd2_capture_cleanup(capture_data);
|
||||
ftd2_capture_cleanup_shared(capture_data);
|
||||
#endif
|
||||
#ifdef USE_DS_3DS_USB
|
||||
if(capture_data->status.device.cc_type == CAPTURE_CONN_USB)
|
||||
@ -228,10 +228,12 @@ uint64_t get_video_in_size(CaptureData* capture_data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string get_name_of_device(CaptureStatus* capture_status) {
|
||||
std::string get_name_of_device(CaptureStatus* capture_status, bool use_long) {
|
||||
if(!capture_status->connected)
|
||||
return "Not connected";
|
||||
return capture_status->device.name + " - " + capture_status->device.serial_number;
|
||||
if(!use_long)
|
||||
return capture_status->device.name + " - " + capture_status->device.serial_number;
|
||||
return capture_status->device.long_name + " - " + capture_status->device.serial_number;
|
||||
}
|
||||
|
||||
void capture_init() {
|
||||
@ -241,6 +243,9 @@ void capture_init() {
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
usb_is_nitro_init();
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
ftd2_init_shared();
|
||||
#endif
|
||||
}
|
||||
|
||||
void capture_close() {
|
||||
@ -250,4 +255,7 @@ void capture_close() {
|
||||
#ifdef USE_IS_NITRO_USB
|
||||
usb_is_nitro_close();
|
||||
#endif
|
||||
#ifdef USE_FTD2
|
||||
ftd2_end_shared();
|
||||
#endif
|
||||
}
|
||||
|
@ -30,14 +30,14 @@ static bool _is_be = false;
|
||||
bool is_big_endian(void) {
|
||||
if(checked_be_once)
|
||||
return _is_be;
|
||||
union {
|
||||
uint32_t i;
|
||||
char c[4];
|
||||
} value = {0x01020304};
|
||||
union {
|
||||
uint32_t i;
|
||||
char c[4];
|
||||
} value = {0x01020304};
|
||||
|
||||
checked_be_once = true;
|
||||
_is_be = value.c[0] == 1;
|
||||
return _is_be;
|
||||
return _is_be;
|
||||
}
|
||||
|
||||
static uint32_t reverse_endianness(uint32_t value) {
|
||||
|
@ -39,3 +39,29 @@ add_custom_command(
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${OUTPUT_NAME}> ${CMAKE_BINARY_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
set(OUTPUT_NAME CMakeRenameLibFunctions)
|
||||
project(${OUTPUT_NAME} VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
add_executable(${OUTPUT_NAME} rename_lib_functions.cpp)
|
||||
target_compile_features(${OUTPUT_NAME} PRIVATE cxx_std_17)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy Output"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${OUTPUT_NAME}> ${CMAKE_BINARY_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
set(OUTPUT_NAME CMakeRenameSymbols)
|
||||
project(${OUTPUT_NAME} VERSION 1.0.0 LANGUAGES CXX)
|
||||
|
||||
add_executable(${OUTPUT_NAME} rename_symbols_list.cpp)
|
||||
target_compile_features(${OUTPUT_NAME} PRIVATE cxx_std_17)
|
||||
|
||||
add_custom_command(
|
||||
TARGET ${OUTPUT_NAME}
|
||||
COMMENT "Copy Output"
|
||||
POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:${OUTPUT_NAME}> ${CMAKE_BINARY_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
|
93
tools/rename_lib_functions.cpp
Normal file
93
tools/rename_lib_functions.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#if (!defined(_MSC_VER)) || (_MSC_VER > 1916)
|
||||
#include <filesystem>
|
||||
#else
|
||||
#include <experimental/filesystem>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 4) {
|
||||
cout << "Usage: " << argv[0] << " text_file new_start lib_file" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
string new_start(argv[2]);
|
||||
ifstream input(argv[1], ios::in);
|
||||
if(!input) {
|
||||
cout << "Couldn't open input file!" << endl;
|
||||
return -2;
|
||||
}
|
||||
vector<string> file_lines;
|
||||
vector<string> new_start_lines;
|
||||
string single_str = "";
|
||||
while (getline(input, single_str)) {
|
||||
file_lines.push_back(single_str);
|
||||
string new_string = single_str;
|
||||
for(int i = 0; i < new_start.length(); i++)
|
||||
new_string[i] = new_start[i];
|
||||
new_start_lines.push_back(new_string);
|
||||
}
|
||||
|
||||
input.close();
|
||||
|
||||
vector<uint8_t> buffer;
|
||||
ifstream lib_in(argv[3], ios::in | ios::binary);
|
||||
if(!lib_in) {
|
||||
cout << "Couldn't open in library file!" << endl;
|
||||
return -2;
|
||||
}
|
||||
// Get length of file
|
||||
lib_in.seekg(0, ios::end);
|
||||
size_t length = lib_in.tellg();
|
||||
lib_in.seekg(0, ios::beg);
|
||||
|
||||
//read file
|
||||
if (length > 0) {
|
||||
buffer.resize(length);
|
||||
lib_in.read((char*)&buffer[0], length);
|
||||
}
|
||||
|
||||
for(int u = 0; u < new_start_lines.size(); u++) {
|
||||
const uint8_t* old_data = (const uint8_t*)file_lines[u].c_str();
|
||||
const uint8_t* new_data = (const uint8_t*)new_start_lines[u].c_str();
|
||||
auto start_iterator = std::begin(buffer);
|
||||
uint8_t* inner_buffer = &buffer[0];
|
||||
size_t old_data_size = strlen((const char*)old_data);
|
||||
while(1) {
|
||||
start_iterator = search(
|
||||
start_iterator, std::end(buffer),
|
||||
std::begin(file_lines[u]), std::end(file_lines[u]));
|
||||
|
||||
if (start_iterator == std::end(buffer))
|
||||
break;
|
||||
else
|
||||
{
|
||||
size_t match_pos = std::distance(std::begin(buffer), start_iterator);
|
||||
// This is technically wrong, but it works, so...
|
||||
if((match_pos > 0) && (inner_buffer[match_pos - 1] == 0)) {
|
||||
for(int i = 0; i < old_data_size; i++)
|
||||
inner_buffer[match_pos + i] = new_data[i];
|
||||
}
|
||||
start_iterator += old_data_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ofstream lib_out(argv[3], ios::out | ios::binary);
|
||||
if(!lib_out) {
|
||||
cout << "Couldn't open out library file!" << endl;
|
||||
return -2;
|
||||
}
|
||||
lib_out.write((char*)&buffer[0], buffer.size());
|
||||
lib_out.close();
|
||||
|
||||
return 0;
|
||||
}
|
52
tools/rename_symbols_list.cpp
Normal file
52
tools/rename_symbols_list.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#if (!defined(_MSC_VER)) || (_MSC_VER > 1916)
|
||||
#include <filesystem>
|
||||
#else
|
||||
#include <experimental/filesystem>
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if(argc < 4) {
|
||||
cout << "Usage: " << argv[0] << " text_file new_start define_file" << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
string new_start(argv[2]);
|
||||
ifstream input(argv[1], ios::in);
|
||||
if(!input) {
|
||||
cout << "Couldn't open input file!" << endl;
|
||||
return -2;
|
||||
}
|
||||
vector<string> file_lines;
|
||||
vector<string> new_start_lines;
|
||||
string single_str = "";
|
||||
while (getline(input, single_str)) {
|
||||
file_lines.push_back(single_str);
|
||||
string new_string = single_str;
|
||||
for(int i = 0; i < new_start.length(); i++)
|
||||
new_string[i] = new_start[i];
|
||||
new_start_lines.push_back(new_string);
|
||||
}
|
||||
|
||||
input.close();
|
||||
|
||||
ofstream output_define(argv[3], ios::out);
|
||||
if(!output_define) {
|
||||
cout << "Couldn't open output define file!" << endl;
|
||||
return -2;
|
||||
}
|
||||
for(int i = 0; i < file_lines.size(); i++)
|
||||
output_define << "#define " << file_lines[i] << " " << new_start_lines[i] << endl;
|
||||
|
||||
output_define.close();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user