Compare commits

..

1 Commits

Author SHA1 Message Date
Evan Amara
0e1c6448d0 Remove Example Text From license.txt
The example text is not supposed to be included with the license file and should be removed.
2018-01-16 16:01:21 -05:00
71 changed files with 521 additions and 1087 deletions

View File

@@ -1,14 +1,6 @@
language: cpp
matrix:
include:
- os: linux
env: NAME="clang-format"
dist: trusty
addons:
apt:
packages:
- clang-format-3.9
script: "./.travis/clang-format/script.sh"
- os: linux
env: NAME="linux build"
sudo: required
@@ -28,6 +20,14 @@ matrix:
install: "./.travis/macos/deps.sh"
script: "./.travis/macos/build.sh"
after_success: "./.travis/macos/upload.sh"
- os: linux
env: NAME="clang-format"
dist: trusty
addons:
apt:
packages:
- clang-format-3.9
script: "./.travis/clang-format/script.sh"
deploy:
provider: releases

View File

@@ -2,4 +2,3 @@
brew update
brew install dylibbundler p7zip qt5 sdl2
brew outdated cmake || brew upgrade cmake

View File

@@ -278,62 +278,3 @@ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -43,7 +43,6 @@ namespace Log {
SUB(HW, LCD) \
SUB(HW, GPU) \
SUB(HW, AES) \
CLS(IPC) \
CLS(Frontend) \
CLS(Render) \
SUB(Render, Software) \
@@ -92,8 +91,8 @@ const char* GetLevelName(Level log_level) {
Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr,
const char* function, const char* format, va_list args) {
using std::chrono::duration_cast;
using std::chrono::steady_clock;
using std::chrono::duration_cast;
static steady_clock::time_point time_origin = steady_clock::now();

View File

@@ -60,7 +60,6 @@ enum class Class : ClassType {
HW_LCD, ///< LCD register emulation
HW_GPU, ///< GPU control emulation
HW_AES, ///< AES engine emulation
IPC, ///< IPC interface
Frontend, ///< Emulator UI
Render, ///< Emulator video output and hardware acceleration
Render_Software, ///< Software renderer backend

View File

@@ -37,8 +37,6 @@ set(SRCS
hle/kernel/wait_object.cpp
hle/lock.cpp
hle/romfs.cpp
hle/service/acc/acc.cpp
hle/service/acc/acc_u0.cpp
hle/service/am/am.cpp
hle/service/am/applet_oe.cpp
hle/service/aoc/aoc_u.cpp
@@ -50,14 +48,15 @@ set(SRCS
hle/service/nvdrv/devices/nvdisp_disp0.cpp
hle/service/nvdrv/devices/nvhost_as_gpu.cpp
hle/service/nvdrv/devices/nvmap.cpp
hle/service/nvdrv/interface.cpp
hle/service/nvdrv/nvdrv.cpp
hle/service/nvdrv/nvdrv_a.cpp
hle/service/pctl/pctl.cpp
hle/service/pctl/pctl_a.cpp
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
@@ -89,7 +88,6 @@ set(HEADERS
file_sys/ivfc_archive.h
file_sys/path_parser.h
file_sys/savedata_archive.h
file_sys/title_metadata.h
frontend/emu_window.h
frontend/framebuffer_layout.h
frontend/input.h
@@ -126,8 +124,6 @@ set(HEADERS
hle/lock.h
hle/result.h
hle/romfs.h
hle/service/acc/acc.h
hle/service/acc/acc_u0.h
hle/service/am/am.h
hle/service/am/applet_oe.h
hle/service/aoc/aoc_u.h
@@ -140,14 +136,15 @@ set(HEADERS
hle/service/nvdrv/devices/nvdisp_disp0.h
hle/service/nvdrv/devices/nvhost_as_gpu.h
hle/service/nvdrv/devices/nvmap.h
hle/service/nvdrv/interface.h
hle/service/nvdrv/nvdrv.h
hle/service/nvdrv/nvdrv_a.h
hle/service/pctl/pctl.h
hle/service/pctl/pctl_a.h
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

@@ -39,8 +39,7 @@ public:
Run(1);
}
virtual void MapBackingMemory(VAddr address, size_t size, u8* memory,
Kernel::VMAPermission perms) {}
virtual void MapBackingMemory(VAddr address, size_t size, u8* memory, Kernel::VMAPermission perms) {}
/// Clear all instruction cache
virtual void ClearInstructionCache() = 0;

View File

@@ -4,7 +4,6 @@
#pragma once
#include <array>
#include <string>
#include <vector>
#include "common/common_types.h"

View File

@@ -905,7 +905,7 @@ void ToggleServer(bool status) {
server_enabled = status;
// Start server
if (!IsConnected() && Core::System::GetInstance().IsPoweredOn()) {
if (!IsConnected() && Core::System().GetInstance().IsPoweredOn()) {
Init();
}
} else {

View File

@@ -19,6 +19,7 @@ constexpr size_t COMMAND_BUFFER_LENGTH = 0x100 / sizeof(u32);
// TODO(yuriks): These will probably go away once translation is implemented inside the kernel.
constexpr auto ERR_INVALID_HANDLE = Kernel::ERR_INVALID_HANDLE_OS;
enum class ControlCommand : u32 {
ConvertSessionToDomain = 0,
ConvertDomainToSession = 1,
@@ -80,13 +81,13 @@ struct BufferDescriptorX {
u32_le address_bits_0_31;
u32_le Counter() const {
u32_le counter{counter_bits_0_5};
u32_le counter{ counter_bits_0_5 };
counter |= counter_bits_9_11 << 9;
return counter;
}
VAddr Address() const {
VAddr address{address_bits_0_31};
VAddr address{ address_bits_0_31 };
address |= static_cast<VAddr>(address_bits_32_35) << 32;
address |= static_cast<VAddr>(address_bits_36_38) << 36;
return address;
@@ -106,14 +107,14 @@ struct BufferDescriptorABW {
};
VAddr Address() const {
VAddr address{address_bits_0_31};
VAddr address{ address_bits_0_31 };
address |= static_cast<VAddr>(address_bits_32_35) << 32;
address |= static_cast<VAddr>(address_bits_36_38) << 36;
return address;
}
u64 Size() const {
u64 size{size_bits_0_31};
u64 size{ size_bits_0_31 };
size |= static_cast<u64>(size_bits_32_35) << 32;
return size;
}
@@ -129,7 +130,7 @@ struct BufferDescriptorC {
};
VAddr Address() const {
VAddr address{address_bits_0_31};
VAddr address{ address_bits_0_31 };
address |= static_cast<VAddr>(address_bits_32_47) << 32;
return address;
}
@@ -143,11 +144,6 @@ struct DataPayloadHeader {
static_assert(sizeof(DataPayloadHeader) == 8, "DataPayloadRequest size is incorrect");
struct DomainMessageHeader {
enum class CommandType : u32_le {
SendMessage = 1,
CloseVirtualHandle = 2,
};
union {
// Used when responding to an IPC request, Server -> Client.
struct {
@@ -158,7 +154,7 @@ struct DomainMessageHeader {
// Used when performing an IPC request, Client -> Server.
struct {
union {
BitField<0, 8, CommandType> command;
BitField<0, 8, u32_le> command;
BitField<16, 16, u32_le> size;
};
u32_le object_id;

View File

@@ -9,13 +9,10 @@
#include <type_traits>
#include <utility>
#include "core/hle/ipc.h"
#include "core/hle/kernel/client_port.h"
#include "core/hle/kernel/client_session.h"
#include "core/hle/kernel/domain.h"
#include "core/hle/kernel/handle_table.h"
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/server_port.h"
namespace IPC {
@@ -66,20 +63,13 @@ public:
: RequestHelperBase(context) {
memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH);
context.ClearIncomingObjects();
IPC::CommandHeader header{};
// The entire size of the raw data section in u32 units, including the 16 bytes of mandatory
// padding.
u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size;
if (context.IsDomain()) {
if (context.IsDomain())
raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects;
} else {
// If we're not in a domain, turn the domain object parameters into move handles.
num_handles_to_move += num_domain_objects;
num_domain_objects = 0;
}
header.data_size.Assign(raw_data_size);
if (num_handles_to_copy || num_handles_to_move) {
@@ -110,15 +100,7 @@ public:
template <class T, class... Args>
void PushIpcInterface(Args&&... args) {
auto iface = std::make_shared<T>(std::forward<Args>(args)...);
if (context->IsDomain()) {
context->AddDomainObject(std::move(iface));
} else {
auto port = iface->CreatePort();
auto session = port->Connect();
ASSERT(session.Succeeded());
context->AddMoveObject(std::move(session).Unwrap());
}
context->AddDomainObject(std::make_shared<T>(std::forward<Args>(args)...));
}
// Validate on destruction, as there shouldn't be any case where we don't want it

View File

@@ -2,8 +2,6 @@
// 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/kernel/client_port.h"
#include "core/hle/kernel/domain.h"
#include "core/hle/kernel/handle_table.h"
@@ -38,24 +36,7 @@ ResultCode Domain::SendSyncRequest(SharedPtr<Thread> thread) {
if (domain_message_header) {
// If there is a DomainMessageHeader, then this is CommandType "Request"
const u32 object_id{context.GetDomainMessageHeader()->object_id};
switch (domain_message_header->command) {
case IPC::DomainMessageHeader::CommandType::SendMessage:
return request_handlers[object_id - 1]->HandleSyncRequest(context);
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x%08X", object_id);
request_handlers[object_id - 1] = nullptr;
IPC::RequestBuilder rb{context, 2};
rb.Push(RESULT_SUCCESS);
return RESULT_SUCCESS;
}
}
LOG_CRITICAL(IPC, "Unknown domain command=%d", domain_message_header->command.Value());
UNIMPLEMENTED();
return request_handlers[object_id - 1]->HandleSyncRequest(context);
}
return request_handlers.front()->HandleSyncRequest(context);
}

View File

@@ -102,21 +102,13 @@ void HLERequestContext::ParseCommandBuffer(u32_le* src_cmdbuf, bool incoming) {
data_payload_header =
std::make_unique<IPC::DataPayloadHeader>(rp.PopRaw<IPC::DataPayloadHeader>());
data_payload_offset = rp.GetCurrentOffset();
if (domain_message_header &&
domain_message_header->command ==
IPC::DomainMessageHeader::CommandType::CloseVirtualHandle) {
// CloseVirtualHandle command does not have SFC* or any data
return;
}
if (incoming) {
ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'I'));
} else {
ASSERT(data_payload_header->magic == Common::MakeMagic('S', 'F', 'C', 'O'));
}
data_payload_offset = rp.GetCurrentOffset();
command = rp.Pop<u32_le>();
rp.Skip(1, false); // The command is actually an u64, but we don't use the high part.
}

View File

@@ -151,13 +151,13 @@ public:
return domain != nullptr;
}
template <typename T>
template<typename T>
SharedPtr<T> GetCopyObject(size_t index) {
ASSERT(index < copy_objects.size());
return DynamicObjectCast<T>(copy_objects[index]);
}
template <typename T>
template<typename T>
SharedPtr<T> GetMoveObject(size_t index) {
ASSERT(index < move_objects.size());
return DynamicObjectCast<T>(move_objects[index]);
@@ -175,14 +175,6 @@ public:
domain_objects.emplace_back(std::move(object));
}
/// Clears the list of objects so that no lingering objects are written accidentally to the
/// response buffer.
void ClearIncomingObjects() {
move_objects.clear();
copy_objects.clear();
domain_objects.clear();
}
private:
std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf;
SharedPtr<Kernel::Domain> domain;

View File

@@ -105,6 +105,7 @@ public:
UNREACHABLE();
}
public:
static unsigned int next_object_id;

View File

@@ -95,8 +95,10 @@ MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
}
}
void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {}
void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {
}
void MapSharedPages(VMManager& address_space) {}
void MapSharedPages(VMManager& address_space) {
}
} // namespace Kernel

View File

@@ -41,9 +41,9 @@ public:
return HANDLE_TYPE;
}
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
VAddr guest_addr; ///< Address of the guest mutex value
u32 priority; ///< The priority of the mutex, used for priority inheritance.
std::string name; ///< Name of mutex (optional)
VAddr guest_addr; ///< Address of the guest mutex value
/**
* Elevate the mutex priority to the best priority

View File

@@ -131,8 +131,6 @@ public:
/// Bitmask of allowed CPUs that this process' threads can run on. TODO(Subv): Actually parse
/// this value from the process header.
u32 allowed_processor_mask = THREADPROCESSORID_DEFAULT_MASK;
u32 allowed_thread_priority_mask = 0xFFFFFFFF;
u32 is_virtual_address_memory_enabled = 0;
/// Current status of the process
ProcessStatus status;

View File

@@ -255,8 +255,9 @@ static ResultCode CancelSynchronization(Handle thread_handle) {
/// Attempts to locks a mutex, creating it if it does not already exist
static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr,
Handle requesting_thread_handle) {
LOG_TRACE(Kernel_SVC, "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, "
"requesting_current_thread_handle=0x%08X",
LOG_TRACE(Kernel_SVC,
"called holding_thread_handle=0x%08X, mutex_addr=0x%llx, "
"requesting_current_thread_handle=0x%08X",
holding_thread_handle, mutex_addr, requesting_thread_handle);
SharedPtr<Thread> holding_thread = g_handle_table.Get<Thread>(holding_thread_handle);
@@ -304,27 +305,14 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id,
info_sub_id, handle);
ASSERT(handle == 0 || handle == CurrentProcess);
auto& vm_manager = g_current_process->vm_manager;
switch (static_cast<GetInfoType>(info_id)) {
case GetInfoType::AllowedCpuIdBitmask:
*result = g_current_process->allowed_processor_mask;
break;
case GetInfoType::AllowedThreadPrioBitmask:
*result = g_current_process->allowed_thread_priority_mask;
break;
case GetInfoType::MapRegionBaseAddr:
*result = vm_manager.GetAddressSpaceBaseAddr();
break;
case GetInfoType::MapRegionSize:
*result = vm_manager.GetAddressSpaceSize();
break;
case GetInfoType::HeapRegionBaseAddr:
*result = vm_manager.GetNewMapRegionBaseAddr() + vm_manager.GetNewMapRegionSize();
break;
case GetInfoType::HeapRegionSize:
*result = Memory::HEAP_SIZE;
break;
case GetInfoType::TotalMemoryUsage:
*result = vm_manager.GetTotalMemoryUsage();
break;
@@ -346,18 +334,6 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id)
case GetInfoType::NewMapRegionSize:
*result = vm_manager.GetNewMapRegionSize();
break;
case GetInfoType::IsVirtualAddressMemoryEnabled:
*result = g_current_process->is_virtual_address_memory_enabled;
break;
case GetInfoType::TitleId:
LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0");
*result = 0;
break;
case GetInfoType::PrivilegedProcessId:
LOG_WARNING(Kernel_SVC,
"(STUBBED) Attempted to query priviledged process id bounds, returned 0");
*result = 0;
break;
default:
UNIMPLEMENTED();
}
@@ -546,8 +522,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
Core::System::GetInstance().PrepareReschedule();
LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
"threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X",
LOG_TRACE(Kernel_SVC,
"called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, "
"threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X",
entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle);
return RESULT_SUCCESS;
@@ -732,11 +709,6 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
return RESULT_SUCCESS;
}
static ResultCode SetThreadCoreMask(u64, u64, u64) {
LOG_WARNING(Kernel_SVC, "(STUBBED) called");
return RESULT_SUCCESS;
}
namespace {
struct FunctionDef {
using Func = void();
@@ -763,7 +735,7 @@ static const FunctionDef SVC_Table[] = {
{0x0C, SvcWrap<GetThreadPriority>, "GetThreadPriority"},
{0x0D, SvcWrap<SetThreadPriority>, "SetThreadPriority"},
{0x0E, nullptr, "GetThreadCoreMask"},
{0x0F, SvcWrap<SetThreadCoreMask>, "SetThreadCoreMask"},
{0x0F, nullptr, "SetThreadCoreMask"},
{0x10, SvcWrap<GetCurrentProcessorNumber>, "GetCurrentProcessorNumber"},
{0x11, nullptr, "SignalEvent"},
{0x12, nullptr, "ClearEvent"},

View File

@@ -24,28 +24,14 @@ struct PageInfo {
enum class GetInfoType : u64 {
// 1.0.0+
AllowedCpuIdBitmask = 0,
AllowedThreadPrioBitmask = 1,
MapRegionBaseAddr = 2,
MapRegionSize = 3,
HeapRegionBaseAddr = 4,
HeapRegionSize = 5,
TotalMemoryUsage = 6,
TotalHeapUsage = 7,
IsCurrentProcessBeingDebugged = 8,
ResourceHandleLimit = 9,
IdleTickCount = 10,
RandomEntropy = 11,
PerformanceCounter = 0xF0000002,
// 2.0.0+
AddressSpaceBaseAddr = 12,
AddressSpaceSize = 13,
NewMapRegionBaseAddr = 14,
NewMapRegionSize = 15,
// 3.0.0+
IsVirtualAddressMemoryEnabled = 16,
TitleId = 18,
// 4.0.0+
PrivilegedProcessId = 19,
};
void CallSVC(u32 immediate);

View File

@@ -6,9 +6,9 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/vm_manager.h"
#include "core/core.h"
#include "core/memory.h"
#include "core/memory_setup.h"
#include "core/mmio.h"
@@ -86,8 +86,7 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
VirtualMemoryArea& final_vma = vma_handle->second;
ASSERT(final_vma.size == size);
Core::CPU().MapBackingMemory(target, size, block->data() + offset,
VMAPermission::ReadWriteExecute);
Core::CPU().MapBackingMemory(target, size, block->data() + offset, VMAPermission::ReadWriteExecute);
final_vma.type = VMAType::AllocatedMemoryBlock;
final_vma.permissions = VMAPermission::ReadWrite;
@@ -357,12 +356,12 @@ void VMManager::UpdatePageTableForVMA(const VirtualMemoryArea& vma) {
u64 VMManager::GetTotalMemoryUsage() {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0xBE000000;
return 0x400000;
}
u64 VMManager::GetTotalHeapUsage() {
LOG_WARNING(Kernel, "(STUBBED) called");
return 0x0;
return 0x10000;
}
VAddr VMManager::GetAddressSpaceBaseAddr() {

View File

@@ -1,16 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/service/acc/acc.h"
#include "core/hle/service/acc/acc_u0.h"
namespace Service {
namespace Account {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<ACC_U0>()->InstallAsService(service_manager);
}
} // namespace Account
} // namespace Service

View File

@@ -1,16 +0,0 @@
// 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 Account {
/// Registers all ACC services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
} // namespace Account
} // namespace Service

View File

@@ -1,26 +0,0 @@
// 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/acc/acc_u0.h"
namespace Service {
namespace Account {
void ACC_U0::InitializeApplicationInfo(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
ACC_U0::ACC_U0() : ServiceFramework("acc:u0") {
static const FunctionInfo functions[] = {
{100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
};
RegisterHandlers(functions);
}
} // namespace Account
} // namespace Service

View File

@@ -6,7 +6,6 @@
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/service/am/applet_oe.h"
#include "core/hle/service/apm/apm.h"
namespace Service {
namespace AM {
@@ -55,14 +54,7 @@ class ISelfController final : public ServiceFramework<ISelfController> {
public:
ISelfController() : ServiceFramework("ISelfController") {
static const FunctionInfo functions[] = {
{11, &ISelfController::SetOperationModeChangedNotification,
"SetOperationModeChangedNotification"},
{12, &ISelfController::SetPerformanceModeChangedNotification,
"SetPerformanceModeChangedNotification"},
{13, &ISelfController::SetFocusHandlingMode, "SetFocusHandlingMode"},
{14, &ISelfController::SetRestartMessageEnabled, "SetRestartMessageEnabled"},
{16, &ISelfController::SetOutOfFocusSuspendingEnabled,
"SetOutOfFocusSuspendingEnabled"},
};
RegisterHandlers(functions);
}
@@ -72,62 +64,11 @@ private:
// Takes 3 input u8s with each field located immediately after the previous u8, these are
// bool flags. No output.
IPC::RequestParser rp{ctx};
struct FocusHandlingModeParams {
u8 unknown0;
u8 unknown1;
u8 unknown2;
};
auto flags = rp.PopRaw<FocusHandlingModeParams>();
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called");
}
void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called");
}
void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
bool flag = rp.Pop<bool>();
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
}
void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
bool flag = rp.Pop<bool>();
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag));
}
void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) {
// Takes 3 input u8s with each field located immediately after the previous u8, these are
// bool flags. No output.
IPC::RequestParser rp{ctx};
bool enabled = rp.Pop<bool>();
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled));
}
};
class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> {
@@ -136,8 +77,6 @@ public:
static const FunctionInfo functions[] = {
{0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"},
{1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"},
{5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"},
{6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"},
{9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"},
};
RegisterHandlers(functions);
@@ -146,16 +85,6 @@ public:
}
private:
enum class FocusState : u8 {
InFocus = 1,
NotInFocus = 2,
};
enum class OperationMode : u8 {
Handheld = 0,
Docked = 1,
};
void GetEventHandle(Kernel::HLERequestContext& ctx) {
event->Signal();
@@ -177,23 +106,7 @@ private:
void GetCurrentFocusState(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(FocusState::InFocus));
LOG_WARNING(Service, "(STUBBED) called");
}
void GetOperationMode(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u8>(OperationMode::Handheld));
LOG_WARNING(Service, "(STUBBED) called");
}
void GetPerformanceMode(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld));
rb.Push<u32>(1); // 1: In focus, 2/3: Out of focus(running in "background")
LOG_WARNING(Service, "(STUBBED) called");
}
@@ -206,10 +119,6 @@ public:
IApplicationFunctions() : ServiceFramework("IApplicationFunctions") {
static const FunctionInfo functions[] = {
{22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
{66, &IApplicationFunctions::InitializeGamePlayRecording,
"InitializeGamePlayRecording"},
{67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"},
{40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"},
};
RegisterHandlers(functions);
}
@@ -227,27 +136,6 @@ private:
LOG_WARNING(Service, "(STUBBED) called, result=0x%08X", result);
}
void InitializeGamePlayRecording(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called");
}
void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called");
}
void NotifyRunning(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u8>(0); // Unknown, seems to be ignored by official processes
LOG_WARNING(Service, "(STUBBED) called");
}
};
class ILibraryAppletCreator final : public ServiceFramework<ILibraryAppletCreator> {

View File

@@ -13,54 +13,13 @@ void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<APM>()->InstallAsService(service_manager);
}
class ISession final : public ServiceFramework<ISession> {
public:
ISession() : ServiceFramework("ISession") {
static const FunctionInfo functions[] = {
{0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"},
{1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"},
};
RegisterHandlers(functions);
}
private:
void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
u32 config = rp.Pop<u32>();
IPC::RequestBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
LOG_WARNING(Service, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode), config);
}
void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
auto mode = static_cast<PerformanceMode>(rp.Pop<u32>());
IPC::RequestBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0); // Performance configuration
LOG_WARNING(Service, "(STUBBED) called mode=%u", static_cast<u32>(mode));
}
};
APM::APM() : ServiceFramework("apm") {
static const FunctionInfo functions[] = {
{0x00000000, &APM::OpenSession, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"},
{0x00000000, nullptr, "OpenSession"},
{0x00000001, nullptr, "GetPerformanceMode"},
};
RegisterHandlers(functions);
}
void APM::OpenSession(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ISession>();
}
} // namespace APM
} // namespace Service

View File

@@ -9,18 +9,10 @@
namespace Service {
namespace APM {
enum class PerformanceMode : u8 {
Handheld = 0,
Docked = 1,
};
class APM final : public ServiceFramework<APM> {
public:
APM();
~APM() = default;
private:
void OpenSession(Kernel::HLERequestContext& ctx);
};
/// Registers all AM services with the specified service manager.

View File

@@ -18,9 +18,9 @@ namespace HID {
// Updating period for each HID device.
// TODO(shinyquagsire23): These need better values.
constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 10000;
constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 10000;
constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 10000;
constexpr u64 pad_update_ticks = BASE_CLOCK_RATE / 234;
constexpr u64 accelerometer_update_ticks = BASE_CLOCK_RATE / 104;
constexpr u64 gyroscope_update_ticks = BASE_CLOCK_RATE / 101;
class IAppletResource final : public ServiceFramework<IAppletResource> {
public:
@@ -65,71 +65,44 @@ private:
if (is_device_reload_pending.exchange(false))
LoadInputDevices();
// Set up controllers as neon red+blue Joy-Con attached to console
ControllerHeader& controller_header = mem->controllers[Controller_Handheld].header;
controller_header.type = ControllerType_Handheld | ControllerType_JoyconPair;
controller_header.single_colors_descriptor = ColorDesc_ColorsNonexistent;
controller_header.right_color_body = JOYCON_BODY_NEON_RED;
controller_header.right_color_buttons = JOYCON_BUTTONS_NEON_RED;
controller_header.left_color_body = JOYCON_BODY_NEON_BLUE;
controller_header.left_color_buttons = JOYCON_BUTTONS_NEON_BLUE;
// 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());
for (int layoutIdx = 0; layoutIdx < HID_NUM_LAYOUTS; layoutIdx++) {
ControllerLayout& layout = mem->controllers[Controller_Handheld].layouts[layoutIdx];
layout.header.num_entries = HID_NUM_ENTRIES;
layout.header.max_entry_index = HID_NUM_ENTRIES - 1;
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());
// HID shared memory stores the state of the past 17 samples in a circlular buffer,
// each with a timestamp in number of samples since boot.
layout.header.timestamp_ticks = CoreTiming::GetTicks();
layout.header.latest_entry = (layout.header.latest_entry + 1) % HID_NUM_ENTRIES;
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());
ControllerInputEntry& entry = layout.entries[layout.header.latest_entry];
entry.connection_state = ConnectionState_Connected | ConnectionState_Wired;
entry.timestamp++;
entry.timestamp_2++; // TODO(shinyquagsire23): Is this always identical to timestamp?
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());
// TODO(shinyquagsire23): Set up some LUTs for each layout mapping in the future?
// For now everything is just the default handheld layout, but split Joy-Con will
// rotate the face buttons and directions for certain layouts.
ControllerPadState& state = entry.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.sl.Assign(buttons[SL - BUTTON_HID_BEGIN]->GetStatus());
state.sr.Assign(buttons[SR - 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());
// TODO(shinyquagsire23): Analog stick vals
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 pad info proper, (circular buffers, timestamps, layouts)
// TODO(shinyquagsire23): Update touch info

View File

@@ -12,16 +12,6 @@ namespace HID {
// Begin enums and output structs
constexpr u32 HID_NUM_ENTRIES = 17;
constexpr u32 HID_NUM_LAYOUTS = 7;
constexpr s32 HID_JOYSTICK_MAX = 0x8000;
constexpr s32 HID_JOYSTICK_MIN = -0x8000;
constexpr u32 JOYCON_BODY_NEON_RED = 0xFF3C28;
constexpr u32 JOYCON_BUTTONS_NEON_RED = 0x1E0A0A;
constexpr u32 JOYCON_BODY_NEON_BLUE = 0x0AB9E6;
constexpr u32 JOYCON_BUTTONS_NEON_BLUE = 0x001E1E;
enum ControllerType : u32 {
ControllerType_ProController = 1 << 0,
ControllerType_Handheld = 1 << 1,
@@ -67,10 +57,10 @@ enum ControllerID {
// Begin TouchScreen
struct TouchScreenHeader {
u64 timestamp_ticks;
u64 num_entries;
u64 latest_entry;
u64 max_entry_index;
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
u64 timestamp;
};
static_assert(sizeof(TouchScreenHeader) == 0x28,
@@ -78,7 +68,7 @@ static_assert(sizeof(TouchScreenHeader) == 0x28,
struct TouchScreenEntryHeader {
u64 timestamp;
u64 num_touches;
u64 numTouches;
};
static_assert(sizeof(TouchScreenEntryHeader) == 0x10,
"HID touch screen entry header structure has incorrect size");
@@ -86,11 +76,11 @@ static_assert(sizeof(TouchScreenEntryHeader) == 0x10,
struct TouchScreenEntryTouch {
u64 timestamp;
u32 padding;
u32 touch_index;
u32 touchIndex;
u32 x;
u32 y;
u32 diameter_x;
u32 diameter_y;
u32 diameterX;
u32 diameterY;
u32 angle;
u32 padding_2;
};
@@ -117,10 +107,10 @@ static_assert(sizeof(TouchScreen) == 0x3000, "HID touch screen structure has inc
// Begin Mouse
struct MouseHeader {
u64 timestamp_ticks;
u64 num_entries;
u64 latest_entry;
u64 max_entry_index;
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
};
static_assert(sizeof(MouseHeader) == 0x20, "HID mouse header structure has incorrect size");
@@ -142,10 +132,10 @@ struct MouseEntry {
u64 timestamp_2;
u32 x;
u32 y;
u32 velocity_x;
u32 velocity_y;
u32 scroll_velocity_x;
u32 scroll_velocity_y;
u32 velocityX;
u32 velocityY;
u32 scrollVelocityX;
u32 scrollVelocityY;
MouseButtonState buttons;
};
static_assert(sizeof(MouseEntry) == 0x30, "HID mouse entry structure has incorrect size");
@@ -162,10 +152,10 @@ static_assert(sizeof(Mouse) == 0x400, "HID mouse structure has incorrect size");
// Begin Keyboard
struct KeyboardHeader {
u64 timestamp_ticks;
u64 num_entries;
u64 latest_entry;
u64 max_entry_index;
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
};
static_assert(sizeof(KeyboardHeader) == 0x20, "HID keyboard header structure has incorrect size");
@@ -217,24 +207,24 @@ static_assert(sizeof(ControllerMAC) == 0x20, "HID controller MAC structure has i
struct ControllerHeader {
u32 type;
u32 is_half;
u32 single_colors_descriptor;
u32 single_color_body;
u32 single_color_buttons;
u32 split_colors_descriptor;
u32 left_color_body;
u32 left_color_buttons;
u32 right_color_body;
u32 right_color_buttons;
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 timestamp_ticks;
u64 num_entries;
u64 latest_entry;
u64 max_entry_index;
u64 timestampTicks;
u64 numEntries;
u64 latestEntry;
u64 maxEntryIndex;
};
static_assert(sizeof(ControllerLayoutHeader) == 0x20,
"HID controller layout header structure has incorrect size");
@@ -284,11 +274,11 @@ struct ControllerInputEntry {
u64 timestamp;
u64 timestamp_2;
ControllerPadState buttons;
u32 joystick_left_x;
u32 joystick_left_y;
u32 joystick_right_x;
u32 joystick_right_y;
u64 connection_state;
u32 joystickLeftX;
u32 joystickLeftY;
u32 joystickRightX;
u32 joystickRightY;
u64 connectionState;
};
static_assert(sizeof(ControllerInputEntry) == 0x30,
"HID controller input entry structure has incorrect size");
@@ -304,8 +294,8 @@ struct Controller {
ControllerHeader header;
std::array<ControllerLayout, 7> layouts;
std::array<u8, 0x2a70> unk_1;
ControllerMAC mac_left;
ControllerMAC mac_right;
ControllerMAC macLeft;
ControllerMAC macRight;
std::array<u8, 0xdf8> unk_2;
};
static_assert(sizeof(Controller) == 0x5000, "HID controller structure has incorrect size");
@@ -317,17 +307,17 @@ struct SharedMemory {
TouchScreen touchscreen;
Mouse mouse;
Keyboard keyboard;
std::array<u8, 0x400> unk_section_1;
std::array<u8, 0x400> unk_section_2;
std::array<u8, 0x400> unk_section_3;
std::array<u8, 0x400> unk_section_4;
std::array<u8, 0x200> unk_section_5;
std::array<u8, 0x200> unk_section_6;
std::array<u8, 0x200> unk_section_7;
std::array<u8, 0x800> unk_section_8;
std::array<u8, 0x4000> controller_serials;
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> unk_section_9;
std::array<u8, 0x4600> unkSection9;
};
static_assert(sizeof(SharedMemory) == 0x40000, "HID Shared Memory structure has incorrect size");

View File

@@ -8,7 +8,7 @@
#include "common/common_types.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
/// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to
@@ -29,5 +29,5 @@ public:
};
} // namespace Devices
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -4,14 +4,13 @@
#include "common/assert.h"
#include "common/logging/log.h"
#include "core/core.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
@@ -29,11 +28,9 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
using PixelFormat = RendererBase::FramebufferInfo::PixelFormat;
const RendererBase::FramebufferInfo framebuffer_info{
addr, offset, width, height, stride, static_cast<PixelFormat>(format)};
Core::System::GetInstance().perf_stats.EndGameFrame();
VideoCore::g_renderer->SwapBuffers(framebuffer_info);
}
} // namespace Devices
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -10,7 +10,7 @@
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
class nvmap;
@@ -30,5 +30,5 @@ private:
};
} // namespace Devices
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -7,7 +7,7 @@
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
@@ -16,5 +16,5 @@ u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<
}
} // namespace Devices
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -9,7 +9,7 @@
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
class nvhost_as_gpu final : public nvdevice {
@@ -21,5 +21,5 @@ public:
};
} // namespace Devices
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -9,7 +9,7 @@
#include "core/hle/service/nvdrv/devices/nvmap.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
VAddr nvmap::GetObjectAddress(u32 handle) const {
@@ -151,5 +151,5 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
}
} // namespace Devices
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -13,7 +13,7 @@
#include "core/hle/service/nvdrv/devices/nvdevice.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
class nvmap final : public nvdevice {
@@ -104,5 +104,5 @@ private:
};
} // namespace Devices
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -1,30 +0,0 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <string>
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/service.h"
namespace Service {
namespace Nvidia {
class NVDRV final : public ServiceFramework<NVDRV> {
public:
NVDRV(std::shared_ptr<Module> nvdrv, const char* name);
~NVDRV() = default;
private:
void Open(Kernel::HLERequestContext& ctx);
void Ioctl(Kernel::HLERequestContext& ctx);
void Close(Kernel::HLERequestContext& ctx);
void Initialize(Kernel::HLERequestContext& ctx);
std::shared_ptr<Module> nvdrv;
};
} // namespace Nvidia
} // namespace Service

View File

@@ -2,62 +2,19 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/interface.h"
#include "core/hle/service/nvdrv/nvdrv_a.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
std::weak_ptr<Module> nvdrv;
std::weak_ptr<NVDRV_A> nvdrv_a;
void InstallInterfaces(SM::ServiceManager& service_manager) {
auto module_ = std::make_shared<Module>();
std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager);
std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager);
nvdrv = module_;
auto nvdrv = std::make_shared<NVDRV_A>();
nvdrv->InstallAsService(service_manager);
nvdrv_a = nvdrv;
}
Module::Module() {
auto nvmap_dev = std::make_shared<Devices::nvmap>();
devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>();
devices["/dev/nvmap"] = nvmap_dev;
devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev);
}
u32 Module::Open(std::string device_name) {
ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device %s",
device_name.c_str());
auto device = devices[device_name];
u32 fd = next_fd++;
open_files[fd] = device;
return fd;
}
u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) {
auto itr = open_files.find(fd);
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
auto device = itr->second;
return device->ioctl(command, input, output);
}
ResultCode Module::Close(u32 fd) {
auto itr = open_files.find(fd);
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
open_files.erase(itr);
// TODO(flerovium): return correct result code if operation failed.
return RESULT_SUCCESS;
}
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -11,48 +11,109 @@
#include "core/hle/service/service.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
namespace Devices {
class nvdevice;
}
class Module final {
class nvdevice {
public:
Module();
~Module() = default;
virtual ~nvdevice() = default;
/// Returns a pointer to one of the available devices, identified by its name.
template <typename T>
std::shared_ptr<T> GetDevice(std::string name) {
auto itr = devices.find(name);
if (itr == devices.end())
return nullptr;
return std::static_pointer_cast<T>(itr->second);
}
virtual u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) = 0;
};
/// Opens a device node and returns a file descriptor to it.
u32 Open(std::string device_name);
/// Sends an ioctl command to the specified file descriptor.
u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output);
/// Closes a device file descriptor and returns operation success.
ResultCode Close(u32 fd);
class nvmap : public nvdevice {
public:
/// Returns the allocated address of an nvmap object given its handle.
VAddr GetObjectAddress(u32 handle) const;
u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override;
private:
// Represents an nvmap object.
struct Object {
enum class Status { Created, Allocated };
u32 id;
u32 size;
u32 flags;
u32 align;
u8 kind;
VAddr addr;
Status status;
};
u32 next_handle = 1;
u32 next_id = 1;
std::unordered_map<u32, std::shared_ptr<Object>> handles;
enum IoctlCommands {
IocCreateCommand = 0xC0080101,
IocFromIdCommand = 0xC0080103,
IocAllocCommand = 0xC0200104,
IocParamCommand = 0xC00C0109,
IocGetIdCommand = 0xC008010E
};
struct IocCreateParams {
// Input
u32_le size;
// Output
u32_le handle;
};
struct IocAllocParams {
// Input
u32_le handle;
u32_le heap_mask;
u32_le flags;
u32_le align;
u8 kind;
INSERT_PADDING_BYTES(7);
u64_le addr;
};
struct IocGetIdParams {
// Output
u32_le id;
// Input
u32_le handle;
};
struct IocFromIdParams {
// Input
u32_le id;
// Output
u32_le handle;
};
struct IocParamParams {
// Input
u32_le handle;
u32_le type;
// Output
u32_le value;
};
u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output);
u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output);
};
class nvdisp_disp0 : public nvdevice {
public:
nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {}
~nvdisp_disp0() = default;
u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override;
/// Performs a screen flip, drawing the buffer pointed to by the handle.
void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride);
private:
/// Id to use for the next open file descriptor.
u32 next_fd = 1;
/// Mapping of file descriptors to the devices they reference.
std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files;
/// Mapping of device node names to their implementation.
std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices;
std::shared_ptr<nvmap> nvmap_dev;
};
/// Registers all NVDRV services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);
extern std::weak_ptr<Module> nvdrv;
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -4,27 +4,35 @@
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/nvdrv/interface.h"
#include "core/hle/service/nvdrv/devices/nvdevice.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h"
#include "core/hle/service/nvdrv/devices/nvmap.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/nvdrv/nvdrv_a.h"
namespace Service {
namespace Nvidia {
namespace NVDRV {
void NVDRV::Open(Kernel::HLERequestContext& ctx) {
void NVDRV_A::Open(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
auto buffer = ctx.BufferDescriptorA()[0];
std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size());
u32 fd = nvdrv->Open(device_name);
auto device = devices[device_name];
u32 fd = next_fd++;
open_files[fd] = device;
IPC::RequestBuilder rb{ctx, 4};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(fd);
rb.Push<u32>(0);
}
void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
@@ -38,8 +46,11 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
std::vector<u8> output(output_buffer.Size());
Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size());
auto itr = open_files.find(fd);
ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device");
u32 nv_result = nvdrv->Ioctl(fd, command, input, output);
auto device = itr->second;
u32 nv_result = device->ioctl(command, input, output);
Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size());
@@ -48,35 +59,26 @@ void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) {
rb.Push(nv_result);
}
void NVDRV::Close(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u32 fd = rp.Pop<u32>();
auto result = nvdrv->Close(fd);
IPC::RequestBuilder rb{ctx, 2};
rb.Push(result);
}
void NVDRV::Initialize(Kernel::HLERequestContext& ctx) {
void NVDRV_A::Initialize(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
rb.Push<u32>(0);
}
NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
: ServiceFramework(name), nvdrv(std::move(nvdrv)) {
NVDRV_A::NVDRV_A() : ServiceFramework("nvdrv:a") {
static const FunctionInfo functions[] = {
{0, &NVDRV::Open, "Open"},
{1, &NVDRV::Ioctl, "Ioctl"},
{2, &NVDRV::Close, "Close"},
{3, &NVDRV::Initialize, "Initialize"},
{0, &NVDRV_A::Open, "Open"},
{1, &NVDRV_A::Ioctl, "Ioctl"},
{3, &NVDRV_A::Initialize, "Initialize"},
};
RegisterHandlers(functions);
auto nvmap_dev = std::make_shared<Devices::nvmap>();
devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>();
devices["/dev/nvmap"] = nvmap_dev;
devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev);
}
} // namespace Nvidia
} // namespace NVDRV
} // namespace Service

View File

@@ -0,0 +1,51 @@
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <string>
#include "core/hle/service/nvdrv/nvdrv.h"
#include "core/hle/service/service.h"
namespace Service {
namespace NVDRV {
namespace Devices {
class nvdevice;
}
class NVDRV_A final : public ServiceFramework<NVDRV_A> {
public:
NVDRV_A();
~NVDRV_A() = default;
/// Returns a pointer to one of the available devices, identified by its name.
template <typename T>
std::shared_ptr<T> GetDevice(std::string name) {
auto itr = devices.find(name);
if (itr == devices.end())
return nullptr;
return std::static_pointer_cast<T>(itr->second);
}
private:
void Open(Kernel::HLERequestContext& ctx);
void Ioctl(Kernel::HLERequestContext& ctx);
void Initialize(Kernel::HLERequestContext& ctx);
/// Id to use for the next open file descriptor.
u32 next_fd = 1;
/// Mapping of file descriptors to the devices they reference.
std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files;
/// Mapping of device node names to their implementation.
std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices;
};
extern std::weak_ptr<NVDRV_A> nvdrv_a;
} // namespace NVDRV
} // namespace Service

View File

@@ -14,7 +14,6 @@
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/server_port.h"
#include "core/hle/kernel/thread.h"
#include "core/hle/service/acc/acc.h"
#include "core/hle/service/am/am.h"
#include "core/hle/service/aoc/aoc_u.h"
#include "core/hle/service/apm/apm.h"
@@ -165,14 +164,13 @@ void Init() {
SM::g_service_manager = std::make_shared<SM::ServiceManager>();
SM::ServiceManager::InstallInterfaces(SM::g_service_manager);
Account::InstallInterfaces(*SM::g_service_manager);
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);
Nvidia::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);

View File

@@ -2,140 +2,14 @@
// 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.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");
}
};
class ISteadyClock final : public ServiceFramework<ISteadyClock> {
public:
ISteadyClock() : ServiceFramework("ISteadyClock") {}
};
class ITimeZoneService final : public ServiceFramework<ITimeZoneService> {
public:
ITimeZoneService() : ServiceFramework("ITimeZoneService") {
static const FunctionInfo functions[] = {
{0, &ITimeZoneService::GetDeviceLocationName, "GetDeviceLocationName"},
{101, &ITimeZoneService::ToCalendarTimeWithMyRule, "ToCalendarTimeWithMyRule"},
};
RegisterHandlers(functions);
}
private:
void GetDeviceLocationName(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
LocationName name{};
IPC::RequestBuilder rb{ctx, 11};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(name);
}
void ToCalendarTimeWithMyRule(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
u64 posixTime = rp.Pop<u64>();
LOG_WARNING(Service, "(STUBBED) called, posixTime=0x%016llX", posixTime);
CalendarTime calendarTime{2018, 1, 1, 0, 0, 0};
CalendarAdditionalInfo additionalInfo{};
IPC::RequestBuilder rb{ctx, 10};
rb.Push(RESULT_SUCCESS);
rb.PushRaw(calendarTime);
rb.PushRaw(additionalInfo);
}
};
void TIME::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();
}
}
void TIME::GetStandardNetworkSystemClock(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();
}
}
void TIME::GetStandardSteadyClock(Kernel::HLERequestContext& ctx) {
auto client_port = std::make_shared<ISteadyClock>()->CreatePort();
auto session = client_port->Connect();
if (session.Succeeded()) {
LOG_DEBUG(Service, "called, initialized ISteadyClock -> session=%u",
(*session)->GetObjectId());
IPC::RequestBuilder rb{ctx, 2, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushMoveObjects(std::move(session).Unwrap());
} else {
UNIMPLEMENTED();
}
}
void TIME::GetTimeZoneService(Kernel::HLERequestContext& ctx) {
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<ITimeZoneService>();
LOG_DEBUG(Service, "called");
}
TIME::TIME(const char* name) : ServiceFramework(name) {
static const FunctionInfo functions[] = {
{0x00000000, &TIME::GetStandardUserSystemClock, "GetStandardUserSystemClock"},
{0x00000001, &TIME::GetStandardNetworkSystemClock, "GetStandardNetworkSystemClock"},
{0x00000002, &TIME::GetStandardSteadyClock, "GetStandardSteadyClock"},
{0x00000003, &TIME::GetTimeZoneService, "GetTimeZoneService"},
};
RegisterHandlers(functions);
}
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<TIME>("time:a")->InstallAsService(service_manager);
std::make_shared<TIME>("time:r")->InstallAsService(service_manager);
std::make_shared<TIME>("time:s")->InstallAsService(service_manager);
std::make_shared<TIME>("time:u")->InstallAsService(service_manager);
std::make_shared<TimeS>()->InstallAsService(service_manager);
}
} // namespace Time

View File

@@ -9,42 +9,6 @@
namespace Service {
namespace Time {
// TODO(Rozelette) RE this structure
struct LocationName {
INSERT_PADDING_BYTES(0x24);
};
static_assert(sizeof(LocationName) == 0x24, "LocationName structure has incorrect size");
struct CalendarTime {
u16_le year;
u8 month; // Starts at 1
u8 day; // Starts at 1
u8 hour;
u8 minute;
u8 second;
INSERT_PADDING_BYTES(1);
};
static_assert(sizeof(CalendarTime) == 0x8, "CalendarTime structure has incorrect size");
// TODO(Rozelette) RE this structure
struct CalendarAdditionalInfo {
INSERT_PADDING_BYTES(0x18);
};
static_assert(sizeof(CalendarAdditionalInfo) == 0x18,
"CalendarAdditionalInfo structure has incorrect size");
class TIME final : public ServiceFramework<TIME> {
public:
explicit TIME(const char* name);
~TIME() = default;
private:
void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
void GetStandardNetworkSystemClock(Kernel::HLERequestContext& ctx);
void GetStandardSteadyClock(Kernel::HLERequestContext& ctx);
void GetTimeZoneService(Kernel::HLERequestContext& ctx);
};
/// Registers all Time services with the specified service manager.
void InstallInterfaces(SM::ServiceManager& service_manager);

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

@@ -4,19 +4,20 @@
#pragma once
#include "core/hle/kernel/hle_ipc.h"
#include "core/hle/service/service.h"
namespace Service {
namespace Account {
namespace Time {
class ACC_U0 final : public ServiceFramework<ACC_U0> {
class TimeS final : public ServiceFramework<TimeS> {
public:
ACC_U0();
~ACC_U0() = default;
TimeS();
~TimeS() = default;
private:
void InitializeApplicationInfo(Kernel::HLERequestContext& ctx);
void GetStandardUserSystemClock(Kernel::HLERequestContext& ctx);
};
} // namespace Account
} // namespace Time
} // namespace Service

View File

@@ -9,7 +9,7 @@
#include "core/core_timing.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
#include "core/hle/service/nvdrv/nvdrv.h"
#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"
@@ -47,9 +47,8 @@ public:
}
std::vector<u8> ReadBlock(size_t length) {
const u8* const begin = buffer.data() + read_index;
const u8* const end = begin + length;
std::vector<u8> data(begin, end);
std::vector<u8> data(length);
std::memcpy(data.data(), buffer.data() + read_index, length);
read_index += length;
read_index = Common::AlignUp(read_index, 4);
return data;
@@ -362,7 +361,7 @@ public:
static const FunctionInfo functions[] = {
{0, &IHOSBinderDriver::TransactParcel, "TransactParcel"},
{1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"},
{2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"},
{2, nullptr, "GetNativeHandle"},
{3, nullptr, "TransactParcelAuto"},
};
RegisterHandlers(functions);
@@ -464,21 +463,6 @@ private:
rb.Push(RESULT_SUCCESS);
}
void GetNativeHandle(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
u32 id = rp.Pop<u32>();
u32 unknown = rp.Pop<u32>();
auto buffer_queue = nv_flinger->GetBufferQueue(id);
// TODO(Subv): Find out what this actually is.
LOG_WARNING(Service, "(STUBBED) called id=%u, unknown=%08X", id, unknown);
IPC::RequestBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
rb.PushCopyObjects(buffer_queue->GetNativeHandle());
}
std::shared_ptr<NVFlinger> nv_flinger;
};
@@ -581,15 +565,6 @@ void IApplicationDisplayService::GetManagerDisplayService(Kernel::HLERequestCont
rb.PushIpcInterface<IManagerDisplayService>(nv_flinger);
}
void IApplicationDisplayService::GetIndirectDisplayTransactionService(
Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestBuilder rb{ctx, 2, 0, 0, 1};
rb.Push(RESULT_SUCCESS);
rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger);
}
void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
@@ -605,15 +580,6 @@ void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) {
rb.Push<u64>(nv_flinger->OpenDisplay(name));
}
void IApplicationDisplayService::CloseDisplay(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u64 display_id = rp.Pop<u64>();
IPC::RequestBuilder rb = rp.MakeBuilder(4, 0, 0, 0);
rb.Push(RESULT_SUCCESS);
}
void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
@@ -639,40 +605,6 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) {
rb.Push<u64>(data.size());
}
void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u32 flags = rp.Pop<u32>();
u64 display_id = rp.Pop<u64>();
auto& buffer = ctx.BufferDescriptorB()[0];
// TODO(Subv): What's the difference between a Stray and a Managed layer?
u64 layer_id = nv_flinger->CreateLayer(display_id);
u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id);
NativeWindow native_window{buffer_queue_id};
auto data = native_window.Serialize();
Memory::WriteBlock(buffer.Address(), data.data(), data.size());
IPC::RequestBuilder rb = rp.MakeBuilder(6, 0, 0, 0);
rb.Push(RESULT_SUCCESS);
rb.Push(layer_id);
rb.Push<u64>(data.size());
}
void IApplicationDisplayService::DestroyStrayLayer(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
u64 layer_id = rp.Pop<u64>();
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0, 0, 0);
rb.Push(RESULT_SUCCESS);
}
void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::RequestParser rp{ctx};
@@ -701,15 +633,11 @@ IApplicationDisplayService::IApplicationDisplayService(std::shared_ptr<NVFlinger
{100, &IApplicationDisplayService::GetRelayService, "GetRelayService"},
{101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"},
{102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"},
{103, &IApplicationDisplayService::GetIndirectDisplayTransactionService,
"GetIndirectDisplayTransactionService"},
{103, nullptr, "GetIndirectDisplayTransactionService"},
{1000, nullptr, "ListDisplays"},
{1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
{1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
{2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
{2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
{2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
{2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
{5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
};
RegisterHandlers(functions);
@@ -835,12 +763,12 @@ void NVFlinger::Compose() {
auto& igbp_buffer = buffer->igbp_buffer;
// Now send the buffer to the GPU for drawing.
auto nvdrv = Nvidia::nvdrv.lock();
auto nvdrv = NVDRV::nvdrv_a.lock();
ASSERT(nvdrv);
// TODO(Subv): Support more than just disp0. The display device selection is probably based
// on which display we're drawing (Default, Internal, External, etc)
auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
auto nvdisp = nvdrv->GetDevice<NVDRV::Devices::nvdisp_disp0>("/dev/nvdisp_disp0");
ASSERT(nvdisp);
nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format,
@@ -850,9 +778,7 @@ void NVFlinger::Compose() {
}
}
BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {
native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle");
}
BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {}
void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) {
Buffer buffer{};

View File

@@ -59,16 +59,11 @@ public:
return id;
}
Kernel::SharedPtr<Kernel::Event> GetNativeHandle() const {
return native_handle;
}
private:
u32 id;
u64 layer_id;
std::vector<Buffer> queue;
Kernel::SharedPtr<Kernel::Event> native_handle;
};
struct Layer {
@@ -143,13 +138,9 @@ private:
void GetRelayService(Kernel::HLERequestContext& ctx);
void GetSystemDisplayService(Kernel::HLERequestContext& ctx);
void GetManagerDisplayService(Kernel::HLERequestContext& ctx);
void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx);
void OpenDisplay(Kernel::HLERequestContext& ctx);
void CloseDisplay(Kernel::HLERequestContext& ctx);
void SetLayerScalingMode(Kernel::HLERequestContext& ctx);
void OpenLayer(Kernel::HLERequestContext& ctx);
void CreateStrayLayer(Kernel::HLERequestContext& ctx);
void DestroyStrayLayer(Kernel::HLERequestContext& ctx);
void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx);
std::shared_ptr<NVFlinger> nv_flinger;

View File

@@ -48,9 +48,9 @@ struct Elf64_Sym {
};
static_assert(sizeof(Elf64_Sym) == 0x18, "Elf64_Sym has incorrect size.");
void Linker::WriteRelocations(std::vector<u8>& program_image, const std::vector<Symbol>& symbols,
u64 relocation_offset, u64 size, bool is_jump_relocation,
VAddr load_base) {
void Linker::WriteRelocations(std::vector<u8>& program_image,
const std::vector<Symbol>& symbols, u64 relocation_offset,
u64 size, bool is_jump_relocation, VAddr load_base) {
for (u64 i = 0; i < size; i += sizeof(Elf64_Rela)) {
Elf64_Rela rela;
std::memcpy(&rela, &program_image[relocation_offset + i], sizeof(Elf64_Rela));
@@ -90,7 +90,8 @@ void Linker::WriteRelocations(std::vector<u8>& program_image, const std::vector<
}
}
void Linker::Relocate(std::vector<u8>& program_image, u32 dynamic_section_offset, VAddr load_base) {
void Linker::Relocate(std::vector<u8>& program_image, u32 dynamic_section_offset,
VAddr load_base) {
std::map<u64, u64> dynamic;
while (dynamic_section_offset < program_image.size()) {
Elf64_Dyn dyn;
@@ -140,7 +141,8 @@ void Linker::ResolveImports() {
const auto& search = exports.find(import.first);
if (search != exports.end()) {
Memory::Write64(import.second.ea, search->second + import.second.addend);
} else {
}
else {
LOG_ERROR(Loader, "Unresolved import: %s", import.first.c_str());
}
}

View File

@@ -118,6 +118,13 @@ bool AppLoader_NRO::LoadNro(const std::string& path, VAddr load_base) {
}
program_image.resize(PageAlignSize(static_cast<u32>(program_image.size()) + bss_size));
// Relocate symbols if there was a proper MOD header - This must happen after the image has been
// loaded into memory
if (has_mod_header) {
Relocate(program_image, nro_header.module_header_offset + mod_header.dynamic_offset,
load_base);
}
// Load codeset for current process
codeset->name = path;
codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
@@ -147,6 +154,8 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(base_addr, 48, Kernel::DEFAULT_STACK_SIZE);
ResolveImports();
is_loaded = true;
return ResultStatus::Success;
}

View File

@@ -19,10 +19,7 @@ struct NsoSegmentHeader {
u32_le offset;
u32_le location;
u32_le size;
union {
u32_le alignment;
u32_le bss_size;
};
u32_le alignment;
};
static_assert(sizeof(NsoSegmentHeader) == 0x10, "NsoSegmentHeader has incorrect size.");
@@ -88,7 +85,7 @@ static constexpr u32 PageAlignSize(u32 size) {
return (size + Memory::PAGE_MASK) & ~Memory::PAGE_MASK;
}
VAddr AppLoader_NSO::LoadNso(const std::string& path, VAddr load_base) {
VAddr AppLoader_NSO::LoadNso(const std::string& path, VAddr load_base, bool relocate) {
FileUtil::IOFile file(path, "rb");
if (!file.IsOpen()) {
return {};
@@ -123,18 +120,23 @@ VAddr AppLoader_NSO::LoadNso(const std::string& path, VAddr load_base) {
// Read MOD header
ModHeader mod_header{};
// Default .bss to size in segment header if MOD0 section doesn't exist
u32 bss_size{PageAlignSize(nso_header.segments[2].bss_size)};
u32 bss_size{Memory::PAGE_SIZE}; // Default .bss to page size if MOD0 section doesn't exist
std::memcpy(&mod_header, program_image.data() + module_offset, sizeof(ModHeader));
const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')};
if (has_mod_header) {
// Resize program image to include .bss section and page align each section
bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset);
codeset->data.size += bss_size;
}
codeset->data.size += bss_size;
const u32 image_size{PageAlignSize(static_cast<u32>(program_image.size()) + bss_size)};
program_image.resize(image_size);
// Relocate symbols if there was a proper MOD header - This must happen after the image has been
// loaded into memory
if (has_mod_header && relocate) {
Relocate(program_image, module_offset + mod_header.dynamic_offset, load_base);
}
// Load codeset for current process
codeset->name = path;
codeset->memory = std::make_shared<std::vector<u8>>(std::move(program_image));
@@ -155,8 +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", "subsdk4"}) {
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);
@@ -175,6 +176,8 @@ ResultStatus AppLoader_NSO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
Kernel::ResourceLimit::GetForCategory(Kernel::ResourceLimitCategory::APPLICATION);
process->Run(Memory::PROCESS_IMAGE_VADDR, 48, Kernel::DEFAULT_STACK_SIZE);
ResolveImports();
is_loaded = true;
return ResultStatus::Success;
}

View File

@@ -18,7 +18,8 @@ namespace Loader {
class AppLoader_NSO final : public AppLoader, Linker {
public:
AppLoader_NSO(FileUtil::IOFile&& file, std::string filepath)
: AppLoader(std::move(file)), filepath(std::move(filepath)) {}
: AppLoader(std::move(file)), filepath(std::move(filepath)) {
}
/**
* Returns the type of the file
@@ -34,7 +35,7 @@ public:
ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
private:
VAddr LoadNso(const std::string& path, VAddr load_base);
VAddr LoadNso(const std::string& path, VAddr load_base, bool relocate = false);
std::string filepath;
};

View File

@@ -136,7 +136,7 @@ enum : VAddr {
/// Application heap (includes stack).
HEAP_VADDR = 0x108000000,
HEAP_SIZE = 0xF0000000,
HEAP_SIZE = 0x18000000,
HEAP_VADDR_END = HEAP_VADDR + HEAP_SIZE,
/// Area where shared memory buffers are mapped onto.
@@ -177,7 +177,7 @@ enum : VAddr {
SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE,
/// Area where TLS (Thread-Local Storage) buffers are allocated.
TLS_AREA_VADDR = 0x228000000,
TLS_AREA_VADDR = 0x1FF82000,
TLS_ENTRY_SIZE = 0x200,
/// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS.

View File

@@ -69,7 +69,7 @@ PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) {
double PerfStats::GetLastFrameTimeScale() {
std::lock_guard<std::mutex> lock(object_mutex);
constexpr double FRAME_LENGTH = 1.0 / 60;
constexpr double FRAME_LENGTH = 1.0 / 60; // GPU::SCREEN_REFRESH_RATE;
return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH;
}

View File

@@ -61,8 +61,7 @@ private:
// Loads framebuffer from emulated memory into the display information structure
void LoadFBToScreenInfo(const FramebufferInfo& framebuffer_info, ScreenInfo& screen_info);
// Fills active OpenGL texture with the given RGBA color.
void LoadColorToActiveGLTexture(u8 color_r, u8 color_g, u8 color_b, u8 color_a,
const TextureInfo& texture);
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

@@ -66,7 +66,11 @@ file(GLOB_RECURSE THEMES ${CMAKE_SOURCE_DIR}/dist/qt_themes/*)
create_directory_groups(${SRCS} ${HEADERS} ${UIS})
qt5_wrap_ui(UI_HDRS ${UIS})
if (Qt5_FOUND)
qt5_wrap_ui(UI_HDRS ${UIS})
else()
qt4_wrap_ui(UI_HDRS ${UIS})
endif()
if (APPLE)
set(MACOSX_ICON "../../dist/yuzu.icns")

View File

@@ -9,7 +9,7 @@
AboutDialog::AboutDialog(QWidget* parent) : QDialog(parent), ui(new Ui::AboutDialog) {
ui->setupUi(this);
ui->labelBuildInfo->setText(ui->labelBuildInfo->text().arg(
Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));
Common::g_build_name, Common::g_scm_branch, Common::g_scm_desc));
}
AboutDialog::~AboutDialog() {}

View File

@@ -1,8 +1,12 @@
#include <QApplication>
#include <QHBoxLayout>
#include <QKeyEvent>
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
// Required for screen DPI information
#include <QScreen>
#include <QWindow>
#endif
#include "common/microprofile.h"
#include "common/scm_rev.h"
@@ -116,13 +120,15 @@ GRenderWindow::~GRenderWindow() {
void GRenderWindow::moveContext() {
DoneCurrent();
// We need to move GL context to the swapping thread in Qt5
#if QT_VERSION > QT_VERSION_CHECK(5, 0, 0)
// If the thread started running, move the GL Context to the new thread. Otherwise, move it
// back.
auto thread = (QThread::currentThread() == qApp->thread() && emu_thread != nullptr)
? emu_thread
: qApp->thread();
child->context()->moveToThread(thread);
#endif
}
void GRenderWindow::SwapBuffers() {
@@ -185,8 +191,12 @@ QByteArray GRenderWindow::saveGeometry() {
}
qreal GRenderWindow::windowPixelRatio() {
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
// windowHandle() might not be accessible until the window is displayed to screen.
return windowHandle() ? windowHandle()->screen()->devicePixelRatio() : 1.0f;
#else
return 1.0f;
#endif
}
void GRenderWindow::closeEvent(QCloseEvent* event) {
@@ -289,7 +299,9 @@ void GRenderWindow::OnEmulationStopping() {
void GRenderWindow::showEvent(QShowEvent* event) {
QWidget::showEvent(event);
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
// windowHandle() is not initialized until the Window is shown, so we connect it here.
connect(this->windowHandle(), SIGNAL(screenChanged(QScreen*)), this,
SLOT(OnFramebufferSizeChanged()), Qt::UniqueConnection);
#endif
}

View File

@@ -18,10 +18,10 @@ 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_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,
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{{

View File

@@ -6,6 +6,7 @@
#include "ui_configure_debug.h"
#include "yuzu/configuration/configure_debug.h"
ConfigureDebug::ConfigureDebug(QWidget* parent) : QWidget(parent), ui(new Ui::ConfigureDebug) {
ui->setupUi(this);
this->setConfiguration();

View File

@@ -13,24 +13,24 @@
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_2">
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>GDB</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="label_1">
<widget class="QLabel">
<property name="text">
<string>The GDB Stub only works correctly when the CPU JIT is off.</string>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_1">
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QCheckBox" name="toggle_gdbstub">
<property name="text">
@@ -52,7 +52,7 @@
</spacer>
</item>
<item>
<widget class="QLabel" name="label_2">
<widget class="QLabel" name="label">
<property name="text">
<string>Port:</string>
</property>

View File

@@ -7,6 +7,7 @@
#include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_dialog.h"
ConfigureDialog::ConfigureDialog(QWidget* parent) : QDialog(parent), ui(new Ui::ConfigureDialog) {
ui->setupUi(this);
this->setConfiguration();

View File

@@ -42,52 +42,6 @@ static void SetAnalogButton(const Common::ParamPackage& input_param,
analog_param.Set(button_name, input_param.Serialize());
}
static QString ButtonToText(const Common::ParamPackage& param) {
if (!param.Has("engine")) {
return QObject::tr("[not set]");
} else if (param.Get("engine", "") == "keyboard") {
return getKeyName(param.Get("code", 0));
} else if (param.Get("engine", "") == "sdl") {
QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str());
if (param.Has("hat")) {
text += QString(QObject::tr(" Hat %1 %2"))
.arg(param.Get("hat", "").c_str(), param.Get("direction", "").c_str());
}
if (param.Has("axis")) {
text += QString(QObject::tr(" Axis %1%2"))
.arg(param.Get("axis", "").c_str(), param.Get("direction", "").c_str());
}
if (param.Has("button")) {
text += QString(QObject::tr(" Button %1")).arg(param.Get("button", "").c_str());
}
return text;
} else {
return QObject::tr("[unknown]");
}
};
static QString AnalogToText(const Common::ParamPackage& param, const std::string& dir) {
if (!param.Has("engine")) {
return QObject::tr("[not set]");
} else if (param.Get("engine", "") == "analog_from_button") {
return ButtonToText(Common::ParamPackage{param.Get(dir, "")});
} else if (param.Get("engine", "") == "sdl") {
if (dir == "modifier") {
return QString(QObject::tr("[unused]"));
}
QString text = QString(QObject::tr("Joystick %1")).arg(param.Get("joystick", "").c_str());
if (dir == "left" || dir == "right") {
text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_x", "").c_str());
} else if (dir == "up" || dir == "down") {
text += QString(QObject::tr(" Axis %1")).arg(param.Get("axis_y", "").c_str());
}
return text;
} else {
return QObject::tr("[unknown]");
}
};
ConfigureInput::ConfigureInput(QWidget* parent)
: QWidget(parent), ui(std::make_unique<Ui::ConfigureInput>()),
timeout_timer(std::make_unique<QTimer>()), poll_timer(std::make_unique<QTimer>()) {
@@ -96,13 +50,13 @@ ConfigureInput::ConfigureInput(QWidget* parent)
setFocusPolicy(Qt::ClickFocus);
button_map = {
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,
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_buttons = {{
@@ -212,18 +166,37 @@ void ConfigureInput::restoreDefaults() {
}
void ConfigureInput::updateButtonLabels() {
QString non_keyboard(tr("[non-keyboard]"));
auto KeyToText = [&non_keyboard](const Common::ParamPackage& param) {
if (!param.Has("engine")) {
return QString("[not set]");
} else if (param.Get("engine", "") != "keyboard") {
return non_keyboard;
} else {
return getKeyName(param.Get("code", 0));
}
};
for (int button = 0; button < Settings::NativeButton::NumButtons; button++) {
button_map[button]->setText(ButtonToText(buttons_param[button]));
button_map[button]->setText(KeyToText(buttons_param[button]));
}
for (int analog_id = 0; analog_id < Settings::NativeAnalog::NumAnalogs; analog_id++) {
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
if (analog_map_buttons[analog_id][sub_button_id]) {
analog_map_buttons[analog_id][sub_button_id]->setText(
AnalogToText(analogs_param[analog_id], analog_sub_buttons[sub_button_id]));
if (analogs_param[analog_id].Get("engine", "") != "analog_from_button") {
for (QPushButton* button : analog_map_buttons[analog_id]) {
if (button)
button->setText(non_keyboard);
}
} else {
for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; sub_button_id++) {
Common::ParamPackage param(
analogs_param[analog_id].Get(analog_sub_buttons[sub_button_id], ""));
if (analog_map_buttons[analog_id][sub_button_id])
analog_map_buttons[analog_id][sub_button_id]->setText(KeyToText(param));
}
}
analog_map_stick[analog_id]->setText(tr("Set Analog Stick"));
analog_map_stick[analog_id]->setText("Set Analog Stick");
}
}

View File

@@ -8,6 +8,7 @@
#include "yuzu/configuration/configure_system.h"
#include "yuzu/ui_settings.h"
static const std::array<int, 12> days_in_month = {{
31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31,
}};
@@ -72,6 +73,5 @@ void ConfigureSystem::refreshConsoleID() {
if (reply == QMessageBox::No)
return;
u64 console_id{};
ui->label_console_id->setText(
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper());
}

View File

@@ -8,6 +8,7 @@
#include "yuzu/debugger/registers.h"
#include "yuzu/util/util.h"
RegistersWidget::RegistersWidget(QWidget* parent) : QDockWidget(parent) {
cpu_regs_ui.setupUi(this);

View File

@@ -174,7 +174,7 @@ void GameList::onTextChanged(const QString& newText) {
child_file->data(GameListItemPath::ProgramIdRole).toString().toLower();
// Only items which filename in combination with its title contains all words
// that are in the searchfield will be visible in the gamelist
// that are in the searchfiel will be visible in the gamelist
// The search is case insensitive because of toLower()
// I decided not to use Qt::CaseInsensitive in containsAllWords to prevent
// multiple conversions of edit_filter_text for each game in the gamelist

View File

@@ -9,8 +9,8 @@
#include <QRunnable>
#include <QStandardItem>
#include <QString>
#include "common/string_util.h"
#include "yuzu/util/util.h"
#include "common/string_util.h"
/**
* Gets the default icon (for games without valid SMDH)

View File

@@ -122,9 +122,8 @@ void GMainWindow::InitializeWidgets() {
statusBar()->addPermanentWidget(message_label, 1);
emu_speed_label = new QLabel();
emu_speed_label->setToolTip(
tr("Current emulation speed. Values higher or lower than 100% "
"indicate emulation is running faster or slower than a Switch."));
emu_speed_label->setToolTip(tr("Current emulation speed. Values higher or lower than 100% "
"indicate emulation is running faster or slower than a Switch."));
game_fps_label = new QLabel();
game_fps_label->setToolTip(tr("How many frames per second the game is currently displaying. "
"This will vary from game to game and scene to scene."));
@@ -186,8 +185,8 @@ void GMainWindow::InitializeRecentFileMenuActions() {
void GMainWindow::InitializeHotkeys() {
RegisterHotkey("Main Window", "Load File", QKeySequence::Open);
RegisterHotkey("Main Window", "Start Emulation");
RegisterHotkey("Main Window", "Fullscreen", QKeySequence::FullScreen);
RegisterHotkey("Main Window", "Exit Fullscreen", QKeySequence::Cancel, Qt::ApplicationShortcut);
RegisterHotkey( "Main Window", "Fullscreen", QKeySequence::FullScreen );
RegisterHotkey( "Main Window", "Exit Fullscreen", QKeySequence::Cancel, Qt::ApplicationShortcut );
LoadHotkeys();
connect(GetHotkey("Main Window", "Load File", this), SIGNAL(activated()), this,
@@ -195,9 +194,9 @@ void GMainWindow::InitializeHotkeys() {
connect(GetHotkey("Main Window", "Start Emulation", this), SIGNAL(activated()), this,
SLOT(OnStartGame()));
connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activated,
ui.action_Fullscreen, &QAction::trigger);
ui.action_Fullscreen, &QAction::trigger);
connect(GetHotkey("Main Window", "Fullscreen", render_window), &QShortcut::activatedAmbiguously,
ui.action_Fullscreen, &QAction::trigger);
ui.action_Fullscreen, &QAction::trigger);
connect(GetHotkey("Main Window", "Exit Fullscreen", this), &QShortcut::activated, this, [&] {
if (emulation_running) {
ui.action_Fullscreen->setChecked(false);

View File

@@ -31,8 +31,8 @@
#include <cstdlib>
#include <QLineEdit>
#include <QRegExpValidator>
#include "common/assert.h"
#include "yuzu/util/spinbox.h"
#include "common/assert.h"
CSpinBox::CSpinBox(QWidget* parent)
: QAbstractSpinBox(parent), min_value(-100), max_value(100), value(0), base(10), num_digits(0) {

View File

@@ -124,8 +124,8 @@ custom_bottom_top =
custom_bottom_right =
custom_bottom_bottom =
# Whether to toggle frame limiter on or off.
# 0: Off, 1 (default): On
#Whether to toggle frame limiter on or off.
# 0: Off , 1 (default): On
toggle_framelimit =
# Swaps the prominent screen with the other screen.

View File

@@ -37,6 +37,7 @@
#include "yuzu_cmd/config.h"
#include "yuzu_cmd/emu_window/emu_window_sdl2.h"
static void PrintHelp(const char* argv0) {
std::cout << "Usage: " << argv0
<< " [options] <filename>\n"