Compare commits

...

43 Commits

Author SHA1 Message Date
David Thetford
64a5cfa424 Create Function 2018-01-16 01:44:32 -06:00
David Thetford
6680561187 Create Emulator 2018-01-16 01:43:04 -06:00
Flame Sage
713c1ed203 Merge pull request #25 from chris062689/master
Updated Discord link to match website.
2018-01-15 20:35:26 -05:00
Flame Sage
21f5161ad8 Updated Discord link to match website. 2018-01-16 01:35:04 +00:00
bunnei
20a745aa71 Merge pull request #23 from Simonx22/cmake_rename
CMakeList.txt: rename CITRA to YUZU
2018-01-15 17:48:02 -05:00
bunnei
6f904bb622 nso: Load subsdk4 if available. 2018-01-15 17:18:24 -05:00
Simonx22
e9cf161917 rename CITRA to YUZU 2018-01-15 23:05:20 +01:00
bunnei
1a3b3e9100 pctl: Clang format. 2018-01-15 15:16:06 -05:00
bunnei
1148e2ce7b pctl: GetService should return an IParentalControlService interface. 2018-01-15 15:10:18 -05:00
bunnei
5bc14ab0de applet_oe: Stub SetFocusHandlingMode, GetCurrentFocusState, SetTerminateResult. 2018-01-15 14:41:06 -05:00
bunnei
8e2f62c6a5 settings: Fix button mappings array to have correct entries. 2018-01-15 13:09:14 -05:00
bunnei
67c8b671d2 Merge pull request #17 from spycrab/bindir
CMake: Output binaries to bin/
2018-01-15 12:56:58 -05:00
bunnei
054d3e5fc3 Merge pull request #20 from Andrix44/fixes
Various fixes
2018-01-15 12:56:16 -05:00
bunnei
325f72aceb Merge pull request #16 from shinyquagsire23/hid-sharedmem-impl-start
HID Sharedmem Impl Start
2018-01-15 12:54:54 -05:00
unknown
a4f5ccbf0a Clanggit rebase -i fixes 2018-01-15 18:20:53 +01:00
unknown
8d968780c1 Clang format 2018-01-15 17:55:16 +01:00
unknown
58ee23f16d Change default log level to info 2018-01-15 17:15:10 +01:00
unknown
27960d8c2c Update the internal resolution settings 2018-01-15 16:59:02 +01:00
unknown
af6e0faf0a Fix some warnings 2018-01-15 16:24:29 +01:00
spycrab
8a440faa69 CMake: Output binaries to bin/ 2018-01-15 13:47:38 +01:00
shinyquagsire23
9fba2d68fe yuzu_cmd: Fix default ini, add screenshot button 2018-01-15 02:30:58 -07:00
shinyquagsire23
1ea49442f9 hid: Bare-minimum sharedmem input 2018-01-15 02:30:58 -07:00
shinyquagsire23
bb1fcfac33 hid: Remove redundant HID prefix on structs/enums 2018-01-15 02:30:58 -07:00
shinyquagsire23
aa4fa8bded configure_input: update w/ Switch buttons 2018-01-15 02:30:53 -07:00
shinyquagsire23
801d6c1b6f settings: Screenshot button 2018-01-15 02:30:53 -07:00
shinyquagsire23
cdb43e64c1 yuzu_cmd: fix default ini 2018-01-15 02:30:53 -07:00
shinyquagsire23
74aa14c9b4 settings: adjust button configs for Switch controllers 2018-01-15 02:30:53 -07:00
shinyquagsire23
e08c132175 hid: Add sharedmem structs 2018-01-15 02:30:53 -07:00
Harry Prevor
f2d55bb881 fixed build for gcc c++17 / boost.icl incompatibility 2018-01-15 02:30:53 -07:00
bunnei
22347e8844 Merge pull request #15 from bsaleil/master
vi: Add IManagerDisplayService::CloseDisplay function
2018-01-15 02:56:53 -05:00
bsaleil
af1ca87be1 vi: Add IManagerDisplayService::CloseDisplay function 2018-01-15 01:29:00 -05:00
bunnei
2678dbfbe6 Merge pull request #13 from hpr/fno-new-ttp-matching
Fix build for gcc c++17 / boost.icl incompatibility
2018-01-15 00:22:06 -05:00
bunnei
b1712b8312 Merge pull request #14 from ogniK5377/master
Changed ICommonStateGetter::ReceiveMessage to allow further execution in games
2018-01-15 00:21:16 -05:00
bunnei
92801b1c34 renderer_gl: Clear screen to black before rendering framebuffer. 2018-01-15 00:20:19 -05:00
David Marcec
f3264dd78d Games expect 15 for ICommonStateGetter::ReceiveMessage in order to continue execution 2018-01-14 21:06:34 -08:00
bunnei
ebd613c2cc renderer: Render previous frame when no new one is available. 2018-01-14 23:54:56 -05:00
bunnei
2adde6ae8b Update README.md with Travis link. 2018-01-14 21:53:58 -05:00
bunnei
71eeab257f lm: Fix IPC header for Initialize. 2018-01-14 21:45:06 -05:00
bunnei
7bedea73a8 time: Implement GetStandardUserSystemClock, GetCurrentTime. 2018-01-14 21:45:06 -05:00
bunnei
d81a984d4a audio: Add files to CMake. 2018-01-14 21:45:06 -05:00
bunnei
2e8246a02c hid: Remove unused registered_loggers. 2018-01-14 21:45:06 -05:00
bunnei
7a50d56d0e audio: Stub out AudOutU::ListAudioOuts. 2018-01-14 21:45:06 -05:00
bunnei
f4a3d28224 hid: Implement IAppletResource::GetSharedMemoryHandle. 2018-01-14 21:45:06 -05:00
34 changed files with 1102 additions and 246 deletions

