Make the software compatible with lower end hardware

This commit is contained in:
Lorenzooone 2025-04-27 01:29:22 +02:00
parent 33660b3ef7
commit 64dec0a515
68 changed files with 846 additions and 296 deletions

View File

@ -16,9 +16,9 @@ jobs:
fail-fast: false
matrix:
platform:
- { name: Windows VS2022 x64, os: windows-2022, flags: -A x64, artifact_name: win64}
- { name: Windows VS2022 ARM, os: windows-2022, flags: -A ARM64, artifact_name: winarm64}
- { name: Windows VS2022 Win32, os: windows-2022, flags: -A Win32, artifact_name: win32}
- { name: Windows VS2022 x64, os: windows-2022, flags: -A x64 -DCMAKE_PARALLEL_MSVC=TRUE, artifact_name: win64}
- { name: Windows VS2022 ARM, os: windows-2022, flags: -A ARM64 -DCMAKE_PARALLEL_MSVC=TRUE, artifact_name: winarm64}
- { name: Windows VS2022 Win32, os: windows-2022, flags: -A Win32 -DCMAKE_PARALLEL_MSVC=TRUE, artifact_name: win32}
- { name: Linux GCC x64, os: ubuntu-latest, flags: 64, artifact_name: linux64}
- { name: Linux GCC 32, os: ubuntu-latest, flags: 32, artifact_name: linux32}
- { name: Linux GCC ARM 64, os: ubuntu-latest, flags: arm64, artifact_name: linuxarm64}

View File

@ -1,11 +1,25 @@
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_PARALLEL_MSVC FALSE CACHE BOOL "Enables parallel compilation with MSVC")
#Workaround due to cmake parallel being broken, and needing to set these
#flags before the project is defined...
if(${CMAKE_PARALLEL_MSVC})
message("Parallel build MSVC configuration")
set(CMAKE_C_FLAGS_INIT "${CMAKE_C_FLAGS_INIT} /MP")
set(CMAKE_CXX_FLAGS_INIT "${CMAKE_CXX_FLAGS_INIT} /MP")
endif()
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
set(TARGET_LANGUAGES CXX C)
project(cc3dsfs VERSION 1.0.0 LANGUAGES ${TARGET_LANGUAGES})
include(ExternalProject)
if((${CMAKE_PARALLEL_MSVC}) AND (NOT (MSVC)))
message(FATAL_ERROR "Parallel build option specific to MSVC used with wrong compiler!")
endif()
set(N3DSXL_LOOPY_SUPPORT 1)
set(NEW_DS_LOOPY_SUPPORT 1)
set(IS_DEVICES_SUPPORT 1)
@ -57,6 +71,7 @@ else()
list(APPEND EXTRA_CXX_FLAGS "-Wno-ignored-qualifiers")
list(APPEND EXTRA_CXX_FLAGS "-Wno-missing-field-initializers")
endif()
set(RASPBERRY_PI_COMPILATION FALSE CACHE BOOL "Option for compiling the Raspberry Pi GPIO library in")
set(SFML_BUILD_NETWORK FALSE)
set(EXTRA_LIBRARIES "")
@ -532,7 +547,7 @@ else()
set_source_files_properties(source/conversions.cpp PROPERTIES COMPILE_OPTIONS "$<$<CONFIG:Release>:-O3;-funroll-loops>")
endif()
add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp source/Menus/AudioDeviceMenu.cpp source/Menus/SeparatorMenu.cpp source/Menus/ColorCorrectionMenu.cpp source/Menus/Main3DMenu.cpp source/Menus/SecondScreen3DRelativePositionMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES})
add_executable(${OUTPUT_NAME} source/cc3dsfs.cpp source/utils.cpp source/audio_data.cpp source/audio.cpp source/frontend.cpp source/TextRectangle.cpp source/TextRectanglePool.cpp source/WindowScreen.cpp source/WindowScreen_Menu.cpp source/devicecapture.cpp source/conversions.cpp source/ExtraButtons.cpp source/Menus/ConnectionMenu.cpp source/Menus/OptionSelectionMenu.cpp source/Menus/MainMenu.cpp source/Menus/VideoMenu.cpp source/Menus/CropMenu.cpp source/Menus/PARMenu.cpp source/Menus/RotationMenu.cpp source/Menus/OffsetMenu.cpp source/Menus/AudioMenu.cpp source/Menus/BFIMenu.cpp source/Menus/RelativePositionMenu.cpp source/Menus/ResolutionMenu.cpp source/Menus/FileConfigMenu.cpp source/Menus/ExtraSettingsMenu.cpp source/Menus/StatusMenu.cpp source/Menus/LicenseMenu.cpp source/WindowCommands.cpp source/Menus/ShortcutMenu.cpp source/Menus/ActionSelectionMenu.cpp source/Menus/ScalingRatioMenu.cpp source/Menus/ISNitroMenu.cpp source/Menus/VideoEffectsMenu.cpp source/CaptureDataBuffers.cpp source/Menus/InputMenu.cpp source/Menus/AudioDeviceMenu.cpp source/Menus/SeparatorMenu.cpp source/Menus/ColorCorrectionMenu.cpp source/Menus/Main3DMenu.cpp source/Menus/SecondScreen3DRelativePositionMenu.cpp ${TOOLS_DATA_DIR}/font_ttf.cpp ${TOOLS_DATA_DIR}/shaders_list.cpp ${SOURCE_CPP_EXTRA_FILES})
if(NOT ("${EXTRA_DEPENDENCIES}" STREQUAL ""))
add_dependencies(${OUTPUT_NAME} ${EXTRA_DEPENDENCIES})

View File

@ -14,7 +14,7 @@
class ActionSelectionMenu : public OptionSelectionMenu {
public:
ActionSelectionMenu(bool font_load_success, sf::Font &text_font);
ActionSelectionMenu(TextRectanglePool* text_pool);
~ActionSelectionMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, PossibleWindowCommands curr_cmd);
void insert_data(std::vector<const WindowCommand*> &possible_actions);

View File

@ -14,7 +14,7 @@
class AudioDeviceMenu : public OptionSelectionMenu {
public:
AudioDeviceMenu(bool font_load_success, sf::Font &text_font);
AudioDeviceMenu(TextRectanglePool* text_pool);
~AudioDeviceMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, const audio_output_device_data curr_device_data);
void insert_data(std::vector<std::string>* possible_devices);

View File

