diff options
33 files changed, 1070 insertions, 238 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 791a3357f..d60d1a5bf 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 @@ -1,5 +1,7 @@  yuzu emulator  ============= +[](https://travis-ci.org/yuzu-emu/yuzu) +  yuzu is an experimental open-source emulator for the Nintendo Switch from the creators of [Citra](https://citra-emu.org/).  It is written in C++ with portability in mind, with builds actively maintained for Windows, Linux and macOS. The emulator is currently only useful for homebrew development and research purposes. diff --git a/externals/microprofile/microprofileui.h b/externals/microprofile/microprofileui.h index 09223b33f..ddaebe55b 100644 --- a/externals/microprofile/microprofileui.h +++ b/externals/microprofile/microprofileui.h @@ -1853,7 +1853,7 @@ void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeight)                  {                      if(nMetaIndex < MICROPROFILE_META_MAX && S.MetaCounters[nMetaIndex].pName)                      { -                        uint32_t nStrWidth = strlen(S.MetaCounters[nMetaIndex].pName); +                        uint32_t nStrWidth = static_cast<uint32_t>(strlen(S.MetaCounters[nMetaIndex].pName));                          if(S.nBars & MP_DRAW_TIMERS)                              nWidth += 6 + (1+MICROPROFILE_TEXT_WIDTH) * (nStrWidth);                          if(S.nBars & MP_DRAW_AVERAGE) @@ -1907,7 +1907,7 @@ void MicroProfileDrawBarView(uint32_t nScreenWidth, uint32_t nScreenHeight)      {          if(0 != (S.nBars & (MP_DRAW_META_FIRST<<i)) && S.MetaCounters[i].pName)          { -            uint32_t nBufferSize = strlen(S.MetaCounters[i].pName) + 32; +            uint32_t nBufferSize = static_cast<uint32_t>(strlen(S.MetaCounters[i].pName) + 32);              char* buffer = (char*)alloca(nBufferSize);              if(S.nBars & MP_DRAW_TIMERS)                  nX += MicroProfileDrawBarMetaCount(nX, nY, &S.MetaCounters[i].nCounters[0], S.MetaCounters[i].pName, nTotalHeight) + 1; @@ -1991,7 +1991,7 @@ const char* MicroProfileUIMenuGroups(int nIndex, bool* bSelected)      else      {          nIndex = nIndex-1; -        if(nIndex < UI.GroupMenuCount) +        if(static_cast<uint32_t>(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<uint32_t>(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<uint32_t>(nIndex) < UI.GroupMenuCount)          {              MicroProfileGroupMenuItem& Item = UI.GroupMenu[nIndex];              if(Item.nIsCategory) @@ -2599,7 +2599,7 @@ void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)              nOffsetY = nOffsetYBase;              float* pMs = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? pTimeMax : pTimeAvg;              const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_BAR_SOURCE_MAX ? "Max" : "Avg"; -            MicroProfileDrawText(nMaxOffsetX, nOffsetY, (uint32_t)-1, pString, strlen(pString)); +            MicroProfileDrawText(nMaxOffsetX, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));              int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);              MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);              for(uint32_t i = 0; i < nCount; ++i) @@ -2613,7 +2613,7 @@ void MicroProfileDrawCustom(uint32_t nWidth, uint32_t nHeight)          {              nOffsetY += 2*(1+MICROPROFILE_TEXT_HEIGHT);              const char* pString = pCustom->nFlags & MICROPROFILE_CUSTOM_STACK_SOURCE_MAX ? "Max" : "Avg"; -            MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, (uint32_t)-1, pString, strlen(pString)); +            MicroProfileDrawText(MICROPROFILE_CUSTOM_PADDING, nOffsetY, (uint32_t)-1, pString, static_cast<uint32_t>(strlen(pString)));              int nSize = snprintf(Buffer, sizeof(Buffer)-1, "%6.2fms", fReference);              MicroProfileDrawText(nReducedWidth - (1+nSize) * (MICROPROFILE_TEXT_WIDTH+1), nOffsetY, (uint32_t)-1, Buffer, nSize);              nOffsetY += (1+MICROPROFILE_TEXT_HEIGHT); diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 021e2f152..f5c92a5aa 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -41,6 +41,8 @@ set(SRCS              hle/service/am/applet_oe.cpp              hle/service/aoc/aoc_u.cpp              hle/service/apm/apm.cpp +            hle/service/audio/audio.cpp +            hle/service/audio/audout_u.cpp              hle/service/hid/hid.cpp              hle/service/lm/lm.cpp              hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -53,6 +55,8 @@ set(SRCS              hle/service/service.cpp              hle/service/sm/controller.cpp              hle/service/sm/sm.cpp +            hle/service/time/time.cpp +            hle/service/time/time_s.cpp              hle/service/vi/vi.cpp              hle/service/vi/vi_m.cpp              hle/shared_page.cpp @@ -124,6 +128,8 @@ set(HEADERS              hle/service/am/applet_oe.h              hle/service/aoc/aoc_u.h              hle/service/apm/apm.h +            hle/service/audio/audio.h +            hle/service/audio/audout_u.h              hle/service/hid/hid.h              hle/service/lm/lm.h              hle/service/nvdrv/devices/nvdevice.h @@ -137,6 +143,8 @@ set(HEADERS              hle/service/service.h              hle/service/sm/controller.h              hle/service/sm/sm.h +            hle/service/time/time.h +            hle/service/time/time_s.h              hle/service/vi/vi.h              hle/service/vi/vi_m.h              hle/shared_page.h diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index a1f2090f7..df3b4083e 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -35,7 +35,7 @@ enum class HandleType : u32 {  };  enum { -    DEFAULT_STACK_SIZE = 0x4000, +    DEFAULT_STACK_SIZE = 0x10000,  };  enum class ResetType { diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp index d45daca35..7279366ec 100644 --- a/src/core/hle/kernel/shared_memory.cpp +++ b/src/core/hle/kernel/shared_memory.cpp @@ -106,14 +106,14 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi      // Error out if the requested permissions don't match what the creator process allows.      if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) { -        LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", +        LOG_ERROR(Kernel, "cannot map id=%u, address=0x%llx name=%s, permissions don't match",                    GetObjectId(), address, name.c_str());          return ERR_INVALID_COMBINATION;      }      // Heap-backed memory blocks can not be mapped with other_permissions = DontCare      if (base_address != 0 && other_permissions == MemoryPermission::DontCare) { -        LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", +        LOG_ERROR(Kernel, "cannot map id=%u, address=0x%llx name=%s, permissions don't match",                    GetObjectId(), address, name.c_str());          return ERR_INVALID_COMBINATION;      } @@ -121,7 +121,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi      // Error out if the provided permissions are not compatible with what the creator process needs.      if (other_permissions != MemoryPermission::DontCare &&          static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) { -        LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, permissions don't match", +        LOG_ERROR(Kernel, "cannot map id=%u, address=0x%llx name=%s, permissions don't match",                    GetObjectId(), address, name.c_str());          return ERR_WRONG_PERMISSION;      } @@ -136,8 +136,8 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi      // can not map it in its own address space unless it was created with addr=0, result 0xD900182C.      if (address != 0) { -        if (address < Memory::HEAP_VADDR || address + size >= Memory::SHARED_MEMORY_VADDR_END) { -            LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, invalid address", +        if (address < Memory::HEAP_VADDR) { +            LOG_ERROR(Kernel, "cannot map id=%u, address=0x%llx name=%s, invalid address",                        GetObjectId(), address, name.c_str());              return ERR_INVALID_ADDRESS;          } @@ -156,7 +156,7 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi      if (result.Failed()) {          LOG_ERROR(              Kernel, -            "cannot map id=%u, target_address=0x%08X name=%s, error mapping to virtual memory", +            "cannot map id=%u, target_address=0x%llx name=%s, error mapping to virtual memory",              GetObjectId(), target_address, name.c_str());          return result.Code();      } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index eb02dbde3..9c60576c1 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -17,6 +17,7 @@  #include "core/hle/kernel/object_address_table.h"  #include "core/hle/kernel/process.h"  #include "core/hle/kernel/resource_limit.h" +#include "core/hle/kernel/shared_memory.h"  #include "core/hle/kernel/svc.h"  #include "core/hle/kernel/svc_wrap.h"  #include "core/hle/kernel/sync_object.h" @@ -384,6 +385,37 @@ static u32 GetCurrentProcessorNumber() {      return 0;  } +static ResultCode MapSharedMemory(Handle shared_memory_handle, VAddr addr, u64 size, +                                  u32 permissions) { +    LOG_TRACE(Kernel_SVC, +              "called, shared_memory_handle=0x%08X, addr=0x%llx, size=0x%llx, permissions=0x%08X", +              shared_memory_handle, addr, size, permissions); + +    SharedPtr<SharedMemory> shared_memory = +        Kernel::g_handle_table.Get<SharedMemory>(shared_memory_handle); +    if (!shared_memory) { +        return ERR_INVALID_HANDLE; +    } + +    MemoryPermission permissions_type = static_cast<MemoryPermission>(permissions); +    switch (permissions_type) { +    case MemoryPermission::Read: +    case MemoryPermission::Write: +    case MemoryPermission::ReadWrite: +    case MemoryPermission::Execute: +    case MemoryPermission::ReadExecute: +    case MemoryPermission::WriteExecute: +    case MemoryPermission::ReadWriteExecute: +    case MemoryPermission::DontCare: +        return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type, +                                  MemoryPermission::DontCare); +    default: +        LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); +    } + +    return RESULT_SUCCESS; +} +  /// Query process memory  static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* /*page_info*/,                                       Handle process_handle, u64 addr) { @@ -707,7 +739,7 @@ static const FunctionDef SVC_Table[] = {      {0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"},      {0x11, nullptr, "SignalEvent"},      {0x12, nullptr, "ClearEvent"}, -    {0x13, nullptr, "MapSharedMemory"}, +    {0x13, SvcWrap<MapSharedMemory>, "MapSharedMemory"},      {0x14, nullptr, "UnmapSharedMemory"},      {0x15, SvcWrap<CreateTransferMemory>, "CreateTransferMemory"},      {0x16, SvcWrap<CloseHandle>, "CloseHandle"}, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index e66911fa5..fd7054bbd 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h @@ -86,6 +86,11 @@ void SvcWrap() {      FuncReturn(func(PARAM(0), PARAM(1), PARAM(2)).raw);  } +template <ResultCode func(u32, u64, u64, u32)> +void SvcWrap() { +    FuncReturn(func((u32)PARAM(0), PARAM(1), PARAM(2), (u32)PARAM(3)).raw); +} +  template <ResultCode func(u32*, u64, u64, s64)>  void SvcWrap() {      u32 param_1 = 0; diff --git a/src/core/hle/service/am/applet_oe.cpp b/src/core/hle/service/am/applet_oe.cpp index e2bb581ff..f3d66ea96 100644 --- a/src/core/hle/service/am/applet_oe.cpp +++ b/src/core/hle/service/am/applet_oe.cpp @@ -81,7 +81,7 @@ private:      void ReceiveMessage(Kernel::HLERequestContext& ctx) {          IPC::RequestBuilder rb{ctx, 3};          rb.Push(RESULT_SUCCESS); -        rb.Push<u32>(1); +        rb.Push<u32>(15);          LOG_WARNING(Service, "(STUBBED) called");      } diff --git a/src/core/hle/service/audio/audio.cpp b/src/core/hle/service/audio/audio.cpp new file mode 100644 index 000000000..2b4c6c5d0 --- /dev/null +++ b/src/core/hle/service/audio/audio.cpp @@ -0,0 +1,16 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/audio/audio.h" +#include "core/hle/service/audio/audout_u.h" + +namespace Service { +namespace Audio { + +void InstallInterfaces(SM::ServiceManager& service_manager) { +    std::make_shared<AudOutU>()->InstallAsService(service_manager); +} + +} // namespace Audio +} // namespace Service diff --git a/src/core/hle/service/audio/audio.h b/src/core/hle/service/audio/audio.h new file mode 100644 index 000000000..cbd56b2a8 --- /dev/null +++ b/src/core/hle/service/audio/audio.h @@ -0,0 +1,16 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace Audio { + +/// Registers all Audio services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Audio +} // namespace Service diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp new file mode 100644 index 000000000..c028262c6 --- /dev/null +++ b/src/core/hle/service/audio/audout_u.cpp @@ -0,0 +1,26 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/audio/audout_u.h" + +namespace Service { +namespace Audio { + +void AudOutU::ListAudioOuts(Kernel::HLERequestContext& ctx) { +    LOG_WARNING(Service, "(STUBBED) called"); +    IPC::RequestBuilder rb{ctx, 2}; +    rb.Push(RESULT_SUCCESS); +} + +AudOutU::AudOutU() : ServiceFramework("audout:u") { +    static const FunctionInfo functions[] = { +        {0x00000000, &AudOutU::ListAudioOuts, "ListAudioOuts"}, +    }; +    RegisterHandlers(functions); +} + +} // namespace Audio +} // namespace Service diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h new file mode 100644 index 000000000..42680af94 --- /dev/null +++ b/src/core/hle/service/audio/audout_u.h @@ -0,0 +1,23 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace Audio { + +class AudOutU final : public ServiceFramework<AudOutU> { +public: +    AudOutU(); +    ~AudOutU() = default; + +private: +    void ListAudioOuts(Kernel::HLERequestContext& ctx); +}; + +} // namespace Audio +} // namespace Service diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index f838713a3..3c4259d27 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -1,19 +1,160 @@ -// Copyright 2015 Citra Emulator Project +// Copyright 2018 yuzu emulator team  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included. +#include <atomic>  #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" +#include "core/hle/kernel/shared_memory.h"  #include "core/hle/service/hid/hid.h"  #include "core/hle/service/service.h"  namespace Service {  namespace HID { -void Init() {} +// 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; -void Shutdown() {} +class IAppletResource final : public ServiceFramework<IAppletResource> { +public: +    IAppletResource() : ServiceFramework("IAppletResource") { +        static const FunctionInfo functions[] = { +            {0, &IAppletResource::GetSharedMemoryHandle, "GetSharedMemoryHandle"}, +        }; +        RegisterHandlers(functions); + +        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: +    void GetSharedMemoryHandle(Kernel::HLERequestContext& ctx) { +        IPC::RequestBuilder rb{ctx, 2, 1}; +        rb.Push(RESULT_SUCCESS); +        rb.PushCopyObjects(shared_mem); +        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<Input::ButtonDevice>); +        // TODO(shinyquagsire23): sticks, gyro, touch, mouse, keyboard +    } + +    void UpdatePadCallback(u64 userdata, int cycles_late) { +        SharedMemory* mem = reinterpret_cast<SharedMemory*>(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<Kernel::SharedMemory> shared_mem; + +    // CoreTiming update events +    CoreTiming::EventType* pad_update_event; + +    // Stored input state info +    std::atomic<bool> is_device_reload_pending{true}; +    std::array<std::unique_ptr<Input::ButtonDevice>, Settings::NativeButton::NUM_BUTTONS_HID> +        buttons; +}; + +class Hid final : public ServiceFramework<Hid> { +public: +    Hid() : ServiceFramework("hid") { +        static const FunctionInfo functions[] = { +            {0x00000000, &Hid::CreateAppletResource, "CreateAppletResource"}, +        }; +        RegisterHandlers(functions); +    } +    ~Hid() = default; + +private: +    void CreateAppletResource(Kernel::HLERequestContext& ctx) { +        auto client_port = std::make_shared<IAppletResource>()->CreatePort(); +        auto session = client_port->Connect(); +        if (session.Succeeded()) { +            LOG_DEBUG(Service, "called, initialized IAppletResource -> session=%u", +                      (*session)->GetObjectId()); +            IPC::RequestBuilder rb{ctx, 2, 0, 1}; +            rb.Push(RESULT_SUCCESS); +            rb.PushMoveObjects(std::move(session).Unwrap()); +        } else { +            UNIMPLEMENTED(); +        } +    } +};  void ReloadInputDevices() {} +void InstallInterfaces(SM::ServiceManager& service_manager) { +    std::make_shared<Hid>()->InstallAsService(service_manager); +} +  } // namespace HID  } // namespace Service diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index a1d227dfe..486e64800 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -1,20 +1,331 @@ -// Copyright 2015 Citra Emulator Project +// Copyright 2018 yuzu emulator team  // Licensed under GPLv2 or any later version  // Refer to the license.txt file included.  #pragma once +#include "core/hle/service/service.h" +#include "core/settings.h" +  namespace Service {  namespace HID { -/// Initialize HID service -void Init(); +// Begin enums and output structs + +enum ControllerType : u32 { +    ControllerType_ProController = 1 << 0, +    ControllerType_Handheld = 1 << 1, +    ControllerType_JoyconPair = 1 << 2, +    ControllerType_JoyconLeft = 1 << 3, +    ControllerType_JoyconRight = 1 << 4, +}; + +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 +    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 ControllerColorDescription { +    ColorDesc_ColorsNonexistent = 1 << 1, +}; + +enum ControllerConnectionState { +    ConnectionState_Connected = 1 << 0, +    ConnectionState_Wired = 1 << 1, +}; + +enum ControllerID { +    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 TouchScreen + +struct TouchScreenHeader { +    u64 timestampTicks; +    u64 numEntries; +    u64 latestEntry; +    u64 maxEntryIndex; +    u64 timestamp; +}; +static_assert(sizeof(TouchScreenHeader) == 0x28, +              "HID touch screen header structure has incorrect size"); + +struct TouchScreenEntryHeader { +    u64 timestamp; +    u64 numTouches; +}; +static_assert(sizeof(TouchScreenEntryHeader) == 0x10, +              "HID touch screen entry header structure has incorrect size"); + +struct TouchScreenEntryTouch { +    u64 timestamp; +    u32 padding; +    u32 touchIndex; +    u32 x; +    u32 y; +    u32 diameterX; +    u32 diameterY; +    u32 angle; +    u32 padding_2; +}; +static_assert(sizeof(TouchScreenEntryTouch) == 0x28, +              "HID touch screen touch structure has incorrect size"); + +struct TouchScreenEntry { +    TouchScreenEntryHeader header; +    std::array<TouchScreenEntryTouch, 16> touches; +    u64 unk; +}; +static_assert(sizeof(TouchScreenEntry) == 0x298, +              "HID touch screen entry structure has incorrect size"); + +struct TouchScreen { +    TouchScreenHeader header; +    std::array<TouchScreenEntry, 17> entries; +    std::array<u8, 0x3c0> padding; +}; +static_assert(sizeof(TouchScreen) == 0x3000, "HID touch screen structure has incorrect size"); + +// End TouchScreen + +// Begin Mouse + +struct MouseHeader { +    u64 timestampTicks; +    u64 numEntries; +    u64 latestEntry; +    u64 maxEntryIndex; +}; +static_assert(sizeof(MouseHeader) == 0x20, "HID mouse header structure has incorrect size"); + +struct MouseButtonState { +    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 MouseEntry { +    u64 timestamp; +    u64 timestamp_2; +    u32 x; +    u32 y; +    u32 velocityX; +    u32 velocityY; +    u32 scrollVelocityX; +    u32 scrollVelocityY; +    MouseButtonState buttons; +}; +static_assert(sizeof(MouseEntry) == 0x30, "HID mouse entry structure has incorrect size"); + +struct Mouse { +    MouseHeader header; +    std::array<MouseEntry, 17> entries; +    std::array<u8, 0xB0> padding; +}; +static_assert(sizeof(Mouse) == 0x400, "HID mouse structure has incorrect size"); + +// End Mouse + +// Begin Keyboard -/// Shutdown HID service -void Shutdown(); +struct KeyboardHeader { +    u64 timestampTicks; +    u64 numEntries; +    u64 latestEntry; +    u64 maxEntryIndex; +}; +static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size"); + +struct KeyboardModifierKeyState { +    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 KeyboardEntry { +    u64 timestamp; +    u64 timestamp_2; +    KeyboardModifierKeyState modifier; +    u32 keys[8]; +}; +static_assert(sizeof(KeyboardEntry) == 0x38, "HID keyboard entry structure has incorrect size"); + +struct Keyboard { +    KeyboardHeader header; +    std::array<KeyboardEntry, 17> entries; +    std::array<u8, 0x28> padding; +}; +static_assert(sizeof(Keyboard) == 0x400, "HID keyboard structure has incorrect size"); + +// End Keyboard + +// Begin Controller + +struct ControllerMAC { +    u64 timestamp; +    std::array<u8, 0x8> mac; +    u64 unk; +    u64 timestamp_2; +}; +static_assert(sizeof(ControllerMAC) == 0x20, "HID controller MAC structure has incorrect size"); + +struct ControllerHeader { +    u32 type; +    u32 isHalf; +    u32 singleColorsDescriptor; +    u32 singleColorBody; +    u32 singleColorButtons; +    u32 splitColorsDescriptor; +    u32 leftColorBody; +    u32 leftColorButtons; +    u32 rightColorBody; +    u32 rightColorbuttons; +}; +static_assert(sizeof(ControllerHeader) == 0x28, +              "HID controller header structure has incorrect size"); + +struct ControllerLayoutHeader { +    u64 timestampTicks; +    u64 numEntries; +    u64 latestEntry; +    u64 maxEntryIndex; +}; +static_assert(sizeof(ControllerLayoutHeader) == 0x20, +              "HID controller layout header structure has incorrect size"); + +struct ControllerPadState { +    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 ControllerInputEntry { +    u64 timestamp; +    u64 timestamp_2; +    ControllerPadState buttons; +    u32 joystickLeftX; +    u32 joystickLeftY; +    u32 joystickRightX; +    u32 joystickRightY; +    u64 connectionState; +}; +static_assert(sizeof(ControllerInputEntry) == 0x30, +              "HID controller input entry structure has incorrect size"); + +struct ControllerLayout { +    ControllerLayoutHeader header; +    std::array<ControllerInputEntry, 17> entries; +}; +static_assert(sizeof(ControllerLayout) == 0x350, +              "HID controller layout structure has incorrect size"); + +struct Controller { +    ControllerHeader header; +    std::array<ControllerLayout, 7> layouts; +    std::array<u8, 0x2a70> unk_1; +    ControllerMAC macLeft; +    ControllerMAC macRight; +    std::array<u8, 0xdf8> unk_2; +}; +static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorrect size"); + +// End Controller + +struct SharedMemory { +    std::array<u8, 0x400> header; +    TouchScreen touchscreen; +    Mouse mouse; +    Keyboard keyboard; +    std::array<u8, 0x400> unkSection1; +    std::array<u8, 0x400> unkSection2; +    std::array<u8, 0x400> unkSection3; +    std::array<u8, 0x400> unkSection4; +    std::array<u8, 0x200> unkSection5; +    std::array<u8, 0x200> unkSection6; +    std::array<u8, 0x200> unkSection7; +    std::array<u8, 0x800> unkSection8; +    std::array<u8, 0x4000> controllerSerials; +    std::array<Controller, 10> controllers; +    std::array<u8, 0x4600> unkSection9; +}; +static_assert(sizeof(SharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size");  /// Reload input devices. Used when input configuration changed  void ReloadInputDevices(); +/// Registers all HID services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); +  } // namespace HID  } // namespace Service diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index ca429e15f..2d0d2fb65 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp @@ -144,7 +144,7 @@ void LM::Initialize(Kernel::HLERequestContext& ctx) {      if (session.Succeeded()) {          LOG_DEBUG(Service_SM, "called, initialized logger -> session=%u",                    (*session)->GetObjectId()); -        IPC::RequestBuilder rb{ctx, 1, 0, 1}; +        IPC::RequestBuilder rb{ctx, 2, 0, 1};          rb.Push(RESULT_SUCCESS);          rb.PushMoveObjects(std::move(session).Unwrap());          registered_loggers.emplace_back(std::move(client_port)); diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index b82df6f35..02d434660 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -17,6 +17,7 @@  #include "core/hle/service/am/am.h"  #include "core/hle/service/aoc/aoc_u.h"  #include "core/hle/service/apm/apm.h" +#include "core/hle/service/audio/audio.h"  #include "core/hle/service/hid/hid.h"  #include "core/hle/service/lm/lm.h"  #include "core/hle/service/nvdrv/nvdrv.h" @@ -24,6 +25,7 @@  #include "core/hle/service/service.h"  #include "core/hle/service/sm/controller.h"  #include "core/hle/service/sm/sm.h" +#include "core/hle/service/time/time.h"  #include "core/hle/service/vi/vi.h"  using Kernel::ClientPort; @@ -78,7 +80,8 @@ Kernel::SharedPtr<Kernel::ClientPort> ServiceFrameworkBase::CreatePort() {      ASSERT(port == nullptr);      Kernel::SharedPtr<Kernel::ServerPort> server_port;      Kernel::SharedPtr<Kernel::ClientPort> client_port; -    std::tie(server_port, client_port) = Kernel::ServerPort::CreatePortPair(max_sessions, service_name); +    std::tie(server_port, client_port) = +        Kernel::ServerPort::CreatePortPair(max_sessions, service_name);      port = MakeResult<Kernel::SharedPtr<Kernel::ServerPort>>(std::move(server_port)).Unwrap();      port->SetHleHandler(shared_from_this());      return client_port; @@ -164,20 +167,19 @@ void Init() {      AM::InstallInterfaces(*SM::g_service_manager);      AOC::InstallInterfaces(*SM::g_service_manager);      APM::InstallInterfaces(*SM::g_service_manager); +    Audio::InstallInterfaces(*SM::g_service_manager); +    HID::InstallInterfaces(*SM::g_service_manager);      LM::InstallInterfaces(*SM::g_service_manager);      NVDRV::InstallInterfaces(*SM::g_service_manager);      PCTL::InstallInterfaces(*SM::g_service_manager); +    Time::InstallInterfaces(*SM::g_service_manager);      VI::InstallInterfaces(*SM::g_service_manager); -    HID::Init(); -      LOG_DEBUG(Service, "initialized OK");  }  /// Shutdown ServiceManager  void Shutdown() { -    HID::Shutdown(); -      SM::g_service_manager = nullptr;      g_kernel_named_ports.clear();      LOG_DEBUG(Service, "shutdown OK"); diff --git a/src/core/hle/service/time/time.cpp b/src/core/hle/service/time/time.cpp new file mode 100644 index 000000000..e3d58aa60 --- /dev/null +++ b/src/core/hle/service/time/time.cpp @@ -0,0 +1,16 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/hle/service/time/time.h" +#include "core/hle/service/time/time_s.h" + +namespace Service { +namespace Time { + +void InstallInterfaces(SM::ServiceManager& service_manager) { +    std::make_shared<TimeS>()->InstallAsService(service_manager); +} + +} // namespace Time +} // namespace Service diff --git a/src/core/hle/service/time/time.h b/src/core/hle/service/time/time.h new file mode 100644 index 000000000..7d0803e24 --- /dev/null +++ b/src/core/hle/service/time/time.h @@ -0,0 +1,16 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/service/service.h" + +namespace Service { +namespace Time { + +/// Registers all Time services with the specified service manager. +void InstallInterfaces(SM::ServiceManager& service_manager); + +} // namespace Time +} // namespace Service diff --git a/src/core/hle/service/time/time_s.cpp b/src/core/hle/service/time/time_s.cpp new file mode 100644 index 000000000..6b0597d8e --- /dev/null +++ b/src/core/hle/service/time/time_s.cpp @@ -0,0 +1,58 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include <chrono> +#include "common/logging/log.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/client_port.h" +#include "core/hle/kernel/client_session.h" +#include "core/hle/service/time/time_s.h" + +namespace Service { +namespace Time { + +class ISystemClock final : public ServiceFramework<ISystemClock> { +public: +    ISystemClock() : ServiceFramework("ISystemClock") { +        static const FunctionInfo functions[] = { +            {0, &ISystemClock::GetCurrentTime, "GetCurrentTime"}, +        }; +        RegisterHandlers(functions); +    } + +private: +    void GetCurrentTime(Kernel::HLERequestContext& ctx) { +        const s64 time_since_epoch{std::chrono::duration_cast<std::chrono::milliseconds>( +                                       std::chrono::system_clock::now().time_since_epoch()) +                                       .count()}; +        IPC::RequestBuilder rb{ctx, 4}; +        rb.Push(RESULT_SUCCESS); +        rb.Push<u64>(time_since_epoch); +        LOG_DEBUG(Service, "called"); +    } +}; + +void TimeS::GetStandardUserSystemClock(Kernel::HLERequestContext& ctx) { +    auto client_port = std::make_shared<ISystemClock>()->CreatePort(); +    auto session = client_port->Connect(); +    if (session.Succeeded()) { +        LOG_DEBUG(Service, "called, initialized ISystemClock -> session=%u", +                  (*session)->GetObjectId()); +        IPC::RequestBuilder rb{ctx, 2, 0, 1}; +        rb.Push(RESULT_SUCCESS); +        rb.PushMoveObjects(std::move(session).Unwrap()); +    } else { +        UNIMPLEMENTED(); +    } +} + +TimeS::TimeS() : ServiceFramework("time:s") { +    static const FunctionInfo functions[] = { +        {0x00000000, &TimeS::GetStandardUserSystemClock, "GetStandardUserSystemClock"}, +    }; +    RegisterHandlers(functions); +} + +} // namespace Time +} // namespace Service diff --git a/src/core/hle/service/time/time_s.h b/src/core/hle/service/time/time_s.h new file mode 100644 index 000000000..073227910 --- /dev/null +++ b/src/core/hle/service/time/time_s.h @@ -0,0 +1,23 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include "core/hle/kernel/hle_ipc.h" +#include "core/hle/service/service.h" + +namespace Service { +namespace Time { + +class TimeS final : public ServiceFramework<TimeS> { +public: +    TimeS(); +    ~TimeS() = default; + +private: +    void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx); +}; + +} // namespace Time +} // namespace Service diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index d3b63949e..93ebbe75f 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -12,6 +12,8 @@  #include "core/hle/service/nvdrv/nvdrv_a.h"  #include "core/hle/service/vi/vi.h"  #include "core/hle/service/vi/vi_m.h" +#include "video_core/renderer_base.h" +#include "video_core/video_core.h"  namespace Service {  namespace VI { @@ -492,6 +494,7 @@ public:      IManagerDisplayService(std::shared_ptr<NVFlinger> 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"}, @@ -501,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<u64>(); + +        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}; @@ -743,7 +755,8 @@ void NVFlinger::Compose() {          auto buffer = buffer_queue->AcquireBuffer();          if (buffer == boost::none) { -            // There was no queued buffer to draw. +            // There was no queued buffer to draw, render previous frame +            VideoCore::g_renderer->SwapBuffers({});              continue;          } diff --git a/src/core/settings.h b/src/core/settings.h index f2c88e5d4..bd9a3d9fe 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -16,52 +16,87 @@ 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, +    Screenshot,      NumButtons,  };  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<const char*, NumButtons> 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", +    "button_screenshot",  }};  } // namespace NativeButton  namespace NativeAnalog {  enum Values { -    CirclePad, -    CStick, +    LStick, +    RStick,      NumAnalogs,  };  static const std::array<const char*, NumAnalogs> mapping = {{ -    "circle_pad", "c_stick", +    "lstick", +    "rstick",  }};  } // namespace NativeAnalog diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index d15db6c8c..28893b181 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h @@ -5,6 +5,7 @@  #pragma once  #include <memory> +#include <boost/optional.hpp>  #include "common/assert.h"  #include "common/common_types.h" @@ -47,7 +48,7 @@ public:      virtual ~RendererBase() {}      /// Swap buffers (render frame) -    virtual void SwapBuffers(const FramebufferInfo& framebuffer_info) = 0; +    virtual void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) = 0;      /**       * Set the emulator window to use for renderer diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index a5df91604..50396b5c1 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -4,8 +4,8 @@  #include <algorithm>  #include <cstddef> -#include <cstring>  #include <cstdlib> +#include <cstring>  #include <memory>  #include <glad/glad.h>  #include "common/assert.h" @@ -98,20 +98,23 @@ RendererOpenGL::RendererOpenGL() = default;  RendererOpenGL::~RendererOpenGL() = default;  /// Swap buffers (render frame) -void RendererOpenGL::SwapBuffers(const FramebufferInfo& framebuffer_info) { +void RendererOpenGL::SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) {      // Maintain the rasterizer's state as a priority      OpenGLState prev_state = OpenGLState::GetCurState();      state.Apply(); -    if (screen_info.texture.width != (GLsizei)framebuffer_info.width || -        screen_info.texture.height != (GLsizei)framebuffer_info.height || -        screen_info.texture.pixel_format != framebuffer_info.pixel_format) { -        // Reallocate texture if the framebuffer size has changed. -        // This is expected to not happen very often and hence should not be a -        // performance problem. -        ConfigureFramebufferTexture(screen_info.texture, framebuffer_info); +    if (framebuffer_info != boost::none) { +        // If framebuffer_info is provided, reload it from memory to a texture +        if (screen_info.texture.width != (GLsizei)framebuffer_info->width || +            screen_info.texture.height != (GLsizei)framebuffer_info->height || +            screen_info.texture.pixel_format != framebuffer_info->pixel_format) { +            // Reallocate texture if the framebuffer size has changed. +            // This is expected to not happen very often and hence should not be a +            // performance problem. +            ConfigureFramebufferTexture(screen_info.texture, *framebuffer_info); +        } +        LoadFBToScreenInfo(*framebuffer_info, screen_info);      } -    LoadFBToScreenInfo(framebuffer_info, screen_info);      DrawScreens(); @@ -290,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(); @@ -361,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 dc21d7a38..dd01e1b1a 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h @@ -37,7 +37,7 @@ public:      ~RendererOpenGL() override;      /// Swap buffers (render frame) -    void SwapBuffers(const FramebufferInfo& framebuffer_info) override; +    void SwapBuffers(boost::optional<const FramebufferInfo&> framebuffer_info) override;      /**       * Set the emulator window to use for renderer @@ -53,17 +53,15 @@ public:  private:      void InitOpenGLObjects(); -    void ConfigureFramebufferTexture(TextureInfo& texture, -                                     const FramebufferInfo& framebuffer_info); +    void ConfigureFramebufferTexture(TextureInfo& texture, const FramebufferInfo& framebuffer_info);      void DrawScreens();      void DrawSingleScreen(const ScreenInfo& screen_info, float x, float y, float w, float h);      void UpdateFramerate();      // 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); +    void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info); +    // 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 diff --git a/src/yuzu/aboutdialog.ui b/src/yuzu/aboutdialog.ui index cdcaa15b0..2680480cc 100644 --- a/src/yuzu/aboutdialog.ui +++ b/src/yuzu/aboutdialog.ui @@ -87,7 +87,7 @@  <html><head><meta name="qrichtext" content="1" /><style type="text/css">  p, li { white-space: pre-wrap; }  </style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">yuzu is an experimental open-source emulator for the Nintendo Switch licensed under GPLv2.0 or any later version.</span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">yuzu is an experimental open-source emulator for the Nintendo Switch licensed under GPLv2.0.</span></p>  <p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'MS Shell Dlg 2'; font-size:8pt;"><br /></p>  <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:12pt;">This software should not be used to play games you have not legally obtained.</span></p></body></html></string>           </property> diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 4c713fcbc..ab6ba0ec9 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"; @@ -19,16 +18,18 @@ Config::Config() {  }  const std::array<int, Settings::NativeButton::NumButtons> 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<std::array<int, 5>, 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,      },  }}; @@ -86,7 +87,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"); diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index 5f91d5492..47b9b6e95 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) { @@ -23,12 +22,6 @@ enum class Resolution : int {      Scale2x,      Scale3x,      Scale4x, -    Scale5x, -    Scale6x, -    Scale7x, -    Scale8x, -    Scale9x, -    Scale10x,  };  float ToResolutionFactor(Resolution option) { @@ -43,18 +36,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 +51,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 489156805..366931a9a 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -34,7 +34,7 @@            <item>             <widget class="QLabel" name="label">              <property name="text"> -             <string>Internal Resolution:</string> +             <string>Internal Resolution:(Currently does nothing.)</string>              </property>             </widget>            </item> @@ -47,52 +47,22 @@              </item>              <item>               <property name="text"> -              <string>Native (400x240)</string> +              <string>Native (1280x720)</string>               </property>              </item>              <item>               <property name="text"> -              <string>2x Native (800x480)</string> +              <string>2x Native (2560x1440)</string>               </property>              </item>              <item>               <property name="text"> -              <string>3x Native (1200x720)</string> +              <string>3x Native (3840x2160)</string>               </property>              </item>              <item>               <property name="text"> -              <string>4x Native (1600x960)</string> -             </property> -            </item> -            <item> -             <property name="text"> -              <string>5x Native (2000x1200)</string> -             </property> -            </item> -            <item> -             <property name="text"> -              <string>6x Native (2400x1440)</string> -             </property> -            </item> -            <item> -             <property name="text"> -              <string>7x Native (2800x1680)</string> -             </property> -            </item> -            <item> -             <property name="text"> -              <string>8x Native (3200x1920)</string> -             </property> -            </item> -            <item> -             <property name="text"> -              <string>9x Native (3600x2160)</string> -             </property> -            </item> -            <item> -             <property name="text"> -              <string>10x Native (4000x2400)</string> +              <string>4x Native (5120x2880)</string>               </property>              </item>             </widget> diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 4c2a3e738..d92a1fed9 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 2760787e5..5143c9d72 100644 --- a/src/yuzu/configuration/configure_input.ui +++ b/src/yuzu/configuration/configure_input.ui @@ -6,8 +6,8 @@     <rect>      <x>0</x>      <y>0</y> -    <width>370</width> -    <height>534</height> +    <width>343</width> +    <height>665</height>     </rect>    </property>    <property name="windowTitle"> @@ -190,7 +190,108 @@         </layout>        </widget>       </item> -     <item row="1" column="0"> +     <item row="3" column="1"> +      <widget class="QGroupBox" name="faceButtons_6"> +       <property name="title"> +        <string>Misc.</string> +       </property> +       <property name="flat"> +        <bool>false</bool> +       </property> +       <property name="checkable"> +        <bool>false</bool> +       </property> +       <layout class="QGridLayout" name="gridLayout_6"> +        <item row="0" column="0"> +         <layout class="QVBoxLayout" name="verticalLayout_25"> +          <item> +           <widget class="QLabel" name="label_29"> +            <property name="text"> +             <string>Plus:</string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QPushButton" name="buttonPlus"> +            <property name="text"> +             <string/> +            </property> +           </widget> +          </item> +         </layout> +        </item> +        <item row="0" column="1"> +         <layout class="QVBoxLayout" name="verticalLayout_26"> +          <item> +           <widget class="QLabel" name="label_30"> +            <property name="text"> +             <string>Minus:</string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QPushButton" name="buttonMinus"> +            <property name="text"> +             <string/> +            </property> +           </widget> +          </item> +         </layout> +        </item> +        <item row="1" column="0"> +         <layout class="QVBoxLayout" name="verticalLayout_27"> +          <item> +           <widget class="QLabel" name="label_31"> +            <property name="text"> +             <string>Home:</string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QPushButton" name="buttonHome"> +            <property name="text"> +             <string/> +            </property> +           </widget> +          </item> +         </layout> +        </item> +        <item row="1" column="1"> +         <layout class="QVBoxLayout" name="verticalLayout_28"> +          <item> +           <widget class="QLabel" name="label_11"> +            <property name="text"> +             <string>Screen +Capture:</string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QPushButton" name="buttonScreenshot"> +            <property name="text"> +             <string/> +            </property> +           </widget> +          </item> +         </layout> +        </item> +        <item row="2" column="1"> +         <spacer name="verticalSpacer"> +          <property name="orientation"> +           <enum>Qt::Vertical</enum> +          </property> +          <property name="sizeHint" stdset="0"> +           <size> +            <width>20</width> +            <height>40</height> +           </size> +          </property> +         </spacer> +        </item> +       </layout> +      </widget> +     </item> +     <item row="3" column="0">        <widget class="QGroupBox" name="faceButtons_3">         <property name="title">          <string>Shoulder Buttons</string> @@ -274,13 +375,49 @@            </item>           </layout>          </item> +        <item row="2" column="0"> +         <layout class="QVBoxLayout" name="verticalLayout_8"> +          <item> +           <widget class="QLabel" name="label_7"> +            <property name="text"> +             <string>SL:</string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QPushButton" name="buttonSL"> +            <property name="text"> +             <string/> +            </property> +           </widget> +          </item> +         </layout> +        </item> +        <item row="2" column="1"> +         <layout class="QVBoxLayout" name="verticalLayout_29"> +          <item> +           <widget class="QLabel" name="label_8"> +            <property name="text"> +             <string>SR:</string> +            </property> +           </widget> +          </item> +          <item> +           <widget class="QPushButton" name="buttonSR"> +            <property name="text"> +             <string/> +            </property> +           </widget> +          </item> +         </layout> +        </item>         </layout>        </widget>       </item> -     <item row="1" column="1"> +     <item row="1" column="0">        <widget class="QGroupBox" name="faceButtons_4">         <property name="title"> -        <string>Circle Pad</string> +        <string>Left Stick</string>         </property>         <property name="flat">          <bool>false</bool> @@ -299,7 +436,7 @@             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCircleLeft"> +           <widget class="QPushButton" name="buttonLStickLeft">              <property name="text">               <string/>              </property> @@ -317,7 +454,7 @@             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCircleRight"> +           <widget class="QPushButton" name="buttonLStickRight">              <property name="text">               <string/>              </property> @@ -335,7 +472,7 @@             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCircleUp"> +           <widget class="QPushButton" name="buttonLStickUp">              <property name="text">               <string/>              </property> @@ -353,7 +490,7 @@             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCircleDown"> +           <widget class="QPushButton" name="buttonLStickDown">              <property name="text">               <string/>              </property> @@ -361,32 +498,17 @@            </item>           </layout>          </item> -       </layout> -      </widget> -     </item> -     <item row="2" column="0"> -      <widget class="QGroupBox" name="faceButtons_5"> -       <property name="title"> -        <string>C-Stick</string> -       </property> -       <property name="flat"> -        <bool>false</bool> -       </property> -       <property name="checkable"> -        <bool>false</bool> -       </property> -       <layout class="QGridLayout" name="gridLayout_5"> -        <item row="0" column="0"> -         <layout class="QVBoxLayout" name="verticalLayout_21"> +        <item row="2" column="0"> +         <layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,0">            <item> -           <widget class="QLabel" name="label_25"> +           <widget class="QLabel" name="label_6">              <property name="text"> -             <string>Left:</string> +             <string>Pressed:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCStickLeft"> +           <widget class="QPushButton" name="buttonLStick">              <property name="text">               <string/>              </property> @@ -394,17 +516,17 @@            </item>           </layout>          </item> -        <item row="0" column="1"> -         <layout class="QVBoxLayout" name="verticalLayout_22"> +        <item row="2" column="1"> +         <layout class="QVBoxLayout" name="verticalLayout_31">            <item> -           <widget class="QLabel" name="label_27"> +           <widget class="QLabel" name="label_9">              <property name="text"> -             <string>Right:</string> +             <string>Modifier:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCStickRight"> +           <widget class="QPushButton" name="buttonLStickMod">              <property name="text">               <string/>              </property> @@ -412,17 +534,35 @@            </item>           </layout>          </item> -        <item row="1" column="0"> -         <layout class="QVBoxLayout" name="verticalLayout_23"> +       </layout> +      </widget> +     </item> +     <item row="1" column="1"> +      <widget class="QGroupBox" name="faceButtons_5"> +       <property name="title"> +        <string>Right Stick</string> +       </property> +       <property name="alignment"> +        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> +       </property> +       <property name="flat"> +        <bool>false</bool> +       </property> +       <property name="checkable"> +        <bool>false</bool> +       </property> +       <layout class="QGridLayout" name="gridLayout_5"> +        <item row="1" column="1"> +         <layout class="QVBoxLayout" name="verticalLayout_24">            <item> -           <widget class="QLabel" name="label_28"> +           <widget class="QLabel" name="label_26">              <property name="text"> -             <string>Up:</string> +             <string>Down:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCStickUp"> +           <widget class="QPushButton" name="buttonRStickDown">              <property name="text">               <string/>              </property> @@ -430,17 +570,17 @@            </item>           </layout>          </item> -        <item row="1" column="1"> -         <layout class="QVBoxLayout" name="verticalLayout_24"> +        <item row="0" column="1"> +         <layout class="QVBoxLayout" name="verticalLayout_22">            <item> -           <widget class="QLabel" name="label_26"> +           <widget class="QLabel" name="label_27">              <property name="text"> -             <string>Down:</string> +             <string>Right:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCStickDown"> +           <widget class="QPushButton" name="buttonRStickRight">              <property name="text">               <string/>              </property> @@ -448,32 +588,17 @@            </item>           </layout>          </item> -       </layout> -      </widget> -     </item> -     <item row="2" column="1"> -      <widget class="QGroupBox" name="faceButtons_6"> -       <property name="title"> -        <string>Misc.</string> -       </property> -       <property name="flat"> -        <bool>false</bool> -       </property> -       <property name="checkable"> -        <bool>false</bool> -       </property> -       <layout class="QGridLayout" name="gridLayout_6"> -        <item row="0" column="0"> -         <layout class="QVBoxLayout" name="verticalLayout_25"> +        <item row="1" column="0"> +         <layout class="QVBoxLayout" name="verticalLayout_23">            <item> -           <widget class="QLabel" name="label_29"> +           <widget class="QLabel" name="label_28">              <property name="text"> -             <string>Start:</string> +             <string>Up:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonStart"> +           <widget class="QPushButton" name="buttonRStickUp">              <property name="text">               <string/>              </property> @@ -481,17 +606,17 @@            </item>           </layout>          </item> -        <item row="0" column="1"> -         <layout class="QVBoxLayout" name="verticalLayout_26"> +        <item row="0" column="0"> +         <layout class="QVBoxLayout" name="verticalLayout_21">            <item> -           <widget class="QLabel" name="label_30"> +           <widget class="QLabel" name="label_25">              <property name="text"> -             <string>Select:</string> +             <string>Left:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonSelect"> +           <widget class="QPushButton" name="buttonRStickLeft">              <property name="text">               <string/>              </property> @@ -499,17 +624,17 @@            </item>           </layout>          </item> -        <item row="1" column="0"> -         <layout class="QVBoxLayout" name="verticalLayout_27"> +        <item row="2" column="1"> +         <layout class="QVBoxLayout" name="verticalLayout_32">            <item> -           <widget class="QLabel" name="label_31"> +           <widget class="QLabel" name="label_10">              <property name="text"> -             <string>Home:</string> +             <string>Modifier:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonHome"> +           <widget class="QPushButton" name="buttonRStickMod">              <property name="text">               <string/>              </property> @@ -517,17 +642,17 @@            </item>           </layout>          </item> -        <item row="1" column="1"> -         <layout class="QVBoxLayout" name="verticalLayout_28"> +        <item row="2" column="0"> +         <layout class="QVBoxLayout" name="verticalLayout_6">            <item> -           <widget class="QLabel" name="label_36"> +           <widget class="QLabel" name="label_5">              <property name="text"> -             <string>Circle Mod:</string> +             <string>Pressed:</string>              </property>             </widget>            </item>            <item> -           <widget class="QPushButton" name="buttonCircleMod"> +           <widget class="QPushButton" name="buttonRStick">              <property name="text">               <string/>              </property> diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index e7941eceb..5a2f539b1 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -30,17 +30,26 @@ 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_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= +button_screenshot=  # for analog input, the following devices are available:  #  - "analog_from_button" (default) for emulating analog input from direction buttons. Required parameters: @@ -53,8 +62,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: @@ -81,8 +90,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.  | 