View File

@@ -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

View File

@@ -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"

View File

@@ -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)
@@ -166,17 +166,20 @@ 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)
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)
@@ -232,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)

1
Emulator Normal file
View File

@@ -0,0 +1 @@
Create Gameboy emulator as built in game operations option a

1
Function Normal file
View File

@@ -0,0 +1 @@
Set start up as basic function add on

View File

@@ -1,5 +1,7 @@
yuzu emulator
=============
[![Travis CI Build Status](https://travis-ci.org/yuzu-emu/yuzu.svg?branch=master)](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.
@@ -10,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

View File

@@ -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)

View File

@@ -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

View File

@@ -52,7 +52,23 @@ public:
class ISelfController final : public ServiceFramework<ISelfController> {
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<ICommonStateGetter> {
@@ -61,6 +77,7 @@ public:
static const FunctionInfo functions[] = {
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
{1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
{9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
};
RegisterHandlers(functions);
@@ -81,7 +98,15 @@ 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");
}
void GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(1); // 1: In focus, 2/3: Out of focus(running in "background")
LOG_WARNING(Service, "(STUBBED) called");
}
@@ -91,7 +116,26 @@ private:
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
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<u32>();
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result);
}
};
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {
@@ -120,48 +164,56 @@ private:
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IAudioController>();
LOG_DEBUG(Service, "called");
}
void GetDisplayController(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDisplayController>();
LOG_DEBUG(Service, "called");
}
void GetDebugFunctions(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IDebugFunctions>();
LOG_DEBUG(Service, "called");
}
void GetWindowController(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IWindowController>();
LOG_DEBUG(Service, "called");
}
void GetSelfController(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISelfController>();
LOG_DEBUG(Service, "called");
}
void GetCommonStateGetter(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ICommonStateGetter>();
LOG_DEBUG(Service, "called");
}
void GetLibraryAppletCreator(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ILibraryAppletCreator>();
LOG_DEBUG(Service, "called");
}
void GetApplicationFunctions(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IApplicationFunctions>();
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<IApplicationProxy>();
LOG_DEBUG(Service, "called");
}
AppletOE::AppletOE() : ServiceFramework("appletOE") {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
/// Shutdown HID service
void Shutdown();
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
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

View File

@@ -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));

