From 554cc9488ffb74d601bc800b886f0530be1aac49 Mon Sep 17 00:00:00 2001 From: Harry Prevor Date: Sun, 14 Jan 2018 21:48:01 -0500 Subject: [PATCH 01/25] fixed build for gcc c++17 / boost.icl incompatibility --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09fe9bcd31..2af11a4e66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,12 @@ else() set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) endif() +# Fix GCC C++17 and Boost.ICL incompatibility (needed to build dynarmic) +# See https://bugzilla.redhat.com/show_bug.cgi?id=1485641#c1 +if (CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-new-ttp-matching") +endif() + # Set file offset size to 64 bits. # # On modern Unixes, this is typically already the case. The lone exception is From 92801b1c345f2aa47d0b89c91313b44c08edbb86 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 15 Jan 2018 00:20:19 -0500 Subject: [PATCH 02/25] renderer_gl: Clear screen to black before rendering framebuffer. --- src/video_core/renderer_opengl/renderer_opengl.cpp | 9 ++++++--- src/video_core/renderer_opengl/renderer_opengl.h | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index f1c3ff9489..50396b5c1f 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -293,16 +293,16 @@ void RendererOpenGL::LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, * Fills active OpenGL texture with the given RGB color. Since the color is solid, the texture can * be 1x1 but will stretch across whatever it's rendered on. */ -void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, +void RendererOpenGL::LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture) { state.texture_units[0].texture_2d = texture.resource.handle; state.Apply(); glActiveTexture(GL_TEXTURE0); - u8 framebuffer_data[3] = {color_r, color_g, color_b}; + u8 framebuffer_data[4] = {color_a, color_b, color_g, color_r}; // Update existing texture - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, framebuffer_data); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, framebuffer_data); state.texture_units[0].texture_2d = 0; state.Apply(); @@ -364,6 +364,9 @@ void RendererOpenGL::InitOpenGLObjects() { state.texture_units[0].texture_2d = 0; state.Apply(); + + // Clear screen to black + LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); } void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 2f5e357875..dd01e1b1ad 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -60,8 +60,8 @@ private: // Loads framebuffer from emulated memory into the display information structure void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info); - // Fills active OpenGL texture with the given RGB color. - void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, const TextureInfo& texture); + // Fills active OpenGL texture with the given RGBA color. + void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a, const TextureInfo& texture); EmuWindow* render_window; ///< Handle to render window From af1ca87be106f7b6778d6b02e788835d8b4c3ffe Mon Sep 17 00:00:00 2001 From: bsaleil Date: Mon, 15 Jan 2018 01:29:00 -0500 Subject: [PATCH 03/25] vi: Add IManagerDisplayService::CloseDisplay function --- src/core/hle/service/vi/vi.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index b35a7a377f..93ebbe75f6 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -494,6 +494,7 @@ public: IManagerDisplayService(std::shared_ptr nv_flinger) : ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) { static const FunctionInfo functions[] = { + {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, {1102, nullptr, "GetDisplayResolution"}, {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, @@ -503,6 +504,15 @@ public: ~IManagerDisplayService() = default; private: + void CloseDisplay(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service, "(STUBBED) called"); + IPC::RequestParser rp{ctx}; + u64 display = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0, 0, 0); + rb.Push(RESULT_SUCCESS); + } + void CreateManagedLayer(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); IPC::RequestParser rp{ctx}; From f2d55bb881902a808c18a7135ec2c257f463af95 Mon Sep 17 00:00:00 2001 From: Harry Prevor Date: Sun, 14 Jan 2018 21:48:01 -0500 Subject: [PATCH 04/25] fixed build for gcc c++17 / boost.icl incompatibility --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 09fe9bcd31..2af11a4e66 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,6 +134,12 @@ else() set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/DEBUG /MANIFEST:NO /INCREMENTAL:NO /OPT:REF,ICF" CACHE STRING "" FORCE) endif() +# Fix GCC C++17 and Boost.ICL incompatibility (needed to build dynarmic) +# See https://bugzilla.redhat.com/show_bug.cgi?id=1485641#c1 +if (CMAKE_COMPILER_IS_GNUCC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-new-ttp-matching") +endif() + # Set file offset size to 64 bits. # # On modern Unixes, this is typically already the case. The lone exception is From e08c132175232aca748321be3fb76b309c281eb6 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 00:13:18 -0700 Subject: [PATCH 05/25] hid: Add sharedmem structs --- src/core/hle/service/hid/hid.h | 312 +++++++++++++++++++++++++++++++++ 1 file changed, 312 insertions(+) diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index f7621f62d1..7803778d47 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -9,6 +9,318 @@ namespace Service { namespace HID { +// Begin enums and output structs + +enum HIDControllerType : u32 { + ControllerType_ProController = 1 << 0, + ControllerType_Handheld = 1 << 1, + ControllerType_JoyconPair = 1 << 2, + ControllerType_JoyconLeft = 1 << 3, + ControllerType_JoyconRight = 1 << 4, +}; + +enum HIDControllerLayoutType : u32 { + Layout_ProController = 0, // Pro Controller or HID gamepad + Layout_Handheld = 1, // Two Joy-Con docked to rails + Layout_Single = 2, // Horizontal single Joy-Con or pair of Joy-Con, adjusted for orientation + Layout_Left = 3, // Only raw left Joy-Con state, no orientation adjustment + Layout_Right = 4, // Only raw right Joy-Con state, no orientation adjustment + Layout_DefaultDigital = 5, // Same as next, but sticks have 8-direction values only + Layout_Default = 6, // Safe default, single Joy-Con have buttons/sticks rotated for orientation +}; + +enum HIDControllerColorDescription { + ColorDesc_ColorsNonexistent = 1 << 1, +}; + +enum HIDControllerConnectionState { + ConnectionState_Connected = 1 << 0, + ConnectionState_Wired = 1 << 1, +}; + +enum HIDControllerID { + Controller_Player1 = 0, + Controller_Player2 = 1, + Controller_Player3 = 2, + Controller_Player4 = 3, + Controller_Player5 = 4, + Controller_Player6 = 5, + Controller_Player7 = 6, + Controller_Player8 = 7, + Controller_Handheld = 8, + Controller_Unknown = 9, +}; + +// End enums and output structs + +// Begin HIDTouchScreen + +struct HIDTouchScreenHeader { + u64 timestampTicks; + u64 numEntries; + u64 latestEntry; + u64 maxEntryIndex; + u64 timestamp; +}; +static_assert(sizeof(HIDTouchScreenHeader) == 0x28, + "HID touch screen header structure has incorrect size"); + +struct HIDTouchScreenEntryHeader { + u64 timestamp; + u64 numTouches; +}; +static_assert(sizeof(HIDTouchScreenEntryHeader) == 0x10, + "HID touch screen entry header structure has incorrect size"); + +struct HIDTouchScreenEntryTouch { + u64 timestamp; + u32 padding; + u32 touchIndex; + u32 x; + u32 y; + u32 diameterX; + u32 diameterY; + u32 angle; + u32 padding_2; +}; +static_assert(sizeof(HIDTouchScreenEntryTouch) == 0x28, + "HID touch screen touch structure has incorrect size"); + +struct HIDTouchScreenEntry { + HIDTouchScreenEntryHeader header; + std::array touches; + u64 unk; +}; +static_assert(sizeof(HIDTouchScreenEntry) == 0x298, + "HID touch screen entry structure has incorrect size"); + +struct HIDTouchScreen { + HIDTouchScreenHeader header; + std::array entries; + std::array padding; +}; +static_assert(sizeof(HIDTouchScreen) == 0x3000, "HID touch screen structure has incorrect size"); + +// End HIDTouchScreen + +// Begin HIDMouse + +struct HIDMouseHeader { + u64 timestampTicks; + u64 numEntries; + u64 latestEntry; + u64 maxEntryIndex; +}; +static_assert(sizeof(HIDMouseHeader) == 0x20, "HID mouse header structure has incorrect size"); + +struct HIDMouseButtonState { + union { + u64 hex{}; + + // Buttons + BitField<0, 1, u64> left; + BitField<1, 1, u64> right; + BitField<2, 1, u64> middle; + BitField<3, 1, u64> forward; + BitField<4, 1, u64> back; + }; +}; + +struct HIDMouseEntry { + u64 timestamp; + u64 timestamp_2; + u32 x; + u32 y; + u32 velocityX; + u32 velocityY; + u32 scrollVelocityX; + u32 scrollVelocityY; + HIDMouseButtonState buttons; +}; +static_assert(sizeof(HIDMouseEntry) == 0x30, "HID mouse entry structure has incorrect size"); + +struct HIDMouse { + HIDMouseHeader header; + std::array entries; + std::array padding; +}; +static_assert(sizeof(HIDMouse) == 0x400, "HID mouse structure has incorrect size"); + +// End HIDMouse + +// Begin HIDKeyboard + +struct HIDKeyboardHeader { + u64 timestampTicks; + u64 numEntries; + u64 latestEntry; + u64 maxEntryIndex; +}; +static_assert(sizeof(HIDKeyboardHeader) == 0x20, + "HID keyboard header structure has incorrect size"); + +struct HIDKeyboardModifierKeyState { + union { + u64 hex{}; + + // Buttons + BitField<0, 1, u64> lctrl; + BitField<1, 1, u64> lshift; + BitField<2, 1, u64> lalt; + BitField<3, 1, u64> lmeta; + BitField<4, 1, u64> rctrl; + BitField<5, 1, u64> rshift; + BitField<6, 1, u64> ralt; + BitField<7, 1, u64> rmeta; + BitField<8, 1, u64> capslock; + BitField<9, 1, u64> scrolllock; + BitField<10, 1, u64> numlock; + }; +}; + +struct HIDKeyboardEntry { + u64 timestamp; + u64 timestamp_2; + HIDKeyboardModifierKeyState modifier; + u32 keys[8]; +}; +static_assert(sizeof(HIDKeyboardEntry) == 0x38, "HID keyboard entry structure has incorrect size"); + +struct HIDKeyboard { + HIDKeyboardHeader header; + std::array entries; + std::array padding; +}; +static_assert(sizeof(HIDKeyboard) == 0x400, "HID keyboard structure has incorrect size"); + +// End HIDKeyboard + +// Begin HIDController + +struct HIDControllerMAC { + u64 timestamp; + std::array mac; + u64 unk; + u64 timestamp_2; +}; +static_assert(sizeof(HIDControllerMAC) == 0x20, "HID controller MAC structure has incorrect size"); + +struct HIDControllerHeader { + u32 type; + u32 isHalf; + u32 singleColorsDescriptor; + u32 singleColorBody; + u32 singleColorButtons; + u32 splitColorsDescriptor; + u32 leftColorBody; + u32 leftColorButtons; + u32 rightColorBody; + u32 rightColorbuttons; +}; +static_assert(sizeof(HIDControllerHeader) == 0x28, + "HID controller header structure has incorrect size"); + +struct HIDControllerLayoutHeader { + u64 timestampTicks; + u64 numEntries; + u64 latestEntry; + u64 maxEntryIndex; +}; +static_assert(sizeof(HIDControllerLayoutHeader) == 0x20, + "HID controller layout header structure has incorrect size"); + +struct HIDControllerPadState { + union { + u64 hex{}; + + // Buttons + BitField<0, 1, u64> a; + BitField<1, 1, u64> b; + BitField<2, 1, u64> x; + BitField<3, 1, u64> y; + BitField<4, 1, u64> lstick; + BitField<5, 1, u64> rstick; + BitField<6, 1, u64> l; + BitField<7, 1, u64> r; + BitField<8, 1, u64> zl; + BitField<9, 1, u64> zr; + BitField<10, 1, u64> plus; + BitField<11, 1, u64> minus; + + // D-pad buttons + BitField<12, 1, u64> dleft; + BitField<13, 1, u64> dup; + BitField<14, 1, u64> dright; + BitField<15, 1, u64> ddown; + + // Left stick directions + BitField<16, 1, u64> lstick_left; + BitField<17, 1, u64> lstick_up; + BitField<18, 1, u64> lstick_right; + BitField<19, 1, u64> lstick_down; + + // Right stick directions + BitField<20, 1, u64> rstick_left; + BitField<21, 1, u64> rstick_up; + BitField<22, 1, u64> rstick_right; + BitField<23, 1, u64> rstick_down; + + BitField<24, 1, u64> sl; + BitField<25, 1, u64> sr; + }; +}; + +struct HIDControllerInputEntry { + u64 timestamp; + u64 timestamp_2; + HIDControllerPadState buttons; + u32 joystickLeftX; + u32 joystickLeftY; + u32 joystickRightX; + u32 joystickRightY; + u64 connectionState; +}; +static_assert(sizeof(HIDControllerInputEntry) == 0x30, + "HID controller input entry structure has incorrect size"); + +struct HIDControllerLayout { + HIDControllerLayoutHeader header; + std::array entries; +}; +static_assert(sizeof(HIDControllerLayout) == 0x350, + "HID controller layout structure has incorrect size"); + +struct HIDController { + HIDControllerHeader header; + std::array layouts; + std::array unk_1; + HIDControllerMAC macLeft; + HIDControllerMAC macRight; + std::array unk_2; +}; +static_assert(sizeof(HIDController) == 0x5000, "HID controller structure has incorrect size"); + +// End HIDController + +struct HIDSharedMemory { + std::array header; + HIDTouchScreen touchscreen; + HIDMouse mouse; + HIDKeyboard keyboard; + std::array unkSection1; + std::array unkSection2; + std::array unkSection3; + std::array unkSection4; + std::array unkSection5; + std::array unkSection6; + std::array unkSection7; + std::array unkSection8; + std::array controllerSerials; + std::array controllers; + std::array unkSection9; +}; +static_assert(sizeof(HIDSharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size"); + /// Reload input devices. Used when input configuration changed void ReloadInputDevices(); From 74aa14c9b47c848a1b9832379d8cd69b558037f8 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 00:24:23 -0700 Subject: [PATCH 06/25] settings: adjust button configs for Switch controllers --- src/core/settings.h | 67 +++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 17 deletions(-) diff --git a/src/core/settings.h b/src/core/settings.h index f2c88e5d40..be79ff78e7 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -16,17 +16,32 @@ enum Values { B, X, Y, - Up, - Down, - Left, - Right, + LStick, + RStick, L, R, - Start, - Select, - ZL, ZR, + Plus, + Minus, + + DLeft, + DUp, + DRight, + DDown, + + LStick_Left, + LStick_Up, + LStick_Right, + LStick_Down, + + RStick_Left, + RStick_Up, + RStick_Right, + RStick_Down, + + SL, + SR, Home, @@ -34,34 +49,52 @@ enum Values { }; constexpr int BUTTON_HID_BEGIN = A; -constexpr int BUTTON_IR_BEGIN = ZL; constexpr int BUTTON_NS_BEGIN = Home; -constexpr int BUTTON_HID_END = BUTTON_IR_BEGIN; -constexpr int BUTTON_IR_END = BUTTON_NS_BEGIN; +constexpr int BUTTON_HID_END = BUTTON_NS_BEGIN; constexpr int BUTTON_NS_END = NumButtons; constexpr int NUM_BUTTONS_HID = BUTTON_HID_END - BUTTON_HID_BEGIN; -constexpr int NUM_BUTTONS_IR = BUTTON_IR_END - BUTTON_IR_BEGIN; constexpr int NUM_BUTTONS_NS = BUTTON_NS_END - BUTTON_NS_BEGIN; static const std::array mapping = {{ - "button_a", "button_b", "button_x", "button_y", "button_up", "button_down", "button_left", - "button_right", "button_l", "button_r", "button_start", "button_select", "button_zl", - "button_zr", "button_home", + "button_a", + "button_b", + "button_x", + "button_y", + "button_lstick", + "button_rstick", + "button_l", + "button_r", + "button_zl", + "button_zr", + "button_plus", + "button_minus", + "button_dleft", + "button_dup", + "button_dright", + "button_ddown", + "button_lstick_left", + "button_lstick_up", + "button_lstick_right", + "button_lstick_down", + "button_sl", + "button_sr", + "button_home", }}; } // namespace NativeButton namespace NativeAnalog { enum Values { - CirclePad, - CStick, + LStick, + RStick, NumAnalogs, }; static const std::array mapping = {{ - "circle_pad", "c_stick", + "lstick", + "rstick", }}; } // namespace NativeAnalog From cdb43e64c1ef33fb4d1e81c1bf2321a7024a8732 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 00:31:59 -0700 Subject: [PATCH 07/25] yuzu_cmd: fix default ini --- src/yuzu_cmd/default_ini.h | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index e7941ecebb..47d1198b31 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -30,17 +30,25 @@ button_a= button_b= button_x= button_y= -button_up= -button_down= -button_left= -button_right= +button_lstick= +button_rstick= button_l= button_r= -button_start= -button_select= button_zl= button_zr= -button_home= +button_plus= +button_minus= +button_dleft= +button_dup= +button_dright= +button_ddown= +button_lstick_left= +button_lstick_up= +button_lstick_right= +button_lstick_down= +button_sl= +button_sr= +button_home" # for analog input, the following devices are available: # - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: @@ -53,8 +61,8 @@ button_home= # - "joystick": the index of the joystick to bind # - "axis_x": the index of the axis to bind as x-axis (default to 0) # - "axis_y": the index of the axis to bind as y-axis (default to 1) -circle_pad= -c_stick= +lstick= +rstick= # for motion input, the following devices are available: # - "motion_emu" (default) for emulating motion input from mouse input. Required parameters: From 801d6c1b6f0e09f57c6d45d0b358416e55b5afc5 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 01:35:25 -0700 Subject: [PATCH 08/25] settings: Screenshot button --- src/core/settings.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/settings.h b/src/core/settings.h index be79ff78e7..bd9a3d9feb 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -44,6 +44,7 @@ enum Values { SR, Home, + Screenshot, NumButtons, }; @@ -81,6 +82,7 @@ static const std::array mapping = {{ "button_sl", "button_sr", "button_home", + "button_screenshot", }}; } // namespace NativeButton From aa4fa8bded307f5472b7934c37b15bd096b99ca1 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 01:35:53 -0700 Subject: [PATCH 09/25] configure_input: update w/ Switch buttons --- src/yuzu/configuration/config.cpp | 10 +- src/yuzu/configuration/configure_input.cpp | 18 +- src/yuzu/configuration/configure_input.ui | 291 +++++++++++++++------ 3 files changed, 225 insertions(+), 94 deletions(-) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 4c713fcbc7..9ce851d174 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -19,16 +19,18 @@ Config::Config() { } const std::array Config::default_buttons = { - Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_T, Qt::Key_G, Qt::Key_F, Qt::Key_H, - Qt::Key_Q, Qt::Key_W, Qt::Key_M, Qt::Key_N, Qt::Key_1, Qt::Key_2, Qt::Key_B, + Qt::Key_A, Qt::Key_S, Qt::Key_Z, Qt::Key_X, Qt::Key_3, Qt::Key_4, Qt::Key_Q, Qt::Key_W, + Qt::Key_1, Qt::Key_2, Qt::Key_N, Qt::Key_M, Qt::Key_F, Qt::Key_T, Qt::Key_H, Qt::Key_G, + Qt::Key_Left, Qt::Key_Up, Qt::Key_Right, Qt::Key_Down, Qt::Key_J, Qt::Key_I, Qt::Key_L, + Qt::Key_K, Qt::Key_D, Qt::Key_C, Qt::Key_B, Qt::Key_V, }; const std::array, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ { - Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D, + Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_E, }, { - Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_D, + Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_R, }, }}; diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 4c2a3e7380..d92a1fed9f 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp @@ -54,19 +54,23 @@ ConfigureInput::ConfigureInput(QWidget* parent) setFocusPolicy(Qt::ClickFocus); button_map = { - ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, ui->buttonDpadUp, - ui->buttonDpadDown, ui->buttonDpadLeft, ui->buttonDpadRight, ui->buttonL, ui->buttonR, - ui->buttonStart, ui->buttonSelect, ui->buttonZL, ui->buttonZR, ui->buttonHome, + ui->buttonA, ui->buttonB, ui->buttonX, ui->buttonY, + ui->buttonLStick, ui->buttonRStick, ui->buttonL, ui->buttonR, + ui->buttonZL, ui->buttonZR, ui->buttonPlus, ui->buttonMinus, + ui->buttonDpadLeft, ui->buttonDpadUp, ui->buttonDpadRight, ui->buttonDpadDown, + ui->buttonLStickLeft, ui->buttonLStickUp, ui->buttonLStickRight, ui->buttonLStickDown, + ui->buttonRStickLeft, ui->buttonRStickUp, ui->buttonRStickRight, ui->buttonRStickDown, + ui->buttonSL, ui->buttonSR, ui->buttonHome, ui->buttonScreenshot, }; analog_map = {{ { - ui->buttonCircleUp, ui->buttonCircleDown, ui->buttonCircleLeft, ui->buttonCircleRight, - ui->buttonCircleMod, + ui->buttonLStickUp, ui->buttonLStickDown, ui->buttonLStickLeft, ui->buttonLStickRight, + ui->buttonLStickMod, }, { - ui->buttonCStickUp, ui->buttonCStickDown, ui->buttonCStickLeft, ui->buttonCStickRight, - nullptr, + ui->buttonRStickUp, ui->buttonRStickDown, ui->buttonRStickLeft, ui->buttonRStickRight, + ui->buttonRStickMod, }, }}; diff --git a/src/yuzu/configuration/configure_input.ui b/src/yuzu/configuration/configure_input.ui index 2760787e59..5143c9d725 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui @@ -6,8 +6,8 @@ 0 0 - 370 - 534 + 343 + 665 @@ -190,7 +190,108 @@ - + + + + Misc. + + + false + + + false + + + + + + + + Plus: + + + + + + + + + + + + + + + + + + Minus: + + + + + + + + + + + + + + + + + + Home: + + + + + + + + + + + + + + + + + + Screen +Capture: + + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Shoulder Buttons @@ -274,13 +375,49 @@ + + + + + + SL: + + + + + + + + + + + + + + + + + + SR: + + + + + + + + + + + + - + - Circle Pad + Left Stick false @@ -299,7 +436,7 @@ - + @@ -317,7 +454,7 @@ - + @@ -335,7 +472,7 @@ - + @@ -353,7 +490,43 @@ - + + + + + + + + + + + + + + Pressed: + + + + + + + + + + + + + + + + + + Modifier: + + + + + @@ -364,10 +537,13 @@ - + - C-Stick + Right Stick + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter false @@ -376,17 +552,17 @@ false - - + + - + - Left: + Down: - + @@ -404,7 +580,7 @@ - + @@ -422,7 +598,7 @@ - + @@ -430,50 +606,17 @@ - - - - - - Down: - - - - - - - - - - - - - - - - - - - Misc. - - - false - - - false - - - + - + - Start: + Left: - + @@ -481,17 +624,17 @@ - - + + - + - Select: + Modifier: - + @@ -499,35 +642,17 @@ - - + + - + - Home: + Pressed: - - - - - - - - - - - - - - Circle Mod: - - - - - + From bb1fcfac3377ca207b3cfc0c50ecae2b31462cd5 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 01:49:32 -0700 Subject: [PATCH 10/25] hid: Remove redundant HID prefix on structs/enums --- src/core/hle/service/hid/hid.h | 146 ++++++++++++++++----------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 7803778d47..7fd45d56f4 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -11,7 +11,7 @@ namespace HID { // Begin enums and output structs -enum HIDControllerType : u32 { +enum ControllerType : u32 { ControllerType_ProController = 1 << 0, ControllerType_Handheld = 1 << 1, ControllerType_JoyconPair = 1 << 2, @@ -19,7 +19,7 @@ enum HIDControllerType : u32 { ControllerType_JoyconRight = 1 << 4, }; -enum HIDControllerLayoutType : u32 { +enum ControllerLayoutType : u32 { Layout_ProController = 0, // Pro Controller or HID gamepad Layout_Handheld = 1, // Two Joy-Con docked to rails Layout_Single = 2, // Horizontal single Joy-Con or pair of Joy-Con, adjusted for orientation @@ -29,16 +29,16 @@ enum HIDControllerLayoutType : u32 { Layout_Default = 6, // Safe default, single Joy-Con have buttons/sticks rotated for orientation }; -enum HIDControllerColorDescription { +enum ControllerColorDescription { ColorDesc_ColorsNonexistent = 1 << 1, }; -enum HIDControllerConnectionState { +enum ControllerConnectionState { ConnectionState_Connected = 1 << 0, ConnectionState_Wired = 1 << 1, }; -enum HIDControllerID { +enum ControllerID { Controller_Player1 = 0, Controller_Player2 = 1, Controller_Player3 = 2, @@ -53,26 +53,26 @@ enum HIDControllerID { // End enums and output structs -// Begin HIDTouchScreen +// Begin TouchScreen -struct HIDTouchScreenHeader { +struct TouchScreenHeader { u64 timestampTicks; u64 numEntries; u64 latestEntry; u64 maxEntryIndex; u64 timestamp; }; -static_assert(sizeof(HIDTouchScreenHeader) == 0x28, +static_assert(sizeof(TouchScreenHeader) == 0x28, "HID touch screen header structure has incorrect size"); -struct HIDTouchScreenEntryHeader { +struct TouchScreenEntryHeader { u64 timestamp; u64 numTouches; }; -static_assert(sizeof(HIDTouchScreenEntryHeader) == 0x10, +static_assert(sizeof(TouchScreenEntryHeader) == 0x10, "HID touch screen entry header structure has incorrect size"); -struct HIDTouchScreenEntryTouch { +struct TouchScreenEntryTouch { u64 timestamp; u32 padding; u32 touchIndex; @@ -83,37 +83,37 @@ struct HIDTouchScreenEntryTouch { u32 angle; u32 padding_2; }; -static_assert(sizeof(HIDTouchScreenEntryTouch) == 0x28, +static_assert(sizeof(TouchScreenEntryTouch) == 0x28, "HID touch screen touch structure has incorrect size"); -struct HIDTouchScreenEntry { - HIDTouchScreenEntryHeader header; - std::array touches; +struct TouchScreenEntry { + TouchScreenEntryHeader header; + std::array touches; u64 unk; }; -static_assert(sizeof(HIDTouchScreenEntry) == 0x298, +static_assert(sizeof(TouchScreenEntry) == 0x298, "HID touch screen entry structure has incorrect size"); -struct HIDTouchScreen { - HIDTouchScreenHeader header; - std::array entries; +struct TouchScreen { + TouchScreenHeader header; + std::array entries; std::array padding; }; -static_assert(sizeof(HIDTouchScreen) == 0x3000, "HID touch screen structure has incorrect size"); +static_assert(sizeof(TouchScreen) == 0x3000, "HID touch screen structure has incorrect size"); -// End HIDTouchScreen +// End TouchScreen -// Begin HIDMouse +// Begin Mouse -struct HIDMouseHeader { +struct MouseHeader { u64 timestampTicks; u64 numEntries; u64 latestEntry; u64 maxEntryIndex; }; -static_assert(sizeof(HIDMouseHeader) == 0x20, "HID mouse header structure has incorrect size"); +static_assert(sizeof(MouseHeader) == 0x20, "HID mouse header structure has incorrect size"); -struct HIDMouseButtonState { +struct MouseButtonState { union { u64 hex{}; @@ -126,7 +126,7 @@ struct HIDMouseButtonState { }; }; -struct HIDMouseEntry { +struct MouseEntry { u64 timestamp; u64 timestamp_2; u32 x; @@ -135,31 +135,31 @@ struct HIDMouseEntry { u32 velocityY; u32 scrollVelocityX; u32 scrollVelocityY; - HIDMouseButtonState buttons; + MouseButtonState buttons; }; -static_assert(sizeof(HIDMouseEntry) == 0x30, "HID mouse entry structure has incorrect size"); +static_assert(sizeof(MouseEntry) == 0x30, "HID mouse entry structure has incorrect size"); -struct HIDMouse { - HIDMouseHeader header; - std::array entries; +struct Mouse { + MouseHeader header; + std::array entries; std::array padding; }; -static_assert(sizeof(HIDMouse) == 0x400, "HID mouse structure has incorrect size"); +static_assert(sizeof(Mouse) == 0x400, "HID mouse structure has incorrect size"); -// End HIDMouse +// End Mouse -// Begin HIDKeyboard +// Begin Keyboard -struct HIDKeyboardHeader { +struct KeyboardHeader { u64 timestampTicks; u64 numEntries; u64 latestEntry; u64 maxEntryIndex; }; -static_assert(sizeof(HIDKeyboardHeader) == 0x20, +static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size"); -struct HIDKeyboardModifierKeyState { +struct KeyboardModifierKeyState { union { u64 hex{}; @@ -178,34 +178,34 @@ struct HIDKeyboardModifierKeyState { }; }; -struct HIDKeyboardEntry { +struct KeyboardEntry { u64 timestamp; u64 timestamp_2; - HIDKeyboardModifierKeyState modifier; + KeyboardModifierKeyState modifier; u32 keys[8]; }; -static_assert(sizeof(HIDKeyboardEntry) == 0x38, "HID keyboard entry structure has incorrect size"); +static_assert(sizeof(KeyboardEntry) == 0x38, "HID keyboard entry structure has incorrect size"); -struct HIDKeyboard { - HIDKeyboardHeader header; - std::array entries; +struct Keyboard { + KeyboardHeader header; + std::array entries; std::array padding; }; -static_assert(sizeof(HIDKeyboard) == 0x400, "HID keyboard structure has incorrect size"); +static_assert(sizeof(Keyboard) == 0x400, "HID keyboard structure has incorrect size"); -// End HIDKeyboard +// End Keyboard -// Begin HIDController +// Begin Controller -struct HIDControllerMAC { +struct ControllerMAC { u64 timestamp; std::array mac; u64 unk; u64 timestamp_2; }; -static_assert(sizeof(HIDControllerMAC) == 0x20, "HID controller MAC structure has incorrect size"); +static_assert(sizeof(ControllerMAC) == 0x20, "HID controller MAC structure has incorrect size"); -struct HIDControllerHeader { +struct ControllerHeader { u32 type; u32 isHalf; u32 singleColorsDescriptor; @@ -217,19 +217,19 @@ struct HIDControllerHeader { u32 rightColorBody; u32 rightColorbuttons; }; -static_assert(sizeof(HIDControllerHeader) == 0x28, +static_assert(sizeof(ControllerHeader) == 0x28, "HID controller header structure has incorrect size"); -struct HIDControllerLayoutHeader { +struct ControllerLayoutHeader { u64 timestampTicks; u64 numEntries; u64 latestEntry; u64 maxEntryIndex; }; -static_assert(sizeof(HIDControllerLayoutHeader) == 0x20, +static_assert(sizeof(ControllerLayoutHeader) == 0x20, "HID controller layout header structure has incorrect size"); -struct HIDControllerPadState { +struct ControllerPadState { union { u64 hex{}; @@ -270,43 +270,43 @@ struct HIDControllerPadState { }; }; -struct HIDControllerInputEntry { +struct ControllerInputEntry { u64 timestamp; u64 timestamp_2; - HIDControllerPadState buttons; + ControllerPadState buttons; u32 joystickLeftX; u32 joystickLeftY; u32 joystickRightX; u32 joystickRightY; u64 connectionState; }; -static_assert(sizeof(HIDControllerInputEntry) == 0x30, +static_assert(sizeof(ControllerInputEntry) == 0x30, "HID controller input entry structure has incorrect size"); -struct HIDControllerLayout { - HIDControllerLayoutHeader header; - std::array entries; +struct ControllerLayout { + ControllerLayoutHeader header; + std::array entries; }; -static_assert(sizeof(HIDControllerLayout) == 0x350, +static_assert(sizeof(ControllerLayout) == 0x350, "HID controller layout structure has incorrect size"); -struct HIDController { - HIDControllerHeader header; - std::array layouts; +struct Controller { + ControllerHeader header; + std::array layouts; std::array unk_1; - HIDControllerMAC macLeft; - HIDControllerMAC macRight; + ControllerMAC macLeft; + ControllerMAC macRight; std::array unk_2; }; -static_assert(sizeof(HIDController) == 0x5000, "HID controller structure has incorrect size"); +static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorrect size"); -// End HIDController +// End Controller -struct HIDSharedMemory { +struct SharedMemory { std::array header; - HIDTouchScreen touchscreen; - HIDMouse mouse; - HIDKeyboard keyboard; + TouchScreen touchscreen; + Mouse mouse; + Keyboard keyboard; std::array unkSection1; std::array unkSection2; std::array unkSection3; @@ -316,10 +316,10 @@ struct HIDSharedMemory { std::array unkSection7; std::array unkSection8; std::array controllerSerials; - std::array controllers; + std::array controllers; std::array unkSection9; }; -static_assert(sizeof(HIDSharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size"); +static_assert(sizeof(SharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size"); /// Reload input devices. Used when input configuration changed void ReloadInputDevices(); From 1ea49442f9c21aa20559894ae18353cee1179c76 Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 02:21:02 -0700 Subject: [PATCH 11/25] hid: Bare-minimum sharedmem input --- src/core/hle/service/hid/hid.cpp | 86 ++++++++++++++++++++++++++++++++ src/core/hle/service/hid/hid.h | 4 +- 2 files changed, 88 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 3f74aed061..3c4259d270 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -2,7 +2,10 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include "common/logging/log.h" +#include "core/core_timing.h" +#include "core/frontend/input.h" #include "core/hle/ipc_helpers.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/client_session.h" @@ -13,6 +16,12 @@ namespace Service { namespace HID { +// Updating period for each HID device. +// TODO(shinyquagsire23): These need better values. +constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 234; +constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 104; +constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 101; + class IAppletResource final : public ServiceFramework { public: IAppletResource() : ServiceFramework("IAppletResource") { @@ -24,6 +33,15 @@ public: shared_mem = Kernel::SharedMemory::Create( nullptr, 0x40000, Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::Read, 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory"); + + // Register update callbacks + pad_update_event = CoreTiming::RegisterEvent( + "HID::UpdatePadCallback", + [this](u64 userdata, int cycles_late) { UpdatePadCallback(userdata, cycles_late); }); + + // TODO(shinyquagsire23): Other update callbacks? (accel, gyro?) + + CoreTiming::ScheduleEvent(pad_update_ticks, pad_update_event); } private: @@ -34,8 +52,76 @@ private: LOG_DEBUG(Service, "called"); } + void LoadInputDevices() { + std::transform(Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, + Settings::values.buttons.begin() + Settings::NativeButton::BUTTON_HID_END, + buttons.begin(), Input::CreateDevice); + // TODO(shinyquagsire23): sticks, gyro, touch, mouse, keyboard + } + + void UpdatePadCallback(u64 userdata, int cycles_late) { + SharedMemory* mem = reinterpret_cast(shared_mem->GetPointer()); + + if (is_device_reload_pending.exchange(false)) + LoadInputDevices(); + + // TODO(shinyquagsire23): This is a hack! + ControllerPadState& state = + mem->controllers[Controller_Handheld].layouts[Layout_Default].entries[0].buttons; + using namespace Settings::NativeButton; + state.a.Assign(buttons[A - BUTTON_HID_BEGIN]->GetStatus()); + state.b.Assign(buttons[B - BUTTON_HID_BEGIN]->GetStatus()); + state.x.Assign(buttons[X - BUTTON_HID_BEGIN]->GetStatus()); + state.y.Assign(buttons[Y - BUTTON_HID_BEGIN]->GetStatus()); + state.lstick.Assign(buttons[LStick - BUTTON_HID_BEGIN]->GetStatus()); + state.rstick.Assign(buttons[RStick - BUTTON_HID_BEGIN]->GetStatus()); + state.l.Assign(buttons[L - BUTTON_HID_BEGIN]->GetStatus()); + state.r.Assign(buttons[R - BUTTON_HID_BEGIN]->GetStatus()); + state.zl.Assign(buttons[ZL - BUTTON_HID_BEGIN]->GetStatus()); + state.zr.Assign(buttons[ZR - BUTTON_HID_BEGIN]->GetStatus()); + state.plus.Assign(buttons[Plus - BUTTON_HID_BEGIN]->GetStatus()); + state.minus.Assign(buttons[Minus - BUTTON_HID_BEGIN]->GetStatus()); + + state.dleft.Assign(buttons[DLeft - BUTTON_HID_BEGIN]->GetStatus()); + state.dup.Assign(buttons[DUp - BUTTON_HID_BEGIN]->GetStatus()); + state.dright.Assign(buttons[DRight - BUTTON_HID_BEGIN]->GetStatus()); + state.ddown.Assign(buttons[DDown - BUTTON_HID_BEGIN]->GetStatus()); + + state.lstick_left.Assign(buttons[LStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + state.lstick_up.Assign(buttons[LStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + state.lstick_right.Assign(buttons[LStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + state.lstick_down.Assign(buttons[LStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + state.rstick_left.Assign(buttons[RStick_Left - BUTTON_HID_BEGIN]->GetStatus()); + state.rstick_up.Assign(buttons[RStick_Up - BUTTON_HID_BEGIN]->GetStatus()); + state.rstick_right.Assign(buttons[RStick_Right - BUTTON_HID_BEGIN]->GetStatus()); + state.rstick_down.Assign(buttons[RStick_Down - BUTTON_HID_BEGIN]->GetStatus()); + + state.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus()); + state.sr.Assign(buttons[SR - BUTTON_HID_BEGIN]->GetStatus()); + + // TODO(shinyquagsire23): Analog stick vals + + // TODO(shinyquagsire23): Update pad info proper, (circular buffers, timestamps, layouts) + + // TODO(shinyquagsire23): Update touch info + + // TODO(shinyquagsire23): Signal events + + // Reschedule recurrent event + CoreTiming::ScheduleEvent(pad_update_ticks - cycles_late, pad_update_event); + } + // Handle to shared memory region designated to HID service Kernel::SharedPtr shared_mem; + + // CoreTiming update events + CoreTiming::EventType* pad_update_event; + + // Stored input state info + std::atomic is_device_reload_pending{true}; + std::array, Settings::NativeButton::NUM_BUTTONS_HID> + buttons; }; class Hid final : public ServiceFramework { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 7fd45d56f4..486e648007 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -5,6 +5,7 @@ #pragma once #include "core/hle/service/service.h" +#include "core/settings.h" namespace Service { namespace HID { @@ -156,8 +157,7 @@ struct KeyboardHeader { u64 latestEntry; u64 maxEntryIndex; }; -static_assert(sizeof(KeyboardHeader) == 0x20, - "HID keyboard header structure has incorrect size"); +static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size"); struct KeyboardModifierKeyState { union { From 9fba2d68fe1c5947b0b9d1e64bb781a8e4be04ba Mon Sep 17 00:00:00 2001 From: shinyquagsire23 Date: Mon, 15 Jan 2018 02:27:30 -0700 Subject: [PATCH 12/25] yuzu_cmd: Fix default ini, add screenshot button --- src/yuzu_cmd/default_ini.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 47d1198b31..469df96cc1 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -48,7 +48,8 @@ button_lstick_right= button_lstick_down= button_sl= button_sr= -button_home" +button_home= +button_screenshot= # for analog input, the following devices are available: # - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: From 8a440faa6901e91a0e81177bcf68431f91e03fae Mon Sep 17 00:00:00 2001 From: spycrab Date: Mon, 15 Jan 2018 10:42:40 +0100 Subject: [PATCH 13/25] CMake: Output binaries to bin/ --- .travis/linux/upload.sh | 4 ++-- .travis/macos/upload.sh | 4 ++-- CMakeLists.txt | 3 +++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis/linux/upload.sh b/.travis/linux/upload.sh index 8a029bbe22..61842be126 100755 --- a/.travis/linux/upload.sh +++ b/.travis/linux/upload.sh @@ -8,7 +8,7 @@ COMPRESSION_FLAGS="-cJvf" mkdir "$REV_NAME" -cp build/src/yuzu_cmd/yuzu-cmd "$REV_NAME" -cp build/src/yuzu/yuzu "$REV_NAME" +cp build/bin/yuzu-cmd "$REV_NAME" +cp build/bin/yuzu "$REV_NAME" . .travis/common/post-upload.sh diff --git a/.travis/macos/upload.sh b/.travis/macos/upload.sh index de0ba91f11..9ba95086b0 100755 --- a/.travis/macos/upload.sh +++ b/.travis/macos/upload.sh @@ -8,8 +8,8 @@ COMPRESSION_FLAGS="-czvf" mkdir "$REV_NAME" -cp build/src/yuzu_cmd/yuzu-cmd "$REV_NAME" -cp -r build/src/yuzu/yuzu.app "$REV_NAME" +cp build/bin/yuzu-cmd "$REV_NAME" +cp -r build/bin/yuzu.app "$REV_NAME" # move qt libs into app bundle for deployment $(brew --prefix)/opt/qt5/bin/macdeployqt "${REV_NAME}/yuzu.app" diff --git a/CMakeLists.txt b/CMakeLists.txt index 09fe9bcd31..791a3357f4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,6 +160,9 @@ if (NOT Boost_FOUND) find_package(Boost QUIET REQUIRED) endif() +# Output binaries to bin/ +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + # Prefer the -pthread flag on Linux. set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) From af6e0faf0a464d00b6ddc5d3526ab89bb635acca Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Jan 2018 16:24:29 +0100 Subject: [PATCH 14/25] Fix some warnings --- externals/microprofile/microprofileui.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/externals/microprofile/microprofileui.h b/externals/microprofile/microprofileui.h index 7670fec5dd..ddaebe55b1 100644 --- a/externals/microprofile/microprofileui.h +++ b/externals/microprofile/microprofileui.h @@ -1991,7 +1991,7 @@ const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected) else { nIndex = nIndex-1; - if(nIndex < UI.GroupMenuCount) + if(static_cast(nIndex) < UI.GroupMenuCount) { MicroProfileGroupMenuItem& Item = UI.GroupMenu[nIndex]; static char buffer[MICROPROFILE_NAME_MAX_LEN+32]; @@ -2134,7 +2134,7 @@ const char* MicroProfileUIMenuCustom(int nIndex, bool* bSelected) case 1: return "--"; default: nIndex -= 2; - if(nIndex < UI.nCustomCount) + if(static_cast(nIndex) < UI.nCustomCount) { return UI.Custom[nIndex].pName; } @@ -2184,7 +2184,7 @@ void MicroProfileUIClickGroups(int nIndex) else { nIndex -= 1; - if(nIndex < UI.GroupMenuCount) + if(static_cast(nIndex) < UI.GroupMenuCount) { MicroProfileGroupMenuItem& Item = UI.GroupMenu[nIndex]; if(Item.nIsCategory) From 27960d8c2cfbe4188584f0186b56ea8806f9e223 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Jan 2018 16:59:02 +0100 Subject: [PATCH 15/25] Update the internal resolution settings --- src/yuzu/configuration/configure_graphics.cpp | 30 -------------- src/yuzu/configuration/configure_graphics.ui | 40 +++---------------- src/yuzu_cmd/default_ini.h | 4 +- 3 files changed, 7 insertions(+), 67 deletions(-) diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 5f91d54925..081819812e 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -23,12 +23,6 @@ enum class Resolution : int { Scale2x, Scale3x, Scale4x, - Scale5x, - Scale6x, - Scale7x, - Scale8x, - Scale9x, - Scale10x, }; float ToResolutionFactor(Resolution option) { @@ -43,18 +37,6 @@ float ToResolutionFactor(Resolution option) { return 3.f; case Resolution::Scale4x: return 4.f; - case Resolution::Scale5x: - return 5.f; - case Resolution::Scale6x: - return 6.f; - case Resolution::Scale7x: - return 7.f; - case Resolution::Scale8x: - return 8.f; - case Resolution::Scale9x: - return 9.f; - case Resolution::Scale10x: - return 10.f; } return 0.f; } @@ -70,18 +52,6 @@ Resolution FromResolutionFactor(float factor) { return Resolution::Scale3x; } else if (factor == 4.f) { return Resolution::Scale4x; - } else if (factor == 5.f) { - return Resolution::Scale5x; - } else if (factor == 6.f) { - return Resolution::Scale6x; - } else if (factor == 7.f) { - return Resolution::Scale7x; - } else if (factor == 8.f) { - return Resolution::Scale8x; - } else if (factor == 9.f) { - return Resolution::Scale9x; - } else if (factor == 10.f) { - return Resolution::Scale10x; } return Resolution::Auto; } diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index 4891568056..366931a9ac 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -34,7 +34,7 @@ - Internal Resolution: + Internal Resolution:(Currently does nothing.) @@ -47,52 +47,22 @@ - Native (400x240) + Native (1280x720) - 2x Native (800x480) + 2x Native (2560x1440) - 3x Native (1200x720) + 3x Native (3840x2160) - 4x Native (1600x960) - - - - - 5x Native (2000x1200) - - - - - 6x Native (2400x1440) - - - - - 7x Native (2800x1680) - - - - - 8x Native (3200x1920) - - - - - 9x Native (3600x2160) - - - - - 10x Native (4000x2400) + 4x Native (5120x2880) diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index e7941ecebb..11ed1237a2 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -81,8 +81,8 @@ use_hw_renderer = use_shader_jit = # Resolution scale factor -# 0: Auto (scales resolution to window size), 1: Native 3DS screen resolution, Otherwise a scale -# factor for the 3DS resolution +# 0: Auto (scales resolution to window size), 1: Native Switch screen resolution, Otherwise a scale +# factor for the Switch resolution resolution_factor = # Whether to enable V-Sync (caps the framerate at 60FPS) or not. From 58ee23f16d73e2284b656c93374f0f7add1d88bf Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Jan 2018 17:15:10 +0100 Subject: [PATCH 16/25] Change default log level to info --- src/yuzu/configuration/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 4c713fcbc7..047e347d18 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -86,7 +86,7 @@ void Config::ReadValues() { qt_config->endGroup(); qt_config->beginGroup("Miscellaneous"); - Settings::values.log_filter = qt_config->value("log_filter", "*:Trace").toString().toStdString(); + Settings::values.log_filter = qt_config->value("log_filter", "*:Info").toString().toStdString(); qt_config->endGroup(); qt_config->beginGroup("Debugging"); From 8d968780c19bed7fb260787c26ee908541c5934c Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Jan 2018 17:55:16 +0100 Subject: [PATCH 17/25] Clang format --- src/yuzu/configuration/config.cpp | 13 ++++++++++--- src/yuzu/configuration/configure_graphics.cpp | 1 - 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 047e347d18..314fc27798 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -8,7 +8,6 @@ #include "yuzu/configuration/config.h" #include "yuzu/ui_settings.h" - Config::Config() { // TODO: Don't hardcode the path; let the frontend decide where to put the config files. qt_config_loc = FileUtil::GetUserPath(D_CONFIG_IDX) + "qt-config.ini"; @@ -25,10 +24,18 @@ const std::array Config::default_button const std::array, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ { - Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D, + Qt::Key_Up, + Qt::Key_Down, + Qt::Key_Left, + Qt::Key_Right, + Qt::Key_D, }, { - Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_D, + Qt::Key_I, + Qt::Key_K, + Qt::Key_J, + Qt::Key_L, + Qt::Key_D, }, }}; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 081819812e..47b9b6e952 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -7,7 +7,6 @@ #include "ui_configure_graphics.h" #include "yuzu/configuration/configure_graphics.h" - ConfigureGraphics::ConfigureGraphics(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureGraphics) { From a4f5ccbf0a834fa231ff584ad333a58be71f058f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 15 Jan 2018 18:20:53 +0100 Subject: [PATCH 18/25] Clanggit rebase -i fixes --- src/yuzu/configuration/config.cpp | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 314fc27798..6e33337c2a 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -24,18 +24,10 @@ const std::array Config::default_button const std::array, Settings::NativeAnalog::NumAnalogs> Config::default_analogs{{ { - Qt::Key_Up, - Qt::Key_Down, - Qt::Key_Left, - Qt::Key_Right, - Qt::Key_D, + Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right, Qt::Key_D, }, { - Qt::Key_I, - Qt::Key_K, - Qt::Key_J, - Qt::Key_L, - Qt::Key_D, + Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_D, }, }}; From 8e2f62c6a59f12be521b46c347f7efd8bf6a025d Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 15 Jan 2018 13:09:14 -0500 Subject: [PATCH 19/25] settings: Fix button mappings array to have correct entries. --- src/core/settings.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/core/settings.h b/src/core/settings.h index bd9a3d9feb..56fb189ae6 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -79,11 +79,16 @@ static const std::array mapping = {{ "button_lstick_up", "button_lstick_right", "button_lstick_down", + "button_rstick_left", + "button_rstick_up", + "button_rstick_right", + "button_rstick_down", "button_sl", "button_sr", "button_home", "button_screenshot", }}; + } // namespace NativeButton namespace NativeAnalog { @@ -95,8 +100,7 @@ enum Values { }; static const std::array mapping = {{ - "lstick", - "rstick", + "lstick", "rstick", }}; } // namespace NativeAnalog From 5bc14ab0deb587f66677737d0a19395e8a4b124b Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 15 Jan 2018 14:41:06 -0500 Subject: [PATCH 20/25] applet_oe: Stub SetFocusHandlingMode, GetCurrentFocusState, SetTerminateResult. --- src/core/hle/service/am/applet_oe.cpp | 57 ++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index f3d66ea96c..f65d6b9f51 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -52,7 +52,23 @@ public: class ISelfController final : public ServiceFramework { public: - ISelfController() : ServiceFramework("ISelfController") {} + ISelfController() : ServiceFramework("ISelfController") { + static const FunctionInfo functions[] = { + {13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"}, + }; + RegisterHandlers(functions); + } + +private: + void SetFocusHandlingMode(Kernel::HLERequestContext& ctx) { + // Takes 3 input u8s with each field located immediately after the previous u8, these are + // bool flags. No output. + + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called"); + } }; class ICommonStateGetter final : public ServiceFramework { @@ -61,6 +77,7 @@ public: static const FunctionInfo functions[] = { {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, + {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, }; RegisterHandlers(functions); @@ -86,12 +103,39 @@ private: LOG_WARNING(Service, "(STUBBED) called"); } + void GetCurrentFocusState(Kernel::HLERequestContext& ctx) { + IPC::RequestBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(1); // 1: In focus, 2/3: Out of focus(running in "background") + + LOG_WARNING(Service, "(STUBBED) called"); + } + Kernel::SharedPtr event; }; class IApplicationFunctions final : public ServiceFramework { public: - IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {} + IApplicationFunctions() : ServiceFramework("IApplicationFunctions") { + static const FunctionInfo functions[] = { + {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"}, + }; + RegisterHandlers(functions); + } + +private: + void SetTerminateResult(Kernel::HLERequestContext& ctx) { + // Takes an input u32 Result, no output. + // For example, in some cases official apps use this with error 0x2A2 then uses svcBreak. + + IPC::RequestParser rp{ctx}; + u32 result = rp.Pop(); + + IPC::RequestBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result); + } }; class ILibraryAppletCreator final : public ServiceFramework { @@ -120,48 +164,56 @@ private: IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } void GetDisplayController(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } void GetDebugFunctions(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } void GetWindowController(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } void GetSelfController(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } void GetCommonStateGetter(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } void GetApplicationFunctions(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } }; @@ -169,6 +221,7 @@ void AppletOE::OpenApplicationProxy(Kernel::HLERequestContext& ctx) { IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } AppletOE::AppletOE() : ServiceFramework("appletOE") { From 1148e2ce7bfad1c43ec1ba50e41f447fa1d782f1 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 15 Jan 2018 15:10:18 -0500 Subject: [PATCH 21/25] pctl: GetService should return an IParentalControlService interface. --- src/core/hle/service/pctl/pctl_a.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/core/hle/service/pctl/pctl_a.cpp b/src/core/hle/service/pctl/pctl_a.cpp index 904a31c6b7..8d44627732 100644 --- a/src/core/hle/service/pctl/pctl_a.cpp +++ b/src/core/hle/service/pctl/pctl_a.cpp @@ -9,11 +9,16 @@ namespace Service { namespace PCTL { +class IParentalControlService final : public ServiceFramework { +public: + IParentalControlService() : ServiceFramework("IParentalControlService") {} +}; + void PCTL_A::GetService(Kernel::HLERequestContext& ctx) { - LOG_WARNING(Service, "(STUBBED) called"); - IPC::RequestBuilder rb{ctx, 2}; + IPC::RequestBuilder rb{ ctx, 2, 0, 0, 1 }; rb.Push(RESULT_SUCCESS); - // TODO(Subv): This should return an IParentalControlService interface. + rb.PushIpcInterface(); + LOG_DEBUG(Service, "called"); } PCTL_A::PCTL_A() : ServiceFramework("pctl:a") { From 1a3b3e91005725102bafbdac03836687d85dae73 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 15 Jan 2018 15:16:06 -0500 Subject: [PATCH 22/25] pctl: Clang format. --- src/core/hle/service/pctl/pctl_a.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/hle/service/pctl/pctl_a.cpp b/src/core/hle/service/pctl/pctl_a.cpp index 8d44627732..7978aecb87 100644 --- a/src/core/hle/service/pctl/pctl_a.cpp +++ b/src/core/hle/service/pctl/pctl_a.cpp @@ -15,7 +15,7 @@ public: }; void PCTL_A::GetService(Kernel::HLERequestContext& ctx) { - IPC::RequestBuilder rb{ ctx, 2, 0, 0, 1 }; + IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; rb.Push(RESULT_SUCCESS); rb.PushIpcInterface(); LOG_DEBUG(Service, "called"); From e9cf161917e051792033faa9b20594d4dca663a3 Mon Sep 17 00:00:00 2001 From: Simonx22 Date: Mon, 15 Jan 2018 23:05:20 +0100 Subject: [PATCH 23/25] rename CITRA to YUZU --- CMakeLists.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d60d1a5bfc..3da8465b96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,10 +7,10 @@ include(DownloadExternals) project(yuzu) option(ENABLE_SDL2 "Enable the SDL2 frontend" ON) -option(CITRA_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" OFF) +option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" OFF) option(ENABLE_QT "Enable the Qt frontend" ON) -option(CITRA_USE_BUNDLED_QT "Download bundled Qt binaries" OFF) +option(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" OFF) option(YUZU_USE_BUNDLED_UNICORN "Download bundled Unicorn binaries" OFF) @@ -174,12 +174,12 @@ set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) if (ENABLE_SDL2) - if (CITRA_USE_BUNDLED_SDL2) + if (YUZU_USE_BUNDLED_SDL2) # Detect toolchain and platform if (MSVC14 AND ARCHITECTURE_x86_64) set(SDL2_VER "SDL2-2.0.5") else() - message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable CITRA_USE_BUNDLED_SDL2 and provide your own.") + message(FATAL_ERROR "No bundled SDL2 binaries for your toolchain. Disable YUZU_USE_BUNDLED_SDL2 and provide your own.") endif() if (DEFINED SDL2_VER) @@ -235,11 +235,11 @@ if (UNICORN_FOUND) endif() if (ENABLE_QT) - if (CITRA_USE_BUNDLED_QT) + if (YUZU_USE_BUNDLED_QT) if (MSVC14 AND ARCHITECTURE_x86_64) set(QT_VER qt-5.7-msvc2015_64) else() - message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable CITRA_USE_BUNDLED_QT and provide your own.") + message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.") endif() if (DEFINED QT_VER) From 6f904bb622d8340a9e10786f4012bdbe1ad7b57f Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 15 Jan 2018 17:18:24 -0500 Subject: [PATCH 24/25] nso: Load subsdk4 if available. --- src/core/loader/nso.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 7efa603a2e..7e1953701b 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp @@ -157,7 +157,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr& process) { // Load NSO modules VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR}; - for (const auto& module : {"rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", "subsdk3"}) { + for (const auto& module : {"rtld", "sdk", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4"}) { const std::string path = filepath.substr(0, filepath.find_last_of("/\\")) + "/" + module; const VAddr load_addr = next_load_addr; next_load_addr = LoadNso(path, load_addr); From 21f5161ad89fb4ed7d9657131d580f746096b7bf Mon Sep 17 00:00:00 2001 From: Flame Sage Date: Tue, 16 Jan 2018 01:35:04 +0000 Subject: [PATCH 25/25] Updated Discord link to match website. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4740c15f85..2f769770c7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ yuzu is licensed under the GPLv2 (or any later version). Refer to the license.tx Check out our [website](https://yuzu-emu.org/)! -For development discussion, please join us on [Discord](https://discord.gg/VXqngT3). +For development discussion, please join us on [Discord](https://discord.gg/XQV6dn9). ### Development