@ -26,7 +26,7 @@ enum AudioMenuOutAction{
class AudioMenu : public OptionSelectionMenu {
public:
AudioMenu(bool font_load_success, sf::Font &text_font);
AudioMenu(TextRectanglePool* text_pool);
~AudioMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, AudioData *audio_data);
void insert_data();

View File

@ -20,7 +20,7 @@ enum BFIMenuOutAction{
class BFIMenu : public OptionSelectionMenu {
public:
BFIMenu(bool font_load_success, sf::Font &text_font);
BFIMenu(TextRectanglePool* text_pool);
~BFIMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info);
void insert_data();

View File

@ -13,7 +13,7 @@
class ColorCorrectionMenu : public OptionSelectionMenu {
public:
ColorCorrectionMenu(bool font_load_success, sf::Font &text_font);
ColorCorrectionMenu(TextRectanglePool* text_pool);
~ColorCorrectionMenu();
void setup_title(std::string added_name);
void prepare(float scaling_factor, int view_size_x, int view_size_y, int current_crop);

View File

@ -9,7 +9,7 @@
class ConnectionMenu : public OptionSelectionMenu {
public:
ConnectionMenu(bool font_load_success, sf::Font &text_font);
ConnectionMenu(TextRectanglePool* text_pool);
~ConnectionMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y);
void insert_data(std::vector<CaptureDevice> *devices_list);

View File

@ -13,7 +13,7 @@
class CropMenu : public OptionSelectionMenu {
public:
CropMenu(bool font_load_success, sf::Font &text_font);
CropMenu(TextRectanglePool* text_pool);
~CropMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, int current_crop);
void insert_data(std::vector<const CropData*>* possible_crops);

View File

@ -18,7 +18,7 @@ enum ExtraSettingsMenuOutAction{
class ExtraSettingsMenu : public OptionSelectionMenu {
public:
ExtraSettingsMenu(bool font_load_success, sf::Font &text_font);
ExtraSettingsMenu(TextRectanglePool* text_pool);
~ExtraSettingsMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y);
void insert_data(ScreenType s_type, bool is_fullscreen);

View File

@ -18,7 +18,7 @@ struct FileData {
class FileConfigMenu : public OptionSelectionMenu {
public:
FileConfigMenu(bool font_load_success, sf::Font &text_font);
FileConfigMenu(TextRectanglePool* text_pool);
~FileConfigMenu();
void setup_title(std::string added_name);
void prepare(float scaling_factor, int view_size_x, int view_size_y);

View File

@ -25,7 +25,7 @@ enum ISNitroMenuOutAction{
class ISNitroMenu : public OptionSelectionMenu {
public:
ISNitroMenu(bool font_load_success, sf::Font &text_font);
ISNitroMenu(TextRectanglePool* text_pool);
~ISNitroMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, CaptureStatus* capture_status);
void insert_data(CaptureDevice* device);

View File

@ -21,7 +21,7 @@ enum InputMenuOutAction{
class InputMenu : public OptionSelectionMenu {
public:
InputMenu(bool font_load_success, sf::Font &text_font);
InputMenu(TextRectanglePool* text_pool);
~InputMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, InputData* input_data);
void insert_data(bool enabled_shortcuts, bool enabled_extra_buttons);

View File

@ -15,7 +15,7 @@ enum LicenseMenuOutAction{
class LicenseMenu : public OptionSelectionMenu {
public:
LicenseMenu(bool font_load_success, sf::Font &text_font);
LicenseMenu(TextRectanglePool* text_pool);
~LicenseMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y);
void insert_data();

View File

@ -24,7 +24,7 @@ enum Main3DMenuOutAction{
class Main3DMenu : public OptionSelectionMenu {
public:
Main3DMenu(bool font_load_success, sf::Font &text_font);
Main3DMenu(TextRectanglePool* text_pool);
~Main3DMenu();
void prepare(float menu_scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info, DisplayData* display_data, CaptureStatus* status);
void insert_data(ScreenType stype);

View File

@ -32,7 +32,7 @@ enum MainMenuOutAction{
class MainMenu : public OptionSelectionMenu {
public:
MainMenu(bool font_load_success, sf::Font &text_font);
MainMenu(TextRectanglePool* text_pool);
~MainMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, bool connected);
void insert_data(ScreenType s_type, bool is_fullscreen, bool mono_app_mode, CaptureDevice* device, bool connected);

View File

@ -23,7 +23,7 @@ enum OffsetMenuOutAction{
class OffsetMenu : public OptionSelectionMenu {
public:
OffsetMenu(bool font_load_success, sf::Font &text_font);
OffsetMenu(TextRectanglePool* text_pool);
~OffsetMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info);
void insert_data();

View File

@ -5,6 +5,7 @@
#include <chrono>
#include "TextRectangle.hpp"
#include "TextRectanglePool.hpp"
#include "event_structs.hpp"
#define BACK_X_OUTPUT_OPTION -1
@ -50,7 +51,7 @@ protected:
int single_option_multiplier;
int get_num_pages();
void initialize(bool font_load_success, sf::Font &text_font);
void initialize(TextRectanglePool* text_pool);
void prepare_options();
void base_prepare(float menu_scaling_factor, int view_size_x, int view_size_y);
std::string setTextOptionInt(int index, int value);

View File

@ -13,7 +13,7 @@
class PARMenu : public OptionSelectionMenu {
public:
PARMenu(bool font_load_success, sf::Font &text_font);
PARMenu(TextRectanglePool* text_pool);
~PARMenu();
void setup_title(std::string added_name);
void prepare(float scaling_factor, int view_size_x, int view_size_y, int current_crop);

View File

@ -5,6 +5,7 @@
#include <chrono>
#include "TextRectangle.hpp"
#include "TextRectanglePool.hpp"
#include "display_structs.hpp"
#include "event_structs.hpp"
@ -19,7 +20,7 @@ enum RelPosMenuOutAction{
class RelativePositionMenu {
public:
RelativePositionMenu();
RelativePositionMenu(bool font_load_success, sf::Font &text_font);
RelativePositionMenu(TextRectanglePool* text_pool);
virtual ~RelativePositionMenu();
bool poll(SFEvent &event_data);
void draw(float scaling_factor, sf::RenderTarget &window);
@ -57,12 +58,13 @@ protected:
sf::Color menu_color;
std::string title;
void initialize(bool font_load_success, sf::Font &text_font);
void initialize(TextRectanglePool* text_pool);
void prepare_options();
void base_prepare(float menu_scaling_factor, int view_size_x, int view_size_y);
void prepare_text_slices(int x_multiplier, int x_divisor, int y_multiplier, int y_divisor, int index, float text_scaling_factor, bool center = false);
virtual bool is_option_selectable(int index);
virtual bool is_option_drawable(int index);
virtual void set_output_option(int index);
virtual std::string get_string_option(int index);
virtual void class_setup();

View File

@ -13,7 +13,7 @@
class ResolutionMenu : public OptionSelectionMenu {
public:
ResolutionMenu(bool font_load_success, sf::Font &text_font);
ResolutionMenu(TextRectanglePool* text_pool);
~ResolutionMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, int fullscreen_mode_width, int fullscreen_mode_height);
void insert_data(std::vector<sf::VideoMode>* possible_resolutions, const sf::VideoMode &desktop_resolution);

View File

@ -21,7 +21,7 @@ enum RotationMenuOutAction{
class RotationMenu : public OptionSelectionMenu {
public:
RotationMenu(bool font_load_success, sf::Font &text_font);
RotationMenu(TextRectanglePool* text_pool);
~RotationMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info);
void insert_data();

View File

@ -22,7 +22,7 @@ enum ScalingRatioMenuOutAction{
class ScalingRatioMenu : public OptionSelectionMenu {
public:
ScalingRatioMenu(bool font_load_success, sf::Font &text_font);
ScalingRatioMenu(TextRectanglePool* text_pool);
~ScalingRatioMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info);
void insert_data();

View File

@ -20,7 +20,7 @@ enum SecondScreen3DRelPosMenuOutAction{
class SecondScreen3DRelativePositionMenu : public RelativePositionMenu {
public:
SecondScreen3DRelativePositionMenu(bool font_load_success, sf::Font &text_font);
SecondScreen3DRelativePositionMenu(TextRectanglePool* text_pool);
~SecondScreen3DRelativePositionMenu();
std::chrono::time_point<std::chrono::high_resolution_clock> last_input_processed_time;
void reset_output_option();
@ -29,6 +29,7 @@ public:
SecondScreen3DRelPosMenuOutAction selected_index = SecondScreen3DRelPosMenuOutAction::SECOND_SCREEN_3D_REL_POS_MENU_NO_ACTION;
SecondScreen3DRelativePosition selected_confirm_value = SECOND_SCREEN_3D_REL_POS_END;
protected:
bool is_option_drawable(int index);
bool is_option_selectable(int index);
void set_output_option(int index);
std::string get_string_option(int index);

View File

@ -23,7 +23,7 @@ enum SeparatorMenuOutAction{
class SeparatorMenu : public OptionSelectionMenu {
public:
SeparatorMenu(bool font_load_success, sf::Font &text_font);
SeparatorMenu(TextRectanglePool* text_pool);
~SeparatorMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info);
void insert_data(bool is_fullscreen);

View File

@ -13,7 +13,7 @@
class ShortcutMenu : public OptionSelectionMenu {
public:
ShortcutMenu(bool font_load_success, sf::Font &text_font);
ShortcutMenu(TextRectanglePool* text_pool);
~ShortcutMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y);
void insert_data(std::vector<std::string> &shortcut_names);

View File

@ -16,7 +16,7 @@ enum StatusMenuOutAction{
class StatusMenu : public OptionSelectionMenu {
public:
StatusMenu(bool font_load_success, sf::Font &text_font);
StatusMenu(TextRectanglePool* text_pool);
~StatusMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, double in_fps, double poll_fps, double draw_fps, CaptureStatus* capture_status);
void insert_data();

View File

@ -20,7 +20,7 @@ enum VideoEffectsMenuOutAction{
class VideoEffectsMenu : public OptionSelectionMenu {
public:
VideoEffectsMenu(bool font_load_success, sf::Font &text_font);
VideoEffectsMenu(TextRectanglePool* text_pool);
~VideoEffectsMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info);
void insert_data();

View File

@ -46,7 +46,7 @@ enum VideoMenuOutAction{
class VideoMenu : public OptionSelectionMenu {
public:
VideoMenu(bool font_load_success, sf::Font &text_font);
VideoMenu(TextRectanglePool* text_pool);
~VideoMenu();
void prepare(float scaling_factor, int view_size_x, int view_size_y, ScreenInfo *info, ScreenType screen_type);
void insert_data(ScreenType s_type, bool is_fullscreen, bool can_have_titlebar);

View File

@ -0,0 +1,20 @@
#ifndef __TEXTRECTANGLEPOOL_HPP
#define __TEXTRECTANGLEPOOL_HPP
#include "TextRectangle.hpp"
class TextRectanglePool {
public:
TextRectanglePool(bool font_load_success, sf::Font *text_font);
~TextRectanglePool();
void request_num_text_rectangles(int num_wanted_text_rectangles);
TextRectangle* get_text_rectangle(int index);
private:
bool font_load_success;
sf::Font *text_font;
int num_loaded_text_rectangles;
TextRectangle** text_rectangles_list;
};
#endif

View File

@ -46,17 +46,18 @@ struct PACKED RGB83DSVideoInputData_3D {
uint8_t screen_data[IN_VIDEO_SIZE_3DS_3D][3];
};
#define OLD_DS_PIXEL_B_BITS 5
#define OLD_DS_PIXEL_G_BITS 6
#define OLD_DS_PIXEL_R_BITS 5
#define OLD_DS_PIXEL_G_BITS 6
#define OLD_DS_PIXEL_B_BITS 5
struct PACKED USBOldDSPixelData {
uint16_t b : OLD_DS_PIXEL_B_BITS;
uint16_t g : OLD_DS_PIXEL_G_BITS;
// The internal order needs to be reversed... This is so confusing...
struct PACKED ALIGNED(2) USBOldDSPixelData {
uint16_t r : OLD_DS_PIXEL_R_BITS;
uint16_t g : OLD_DS_PIXEL_G_BITS;
uint16_t b : OLD_DS_PIXEL_B_BITS;
};
struct PACKED USBOldDSVideoInputData {
struct PACKED ALIGNED(2) USBOldDSVideoInputData {
USBOldDSPixelData screen_data[IN_VIDEO_SIZE_DS];
};
@ -64,10 +65,11 @@ struct PACKED USBOldDSVideoInputData {
#define OPTIMIZE_3DS_PIXEL_G_BITS 6
#define OPTIMIZE_3DS_PIXEL_B_BITS 5
struct PACKED USB5653DSOptimizePixelData {
uint16_t r : OPTIMIZE_3DS_PIXEL_R_BITS;
uint16_t g : OPTIMIZE_3DS_PIXEL_G_BITS;
// The internal order needs to be reversed... This is so confusing...
struct PACKED ALIGNED(2) USB5653DSOptimizePixelData {
uint16_t b : OPTIMIZE_3DS_PIXEL_B_BITS;
uint16_t g : OPTIMIZE_3DS_PIXEL_G_BITS;
uint16_t r : OPTIMIZE_3DS_PIXEL_R_BITS;
};
struct PACKED USB8883DSOptimizePixelData {
@ -100,22 +102,22 @@ struct PACKED USB3DSOptimizeHeaderSoundData {
USB3DSOptimizeSingleSoundData samples[2];
};
struct PACKED USB5653DSOptimizeInputColumnData {
struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData {
USB3DSOptimizeHeaderSoundData header_sound;
USB5653DSOptimizePixelData pixel[HEIGHT_3DS][2];
};
struct PACKED USB5653DSOptimizeInputColumnData3D {
struct PACKED ALIGNED(16) USB5653DSOptimizeInputColumnData3D {
USB3DSOptimizeHeaderSoundData header_sound;
USB5653DSOptimizePixelData pixel[HEIGHT_3DS][3];
};
struct PACKED USB8883DSOptimizeInputColumnData {
struct PACKED ALIGNED(16) USB8883DSOptimizeInputColumnData {
USB3DSOptimizeHeaderSoundData header_sound;
USB8883DSOptimizePixelData pixel[HEIGHT_3DS][2];
};
struct PACKED USB8883DSOptimizeInputColumnData3D {
struct PACKED ALIGNED(16) USB8883DSOptimizeInputColumnData3D {
USB3DSOptimizeHeaderSoundData header_sound;
USB8883DSOptimizePixelData pixel[HEIGHT_3DS][3];
};
@ -124,7 +126,7 @@ struct PACKED ISNitroEmulatorVideoInputData {
uint8_t screen_data[IN_VIDEO_SIZE_DS][3];
};
struct PACKED ISTWLCaptureVideoInputData {
struct PACKED ALIGNED(2) ISTWLCaptureVideoInputData {
USBOldDSPixelData screen_data[IN_VIDEO_SIZE_DS];
uint8_t bit_6_rb_screen_data[(IN_VIDEO_SIZE_DS >> 3) * 2];
};

View File

@ -6,4 +6,6 @@
bool convertVideoToOutput(VideoOutputData *p_out, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status, bool interleaved_3d);
bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &last_buffer_index, const bool is_big_endian, CaptureDataSingleBuffer* data_buffer, CaptureStatus* status);
void manualConvertOutputToRGB(VideoOutputData* src, VideoOutputData* dst, size_t pos_x_data, size_t pos_y_data, size_t width, size_t height, InputVideoDataType video_data_type);
#endif

View File

@ -111,10 +111,59 @@ struct SharedData {
InputData input_data;
};
struct ALIGNED(8) VideoOutputData {
uint8_t screen_data[MAX_IN_VIDEO_SIZE][3];
#pragma pack(push, 1)
// The internal order needs to be reversed... This is so confusing...
struct PACKED ALIGNED(2) VideoPixelRGB16 {
uint16_t b : 5;
uint16_t g : 6;
uint16_t r : 5;
};
// The internal order needs to be reversed... This is so confusing...
struct PACKED ALIGNED(2) VideoPixelBGR16 {
uint16_t r : 5;
uint16_t g : 6;
uint16_t b : 5;
};
struct PACKED VideoPixelRGB {
uint8_t r;
uint8_t g;
uint8_t b;
};
struct PACKED VideoPixelBGR {
uint8_t b;
uint8_t g;
uint8_t r;
};
struct PACKED ALIGNED(16) VideoOutputDataRGB16 {
VideoPixelRGB16 screen_data[MAX_IN_VIDEO_SIZE];
};
struct PACKED ALIGNED(16) VideoOutputDataBGR16 {
VideoPixelBGR16 screen_data[MAX_IN_VIDEO_SIZE];
};
struct PACKED ALIGNED(16) VideoOutputDataRGB {
VideoPixelRGB screen_data[MAX_IN_VIDEO_SIZE];
};
struct PACKED ALIGNED(16) VideoOutputDataBGR {
VideoPixelBGR screen_data[MAX_IN_VIDEO_SIZE];
};
union PACKED ALIGNED(16) VideoOutputData {
VideoOutputDataRGB16 rgb16_video_output_data;
VideoOutputDataBGR16 bgr16_video_output_data;
VideoOutputDataRGB rgb_video_output_data;
VideoOutputDataBGR bgr_video_output_data;
};
#pragma pack(pop)
struct CropData {
int top_width;
int top_height;

View File

@ -11,6 +11,7 @@
#include "audio_data.hpp"
#include "capture_structs.hpp"
#include "TextRectangle.hpp"
#include "TextRectanglePool.hpp"
#include "sfml_gfx_structs.hpp"
#include "ConnectionMenu.hpp"
#include "MainMenu.hpp"
@ -52,11 +53,19 @@ struct FPSArray {
int index;
};
struct OutTextData {
std::string full_text;
std::string small_text;
std::string preamble_name = NAME;
bool consumed = true;
TextKind kind;
};
class WindowScreen {
public:
ScreenInfo m_info;
WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, SharedData* shared_data, AudioData* audio_data, ConsumerMutex *draw_lock, bool created_proper_folder);
WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, SharedData* shared_data, AudioData* audio_data, ConsumerMutex *draw_lock, bool created_proper_folder, bool disable_frame_blending);
~WindowScreen();
void build();
@ -76,6 +85,7 @@ public:
void update_save_menu();
void print_notification(std::string text, TextKind kind = TEXT_KIND_NORMAL);
void process_own_out_text_data(bool print_to_notification = true);
int load_data();
int save_data();
bool open_capture();
@ -103,6 +113,9 @@ private:
const PARData *par;
bool divide_3d_par;
};
OutTextData own_out_text_data;
InputVideoDataType last_update_texture_data_type;
bool use_texture_software_based_conv;
bool created_proper_folder;
CaptureStatus* capture_status;
std::string win_title;
@ -119,7 +132,6 @@ private:
bool m_prepare_quit;
bool m_scheduled_split;
int ret_val;
bool font_load_success;
double frame_time;
DisplayData* display_data;
SharedData* shared_data;
@ -190,7 +202,12 @@ private:
std::chrono::time_point<std::chrono::high_resolution_clock> last_menu_change_time;
int curr_frame_texture_pos = 0;
sf::Texture in_tex;
int num_frames_to_blend;
sf::Texture full_in_tex;
bool shared_texture_available;
sf::Texture top_l_in_tex;
sf::Texture top_r_in_tex;
sf::Texture bot_in_tex;
sf::Font text_font;
@ -212,6 +229,7 @@ private:
sf::VideoMode curr_desk_mode;
TextRectangle* notification;
TextRectanglePool* text_rectangle_pool;
ConsumerMutex display_lock;
ConsumerMutex *draw_lock;
@ -230,6 +248,10 @@ private:
void free_ownership_of_window(bool is_main_thread);
void resize_in_rect(sf::RectangleShape &in_rect, int start_x, int start_y, int width, int height);
int get_pos_x_screen_inside_data(bool is_top, bool is_second = false);
int get_pos_y_screen_inside_data(bool is_top, bool is_second = false);
int get_pos_x_screen_inside_in_tex(bool is_top, bool is_second = false);
int get_pos_y_screen_inside_in_tex(bool is_top, bool is_second = false);
int get_screen_corner_modifier_x(int rotation, int width);
int get_screen_corner_modifier_y(int rotation, int height);
void print_notification_on_off(std::string base_text, bool value);
@ -286,6 +308,10 @@ private:
void prepare_screen_rendering();
bool window_needs_work();
void window_factory(bool is_main_thread);
void opengl_error_out(std::string error_base, std::string error_str);
void opengl_error_check(std::string error_base);
bool single_update_texture(unsigned int m_texture, InputVideoDataType video_data_type, size_t pos_x_data, size_t pos_y_data, size_t width, size_t height, bool manually_converted);
void execute_single_update_texture(bool &manually_converted, bool do_full, bool is_top = false, bool is_second = false);
void update_texture();
int _choose_base_input_shader(bool is_top);
int _choose_color_emulation_shader(bool is_top);
@ -371,32 +397,44 @@ struct FrontendData {
bool reload;
};
void ConsumeOutText(OutTextData &out_text_data, bool update_consumed = true);
void UpdateOutText(OutTextData &out_text_data, std::string full_text, std::string small_text, TextKind kind);
void FPSArrayInit(FPSArray *array);
void FPSArrayDestroy(FPSArray *array);
void FPSArrayInsertElement(FPSArray *array, double frame_time);
void insert_basic_crops(std::vector<const CropData*> &crop_vector, ScreenType s_type, bool is_ds, bool allow_game_specific);
void insert_basic_pars(std::vector<const PARData*> &par_vector);
void insert_basic_color_profiles(std::vector<const ShaderColorEmulationData*> &color_profiles_vector);
void reset_display_data(DisplayData *display_data);
void reset_input_data(InputData* input_data);
void reset_shared_data(SharedData* shared_data);
void reset_fullscreen_info(ScreenInfo &info);
void sanitize_enabled_info(ScreenInfo &top_bot_info, ScreenInfo &top_info, ScreenInfo &bot_info);
void override_set_data_to_screen_info(override_win_data &override_win, ScreenInfo &info);
void reset_screen_info(ScreenInfo &info);
bool load_screen_info(std::string key, std::string value, std::string base, ScreenInfo &info);
std::string save_screen_info(std::string base, const ScreenInfo &info);
const PARData* get_base_par();
void get_par_size(int &width, int &height, float multiplier_factor, const PARData *correction_factor, bool divide_3d_par);
void get_par_size(float &width, float &height, float multiplier_factor, const PARData *correction_factor, bool divide_3d_par);
SecondScreen3DRelativePosition get_second_screen_pos(ScreenInfo* info, ScreenType stype);
void update_output(FrontendData* frontend_data, double frame_time = 0.0, VideoOutputData *out_buf = NULL);
void update_connected_3ds_ds(FrontendData* frontend_data, const CaptureDevice &old_cc_device, const CaptureDevice &new_cc_device);
void update_connected_specific_settings(FrontendData* frontend_data, const CaptureDevice &cc_device);
void screen_display_thread(WindowScreen *screen);
std::string get_name_non_int_mode(NonIntegerScalingModes input);
std::string get_name_frame_blending_mode(FrameBlendingMode input);
std::string get_name_input_colorspace_mode(InputColorspaceMode input);
bool is_input_data_valid(InputData* input_data, bool consider_buttons);
void default_sleep(float wanted_ms = -1);
#endif

View File

@ -70,6 +70,13 @@
#define MAX_IN_VIDEO_SIZE (MAX_IN_VIDEO_WIDTH * MAX_IN_VIDEO_HEIGHT)
#define MAX_IN_VIDEO_BPP_SIZE IN_VIDEO_BPP_SIZE_3DS
#define MAX_IN_VIDEO_WIDTH_TOP IN_VIDEO_WIDTH_DS
#define MAX_IN_VIDEO_HEIGHT_TOP (TOP_WIDTH_3DS + TOP_WIDTH_3DS)
#define MAX_IN_VIDEO_WIDTH_SINGLE_TOP IN_VIDEO_WIDTH_DS
#define MAX_IN_VIDEO_HEIGHT_SINGLE_TOP TOP_WIDTH_3DS
#define MAX_IN_VIDEO_WIDTH_BOTTOM IN_VIDEO_WIDTH_DS
#define MAX_IN_VIDEO_HEIGHT_BOTTOM BOT_WIDTH_3DS
// 1096 is the value when things are ideal. However, it can actually happen that the transfer isn't 100% on time.
// When that happens, a bit more audio data may get transfered. It's a ton on O3DS when Windows underprioritizes USB...
// In general, it should be less than * 2, but you never know. For now, go for safety at x16...

View File

@ -1,7 +1,7 @@
#include "ActionSelectionMenu.hpp"
ActionSelectionMenu::ActionSelectionMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
ActionSelectionMenu::ActionSelectionMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
ActionSelectionMenu::~ActionSelectionMenu() {

View File

@ -1,7 +1,7 @@
#include "AudioDeviceMenu.hpp"
AudioDeviceMenu::AudioDeviceMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
AudioDeviceMenu::AudioDeviceMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
AudioDeviceMenu::~AudioDeviceMenu() {

View File

@ -60,9 +60,9 @@ static const AudioMenuOptionInfo* pollable_options[] = {
&audio_restart_option,
};
AudioMenu::AudioMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
AudioMenu::AudioMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -46,9 +46,9 @@ static const BFIMenuOptionInfo* pollable_options[] = {
&bfi_amount_option,
};
BFIMenu::BFIMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
BFIMenu::BFIMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -1,7 +1,7 @@
#include "ColorCorrectionMenu.hpp"
ColorCorrectionMenu::ColorCorrectionMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
ColorCorrectionMenu::ColorCorrectionMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
ColorCorrectionMenu::~ColorCorrectionMenu() {

View File

@ -1,7 +1,7 @@
#include "ConnectionMenu.hpp"
ConnectionMenu::ConnectionMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
ConnectionMenu::ConnectionMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
ConnectionMenu::~ConnectionMenu() {

View File

@ -1,7 +1,7 @@
#include "CropMenu.hpp"
CropMenu::CropMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
CropMenu::CropMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
CropMenu::~CropMenu() {

View File

@ -58,9 +58,9 @@ static const ExtraSettingsMenuOptionInfo* pollable_options[] = {
&quit_option,
};
ExtraSettingsMenu::ExtraSettingsMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
ExtraSettingsMenu::ExtraSettingsMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -1,7 +1,7 @@
#include "FileConfigMenu.hpp"
FileConfigMenu::FileConfigMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
FileConfigMenu::FileConfigMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
FileConfigMenu::~FileConfigMenu() {

View File

@ -69,9 +69,9 @@ static const ISNitroMenuOptionInfo* pollable_options[] = {
&is_nitro_reset_option,
};
ISNitroMenu::ISNitroMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
ISNitroMenu::ISNitroMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -41,9 +41,9 @@ static const InputMenuOptionInfo* pollable_options[] = {
&input_menu_toggle_buttons_option,
};
InputMenu::InputMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
InputMenu::InputMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -165,9 +165,9 @@ static const LicenseMenuOptionInfo* pollable_options[] = {
&cc3dsfs_license_4_option,
};
LicenseMenu::LicenseMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
LicenseMenu::LicenseMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -83,9 +83,9 @@ static const Main3DMenuOptionInfo* pollable_options[] = {
&main_3d_menu_second_screen_position_settings_option,
};
Main3DMenu::Main3DMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
Main3DMenu::Main3DMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -166,9 +166,9 @@ static const MainMenuOptionInfo* pollable_options[] = {
&shutdown_option,
};
MainMenu::MainMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
MainMenu::MainMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -38,9 +38,9 @@ static const OffsetMenuOptionInfo* pollable_options[] = {
&canvas_y_pos_option,
};
OffsetMenu::OffsetMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
OffsetMenu::OffsetMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -5,25 +5,24 @@ OptionSelectionMenu::OptionSelectionMenu() {
}
OptionSelectionMenu::~OptionSelectionMenu() {
for(int i = 0; i < this->num_elements_displayed_per_screen; i++)
delete this->labels[i];
delete []this->labels;
delete []this->selectable_labels;
delete []this->future_enabled_labels;
delete []this->loaded_enabled_labels;
}
void OptionSelectionMenu::initialize(bool font_load_success, sf::Font &text_font) {
void OptionSelectionMenu::initialize(TextRectanglePool* text_pool) {
this->class_setup();
this->after_class_setup_connected_values();
this->menu_rectangle.setFillColor(this->menu_color);
this->menu_rectangle.setPosition({1, 1});
text_pool->request_num_text_rectangles(this->num_elements_displayed_per_screen);
this->labels = new TextRectangle*[this->num_elements_displayed_per_screen];
this->selectable_labels = new bool[this->num_elements_displayed_per_screen];
this->future_enabled_labels = new bool[this->num_elements_displayed_per_screen];
this->loaded_enabled_labels = new bool[this->num_elements_displayed_per_screen];
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
this->labels[i] = new TextRectangle(font_load_success, text_font);
this->labels[i] = text_pool->get_text_rectangle(i);
this->labels[i]->setProportionalBox(false);
this->labels[i]->setText(std::to_string(i));
this->labels[i]->setShowText(true);

View File

@ -1,7 +1,7 @@
#include "PARMenu.hpp"
PARMenu::PARMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
PARMenu::PARMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
PARMenu::~PARMenu() {

View File

@ -66,8 +66,8 @@ static const RelativePositionMenuOptionInfo* pollable_options[] = {
RelativePositionMenu::RelativePositionMenu() {
}
RelativePositionMenu::RelativePositionMenu(bool font_load_success, sf::Font &text_font) {
this->initialize(font_load_success, text_font);
RelativePositionMenu::RelativePositionMenu(TextRectanglePool* text_rectangle_pool) {
this->initialize(text_rectangle_pool);
}
RelativePositionMenu::~RelativePositionMenu() {
@ -77,15 +77,16 @@ RelativePositionMenu::~RelativePositionMenu() {
delete []this->selectable_labels;
}
void RelativePositionMenu::initialize(bool font_load_success, sf::Font &text_font) {
void RelativePositionMenu::initialize(TextRectanglePool* text_pool) {
this->class_setup();
this->after_class_setup_connected_values();
this->menu_rectangle.setFillColor(this->menu_color);
this->menu_rectangle.setPosition({1, 1});
text_pool->request_num_text_rectangles(this->num_elements_displayed_per_screen);
this->labels = new TextRectangle*[this->num_elements_displayed_per_screen];
this->selectable_labels = new bool[this->num_elements_displayed_per_screen];
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
this->labels[i] = new TextRectangle(font_load_success, text_font);
this->labels[i] = text_pool->get_text_rectangle(i);
this->labels[i]->setProportionalBox(false);
this->labels[i]->setText(std::to_string(i));
this->labels[i]->setShowText(true);
@ -224,6 +225,10 @@ void RelativePositionMenu::set_output_option(int index) {
}
}
bool RelativePositionMenu::is_option_drawable(int index) {
return true;
}
bool RelativePositionMenu::is_option_selectable(int index) {
return pollable_options[index]->is_selectable;
}
@ -428,7 +433,8 @@ void RelativePositionMenu::draw(float scaling_factor, sf::RenderTarget &window)
this->menu_rectangle.setPosition({(float)this->loaded_data.pos_x, (float)this->loaded_data.pos_y});
window.draw(this->menu_rectangle);
for(int i = 0; i < this->num_elements_displayed_per_screen; i++) {
this->labels[i]->draw(window);
if(this->is_option_drawable(i))
this->labels[i]->draw(window);
}
}

View File

@ -1,7 +1,7 @@
#include "ResolutionMenu.hpp"
ResolutionMenu::ResolutionMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
ResolutionMenu::ResolutionMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
ResolutionMenu::~ResolutionMenu() {

View File

@ -32,9 +32,9 @@ static const RotationMenuOptionInfo* pollable_options[] = {
&both_rotation_option,
};
RotationMenu::RotationMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
RotationMenu::RotationMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -46,9 +46,9 @@ static const ScalingRatioMenuOptionInfo* pollable_options[] = {
&force_same_scaling_option,
};
ScalingRatioMenu::ScalingRatioMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
ScalingRatioMenu::ScalingRatioMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -88,8 +88,8 @@ static const SecondScreen3DRelativePositionMenuOptionInfo* pollable_options[] =
&desc2_option,
};
SecondScreen3DRelativePositionMenu::SecondScreen3DRelativePositionMenu(bool font_load_success, sf::Font &text_font) {
this->initialize(font_load_success, text_font);
SecondScreen3DRelativePositionMenu::SecondScreen3DRelativePositionMenu(TextRectanglePool* text_rectangle_pool) {
this->initialize(text_rectangle_pool);
}
SecondScreen3DRelativePositionMenu::~SecondScreen3DRelativePositionMenu() {
@ -138,6 +138,14 @@ void SecondScreen3DRelativePositionMenu::set_output_option(int index) {
}
}
bool SecondScreen3DRelativePositionMenu::is_option_drawable(int index) {
if(index < this->elements_start_id)
return true;
if((this->stype != ScreenType::JOINT) && (!pollable_options[index - this->elements_start_id]->exists_non_joint))
return false;
return true;
}
bool SecondScreen3DRelativePositionMenu::is_option_selectable(int index) {
if((this->stype != ScreenType::JOINT) && (!pollable_options[index]->exists_non_joint))
return false;

View File

@ -44,9 +44,9 @@ static const SeparatorMenuOptionInfo* pollable_options[] = {
&separator_fullscreen_mul_change_option,
};
SeparatorMenu::SeparatorMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
SeparatorMenu::SeparatorMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -1,7 +1,7 @@
#include "ShortcutMenu.hpp"
ShortcutMenu::ShortcutMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
this->initialize(font_load_success, text_font);
ShortcutMenu::ShortcutMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->initialize(text_rectangle_pool);
}
ShortcutMenu::~ShortcutMenu() {

View File

@ -57,9 +57,9 @@ static const StatusMenuOptionInfo* pollable_options[] = {
&status_fps_draw_option,
};
StatusMenu::StatusMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
StatusMenu::StatusMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
this->last_update_time = std::chrono::high_resolution_clock::now();
this->do_update = true;

View File

@ -35,9 +35,9 @@ static const VideoEffectsMenuOptionInfo* pollable_options[] = {
&color_correction_menu_option,
};
VideoEffectsMenu::VideoEffectsMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
VideoEffectsMenu::VideoEffectsMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -231,9 +231,9 @@ static const VideoMenuOptionInfo* pollable_options[] = {
&bfi_settings_option,
};
VideoMenu::VideoMenu(bool font_load_success, sf::Font &text_font) : OptionSelectionMenu(){
VideoMenu::VideoMenu(TextRectanglePool* text_rectangle_pool) : OptionSelectionMenu(){
this->options_indexes = new int[NUM_TOTAL_MENU_OPTIONS];
this->initialize(font_load_success, text_font);
this->initialize(text_rectangle_pool);
this->num_enabled_options = 0;
}

View File

@ -0,0 +1,48 @@
#include "TextRectangle.hpp"
#include "TextRectanglePool.hpp"
TextRectanglePool::TextRectanglePool(bool font_load_success, sf::Font *text_font) {
this->font_load_success = font_load_success;
this->text_font = text_font;
this->num_loaded_text_rectangles = 0;
this->text_rectangles_list = NULL;
}
TextRectanglePool::~TextRectanglePool() {
if(this->num_loaded_text_rectangles > 0) {
for(int i = 0; i < this->num_loaded_text_rectangles; i++)
delete this->text_rectangles_list[i];
delete []this->text_rectangles_list;
}
this->num_loaded_text_rectangles = 0;
}
void TextRectanglePool::request_num_text_rectangles(int num_wanted_text_rectangles) {
if(this->num_loaded_text_rectangles > num_wanted_text_rectangles)
return;
TextRectangle** new_text_rectangle_ptrs = new TextRectangle*[num_wanted_text_rectangles];
// Copy other TextRectangles to new list
for(int i = 0; i < this->num_loaded_text_rectangles; i++) {
new_text_rectangle_ptrs[i] = this->text_rectangles_list[i];
}
// Create new TextRectangles
for(int i = this->num_loaded_text_rectangles; i < num_wanted_text_rectangles; i++) {
new_text_rectangle_ptrs[i] = new TextRectangle(this->font_load_success, *this->text_font);
}
if(this->num_loaded_text_rectangles > 0)
delete []this->text_rectangles_list;
this->text_rectangles_list = new_text_rectangle_ptrs;
this->num_loaded_text_rectangles = num_wanted_text_rectangles;
}
TextRectangle* TextRectanglePool::get_text_rectangle(int index) {
if((this->num_loaded_text_rectangles <= index) || (index < 0))
return NULL;
return this->text_rectangles_list[index];
}

View File

@ -7,6 +7,7 @@
#include "font_ttf.h"
#include "shaders_list.hpp"
#include "devicecapture.hpp"
#include <conversions.hpp>
#define LEFT_ROUNDED_PADDING 5
#define RIGHT_ROUNDED_PADDING 5
@ -36,7 +37,7 @@ static bool is_size_valid(sf::Vector2f size) {
return (size.x > 0.0) && (size.y > 0.0);
}
WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, SharedData* shared_data, AudioData* audio_data, ConsumerMutex *draw_lock, bool created_proper_folder) {
WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, DisplayData* display_data, SharedData* shared_data, AudioData* audio_data, ConsumerMutex *draw_lock, bool created_proper_folder, bool disable_frame_blending) {
this->draw_lock = draw_lock;
this->m_stype = stype;
insert_basic_crops(this->possible_crops, this->m_stype, false, false);
@ -53,16 +54,60 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp
this->m_scheduled_split = false;
this->ret_val = 0;
reset_screen_info(this->m_info);
this->font_load_success = this->text_font.openFromMemory(font_ttf, font_ttf_len);
this->notification = new TextRectangle(this->font_load_success, this->text_font);
bool font_load_success = this->text_font.openFromMemory(font_ttf, font_ttf_len);
this->notification = new TextRectangle(font_load_success, this->text_font);
this->text_rectangle_pool = new TextRectanglePool(font_load_success, &this->text_font);
this->init_menus();
FPSArrayInit(&this->in_fps);
FPSArrayInit(&this->draw_fps);
FPSArrayInit(&this->poll_fps);
(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_top_right.setTexture(&this->in_tex);
this->m_in_rect_bot.setTexture(&this->in_tex);
this->last_update_texture_data_type = VIDEO_DATA_RGB;
this->use_texture_software_based_conv = false;
this->num_frames_to_blend = NUM_FRAMES_BLENDED;
if(disable_frame_blending)
this->num_frames_to_blend = 1;
const size_t top_width = MAX_IN_VIDEO_WIDTH_TOP * this->num_frames_to_blend;
const size_t top_height = MAX_IN_VIDEO_HEIGHT_TOP;
const size_t top_single_width = MAX_IN_VIDEO_WIDTH_SINGLE_TOP * this->num_frames_to_blend;
const size_t top_single_height = MAX_IN_VIDEO_HEIGHT_SINGLE_TOP;
const size_t bottom_width = MAX_IN_VIDEO_WIDTH_BOTTOM * this->num_frames_to_blend;
const size_t bottom_height = MAX_IN_VIDEO_HEIGHT_BOTTOM;
size_t full_width = MAX_IN_VIDEO_WIDTH * this->num_frames_to_blend;
size_t full_height = MAX_IN_VIDEO_HEIGHT;
if(this->m_stype == ScreenType::TOP) {
full_width = top_width;
full_height = top_height;
}
if(this->m_stype == ScreenType::BOTTOM) {
full_width = bottom_width;
full_height = bottom_height;
}
this->shared_texture_available = this->full_in_tex.resize({(unsigned int)full_width, (unsigned int)full_height});
if(this->shared_texture_available) {
this->m_in_rect_top.setTexture(&this->full_in_tex);
this->m_in_rect_top_right.setTexture(&this->full_in_tex);
this->m_in_rect_bot.setTexture(&this->full_in_tex);
}
else {
if((this->m_stype == ScreenType::TOP) || (this->m_stype == ScreenType::JOINT)) {
full_width = top_width;
full_height = top_height;
(void)this->top_l_in_tex.resize({ (unsigned int)top_single_width, (unsigned int)top_single_height });
(void)this->top_r_in_tex.resize({ (unsigned int)top_single_width, (unsigned int)top_single_height });
this->m_in_rect_top.setTexture(&this->top_l_in_tex);
this->m_in_rect_top_right.setTexture(&this->top_r_in_tex);
}
else {
this->m_in_rect_top.setTexture(&this->bot_in_tex);
this->m_in_rect_top_right.setTexture(&this->bot_in_tex);
}
if((this->m_stype == ScreenType::BOTTOM) || (this->m_stype == ScreenType::JOINT)) {
(void)this->bot_in_tex.resize({ (unsigned int)bottom_width, (unsigned int)bottom_height });
this->m_in_rect_bot.setTexture(&this->bot_in_tex);
}
else
this->m_in_rect_bot.setTexture(&this->top_l_in_tex);
}
this->display_data = display_data;
this->shared_data = shared_data;
this->audio_data = audio_data;
@ -76,10 +121,16 @@ WindowScreen::WindowScreen(ScreenType stype, CaptureStatus* capture_status, Disp
this->done_display = true;
this->saved_buf = new VideoOutputData;
this->win_title = NAME;
if(this->m_stype == ScreenType::TOP)
if(this->m_stype == ScreenType::TOP) {
this->win_title += "_top";
if(this->m_stype == ScreenType::BOTTOM)
this->own_out_text_data.preamble_name += " top window";
}
if(this->m_stype == ScreenType::BOTTOM) {
this->win_title += "_bot";
this->own_out_text_data.preamble_name += " bottom window";
}
if(this->m_stype == ScreenType::JOINT)
this->own_out_text_data.preamble_name += " joint window";
this->last_connected_status = false;
this->last_enabled_3d = false;
this->last_interleaved_3d = false;
@ -114,6 +165,7 @@ WindowScreen::~WindowScreen() {
delete this->saved_buf;
delete this->notification;
this->destroy_menus();
delete this->text_rectangle_pool;
FPSArrayDestroy(&this->in_fps);
FPSArrayDestroy(&this->draw_fps);
FPSArrayDestroy(&this->poll_fps);
@ -250,7 +302,7 @@ void WindowScreen::draw(double frame_time, VideoOutputData* out_buf) {
this->last_poll_time = std::chrono::high_resolution_clock::now();
}
if(this->m_win.isOpen() || this->loaded_operations.call_create) {
this->curr_frame_texture_pos = (this->curr_frame_texture_pos + 1) % NUM_FRAMES_BLENDED;
this->curr_frame_texture_pos = (this->curr_frame_texture_pos + 1) % this->num_frames_to_blend;
auto curr_time = std::chrono::high_resolution_clock::now();
const std::chrono::duration<double> diff = curr_time - this->last_draw_time;
FPSArrayInsertElement(&draw_fps, diff.count());
@ -330,6 +382,14 @@ void WindowScreen::free_ownership_of_window(bool is_main_thread) {
}
}
static bool is_vertically_rotated(int rotation) {
return (rotation / 10) % 2;
}
static bool is_negatively_rotated(int rotation) {
return ((rotation / 10) % 4) >= 2;
}
void WindowScreen::resize_in_rect(sf::RectangleShape &in_rect, int start_x, int start_y, int width, int height) {
int target_x = start_x;
int target_y = start_y;
@ -337,7 +397,7 @@ void WindowScreen::resize_in_rect(sf::RectangleShape &in_rect, int start_x, int
int target_height = height;
int target_rotation = -1 * this->capture_status->device.base_rotation;
if((this->capture_status->device.base_rotation / 10) % 2) {
if(is_vertically_rotated(this->capture_status->device.base_rotation)) {
std::swap(target_x, target_y);
std::swap(target_width, target_height);
}
@ -486,8 +546,8 @@ std::string WindowScreen::_title_factory() {
if(this->capture_status->connected)
title += " - " + get_name_of_device(this->capture_status);
return title;
}
}
sf::String WindowScreen::title_factory() {
std::string title = this->_title_factory();
return sf::String::fromUtf8(title.begin(), title.end());
@ -506,32 +566,171 @@ sf::String WindowScreen::title_factory() {
#define GL_UNSIGNED_SHORT_5_6_5_REV 0x8364
#endif
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;
size_t width = this->capture_status->device.width;
size_t height = this->capture_status->device.height;
if(get_3d_enabled(this->capture_status)) {
width = this->capture_status->device.width_3d;
height = this->capture_status->device.height_3d;
}
glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(this->curr_frame_texture_pos * MAX_IN_VIDEO_WIDTH), static_cast<GLint>(0), static_cast<GLsizei>(width), static_cast<GLsizei>(height), format, type, this->saved_buf);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
void WindowScreen::opengl_error_out(std::string error_base, std::string error_str) {
UpdateOutText(this->own_out_text_data, error_base + ": " + error_str, error_base, TEXT_KIND_ERROR);
}
// 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::opengl_error_check(std::string error_base) {
GLenum glCheckInternalError = glGetError();
while (glCheckInternalError != GL_NO_ERROR) {
// Do error processing here... Simply logging it for now
this->opengl_error_out(error_base, std::to_string(glCheckInternalError));
glCheckInternalError = glGetError();
}
}
bool WindowScreen::single_update_texture(unsigned int m_texture, InputVideoDataType video_data_type, size_t pos_x_data, size_t pos_y_data, size_t width, size_t height, bool manually_converted) {
if(!(this->saved_buf && m_texture))
return false;
this->opengl_error_check("Previous OpenGL Error");
// Copy pixels from the given array to the texture
glBindTexture(GL_TEXTURE_2D, m_texture);
GLenum format = GL_RGB;
GLenum type = GL_UNSIGNED_BYTE;
size_t format_size = sizeof(VideoPixelRGB);
if(!manually_converted) {
if(video_data_type == VIDEO_DATA_BGR) {
format = GL_BGR;
format_size = sizeof(VideoPixelBGR);
}
if(video_data_type == VIDEO_DATA_RGB16) {
type = GL_UNSIGNED_SHORT_5_6_5;
format_size = sizeof(VideoPixelRGB16);
}
if(video_data_type == VIDEO_DATA_BGR16) {
type = GL_UNSIGNED_SHORT_5_6_5_REV;
format_size = sizeof(VideoPixelBGR16);
}
}
this->opengl_error_check("BindTexture OpenGL Error");
glTexSubImage2D(GL_TEXTURE_2D, 0, static_cast<GLint>(this->curr_frame_texture_pos * MAX_IN_VIDEO_WIDTH), static_cast<GLint>(0), static_cast<GLsizei>(width), static_cast<GLsizei>(height), format, type, ((uint8_t*)this->saved_buf) + (pos_y_data * width * format_size));
GLenum glCheckInternalError = glGetError();
while (glCheckInternalError != GL_NO_ERROR) {
bool processed = false;
if(glCheckInternalError == GL_INVALID_ENUM) {
if((format != GL_RGB) || (type != GL_UNSIGNED_BYTE)) {
UpdateOutText(this->own_out_text_data, "Switching to software-based texture updating", "", TEXT_KIND_NORMAL);
this->last_update_texture_data_type = video_data_type;
this->use_texture_software_based_conv = true;
return true;
}
}
if(!processed) {
// Do error processing here... Simply logging it for now
this->opengl_error_out("SubImage2D OpenGL Error", std::to_string(glCheckInternalError));
processed = true;
}
glCheckInternalError = glGetError();
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
this->opengl_error_check("TexParameteri OpenGL Error");
// Force an OpenGL flush, so that the texture data will appear updated
// in all contexts immediately (solves problems in multi-threaded apps)
glFlush();
return false;
}
void WindowScreen::execute_single_update_texture(bool &manually_converted, bool do_full, bool is_top, bool is_second) {
InputVideoDataType video_data_type = this->capture_status->device.video_data_type;
size_t top_width = TOP_WIDTH_3DS;
size_t top_height = HEIGHT_3DS;
size_t single_top_width = TOP_WIDTH_3DS;
size_t single_top_height = HEIGHT_3DS;
size_t bot_width = BOT_WIDTH_3DS;
size_t bot_height = HEIGHT_3DS;
if(!this->capture_status->device.is_3ds) {
top_width = WIDTH_DS;
top_height = HEIGHT_DS;
single_top_width = WIDTH_DS;
single_top_height = HEIGHT_DS;
bot_width = WIDTH_DS;
bot_height = HEIGHT_DS;
}
if(get_3d_enabled(this->capture_status))
top_width *= 2;
if(is_vertically_rotated(this->capture_status->device.base_rotation)) {
std::swap(top_width, top_height);
std::swap(single_top_width, single_top_height);
std::swap(bot_width, bot_height);
}
size_t full_width = std::max(top_width, bot_width);
size_t full_height = top_height + bot_height;
size_t width = full_width;
size_t height = full_height;
size_t pos_x_data = 0;
size_t pos_y_data = 0;
if(this->m_stype == ScreenType::TOP) {
full_height = top_height;
height = full_height;
pos_x_data = this->get_pos_x_screen_inside_data(true);
pos_y_data = this->get_pos_y_screen_inside_data(true);
}
if(this->m_stype == ScreenType::BOTTOM) {
full_height = bot_height;
height = full_height;
pos_x_data = this->get_pos_x_screen_inside_data(false);
pos_y_data = this->get_pos_y_screen_inside_data(false);
}
size_t pos_x_conv = pos_x_data;
size_t pos_y_conv = pos_y_data;
sf::Texture* target_texture = &this->full_in_tex;
if(!do_full) {
if(is_top) {
height = single_top_height;
pos_x_data = this->get_pos_x_screen_inside_data(true, is_second);
pos_y_data = this->get_pos_y_screen_inside_data(true, is_second);
sf::Texture* top_l_texture = &this->top_l_in_tex;
sf::Texture* top_r_texture = &this->top_r_in_tex;
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d)) {
if(!this->capture_status->device.is_second_top_screen_right)
std::swap(top_l_texture, top_r_texture);
}
target_texture = top_l_texture;
if(is_second)
target_texture = top_r_texture;
}
else {
height = bot_height;
pos_x_data = this->get_pos_x_screen_inside_data(false);
pos_y_data = this->get_pos_y_screen_inside_data(false);
target_texture = &this->bot_in_tex;
}
}
if(is_vertically_rotated(this->capture_status->device.base_rotation))
std::swap(pos_x_data, pos_y_data);
unsigned int m_texture = target_texture->getNativeHandle();
bool retry = true;
while(retry) {
bool software_based_conv = manually_converted || (this->use_texture_software_based_conv && (video_data_type == this->last_update_texture_data_type));
if(software_based_conv) {
if(!manually_converted)
manualConvertOutputToRGB(this->saved_buf, this->saved_buf, pos_x_conv, pos_y_conv, full_width, full_height, video_data_type);
manually_converted = true;
}
retry = this->single_update_texture(m_texture, video_data_type, pos_x_data, pos_y_data, width, height, manually_converted);
}
}
void WindowScreen::update_texture() {
bool manually_converted = false;
if(this->shared_texture_available)
this->execute_single_update_texture(manually_converted, true);
else {
if((this->m_stype == ScreenType::TOP) || (this->m_stype == ScreenType::JOINT)) {
this->execute_single_update_texture(manually_converted, false, true);
if(get_3d_enabled(this->capture_status))
this->execute_single_update_texture(manually_converted, false, true, true);
}
if((this->m_stype == ScreenType::BOTTOM) || (this->m_stype == ScreenType::JOINT))
this->execute_single_update_texture(manually_converted, false, false);
}
}
@ -692,9 +891,9 @@ bool WindowScreen::apply_shaders_to_input(sf::RectangleShape &rect_data, sf::Ren
if(chosen_shader < 0)
return false;
float old_frame_pos_x = ((float)(NUM_FRAMES_BLENDED - 1)) / NUM_FRAMES_BLENDED;
float old_frame_pos_x = ((float)(this->num_frames_to_blend - 1)) / this->num_frames_to_blend;
if(this->curr_frame_texture_pos > 0)
old_frame_pos_x = -1.0 / NUM_FRAMES_BLENDED;
old_frame_pos_x = -1.0f / this->num_frames_to_blend;
sf::Glsl::Vec2 old_pos = {old_frame_pos_x, 0.0};
usable_shaders[chosen_shader].shader.setUniform("old_frame_offset", old_pos);
to_process_tex_data->draw(final_in_rect, &usable_shaders[chosen_shader].shader);
@ -811,7 +1010,8 @@ void WindowScreen::display_data_to_window(bool actually_draw, bool is_debug) {
this->m_out_rect_bot.to_process_tex = &this->m_out_rect_bot.out_tex;
this->m_out_rect_bot.to_backup_tex = &this->m_out_rect_bot.backup_tex;
this->post_texture_conversion_processing(out_rect_bot, this->m_out_rect_bot.to_process_tex, this->m_out_rect_bot.to_backup_tex, in_rect_bot, actually_draw, false, is_debug);
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d) && (this->m_stype != ScreenType::BOTTOM) && is_size_valid(out_rect_top.getSize())) {
bool has_to_do_top_right_screen = get_3d_enabled(this->capture_status) && ((!this->display_data->interleaved_3d) || (!this->shared_texture_available)) && (this->m_stype != ScreenType::BOTTOM) && is_size_valid(out_rect_top.getSize());
if(has_to_do_top_right_screen) {
out_rect_top_right.setTextureRect(out_rect_top.getTextureRect());
this->m_out_rect_top_right.to_process_tex = &this->m_out_rect_top_right.out_tex;
this->m_out_rect_top_right.to_backup_tex = &this->m_out_rect_top_right.backup_tex;
@ -823,17 +1023,38 @@ void WindowScreen::display_data_to_window(bool actually_draw, bool is_debug) {
else
this->m_win.clear();
this->window_bg_processing();
bool needs_to_glue_textures_3d = has_to_do_top_right_screen && this->display_data->interleaved_3d && (!this->shared_texture_available);
if(needs_to_glue_textures_3d) {
float x_divisor = 2.0f;
float y_divisor = 1.0f;
out_rect_top.setSize({out_rect_top.getSize().x / x_divisor, out_rect_top.getSize().y / y_divisor});
sf::IntRect texture_rect_top = out_rect_top.getTextureRect();
texture_rect_top.size.x /= (int)x_divisor;
texture_rect_top.size.y /= (int)y_divisor;
out_rect_top.setTextureRect(texture_rect_top);
}
this->draw_rect_to_window(out_rect_top, true);
this->draw_rect_to_window(out_rect_bot, false);
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d) && (this->m_stype != ScreenType::BOTTOM) && is_size_valid(out_rect_top.getSize())) {
if(has_to_do_top_right_screen) {
sf::Vector2f offset_second_screen = get_3d_offset_out_rect(&this->loaded_info, true);
if(needs_to_glue_textures_3d) {
float base_multiplier = 1.0f;
if(is_negatively_rotated(this->loaded_info.top_rotation))
base_multiplier = -1.0f;
if(is_vertically_rotated(this->loaded_info.top_rotation))
offset_second_screen = {0, base_multiplier * out_rect_top.getSize().x / 1.0f};
else
offset_second_screen = {base_multiplier * out_rect_top.getSize().x / 1.0f, 0};
}
out_rect_top_right.setTextureRect(out_rect_top.getTextureRect());
out_rect_top_right.setSize(out_rect_top.getSize());
out_rect_top_right.setPosition(out_rect_top.getPosition() + offset_second_screen);
out_rect_top_right.setRotation(out_rect_top.getRotation());
this->draw_rect_to_window(out_rect_top_right, true);
out_rect_bot.setPosition(out_rect_bot.getPosition() + offset_second_screen);
this->draw_rect_to_window(out_rect_bot, false);
if(!needs_to_glue_textures_3d) {
out_rect_bot.setPosition(out_rect_bot.getPosition() + offset_second_screen);
this->draw_rect_to_window(out_rect_bot, false);
}
}
this->execute_menu_draws();
this->notification->draw(this->m_win);
@ -913,9 +1134,9 @@ void WindowScreen::set_position_screens(sf::Vector2f &curr_top_screen_size, sf::
int bot_screen_width = (int)curr_bot_screen_size.x;
int bot_screen_height = (int)curr_bot_screen_size.y;
if((this->loaded_info.top_rotation / 10) % 2)
if(is_vertically_rotated(this->loaded_info.top_rotation))
std::swap(top_screen_width, top_screen_height);
if((this->loaded_info.bot_rotation / 10) % 2)
if(is_vertically_rotated(this->loaded_info.bot_rotation))
std::swap(bot_screen_width, bot_screen_height);
if(this->m_stype == ScreenType::TOP)
@ -986,7 +1207,7 @@ float WindowScreen::get_max_float_screen_multiplier(ResizingScreenData *own_scre
if(!is_size_valid(own_screen->size))
return 0;
if((other_rotation / 10) % 2)
if(is_vertically_rotated(other_rotation))
std::swap(width_limit, height_limit);
sf::Vector2f other_screen_size = sf::Vector2f((float)width_limit, (float)height_limit);
if((!is_size_valid(other_screen_size)) && is_two_screens_merged)
@ -1012,7 +1233,7 @@ float WindowScreen::get_max_float_screen_multiplier(ResizingScreenData *own_scre
float own_width = own_screen->size.x;
float own_height = own_screen->size.y;
get_par_size(own_width, own_height, 1.0, own_screen->par, own_screen->divide_3d_par);
if((own_screen->rotation / 10) % 2)
if(is_vertically_rotated(own_screen->rotation))
std::swap(own_width, own_height);
if((own_height == 0) || (own_width == 0))
return 0;
@ -1157,9 +1378,9 @@ void WindowScreen::non_integer_scale_screens(ResizingScreenData *top_screen_resi
std::swap(min_bigger_screen_height, min_smaller_screen_height);
}
if((top_screen_resize_data->rotation / 10) % 2)
if(is_vertically_rotated(top_screen_resize_data->rotation))
std::swap(min_top_screen_width, min_top_screen_height);
if((bot_screen_resize_data->rotation / 10) % 2)
if(is_vertically_rotated(bot_screen_resize_data->rotation))
std::swap(min_bot_screen_width, min_bot_screen_height);
sf::Vector2u curr_desk_mode_3d_size = get_desk_mode_3d_multiplied(&this->m_info);
@ -1195,9 +1416,9 @@ void WindowScreen::merge_screens_data(ResizingScreenData* top_screen_resize_data
float bot_width = bot_screen_resize_data->size.x;
float bot_height = bot_screen_resize_data->size.y;
get_par_size(bot_width, bot_height, 1.0, bot_screen_resize_data->par, bot_screen_resize_data->divide_3d_par);
if((top_screen_resize_data->rotation / 10) % 2)
if(is_vertically_rotated(top_screen_resize_data->rotation))
std::swap(top_width, top_height);
if((bot_screen_resize_data->rotation / 10) % 2)
if(is_vertically_rotated(bot_screen_resize_data->rotation))
std::swap(bot_width, bot_height);
float final_width = std::max(top_width, bot_width);
float final_height = std::max(top_height, bot_height);
@ -1296,9 +1517,9 @@ void WindowScreen::prepare_size_ratios(bool top_increase, bool bot_increase, boo
}
int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot_width, int bot_height, int separator_contribute) {
if((this->loaded_info.top_rotation / 10) % 2)
if(is_vertically_rotated(this->loaded_info.top_rotation))
std::swap(top_width, top_height);
if((this->loaded_info.bot_rotation / 10) % 2)
if(is_vertically_rotated(this->loaded_info.bot_rotation))
std::swap(bot_width, bot_height);
int greatest_width = std::max(top_width, bot_width);
int offset_contribute = 0;
@ -1319,9 +1540,9 @@ int WindowScreen::get_fullscreen_offset_x(int top_width, int top_height, int bot
}
int WindowScreen::get_fullscreen_offset_y(int top_width, int top_height, int bot_width, int bot_height, int separator_contribute) {
if((this->loaded_info.top_rotation / 10) % 2)
if(is_vertically_rotated(this->loaded_info.top_rotation))
std::swap(top_width, top_height);
if((this->loaded_info.bot_rotation / 10) % 2)
if(is_vertically_rotated(this->loaded_info.bot_rotation))
std::swap(bot_width, bot_height);
int greatest_height = std::max(top_height, bot_height);
int offset_contribute = 0;
@ -1528,6 +1749,46 @@ sf::Vector2f WindowScreen::getShownScreenSize(bool is_top, ScreenInfo* info) {
return {(float)width, (float)height};
}
int WindowScreen::get_pos_x_screen_inside_data(bool is_top, bool is_second) {
if(!is_top)
return this->capture_status->device.bot_screen_x;
if(!is_second)
return this->capture_status->device.top_screen_x;
return this->capture_status->device.second_top_screen_x;
}
int WindowScreen::get_pos_y_screen_inside_data(bool is_top, bool is_second) {
if(!is_top)
return this->capture_status->device.bot_screen_y;
if(!is_second)
return this->capture_status->device.top_screen_y;
return this->capture_status->device.second_top_screen_y;
}
int WindowScreen::get_pos_x_screen_inside_in_tex(bool is_top, bool is_second) {
if(!this->shared_texture_available)
return 0;
if(is_vertically_rotated(this->capture_status->device.base_rotation)) {
if(this->m_stype == ScreenType::TOP)
return this->get_pos_x_screen_inside_data(is_top, is_second) - this->get_pos_x_screen_inside_data(is_top, false);
if(this->m_stype == ScreenType::BOTTOM)
return 0;
}
return this->get_pos_x_screen_inside_data(is_top, is_second);
}
int WindowScreen::get_pos_y_screen_inside_in_tex(bool is_top, bool is_second) {
if(!this->shared_texture_available)
return 0;
if(!is_vertically_rotated(this->capture_status->device.base_rotation)) {
if(this->m_stype == ScreenType::TOP)
return this->get_pos_y_screen_inside_data(is_top, is_second) - this->get_pos_y_screen_inside_data(is_top, false);
if(this->m_stype == ScreenType::BOTTOM)
return 0;
}
return this->get_pos_y_screen_inside_data(is_top, is_second);
}
void WindowScreen::crop() {
std::vector<const CropData*> *crops = this->get_crop_data_vector(&this->loaded_info);
int *crop_value = this->get_crop_index_ptr(&this->loaded_info);
@ -1535,12 +1796,12 @@ void WindowScreen::crop() {
sf::Vector2f top_screen_size = getShownScreenSize(true, &this->loaded_info);
sf::Vector2f bot_screen_size = getShownScreenSize(false, &this->loaded_info);
this->resize_in_rect(this->m_in_rect_bot, this->capture_status->device.bot_screen_x + (*crops)[*crop_value]->bot_x, this->capture_status->device.bot_screen_y + (*crops)[*crop_value]->bot_y, (int)bot_screen_size.x, (int)bot_screen_size.y);
this->resize_in_rect(this->m_in_rect_bot, this->get_pos_x_screen_inside_in_tex(false) + (*crops)[*crop_value]->bot_x, this->get_pos_y_screen_inside_in_tex(false) + (*crops)[*crop_value]->bot_y, (int)bot_screen_size.x, (int)bot_screen_size.y);
if(get_3d_enabled(this->capture_status) && (!this->display_data->interleaved_3d)) {
int left_top_screen_x = this->capture_status->device.top_screen_x;
int left_top_screen_y = this->capture_status->device.top_screen_y;
int right_top_screen_x = this->capture_status->device.second_top_screen_x;
int right_top_screen_y = this->capture_status->device.second_top_screen_y;
int left_top_screen_x = this->get_pos_x_screen_inside_in_tex(true, false);
int left_top_screen_y = this->get_pos_y_screen_inside_in_tex(true, false);
int right_top_screen_x = this->get_pos_x_screen_inside_in_tex(true, true);
int right_top_screen_y = this->get_pos_y_screen_inside_in_tex(true, true);
if(!this->capture_status->device.is_second_top_screen_right) {
std::swap(left_top_screen_x, right_top_screen_x);
std::swap(left_top_screen_y, right_top_screen_y);
@ -1549,10 +1810,19 @@ void WindowScreen::crop() {
this->resize_in_rect(this->m_in_rect_top_right, right_top_screen_x + (*crops)[*crop_value]->top_x, right_top_screen_y + (*crops)[*crop_value]->top_y, (int)top_screen_size.x, (int)top_screen_size.y);
}
else {
float x_multiplier = 1.0;
if(get_3d_enabled(this->capture_status) && this->display_data->interleaved_3d)
x_multiplier = 2.0;
this->resize_in_rect(this->m_in_rect_top, (int)(this->capture_status->device.top_screen_x + ((*crops)[*crop_value]->top_x * x_multiplier)), this->capture_status->device.top_screen_y + (*crops)[*crop_value]->top_y, (int)top_screen_size.x, (int)top_screen_size.y);
bool is_3d_interleaved = get_3d_enabled(this->capture_status) && this->display_data->interleaved_3d;
float x_multiplier = 1.0f;
if(is_3d_interleaved)
x_multiplier = 2.0f;
int starting_in_rect_x = (int)(this->get_pos_x_screen_inside_in_tex(true) + ((*crops)[*crop_value]->top_x * x_multiplier));
int starting_in_rect_y = (int)(this->get_pos_y_screen_inside_in_tex(true) + (*crops)[*crop_value]->top_y);
if(is_3d_interleaved && (!this->shared_texture_available))
top_screen_size.x /= 2.0f;
this->resize_in_rect(this->m_in_rect_top, starting_in_rect_x, starting_in_rect_y, (int)top_screen_size.x, (int)top_screen_size.y);
if(is_3d_interleaved && (!this->shared_texture_available)) {
int second_screen_x_starting_pos = std::max(0, ((int)((*crops)[*crop_value]->top_x * x_multiplier)) - TOP_WIDTH_3DS);
this->resize_in_rect(this->m_in_rect_top_right, second_screen_x_starting_pos, starting_in_rect_y, (int)top_screen_size.x, (int)top_screen_size.y);
}
}
this->loaded_operations.call_screen_settings_update = true;
}
@ -1574,3 +1844,12 @@ void WindowScreen::setWinSize(bool is_main_thread) {
this->draw_lock->unlock();
}
}
void WindowScreen::process_own_out_text_data(bool print_to_notification) {
if(!this->own_out_text_data.consumed) {
ConsumeOutText(this->own_out_text_data, false);
if(print_to_notification)
this->print_notification(this->own_out_text_data.small_text, this->own_out_text_data.kind);
this->own_out_text_data.consumed = true;
}
}

View File

@ -97,32 +97,32 @@ static double FPSArrayGetAverage(FPSArray *array) {
void WindowScreen::init_menus() {
this->last_menu_change_time = std::chrono::high_resolution_clock::now();
this->connection_menu = new ConnectionMenu(this->font_load_success, this->text_font);
this->main_menu = new MainMenu(this->font_load_success, this->text_font);
this->video_menu = new VideoMenu(this->font_load_success, this->text_font);
this->crop_menu = new CropMenu(this->font_load_success, this->text_font);
this->par_menu = new PARMenu(this->font_load_success, this->text_font);
this->offset_menu = new OffsetMenu(this->font_load_success, this->text_font);
this->rotation_menu = new RotationMenu(this->font_load_success, this->text_font);
this->audio_menu = new AudioMenu(this->font_load_success, this->text_font);
this->bfi_menu = new BFIMenu(this->font_load_success, this->text_font);
this->relpos_menu = new RelativePositionMenu(this->font_load_success, this->text_font);
this->resolution_menu = new ResolutionMenu(this->font_load_success, this->text_font);
this->fileconfig_menu = new FileConfigMenu(this->font_load_success, this->text_font);
this->extra_menu = new ExtraSettingsMenu(this->font_load_success, this->text_font);
this->status_menu = new StatusMenu(this->font_load_success, this->text_font);
this->license_menu = new LicenseMenu(this->font_load_success, this->text_font);
this->shortcut_menu = new ShortcutMenu(this->font_load_success, this->text_font);
this->action_selection_menu = new ActionSelectionMenu(this->font_load_success, this->text_font);
this->scaling_ratio_menu = new ScalingRatioMenu(this->font_load_success, this->text_font);
this->is_nitro_menu = new ISNitroMenu(this->font_load_success, this->text_font);
this->video_effects_menu = new VideoEffectsMenu(this->font_load_success, this->text_font);
this->input_menu = new InputMenu(this->font_load_success, this->text_font);
this->audio_device_menu = new AudioDeviceMenu(this->font_load_success, this->text_font);
this->separator_menu = new SeparatorMenu(this->font_load_success, this->text_font);
this->color_correction_menu = new ColorCorrectionMenu(this->font_load_success, this->text_font);
this->main_3d_menu = new Main3DMenu(this->font_load_success, this->text_font);
this->second_screen_3d_relpos_menu = new SecondScreen3DRelativePositionMenu(this->font_load_success, this->text_font);
this->connection_menu = new ConnectionMenu(this->text_rectangle_pool);
this->main_menu = new MainMenu(this->text_rectangle_pool);
this->video_menu = new VideoMenu(this->text_rectangle_pool);
this->crop_menu = new CropMenu(this->text_rectangle_pool);
this->par_menu = new PARMenu(this->text_rectangle_pool);
this->offset_menu = new OffsetMenu(this->text_rectangle_pool);
this->rotation_menu = new RotationMenu(this->text_rectangle_pool);
this->audio_menu = new AudioMenu(this->text_rectangle_pool);
this->bfi_menu = new BFIMenu(this->text_rectangle_pool);
this->relpos_menu = new RelativePositionMenu(this->text_rectangle_pool);
this->resolution_menu = new ResolutionMenu(this->text_rectangle_pool);
this->fileconfig_menu = new FileConfigMenu(this->text_rectangle_pool);
this->extra_menu = new ExtraSettingsMenu(this->text_rectangle_pool);
this->status_menu = new StatusMenu(this->text_rectangle_pool);
this->license_menu = new LicenseMenu(this->text_rectangle_pool);
this->shortcut_menu = new ShortcutMenu(this->text_rectangle_pool);
this->action_selection_menu = new ActionSelectionMenu(this->text_rectangle_pool);
this->scaling_ratio_menu = new ScalingRatioMenu(this->text_rectangle_pool);
this->is_nitro_menu = new ISNitroMenu(this->text_rectangle_pool);
this->video_effects_menu = new VideoEffectsMenu(this->text_rectangle_pool);
this->input_menu = new InputMenu(this->text_rectangle_pool);
this->audio_device_menu = new AudioDeviceMenu(this->text_rectangle_pool);
this->separator_menu = new SeparatorMenu(this->text_rectangle_pool);
this->color_correction_menu = new ColorCorrectionMenu(this->text_rectangle_pool);
this->main_3d_menu = new Main3DMenu(this->text_rectangle_pool);
this->second_screen_3d_relpos_menu = new SecondScreen3DRelativePositionMenu(this->text_rectangle_pool);
}
void WindowScreen::destroy_menus() {

View File

@ -29,17 +29,11 @@
#define NO_DATA_CONSECUTIVE_THRESHOLD 4
#define TIME_AUDIO_DEVICE_CHECK 0.25
struct OutTextData {
std::string full_text;
std::string small_text;
bool consumed;
TextKind kind;
};
struct override_all_data {
override_win_data override_top_bot_data;
override_win_data override_top_data;
override_win_data override_bot_data;
bool disable_frame_blending = false;
bool no_audio = false;
int volume = DEFAULT_NO_VOLUME_VALUE;
bool always_prevent_mouse_showing = false;
@ -51,20 +45,6 @@ struct override_all_data {
bool quit_on_first_connection_failure = false;
};
static void ConsoleOutText(std::string full_text) {
if(full_text != "")
std::cout << "[" << NAME << "] " << full_text << std::endl;
}
static void UpdateOutText(OutTextData &out_text_data, std::string full_text, std::string small_text, TextKind kind) {
if(!out_text_data.consumed)
ConsoleOutText(out_text_data.full_text);
out_text_data.full_text = full_text;
out_text_data.small_text = small_text;
out_text_data.kind = kind;
out_text_data.consumed = false;
}
static void SuccessConnectionOutTextGenerator(OutTextData &out_text_data, CaptureData* capture_data) {
if(capture_data->status.connected)
UpdateOutText(out_text_data, "Connected to " + capture_data->status.device.name + " - " + capture_data->status.device.serial_number, "Connected", TEXT_KIND_SUCCESS);
@ -528,7 +508,6 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data,
bool skip_io = false;
int num_allowed_blanks = MAX_ALLOWED_BLANKS;
OutTextData out_text_data;
out_text_data.consumed = true;
int ret_val = 0;
int poll_timeout = 0;
const bool endianness = is_big_endian();
@ -537,9 +516,9 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data,
memset(out_buf, 0, sizeof(VideoOutputData));
draw_lock.unlock();
WindowScreen *top_screen = new WindowScreen(ScreenType::TOP, &capture_data->status, &frontend_data.display_data, &frontend_data.shared_data, audio_data, &draw_lock, created_proper_folder);
WindowScreen *bot_screen = new WindowScreen(ScreenType::BOTTOM, &capture_data->status, &frontend_data.display_data, &frontend_data.shared_data, audio_data, &draw_lock, created_proper_folder);
WindowScreen *joint_screen = new WindowScreen(ScreenType::JOINT, &capture_data->status, &frontend_data.display_data, &frontend_data.shared_data, audio_data, &draw_lock, created_proper_folder);
WindowScreen *top_screen = new WindowScreen(ScreenType::TOP, &capture_data->status, &frontend_data.display_data, &frontend_data.shared_data, audio_data, &draw_lock, created_proper_folder, override_data.disable_frame_blending);
WindowScreen *bot_screen = new WindowScreen(ScreenType::BOTTOM, &capture_data->status, &frontend_data.display_data, &frontend_data.shared_data, audio_data, &draw_lock, created_proper_folder, override_data.disable_frame_blending);
WindowScreen *joint_screen = new WindowScreen(ScreenType::JOINT, &capture_data->status, &frontend_data.display_data, &frontend_data.shared_data, audio_data, &draw_lock, created_proper_folder, override_data.disable_frame_blending);
frontend_data.top_screen = top_screen;
frontend_data.bot_screen = bot_screen;
frontend_data.joint_screen = joint_screen;
@ -696,8 +675,11 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data,
capture_data->status.new_error_text = false;
}
top_screen->process_own_out_text_data();
bot_screen->process_own_out_text_data();
joint_screen->process_own_out_text_data();
if((!out_text_data.consumed) && (!frontend_data.reload)) {
ConsoleOutText(out_text_data.full_text);
ConsumeOutText(out_text_data, false);
top_screen->print_notification(out_text_data.small_text, out_text_data.kind);
bot_screen->print_notification(out_text_data.small_text, out_text_data.kind);
joint_screen->print_notification(out_text_data.small_text, out_text_data.kind);
@ -719,10 +701,10 @@ static int mainVideoOutputCall(AudioData* audio_data, CaptureData* capture_data,
save_layout_file(override_data.loaded_profile, &frontend_data, audio_data, out_text_data, &capture_data->status, skip_io, false, created_proper_folder);
if(!out_text_data.consumed) {
ConsoleOutText(out_text_data.full_text);
out_text_data.consumed = true;
}
top_screen->process_own_out_text_data(false);
bot_screen->process_own_out_text_data(false);
joint_screen->process_own_out_text_data(false);
ConsumeOutText(out_text_data);
delete out_buf;
return ret_val;
@ -801,6 +783,8 @@ int main(int argc, char **argv) {
continue;
if(parse_existence_arg(i, argv, override_data.recovery_mode, true, "--recovery_mode"))
continue;
if(parse_existence_arg(i, argv, override_data.disable_frame_blending, true, "--no_frame_blend"))
continue;
if(parse_int_arg(i, argc, argv, override_data.override_top_bot_data.pos_x, "--pos_x_both"))
continue;
if(parse_int_arg(i, argc, argv, override_data.override_top_bot_data.pos_y, "--pos_y_both"))
@ -852,41 +836,43 @@ int main(int argc, char **argv) {
continue;
#endif
std::cout << "Help:" << std::endl;
std::cout << " --mono_app Enables special mode for when only this application" << std::endl;
std::cout << " should run on the system. Disabled by default." << std::endl;
std::cout << " --recovery_mode Resets to the defaults." << std::endl;
std::cout << " --pos_x_both Set default x position for the window with both screens." << std::endl;
std::cout << " --pos_y_both Set default y position for the window with both screens." << std::endl;
std::cout << " --scaling_both Overrides the scale factor for the window with both screens." << std::endl;
std::cout << " --enabled_both Overrides the presence of the window with both screens." << std::endl;
std::cout << " 1 On, 0 Off." << std::endl;
std::cout << " --pos_x_top Set default x position for the top screen's window." << std::endl;
std::cout << " --pos_y_top Set default y position for the top screen's window." << std::endl;
std::cout << " --scaling_top Overrides the top screen window's scale factor." << std::endl;
std::cout << " --enabled_top Overrides the presence of the top screen's window." << std::endl;
std::cout << " 1 On, 0 Off." << std::endl;
std::cout << " --pos_x_bot Set default x position for the bottom screen's window." << std::endl;
std::cout << " --pos_y_bot Set default y position for the bottom screen's window." << std::endl;
std::cout << " --scaling_bot Overrides the bottom screen window's scale factor." << std::endl;
std::cout << " --enabled_bot Overrides the presence of the bottom screen's window." << std::endl;
std::cout << " 1 On, 0 Off." << std::endl;
std::cout << " --volume Overrides the saved volume for the audio. 0 - 200" << std::endl;
std::cout << " --no_audio Disables audio output and processing completely." << std::endl;
std::cout << " --no_cursor Prevents the mouse cursor from showing, unless moved." << std::endl;
std::cout << " --auto_connect Automatically connects to the first available device," << std::endl;
std::cout << " even if multiple are present." << std::endl;
std::cout << " --failure_close Automatically closes the software if the first connection" << std::endl;
std::cout << " doesn't succeed." << std::endl;
std::cout << " --auto_close Automatically closes the software on disconnect." << std::endl;
std::cout << " --profile Loads the profile with the specified ID at startup" << std::endl;
std::cout << " instead of the default one. When the program closes," << std::endl;
std::cout << " the data is also saved to the specified profile." << std::endl;
std::cout << " --mono_app Enables special mode for when only this application" << std::endl;
std::cout << " should run on the system. Disabled by default." << std::endl;
std::cout << " --recovery_mode Resets to the defaults." << std::endl;
std::cout << " --pos_x_both Set default x position for the window with both screens." << std::endl;
std::cout << " --pos_y_both Set default y position for the window with both screens." << std::endl;
std::cout << " --scaling_both Overrides the scale factor for the window with both screens." << std::endl;
std::cout << " --enabled_both Overrides the presence of the window with both screens." << std::endl;
std::cout << " 1 On, 0 Off." << std::endl;
std::cout << " --pos_x_top Set default x position for the top screen's window." << std::endl;
std::cout << " --pos_y_top Set default y position for the top screen's window." << std::endl;
std::cout << " --scaling_top Overrides the top screen window's scale factor." << std::endl;
std::cout << " --enabled_top Overrides the presence of the top screen's window." << std::endl;
std::cout << " 1 On, 0 Off." << std::endl;
std::cout << " --pos_x_bot Set default x position for the bottom screen's window." << std::endl;
std::cout << " --pos_y_bot Set default y position for the bottom screen's window." << std::endl;
std::cout << " --scaling_bot Overrides the bottom screen window's scale factor." << std::endl;
std::cout << " --enabled_bot Overrides the presence of the bottom screen's window." << std::endl;
std::cout << " 1 On, 0 Off." << std::endl;
std::cout << " --no_frame_blend Disables support for frame blending shader." << std::endl;
std::cout << " May improve compatibility with lower end hardware." << std::endl;
std::cout << " --volume Overrides the saved volume for the audio. 0 - 200" << std::endl;
std::cout << " --no_audio Disables audio output and processing completely." << std::endl;
std::cout << " --no_cursor Prevents the mouse cursor from showing, unless moved." << std::endl;
std::cout << " --auto_connect Automatically connects to the first available device," << std::endl;
std::cout << " even if multiple are present." << std::endl;
std::cout << " --failure_close Automatically closes the software if the first connection" << std::endl;
std::cout << " doesn't succeed." << std::endl;
std::cout << " --auto_close Automatically closes the software on disconnect." << std::endl;
std::cout << " --profile Loads the profile with the specified ID at startup" << std::endl;
std::cout << " instead of the default one. When the program closes," << std::endl;
std::cout << " the data is also saved to the specified profile." << std::endl;
#ifdef RASPI
std::cout << " --pi_select ID Specifies ID for the select GPIO button." << std::endl;
std::cout << " --pi_menu ID Specifies ID for the menu GPIO button." << std::endl;
std::cout << " --pi_enter ID Specifies ID for the enter GPIO button." << std::endl;
std::cout << " --pi_power ID Specifies ID for the poweroff GPIO button." << std::endl;
std::cout << " --pi_pud_down Sets the pull-up GPIO mode to down. Default is up." << std::endl;
std::cout << " --pi_select ID Specifies ID for the select GPIO button." << std::endl;
std::cout << " --pi_menu ID Specifies ID for the menu GPIO button." << std::endl;
std::cout << " --pi_enter ID Specifies ID for the enter GPIO button." << std::endl;
std::cout << " --pi_power ID Specifies ID for the poweroff GPIO button." << std::endl;
std::cout << " --pi_pud_down Sets the pull-up GPIO mode to down. Default is up." << std::endl;
#endif
return 0;
}

View File

@ -340,11 +340,11 @@ static inline void usb_rgb888convertInterleaveU163DVideoToOutputDirectOptMonoBot
static inline void convertVideoToOutputChunk(RGB83DSVideoInputData *p_in, VideoOutputData *p_out, size_t iters, size_t start_in, size_t start_out) {
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
memcpy(&p_out->rgb_video_output_data.screen_data[start_out], &p_in->screen_data[start_in], iters * sizeof(VideoPixelRGB));
}
static inline void convertVideoToOutputChunk_3D(RGB83DSVideoInputData_3D *p_in, VideoOutputData *p_out, size_t iters, size_t start_in, size_t start_out) {
memcpy(&p_out->screen_data[start_out], &p_in->screen_data[start_in], iters * 3);
memcpy(&p_out->rgb_video_output_data.screen_data[start_out], &p_in->screen_data[start_in], iters * sizeof(VideoPixelRGB));
}
static void expand_2d_to_3d_convertVideoToOutput(uint8_t *out_screen_data, size_t pixels_size, bool interleaved_3d, bool requested_3d) {
@ -368,7 +368,7 @@ static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, (((i * 2) + 0) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, i * IN_VIDEO_WIDTH_3DS);
convertVideoToOutputChunk(&p_in->ftd3_received.video_in, p_out, IN_VIDEO_WIDTH_3DS, (((i * 2) + 1) * IN_VIDEO_WIDTH_3DS) + IN_VIDEO_NO_BOTTOM_SIZE_3DS, BOT_SIZE_3DS + IN_VIDEO_NO_BOTTOM_SIZE_3DS + (i * IN_VIDEO_WIDTH_3DS));
}
expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->screen_data, 3, interleaved_3d, requested_3d);
expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->rgb_video_output_data.screen_data, sizeof(VideoPixelRGB), interleaved_3d, requested_3d);
}
else {
size_t last_line_index = ((IN_VIDEO_SIZE_3DS_3D - IN_VIDEO_NO_BOTTOM_SIZE_3DS_3D) / (IN_VIDEO_WIDTH_3DS_3D * 3)) - 1;
@ -410,10 +410,10 @@ static void ftd3_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_
static inline void usb_oldDSconvertVideoToOutputHalfLineDirectOptLE(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) {
//de-interleave pixels
const int pixels_size = 2;
const int pixels_size = sizeof(VideoPixelBGR16);
const int num_halflines = 2;
const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels);
deinterleaved_rgb565_pixels* out_ptr_top = (deinterleaved_rgb565_pixels*)p_out->screen_data;
deinterleaved_rgb565_pixels* out_ptr_top = (deinterleaved_rgb565_pixels*)p_out->bgr16_video_output_data.screen_data;
deinterleaved_rgb565_pixels* out_ptr_bottom = out_ptr_top + ((WIDTH_DS * HEIGHT_DS * pixels_size) / ptr_out_size);
interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->video_in.screen_data;
const uint32_t halfline_iters = WIDTH_DS / num_halflines;
@ -422,10 +422,10 @@ static inline void usb_oldDSconvertVideoToOutputHalfLineDirectOptLE(USBOldDSCapt
static inline void usb_oldDSconvertVideoToOutputHalfLineDirectOptBE(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, int input_halfline, int output_halfline) {
//de-interleave pixels
const int pixels_size = 2;
const int pixels_size = sizeof(VideoPixelBGR16);
const int num_halflines = 2;
const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels);
deinterleaved_rgb565_pixels* out_ptr_top = (deinterleaved_rgb565_pixels*)p_out->screen_data;
deinterleaved_rgb565_pixels* out_ptr_top = (deinterleaved_rgb565_pixels*)p_out->bgr16_video_output_data.screen_data;
deinterleaved_rgb565_pixels* out_ptr_bottom = out_ptr_top + ((WIDTH_DS * HEIGHT_DS * pixels_size) / ptr_out_size);
interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->video_in.screen_data;
const uint32_t halfline_iters = WIDTH_DS / num_halflines;
@ -442,12 +442,12 @@ static inline bool usb_OptimizeHasExtraHeaderSoundData(USB3DSOptimizeHeaderSound
static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptLE(USB5653DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) {
//de-interleave pixels
const int pixels_size = 2;
const int pixels_size = sizeof(VideoPixelRGB16);
const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2;
const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2);
const size_t column_last_bot_pos = TOP_WIDTH_3DS;
const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels);
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data;
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data;
deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size);
interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column;
if(column < column_last_bot_pos)
@ -471,12 +471,12 @@ static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptLE(USB5653
static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptBE(USB5653DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) {
//de-interleave pixels
const int pixels_size = 2;
const int pixels_size = sizeof(VideoPixelRGB16);
const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2;
const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2);
const size_t column_last_bot_pos = TOP_WIDTH_3DS;
const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels);
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data;
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data;
deinterleaved_rgb565_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size);
interleaved_rgb565_pixels* in_ptr = (interleaved_rgb565_pixels*)p_in->bottom_only_column;
if(column < column_last_bot_pos)
@ -500,12 +500,12 @@ static inline void usb_3DS565OptimizeconvertVideoToOutputLineDirectOptBE(USB5653
static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB5653DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, uint16_t column, bool interleaved_3d) {
//de-interleave pixels
const int pixels_size = 2;
const int pixels_size = sizeof(VideoPixelRGB16);
const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2;
const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2);
const size_t column_last_bot_pos = TOP_WIDTH_3DS;
const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels);
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data;
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data;
deinterleaved_rgb565_pixels* out_ptr_top_l = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size);
deinterleaved_rgb565_pixels* out_ptr_top_r = out_ptr_bottom + (((TOP_SIZE_3DS + BOT_SIZE_3DS) * pixels_size) / ptr_out_size);
interleaved_3d_rgb565_pixels* in_ptr = (interleaved_3d_rgb565_pixels*)p_in->bottom_only_column;
@ -536,12 +536,12 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptLE(USB56
static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB5653DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, uint16_t column, bool interleaved_3d) {
//de-interleave pixels
const int pixels_size = 2;
const int pixels_size = sizeof(VideoPixelRGB16);
const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2;
const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2);
const size_t column_last_bot_pos = TOP_WIDTH_3DS;
const size_t ptr_out_size = sizeof(deinterleaved_rgb565_pixels);
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->screen_data;
deinterleaved_rgb565_pixels* out_ptr_bottom = (deinterleaved_rgb565_pixels*)p_out->rgb16_video_output_data.screen_data;
deinterleaved_rgb565_pixels* out_ptr_top_l = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size);
deinterleaved_rgb565_pixels* out_ptr_top_r = out_ptr_bottom + (((TOP_SIZE_3DS + BOT_SIZE_3DS) * pixels_size) / ptr_out_size);
interleaved_3d_rgb565_pixels* in_ptr = (interleaved_3d_rgb565_pixels*)p_in->bottom_only_column;
@ -572,12 +572,12 @@ static inline void usb_3DS565Optimizeconvert3DVideoToOutputLineDirectOptBE(USB56
static inline void usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(USB8883DSOptimizeCaptureReceived *p_in, VideoOutputData *p_out, uint16_t column) {
//de-interleave pixels
const int pixels_size = 3;
const int pixels_size = sizeof(VideoPixelRGB);
const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2;
const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2);
const size_t column_last_bot_pos = TOP_WIDTH_3DS;
const size_t ptr_out_size = sizeof(deinterleaved_rgb888_u16_pixels);
deinterleaved_rgb888_u16_pixels* out_ptr_bottom = (deinterleaved_rgb888_u16_pixels*)p_out->screen_data;
deinterleaved_rgb888_u16_pixels* out_ptr_bottom = (deinterleaved_rgb888_u16_pixels*)p_out->rgb_video_output_data.screen_data;
deinterleaved_rgb888_u16_pixels* out_ptr_top = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size);
interleaved_rgb888_u16_pixels* in_ptr = (interleaved_rgb888_u16_pixels*)p_in->bottom_only_column;
if(column < column_last_bot_pos)
@ -601,12 +601,12 @@ static inline void usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(USB8883DS
static inline void usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(USB8883DSOptimizeCaptureReceived_3D *p_in, VideoOutputData *p_out, uint16_t column, bool interleaved_3d) {
//de-interleave pixels
const int pixels_size = 3;
const int pixels_size = sizeof(VideoPixelRGB);
const size_t column_start_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2) + 2;
const size_t column_pre_last_bot_pos = (SCREEN_WIDTH_FIRST_PIXEL_BOTTOM_3DS * 2);
const size_t column_last_bot_pos = TOP_WIDTH_3DS;
const size_t ptr_out_size = sizeof(deinterleaved_rgb888_u16_pixels);
deinterleaved_rgb888_u16_pixels* out_ptr_bottom = (deinterleaved_rgb888_u16_pixels*)p_out->screen_data;
deinterleaved_rgb888_u16_pixels* out_ptr_bottom = (deinterleaved_rgb888_u16_pixels*)p_out->rgb_video_output_data.screen_data;
deinterleaved_rgb888_u16_pixels* out_ptr_top_l = out_ptr_bottom + ((BOT_SIZE_3DS * pixels_size) / ptr_out_size);
deinterleaved_rgb888_u16_pixels* out_ptr_top_r = out_ptr_bottom + (((TOP_SIZE_3DS + BOT_SIZE_3DS) * pixels_size) / ptr_out_size);
interleaved_3d_rgb888_u16_pixels* in_ptr = (interleaved_3d_rgb888_u16_pixels*)p_in->bottom_only_column;
@ -638,12 +638,12 @@ static inline void usb_3DS888Optimizeconvert3DVideoToOutputLineDirectOpt(USB8883
static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOutputData *p_out, const bool is_big_endian) {
#ifndef SIMPLE_DS_FRAME_SKIP
if(!p_in->frameinfo.valid) { //LCD was off
memset(p_out->screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * sizeof(uint16_t));
memset(p_out->bgr16_video_output_data.screen_data, 0, WIDTH_DS * (2 * HEIGHT_DS) * sizeof(uint16_t));
return;
}
// Handle first line being off, if needed
memset(p_out->screen_data, 0, WIDTH_DS * sizeof(uint16_t));
memset(p_out->bgr16_video_output_data.screen_data, 0, WIDTH_DS * sizeof(uint16_t));
if(!is_big_endian) {
int input_halfline = 0;
@ -656,7 +656,7 @@ static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOu
if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7)))
usb_oldDSconvertVideoToOutputHalfLineDirectOptLE(p_in, p_out, input_halfline++, i);
else { // deal with missing half-line
uint16_t* out_ptr_top = (uint16_t*)&p_out->screen_data;
uint16_t* out_ptr_top = (uint16_t*)&p_out->bgr16_video_output_data.screen_data;
uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS);
memcpy(&out_ptr_top[i * (WIDTH_DS / 2)], &out_ptr_top[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
memcpy(&out_ptr_bottom[i * (WIDTH_DS / 2)], &out_ptr_bottom[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
@ -674,7 +674,7 @@ static void usb_oldDSconvertVideoToOutput(USBOldDSCaptureReceived *p_in, VideoOu
if(p_in->frameinfo.half_line_flags[(i >> 3)] & (1 << (i & 7)))
usb_oldDSconvertVideoToOutputHalfLineDirectOptBE(p_in, p_out, input_halfline++, i);
else { // deal with missing half-line
uint16_t* out_ptr_top = (uint16_t*)&p_out->screen_data;
uint16_t* out_ptr_top = (uint16_t*)&p_out->bgr16_video_output_data.screen_data;
uint16_t* out_ptr_bottom = out_ptr_top + (WIDTH_DS * HEIGHT_DS);
memcpy(&out_ptr_top[i * (WIDTH_DS / 2)], &out_ptr_top[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
memcpy(&out_ptr_bottom[i * (WIDTH_DS / 2)], &out_ptr_bottom[(i - 2) * (WIDTH_DS / 2)], (WIDTH_DS / 2) * sizeof(uint16_t));
@ -696,7 +696,7 @@ static void ftd2_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_
}
static void usb_3DSconvertVideoToOutput(USB3DSCaptureReceived *p_in, VideoOutputData *p_out) {
memcpy(p_out->screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3);
memcpy(p_out->rgb_video_output_data.screen_data, p_in->video_in.screen_data, IN_VIDEO_HEIGHT_3DS * IN_VIDEO_WIDTH_3DS * 3);
}
static void usb_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out, CaptureDevice* capture_device, bool enabled_3d, const bool is_big_endian, bool interleaved_3d, bool requested_3d) {
@ -712,6 +712,10 @@ inline static uint8_t to_8_bit_6(uint8_t data) {
return (data << 2) | (data >> 4);
}
inline static uint8_t to_8_bit_5(uint8_t data) {
return (data << 3) | (data >> 2);
}
inline static void to_8_bit_6(uint8_t* out, uint8_t* in) {
out[0] = to_8_bit_6(in[0]);
out[1] = to_8_bit_6(in[1]);
@ -720,9 +724,9 @@ inline static void to_8_bit_6(uint8_t* out, uint8_t* in) {
static void usb_cypress_nisetro_ds_convertVideoToOutput(CaptureReceived *p_in, VideoOutputData *p_out) {
int pos_top = 0;
int pos_bottom = WIDTH_DS * HEIGHT_DS * 3;
int pos_bottom = WIDTH_DS * HEIGHT_DS * sizeof(VideoPixelRGB);
uint8_t* data_in = (uint8_t*)p_in->cypress_nisetro_capture_received.video_in.screen_data;
uint8_t* data_out = (uint8_t*)p_out->screen_data;
uint8_t* data_out = (uint8_t*)p_out->rgb_video_output_data.screen_data;
for(size_t i = 0; i < sizeof(CypressNisetroDSCaptureReceived); i++) {
uint8_t conv = to_8_bit_6(data_in[i]);
if(data_in[i] & 0x40)
@ -741,7 +745,7 @@ static void usb_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOu
else
for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++)
usb_3DS565OptimizeconvertVideoToOutputLineDirectOptBE(&p_in->cypress_optimize_received_565, p_out, i);
expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->screen_data, 2, interleaved_3d, requested_3d);
expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->rgb16_video_output_data.screen_data, sizeof(VideoPixelRGB16), interleaved_3d, requested_3d);
}
else {
if(!is_big_endian)
@ -756,7 +760,7 @@ static void usb_3ds_optimize_convertVideoToOutput(CaptureReceived *p_in, VideoOu
if(!enabled_3d) {
for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++)
usb_3DS888OptimizeconvertVideoToOutputLineDirectOpt(&p_in->cypress_optimize_received_888, p_out, i);
expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->screen_data, 3, interleaved_3d, requested_3d);
expand_2d_to_3d_convertVideoToOutput((uint8_t*)p_out->rgb_video_output_data.screen_data, sizeof(VideoPixelRGB), interleaved_3d, requested_3d);
}
else {
for(int i = 0; i < (TOP_WIDTH_3DS + 1); i++)
@ -779,8 +783,8 @@ static void usb_is_device_convertVideoToOutput(CaptureReceived *p_in, VideoOutpu
out_clear_pos = 0;
}
if((capture_type == CAPTURE_SCREENS_BOTTOM) || (capture_type == CAPTURE_SCREENS_TOP))
memset(p_out->screen_data[out_clear_pos], 0, (size_t)(num_pixels * 3));
memcpy(p_out->screen_data[out_start_pos], p_in->is_nitro_capture_received.video_in.screen_data, (size_t)(num_pixels * 3));
memset((uint8_t*)&p_out->bgr_video_output_data.screen_data[out_clear_pos], 0, (size_t)(num_pixels * sizeof(VideoPixelBGR)));
memcpy((uint8_t*)&p_out->bgr_video_output_data.screen_data[out_start_pos], p_in->is_nitro_capture_received.video_in.screen_data, (size_t)(num_pixels * sizeof(VideoPixelBGR)));
return;
}
ISTWLCaptureVideoInputData* data = &p_in->is_twl_capture_received.video_capture_in.video_in;
@ -807,7 +811,7 @@ static void usb_is_device_convertVideoToOutput(CaptureReceived *p_in, VideoOutpu
pixels[3][1] = data_16_bit[index].fourth_g;
pixels[3][2] = (data_16_bit[index].fourth_b << 1) | (data_2_bit[index].fourth_b);
for(int k = 0; k < num_pixels_struct; k++)
to_8_bit_6(p_out->screen_data[out_pos + (u * num_pixels_struct) + k], pixels[k]);
to_8_bit_6((uint8_t*)&p_out->rgb_video_output_data.screen_data[out_pos + (u * num_pixels_struct) + k], pixels[k]);
}
}
}
@ -1010,3 +1014,64 @@ bool convertAudioToOutput(std::int16_t *p_out, uint64_t &n_samples, uint16_t &la
p_out[i] = (base_ptr[(i * 2) + 1] << 8) | base_ptr[i * 2];
return true;
}
static void convert_rgb16_to_rgb(VideoOutputData* src, VideoOutputData* dst, size_t pos_x_data, size_t pos_y_data, size_t width, size_t height) {
for (size_t i = 0; i < height; i++) {
for (size_t j = 0; j < width; j++) {
size_t pixel = ((height - 1 - i) * width) + (width - 1 - j) + pos_x_data + (pos_y_data * width);
uint8_t r = to_8_bit_5(src->rgb16_video_output_data.screen_data[pixel].r);
uint8_t g = to_8_bit_6(src->rgb16_video_output_data.screen_data[pixel].g);
uint8_t b = to_8_bit_5(src->rgb16_video_output_data.screen_data[pixel].b);
dst->rgb_video_output_data.screen_data[pixel].r = r;
dst->rgb_video_output_data.screen_data[pixel].g = g;
dst->rgb_video_output_data.screen_data[pixel].b = b;
}
}
}
static void convert_bgr_to_rgb(VideoOutputData* src, VideoOutputData* dst, size_t pos_x_data, size_t pos_y_data, size_t width, size_t height) {
for (size_t i = 0; i < height; i++) {
for (size_t j = 0; j < width; j++) {
size_t pixel = ((height - 1 - i) * width) + (width - 1 - j) + pos_x_data + (pos_y_data * width);
uint8_t r = src->bgr_video_output_data.screen_data[pixel].r;
uint8_t g = src->bgr_video_output_data.screen_data[pixel].g;
uint8_t b = src->bgr_video_output_data.screen_data[pixel].b;
dst->rgb_video_output_data.screen_data[pixel].r = r;
dst->rgb_video_output_data.screen_data[pixel].g = g;
dst->rgb_video_output_data.screen_data[pixel].b = b;
}
}
}
static void convert_bgr16_to_rgb(VideoOutputData* src, VideoOutputData* dst, size_t pos_x_data, size_t pos_y_data, size_t width, size_t height) {
uint16_t* data_16_ptr = (uint16_t*)src;
for (size_t i = 0; i < height; i++) {
for (size_t j = 0; j < width; j++) {
size_t pixel = ((height - 1 - i) * width) + (width - 1 - j) + pos_x_data + (pos_y_data * width);
uint8_t r = to_8_bit_5(src->bgr16_video_output_data.screen_data[pixel].r);
uint8_t g = to_8_bit_6(src->bgr16_video_output_data.screen_data[pixel].g);
uint8_t b = to_8_bit_5(src->bgr16_video_output_data.screen_data[pixel].b);
dst->rgb_video_output_data.screen_data[pixel].r = r;
dst->rgb_video_output_data.screen_data[pixel].g = g;
dst->rgb_video_output_data.screen_data[pixel].b = b;
}
}
}
void manualConvertOutputToRGB(VideoOutputData* src, VideoOutputData* dst, size_t pos_x_data, size_t pos_y_data, size_t width, size_t height, InputVideoDataType video_data_type) {
switch (video_data_type) {
case VIDEO_DATA_RGB:
break;
case VIDEO_DATA_RGB16:
convert_rgb16_to_rgb(src, dst, pos_x_data, pos_y_data, width, height);
break;
case VIDEO_DATA_BGR:
convert_bgr_to_rgb(src, dst, pos_x_data, pos_y_data, width, height);
break;
case VIDEO_DATA_BGR16:
convert_bgr16_to_rgb(src, dst, pos_x_data, pos_y_data, width, height);
break;
default:
break;
}
}

View File

@ -1,6 +1,7 @@
#include "frontend.hpp"
#include <cmath>
#include <thread>
#include <iostream>
#include <SFML/System.hpp>
const CropData default_3ds_crop = {
@ -1177,3 +1178,24 @@ std::string get_name_input_colorspace_mode(InputColorspaceMode input) {
}
return output;
}
static void ConsoleOutText(std::string full_text, std::string preamble_name) {
if(full_text != "")
std::cout << "[" << preamble_name << "] " << full_text << std::endl;
}
void ConsumeOutText(OutTextData &out_text_data, bool update_consumed) {
if(!out_text_data.consumed)
ConsoleOutText(out_text_data.full_text, out_text_data.preamble_name);
if(update_consumed)
out_text_data.consumed = true;
}
void UpdateOutText(OutTextData &out_text_data, std::string full_text, std::string small_text, TextKind kind) {
if(!out_text_data.consumed)
ConsumeOutText(out_text_data);
out_text_data.full_text = full_text;
out_text_data.small_text = small_text;
out_text_data.kind = kind;
out_text_data.consumed = false;
}