View File

@@ -9,11 +9,16 @@
namespace Service {
namespace PCTL {
class IParentalControlService final : public ServiceFramework<IParentalControlService> {
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<IParentalControlService>();
LOG_DEBUG(Service, "called");
}
PCTL_A::PCTL_A() : ServiceFramework("pctl:a") {

View File

@@ -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");

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -157,7 +157,7 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& 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);

View File

@@ -16,52 +16,91 @@ 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_rstick_left",
"button_rstick_up",
"button_rstick_right",
"button_rstick_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

View File

@@ -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

View File

@@ -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,

View File

@@ -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

View File

@@ -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");

View File

@@ -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;
}

View File

@@ -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>

View File

@@ -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,
},
}};

View File

@@ -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,43 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCircleDown">
<widget class="QPushButton" name="buttonLStickDown">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_7" stretch="0,0">
<item>
<widget class="QLabel" name="label_6">
<property name="text">
<string>Pressed:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonLStick">
<property name="text">
<string/>
</property>
</widget>
</item>
</layout>
</item>
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout_31">
<item>
<widget class="QLabel" name="label_9">
<property name="text">
<string>Modifier:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonLStickMod">
<property name="text">
<string/>
</property>
@@ -364,10 +537,13 @@
</layout>
</widget>
</item>
<item row="2" column="0">
<item row="1" column="1">
<widget class="QGroupBox" name="faceButtons_5">
<property name="title">
<string>C-Stick</string>
<string>Right Stick</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
<property name="flat">
<bool>false</bool>
@@ -376,17 +552,17 @@
<bool>false</bool>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<layout class="QVBoxLayout" name="verticalLayout_21">
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_24">
<item>
<widget class="QLabel" name="label_25">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Left:</string>
<string>Down:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCStickLeft">
<widget class="QPushButton" name="buttonRStickDown">
<property name="text">
<string/>
</property>
@@ -404,7 +580,7 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCStickRight">
<widget class="QPushButton" name="buttonRStickRight">
<property name="text">
<string/>
</property>
@@ -422,7 +598,7 @@
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCStickUp">
<widget class="QPushButton" name="buttonRStickUp">
<property name="text">
<string/>
</property>
@@ -430,50 +606,17 @@
</item>
</layout>
</item>
<item row="1" column="1">
<layout class="QVBoxLayout" name="verticalLayout_24">
<item>
<widget class="QLabel" name="label_26">
<property name="text">
<string>Down:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCStickDown">
<property name="text">
<string/>
</property>
</widget>
</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">
<layout class="QVBoxLayout" name="verticalLayout_21">
<item>
<widget class="QLabel" name="label_29">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Start:</string>
<string>Left:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonStart">
<widget class="QPushButton" name="buttonRStickLeft">
<property name="text">
<string/>
</property>
@@ -481,17 +624,17 @@
</item>
</layout>
</item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout_26">
<item row="2" column="1">
<layout class="QVBoxLayout" name="verticalLayout_32">
<item>
<widget class="QLabel" name="label_30">
<widget class="QLabel" name="label_10">
<property name="text">
<string>Select:</string>
<string>Modifier:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonSelect">
<widget class="QPushButton" name="buttonRStickMod">
<property name="text">
<string/>
</property>
@@ -499,35 +642,17 @@
</item>
</layout>
</item>
<item row="1" column="0">
<layout class="QVBoxLayout" name="verticalLayout_27">
<item row="2" column="0">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="QLabel" name="label_31">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Home:</string>
<string>Pressed:</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_36">
<property name="text">
<string>Circle Mod:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="buttonCircleMod">
<widget class="QPushButton" name="buttonRStick">
<property name="text">
<string/>
</property>

View File

@@ -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.