summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt44
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp16
-rw-r--r--src/core/file_sys/content_archive.cpp19
-rw-r--r--src/core/file_sys/partition_filesystem.cpp5
-rw-r--r--src/core/file_sys/romfs.cpp124
-rw-r--r--src/core/file_sys/romfs.h35
-rw-r--r--src/core/file_sys/vfs.cpp23
-rw-r--r--src/core/file_sys/vfs.h20
-rw-r--r--src/core/file_sys/vfs_offset.cpp7
-rw-r--r--src/core/file_sys/vfs_offset.h3
-rw-r--r--src/core/file_sys/vfs_real.cpp6
-rw-r--r--src/core/file_sys/vfs_real.h3
-rw-r--r--src/core/file_sys/vfs_vector.cpp83
-rw-r--r--src/core/file_sys/vfs_vector.h44
-rw-r--r--src/core/hle/kernel/timer.h22
-rw-r--r--src/core/hle/service/am/am.cpp6
-rw-r--r--src/core/hle/service/am/idle.cpp24
-rw-r--r--src/core/hle/service/am/idle.h16
-rw-r--r--src/core/hle/service/am/omm.cpp42
-rw-r--r--src/core/hle/service/am/omm.h16
-rw-r--r--src/core/hle/service/am/spsm.cpp30
-rw-r--r--src/core/hle/service/am/spsm.h16
-rw-r--r--src/core/hle/service/audio/audout_u.cpp195
-rw-r--r--src/core/hle/service/audio/audout_u.h14
-rw-r--r--src/core/hle/service/audio/hwopus.cpp135
-rw-r--r--src/core/hle/service/audio/hwopus.h1
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp72
-rw-r--r--src/core/hle/service/btdrv/btdrv.h16
-rw-r--r--src/core/hle/service/btm/btm.cpp121
-rw-r--r--src/core/hle/service/btm/btm.h15
-rw-r--r--src/core/hle/service/fgm/fgm.cpp75
-rw-r--r--src/core/hle/service/fgm/fgm.h15
-rw-r--r--src/core/hle/service/grc/grc.cpp31
-rw-r--r--src/core/hle/service/grc/grc.h15
-rw-r--r--src/core/hle/service/hid/hid.cpp243
-rw-r--r--src/core/hle/service/hid/irs.cpp49
-rw-r--r--src/core/hle/service/hid/irs.h21
-rw-r--r--src/core/hle/service/hid/xcd.cpp37
-rw-r--r--src/core/hle/service/hid/xcd.h16
-rw-r--r--src/core/hle/service/lbl/lbl.cpp90
-rw-r--r--src/core/hle/service/lbl/lbl.h15
-rw-r--r--src/core/hle/service/ldn/ldn.cpp142
-rw-r--r--src/core/hle/service/ldn/ldn.h16
-rw-r--r--src/core/hle/service/mii/mii.cpp107
-rw-r--r--src/core/hle/service/mii/mii.h15
-rw-r--r--src/core/hle/service/ncm/ncm.cpp59
-rw-r--r--src/core/hle/service/ncm/ncm.h15
-rw-r--r--src/core/hle/service/nfc/nfc.cpp222
-rw-r--r--src/core/hle/service/nfc/nfc.h15
-rw-r--r--src/core/hle/service/nim/nim.cpp124
-rw-r--r--src/core/hle/service/nim/nim.h15
-rw-r--r--src/core/hle/service/pcie/pcie.cpp64
-rw-r--r--src/core/hle/service/pcie/pcie.h15
-rw-r--r--src/core/hle/service/service.cpp28
-rw-r--r--src/core/hle/service/sockets/bsd.cpp22
-rw-r--r--src/core/hle/service/sockets/bsd.h5
-rw-r--r--src/core/hle/service/sockets/ethc.cpp38
-rw-r--r--src/core/hle/service/sockets/ethc.h21
-rw-r--r--src/core/hle/service/sockets/sockets.cpp7
-rw-r--r--src/core/hle/service/wlan/wlan.cpp172
-rw-r--r--src/core/hle/service/wlan/wlan.h15
61 files changed, 2756 insertions, 141 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 2e2de59b1..3e13fc25b 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -23,6 +23,8 @@ add_library(core STATIC
file_sys/partition_filesystem.h
file_sys/program_metadata.cpp
file_sys/program_metadata.h
+ file_sys/romfs.cpp
+ file_sys/romfs.h
file_sys/romfs_factory.cpp
file_sys/romfs_factory.h
file_sys/savedata_factory.cpp
@@ -35,6 +37,8 @@ add_library(core STATIC
file_sys/vfs_offset.h
file_sys/vfs_real.cpp
file_sys/vfs_real.h
+ file_sys/vfs_vector.cpp
+ file_sys/vfs_vector.h
frontend/emu_window.cpp
frontend/emu_window.h
frontend/framebuffer_layout.cpp
@@ -110,6 +114,12 @@ add_library(core STATIC
hle/service/am/applet_ae.h
hle/service/am/applet_oe.cpp
hle/service/am/applet_oe.h
+ hle/service/am/idle.cpp
+ hle/service/am/idle.h
+ hle/service/am/omm.cpp
+ hle/service/am/omm.h
+ hle/service/am/spsm.cpp
+ hle/service/am/spsm.h
hle/service/aoc/aoc_u.cpp
hle/service/aoc/aoc_u.h
hle/service/apm/apm.cpp
@@ -136,6 +146,10 @@ add_library(core STATIC
hle/service/bcat/bcat.h
hle/service/bcat/module.cpp
hle/service/bcat/module.h
+ hle/service/btdrv/btdrv.cpp
+ hle/service/btdrv/btdrv.h
+ hle/service/btm/btm.cpp
+ hle/service/btm/btm.h
hle/service/erpt/erpt.cpp
hle/service/erpt/erpt.h
hle/service/es/es.cpp
@@ -152,24 +166,44 @@ add_library(core STATIC
hle/service/filesystem/filesystem.h
hle/service/filesystem/fsp_srv.cpp
hle/service/filesystem/fsp_srv.h
+ hle/service/fgm/fgm.cpp
+ hle/service/fgm/fgm.h
hle/service/friend/friend.cpp
hle/service/friend/friend.h
hle/service/friend/interface.cpp
hle/service/friend/interface.h
+ hle/service/grc/grc.cpp
+ hle/service/grc/grc.h
hle/service/hid/hid.cpp
hle/service/hid/hid.h
+ hle/service/hid/irs.cpp
+ hle/service/hid/irs.h
+ hle/service/hid/xcd.cpp
+ hle/service/hid/xcd.h
+ hle/service/lbl/lbl.cpp
+ hle/service/lbl/lbl.h
+ hle/service/ldn/ldn.cpp
+ hle/service/ldn/ldn.h
hle/service/ldr/ldr.cpp
hle/service/ldr/ldr.h
hle/service/lm/lm.cpp
hle/service/lm/lm.h
+ hle/service/mii/mii.cpp
+ hle/service/mii/mii.h
hle/service/mm/mm_u.cpp
hle/service/mm/mm_u.h
+ hle/service/ncm/ncm.cpp
+ hle/service/ncm/ncm.h
+ hle/service/nfc/nfc.cpp
+ hle/service/nfc/nfc.h
hle/service/nfp/nfp.cpp
hle/service/nfp/nfp.h
hle/service/nfp/nfp_user.cpp
hle/service/nfp/nfp_user.h
hle/service/nifm/nifm.cpp
hle/service/nifm/nifm.h
+ hle/service/nim/nim.cpp
+ hle/service/nim/nim.h
hle/service/ns/ns.cpp
hle/service/ns/ns.h
hle/service/ns/pl_u.cpp
@@ -199,6 +233,8 @@ add_library(core STATIC
hle/service/nvflinger/buffer_queue.h
hle/service/nvflinger/nvflinger.cpp
hle/service/nvflinger/nvflinger.h
+ hle/service/pcie/pcie.cpp
+ hle/service/pcie/pcie.h
hle/service/pctl/module.cpp
hle/service/pctl/module.h
hle/service/pctl/pctl.cpp
@@ -225,6 +261,8 @@ add_library(core STATIC
hle/service/sm/sm.h
hle/service/sockets/bsd.cpp
hle/service/sockets/bsd.h
+ hle/service/sockets/ethc.cpp
+ hle/service/sockets/ethc.h
hle/service/sockets/nsd.cpp
hle/service/sockets/nsd.h
hle/service/sockets/sfdnsres.cpp
@@ -251,6 +289,8 @@ add_library(core STATIC
hle/service/vi/vi_s.h
hle/service/vi/vi_u.cpp
hle/service/vi/vi_u.h
+ hle/service/wlan/wlan.cpp
+ hle/service/wlan/wlan.h
hw/hw.cpp
hw/hw.h
hw/lcd.cpp
@@ -287,8 +327,8 @@ add_library(core STATIC
create_target_directory_groups(core)
-target_link_libraries(core PUBLIC common PRIVATE video_core)
-target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static unicorn)
+target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
+target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt lz4_static opus unicorn)
if (ARCHITECTURE_x86_64)
target_sources(core PRIVATE
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 57b8634b9..1d8c15d97 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -139,14 +139,12 @@ void ARM_Dynarmic::Step() {
}
ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index)
- : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)),
- jit(MakeJit()), exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(
- exclusive_monitor)},
- core_index{core_index} {
- ARM_Interface::ThreadContext ctx;
+ : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), core_index{core_index},
+ exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(exclusive_monitor)} {
+ ThreadContext ctx;
inner_unicorn.SaveContext(ctx);
- LoadContext(ctx);
PageTableChanged();
+ LoadContext(ctx);
}
ARM_Dynarmic::~ARM_Dynarmic() = default;
@@ -205,7 +203,7 @@ u64 ARM_Dynarmic::GetTlsAddress() const {
return cb->tpidrro_el0;
}
-void ARM_Dynarmic::SetTlsAddress(u64 address) {
+void ARM_Dynarmic::SetTlsAddress(VAddr address) {
cb->tpidrro_el0 = address;
}
@@ -217,7 +215,7 @@ void ARM_Dynarmic::SetTPIDR_EL0(u64 value) {
cb->tpidr_el0 = value;
}
-void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
+void ARM_Dynarmic::SaveContext(ThreadContext& ctx) {
ctx.cpu_registers = jit->GetRegisters();
ctx.sp = jit->GetSP();
ctx.pc = jit->GetPC();
@@ -226,7 +224,7 @@ void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
ctx.fpscr = jit->GetFpcr();
}
-void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) {
+void ARM_Dynarmic::LoadContext(const ThreadContext& ctx) {
jit->SetRegisters(ctx.cpu_registers);
jit->SetSP(ctx.sp);
jit->SetPC(ctx.pc);
diff --git a/src/core/file_sys/content_archive.cpp b/src/core/file_sys/content_archive.cpp
index d6b20c047..61cb0bbe3 100644
--- a/src/core/file_sys/content_archive.cpp
+++ b/src/core/file_sys/content_archive.cpp
@@ -9,6 +9,7 @@
#include "core/file_sys/content_archive.h"
#include "core/file_sys/vfs_offset.h"
#include "core/loader/loader.h"
+#include "romfs.h"
namespace FileSys {
@@ -46,21 +47,9 @@ struct PFS0Superblock {
};
static_assert(sizeof(PFS0Superblock) == 0x200, "PFS0Superblock has incorrect size.");
-struct IVFCLevel {
- u64_le offset;
- u64_le size;
- u32_le block_size;
- u32_le reserved;
-};
-static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
-
struct RomFSSuperblock {
NCASectionHeaderBlock header_block;
- u32_le magic;
- u32_le magic_number;
- INSERT_PADDING_BYTES(8);
- std::array<IVFCLevel, 6> levels;
- INSERT_PADDING_BYTES(64);
+ IVFCHeader ivfc;
};
static_assert(sizeof(RomFSSuperblock) == 0xE8, "RomFSSuperblock has incorrect size.");
@@ -92,8 +81,8 @@ NCA::NCA(VirtualFile file_) : file(std::move(file_)) {
const size_t romfs_offset =
header.section_tables[i].media_offset * MEDIA_OFFSET_MULTIPLIER +
- sb.levels[IVFC_MAX_LEVEL - 1].offset;
- const size_t romfs_size = sb.levels[IVFC_MAX_LEVEL - 1].size;
+ sb.ivfc.levels[IVFC_MAX_LEVEL - 1].offset;
+ const size_t romfs_size = sb.ivfc.levels[IVFC_MAX_LEVEL - 1].size;
files.emplace_back(std::make_shared<OffsetVfsFile>(file, romfs_size, romfs_offset));
romfs = files.back();
} else if (block.filesystem_type == NCASectionFilesystemType::PFS0) {
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
index 521e21078..47e032b19 100644
--- a/src/core/file_sys/partition_filesystem.cpp
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -97,9 +97,8 @@ void PartitionFilesystem::PrintDebugInfo() const {
LOG_DEBUG(Service_FS, "Magic: {:.4}", pfs_header.magic);
LOG_DEBUG(Service_FS, "Files: {}", pfs_header.num_entries);
for (u32 i = 0; i < pfs_header.num_entries; i++) {
- LOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes, at 0x{:X})", i,
- pfs_files[i]->GetName(), pfs_files[i]->GetSize(),
- dynamic_cast<OffsetVfsFile*>(pfs_files[i].get())->GetOffset());
+ LOG_DEBUG(Service_FS, " > File {}: {} (0x{:X} bytes)", i,
+ pfs_files[i]->GetName(), pfs_files[i]->GetSize());
}
}
diff --git a/src/core/file_sys/romfs.cpp b/src/core/file_sys/romfs.cpp
new file mode 100644
index 000000000..ff3ddb29c
--- /dev/null
+++ b/src/core/file_sys/romfs.cpp
@@ -0,0 +1,124 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/common_types.h"
+#include "common/swap.h"
+#include "core/file_sys/romfs.h"
+#include "core/file_sys/vfs.h"
+#include "core/file_sys/vfs_offset.h"
+#include "core/file_sys/vfs_vector.h"
+
+namespace FileSys {
+
+constexpr u32 ROMFS_ENTRY_EMPTY = 0xFFFFFFFF;
+
+struct TableLocation {
+ u64_le offset;
+ u64_le size;
+};
+static_assert(sizeof(TableLocation) == 0x10, "TableLocation has incorrect size.");
+
+struct RomFSHeader {
+ u64_le header_size;
+ TableLocation directory_hash;
+ TableLocation directory_meta;
+ TableLocation file_hash;
+ TableLocation file_meta;
+ u64_le data_offset;
+};
+static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
+
+struct DirectoryEntry {
+ u32_le sibling;
+ u32_le child_dir;
+ u32_le child_file;
+ u32_le hash;
+ u32_le name_length;
+};
+static_assert(sizeof(DirectoryEntry) == 0x14, "DirectoryEntry has incorrect size.");
+
+struct FileEntry {
+ u32_le parent;
+ u32_le sibling;
+ u64_le offset;
+ u64_le size;
+ u32_le hash;
+ u32_le name_length;
+};
+static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
+
+template <typename Entry>
+static std::pair<Entry, std::string> GetEntry(const VirtualFile& file, size_t offset) {
+ Entry entry{};
+ if (file->ReadObject(&entry, offset) != sizeof(Entry))
+ return {};
+ std::string string(entry.name_length, '\0');
+ if (file->ReadArray(&string[0], string.size(), offset + sizeof(Entry)) != string.size())
+ return {};
+ return {entry, string};
+}
+
+void ProcessFile(VirtualFile file, size_t file_offset, size_t data_offset, u32 this_file_offset,
+ std::shared_ptr<VectorVfsDirectory> parent) {
+ while (true) {
+ auto entry = GetEntry<FileEntry>(file, file_offset + this_file_offset);
+
+ parent->AddFile(std::make_shared<OffsetVfsFile>(
+ file, entry.first.size, entry.first.offset + data_offset, entry.second, parent));
+
+ if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
+ break;
+
+ this_file_offset = entry.first.sibling;
+ }
+}
+
+void ProcessDirectory(VirtualFile file, size_t dir_offset, size_t file_offset, size_t data_offset,
+ u32 this_dir_offset, std::shared_ptr<VectorVfsDirectory> parent) {
+ while (true) {
+ auto entry = GetEntry<DirectoryEntry>(file, dir_offset + this_dir_offset);
+ auto current = std::make_shared<VectorVfsDirectory>(
+ std::vector<VirtualFile>{}, std::vector<VirtualDir>{}, parent, entry.second);
+
+ if (entry.first.child_file != ROMFS_ENTRY_EMPTY) {
+ ProcessFile(file, file_offset, data_offset, entry.first.child_file, current);
+ }
+
+ if (entry.first.child_dir != ROMFS_ENTRY_EMPTY) {
+ ProcessDirectory(file, dir_offset, file_offset, data_offset, entry.first.child_dir,
+ current);
+ }
+
+ parent->AddDirectory(current);
+ if (entry.first.sibling == ROMFS_ENTRY_EMPTY)
+ break;
+ this_dir_offset = entry.first.sibling;
+ }
+}
+
+VirtualDir ExtractRomFS(VirtualFile file) {
+ RomFSHeader header{};
+ if (file->ReadObject(&header) != sizeof(RomFSHeader))
+ return nullptr;
+
+ if (header.header_size != sizeof(RomFSHeader))
+ return nullptr;
+
+ const u64 file_offset = header.file_meta.offset;
+ const u64 dir_offset = header.directory_meta.offset + 4;
+
+ const auto root =
+ std::make_shared<VectorVfsDirectory>(std::vector<VirtualFile>{}, std::vector<VirtualDir>{},
+ file->GetContainingDirectory(), file->GetName());
+
+ ProcessDirectory(file, dir_offset, file_offset, header.data_offset, 0, root);
+
+ VirtualDir out = std::move(root);
+
+ while (out->GetSubdirectory("") != nullptr)
+ out = out->GetSubdirectory("");
+
+ return out;
+}
+} // namespace FileSys
diff --git a/src/core/file_sys/romfs.h b/src/core/file_sys/romfs.h
new file mode 100644
index 000000000..03a876d22
--- /dev/null
+++ b/src/core/file_sys/romfs.h
@@ -0,0 +1,35 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <array>
+#include "common/common_funcs.h"
+#include "common/swap.h"
+#include "core/file_sys/vfs.h"
+
+namespace FileSys {
+
+struct IVFCLevel {
+ u64_le offset;
+ u64_le size;
+ u32_le block_size;
+ u32_le reserved;
+};
+static_assert(sizeof(IVFCLevel) == 0x18, "IVFCLevel has incorrect size.");
+
+struct IVFCHeader {
+ u32_le magic;
+ u32_le magic_number;
+ INSERT_PADDING_BYTES(8);
+ std::array<IVFCLevel, 6> levels;
+ INSERT_PADDING_BYTES(64);
+};
+static_assert(sizeof(IVFCHeader) == 0xE0, "IVFCHeader has incorrect size.");
+
+// Converts a RomFS binary blob to VFS Filesystem
+// Returns nullptr on failure
+VirtualDir ExtractRomFS(VirtualFile file);
+
+} // namespace FileSys
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index b99a4fd5b..84a6a7397 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -46,6 +46,13 @@ size_t VfsFile::WriteBytes(const std::vector<u8>& data, size_t offset) {
return Write(data.data(), data.size(), offset);
}
+std::string VfsFile::GetFullPath() const {
+ if (GetContainingDirectory() == nullptr)
+ return "/" + GetName();
+
+ return GetContainingDirectory()->GetFullPath() + "/" + GetName();
+}
+
std::shared_ptr<VfsFile> VfsDirectory::GetFileRelative(std::string_view path) const {
auto vec = FileUtil::SplitPathComponents(path);
vec.erase(std::remove_if(vec.begin(), vec.end(), [](const auto& str) { return str.empty(); }),
@@ -243,6 +250,13 @@ bool VfsDirectory::Copy(std::string_view src, std::string_view dest) {
return f2->WriteBytes(f1->ReadAllBytes()) == f1->GetSize();
}
+std::string VfsDirectory::GetFullPath() const {
+ if (IsRoot())
+ return GetName();
+
+ return GetParentDirectory()->GetFullPath() + "/" + GetName();
+}
+
bool ReadOnlyVfsDirectory::IsWritable() const {
return false;
}
@@ -270,4 +284,13 @@ bool ReadOnlyVfsDirectory::DeleteFile(std::string_view name) {
bool ReadOnlyVfsDirectory::Rename(std::string_view name) {
return false;
}
+
+bool VfsRawCopy(VirtualFile src, VirtualFile dest) {
+ if (src == nullptr || dest == nullptr)
+ return false;
+ if (!dest->Resize(src->GetSize()))
+ return false;
+ std::vector<u8> data = src->ReadAllBytes();
+ return dest->WriteBytes(data, 0) == data.size();
+}
} // namespace FileSys
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index 4a13b8378..cf871edd6 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -113,6 +113,9 @@ struct VfsFile : NonCopyable {
// Renames the file to name. Returns whether or not the operation was successsful.
virtual bool Rename(std::string_view name) = 0;
+
+ // Returns the full path of this file as a string, recursively
+ virtual std::string GetFullPath() const;
};
// A class representing a directory in an abstract filesystem.
@@ -213,6 +216,17 @@ struct VfsDirectory : NonCopyable {
return ReplaceFileWithSubdirectory(file_p, std::make_shared<Directory>(file_p));
}
+ bool InterpretAsDirectory(const std::function<VirtualDir(VirtualFile)>& function,
+ const std::string& file) {
+ auto file_p = GetFile(file);
+ if (file_p == nullptr)
+ return false;
+ return ReplaceFileWithSubdirectory(file_p, function(file_p));
+ }
+
+ // Returns the full path of this directory as a string, recursively
+ virtual std::string GetFullPath() const;
+
protected:
// Backend for InterpretAsDirectory.
// Removes all references to file and adds a reference to dir in the directory's implementation.
@@ -230,4 +244,10 @@ struct ReadOnlyVfsDirectory : public VfsDirectory {
bool DeleteFile(std::string_view name) override;
bool Rename(std::string_view name) override;
};
+
+// A method that copies the raw data between two different implementations of VirtualFile. If you
+// are using the same implementation, it is probably better to use the Copy method in the parent
+// directory of src/dest.
+bool VfsRawCopy(VirtualFile src, VirtualFile dest);
+
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp
index a40331cef..847cde2f5 100644
--- a/src/core/file_sys/vfs_offset.cpp
+++ b/src/core/file_sys/vfs_offset.cpp
@@ -10,8 +10,9 @@
namespace FileSys {
OffsetVfsFile::OffsetVfsFile(std::shared_ptr<VfsFile> file_, size_t size_, size_t offset_,
- std::string name_)
- : file(std::move(file_)), offset(offset_), size(size_), name(std::move(name_)) {}
+ std::string name_, VirtualDir parent_)
+ : file(file_), offset(offset_), size(size_), name(std::move(name_)),
+ parent(parent_ == nullptr ? file->GetContainingDirectory() : std::move(parent_)) {}
std::string OffsetVfsFile::GetName() const {
return name.empty() ? file->GetName() : name;
@@ -35,7 +36,7 @@ bool OffsetVfsFile::Resize(size_t new_size) {
}
std::shared_ptr<VfsDirectory> OffsetVfsFile::GetContainingDirectory() const {
- return file->GetContainingDirectory();
+ return parent;
}
bool OffsetVfsFile::IsWritable() const {
diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h
index 4f471e3ba..235970dc5 100644
--- a/src/core/file_sys/vfs_offset.h
+++ b/src/core/file_sys/vfs_offset.h
@@ -17,7 +17,7 @@ namespace FileSys {
// the size of this wrapper.
struct OffsetVfsFile : public VfsFile {
OffsetVfsFile(std::shared_ptr<VfsFile> file, size_t size, size_t offset = 0,
- std::string new_name = "");
+ std::string new_name = "", VirtualDir new_parent = nullptr);
std::string GetName() const override;
size_t GetSize() const override;
@@ -44,6 +44,7 @@ private:
size_t offset;
size_t size;
std::string name;
+ VirtualDir parent;
};
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 9ce2e1efa..82d54da4a 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -195,6 +195,12 @@ bool RealVfsDirectory::Rename(std::string_view name) {
return FileUtil::Rename(path, new_name);
}
+std::string RealVfsDirectory::GetFullPath() const {
+ auto out = path;
+ std::replace(out.begin(), out.end(), '\\', '/');
+ return out;
+}
+
bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
const auto iter = std::find(files.begin(), files.end(), file);
if (iter == files.end())
diff --git a/src/core/file_sys/vfs_real.h b/src/core/file_sys/vfs_real.h
index 2151211c9..243d58576 100644
--- a/src/core/file_sys/vfs_real.h
+++ b/src/core/file_sys/vfs_real.h
@@ -41,7 +41,7 @@ private:
// An implementation of VfsDirectory that represents a directory on the user's computer.
struct RealVfsDirectory : public VfsDirectory {
- RealVfsDirectory(const std::string& path, Mode perms);
+ RealVfsDirectory(const std::string& path, Mode perms = Mode::Read);
std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
@@ -54,6 +54,7 @@ struct RealVfsDirectory : public VfsDirectory {
bool DeleteSubdirectory(std::string_view name) override;
bool DeleteFile(std::string_view name) override;
bool Rename(std::string_view name) override;
+ std::string GetFullPath() const override;
protected:
bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
diff --git a/src/core/file_sys/vfs_vector.cpp b/src/core/file_sys/vfs_vector.cpp
new file mode 100644
index 000000000..4c6337e3a
--- /dev/null
+++ b/src/core/file_sys/vfs_vector.cpp
@@ -0,0 +1,83 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include "core/file_sys/vfs_vector.h"
+
+namespace FileSys {
+VectorVfsDirectory::VectorVfsDirectory(std::vector<VirtualFile> files_,
+ std::vector<VirtualDir> dirs_, VirtualDir parent_,
+ std::string name_)
+ : files(std::move(files_)), dirs(std::move(dirs_)), parent(std::move(parent_)),
+ name(std::move(name_)) {}
+
+std::vector<std::shared_ptr<VfsFile>> VectorVfsDirectory::GetFiles() const {
+ return files;
+}
+
+std::vector<std::shared_ptr<VfsDirectory>> VectorVfsDirectory::GetSubdirectories() const {
+ return dirs;
+}
+
+bool VectorVfsDirectory::IsWritable() const {
+ return false;
+}
+
+bool VectorVfsDirectory::IsReadable() const {
+ return true;
+}
+
+std::string VectorVfsDirectory::GetName() const {
+ return name;
+}
+std::shared_ptr<VfsDirectory> VectorVfsDirectory::GetParentDirectory() const {
+ return parent;
+}
+
+template <typename T>
+static bool FindAndRemoveVectorElement(std::vector<T>& vec, std::string_view name) {
+ auto iter = std::find_if(vec.begin(), vec.end(), [name](T e) { return e->GetName() == name; });
+ if (iter == vec.end())
+ return false;
+ auto old_size = vec.size();
+ vec.erase(iter);
+ return true;
+}
+
+bool VectorVfsDirectory::DeleteSubdirectory(std::string_view name) {
+ return FindAndRemoveVectorElement(dirs, name);
+}
+
+bool VectorVfsDirectory::DeleteFile(std::string_view name) {
+ return FindAndRemoveVectorElement(files, name);
+}
+
+bool VectorVfsDirectory::Rename(std::string_view name_) {
+ name = name_;
+ return true;
+}
+
+std::shared_ptr<VfsDirectory> VectorVfsDirectory::CreateSubdirectory(std::string_view name) {
+ return nullptr;
+}
+
+std::shared_ptr<VfsFile> VectorVfsDirectory::CreateFile(std::string_view name) {
+ return nullptr;
+}
+
+void VectorVfsDirectory::AddFile(VirtualFile file) {
+ files.push_back(std::move(file));
+}
+
+void VectorVfsDirectory::AddDirectory(VirtualDir dir) {
+ dirs.push_back(std::move(dir));
+}
+
+bool VectorVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
+ if (!DeleteFile(file->GetName()))
+ return false;
+ dirs.emplace_back(dir);
+ return true;
+}
+} // namespace FileSys
diff --git a/src/core/file_sys/vfs_vector.h b/src/core/file_sys/vfs_vector.h
new file mode 100644
index 000000000..ba469647b
--- /dev/null
+++ b/src/core/file_sys/vfs_vector.h
@@ -0,0 +1,44 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/file_sys/vfs.h"
+
+namespace FileSys {
+
+// An implementation of VfsDirectory that maintains two vectors for subdirectories and files.
+// Vector data is supplied upon construction.
+struct VectorVfsDirectory : public VfsDirectory {
+ explicit VectorVfsDirectory(std::vector<VirtualFile> files = {},
+ std::vector<VirtualDir> dirs = {}, VirtualDir parent = nullptr,
+ std::string name = "");
+
+ std::vector<std::shared_ptr<VfsFile>> GetFiles() const override;
+ std::vector<std::shared_ptr<VfsDirectory>> GetSubdirectories() const override;
+ bool IsWritable() const override;
+ bool IsReadable() const override;
+ std::string GetName() const override;
+ std::shared_ptr<VfsDirectory> GetParentDirectory() const override;
+ bool DeleteSubdirectory(std::string_view name) override;
+ bool DeleteFile(std::string_view name) override;
+ bool Rename(std::string_view name) override;
+ std::shared_ptr<VfsDirectory> CreateSubdirectory(std::string_view name) override;
+ std::shared_ptr<VfsFile> CreateFile(std::string_view name) override;
+
+ virtual void AddFile(VirtualFile file);
+ virtual void AddDirectory(VirtualDir dir);
+
+protected:
+ bool ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) override;
+
+private:
+ std::vector<VirtualFile> files;
+ std::vector<VirtualDir> dirs;
+
+ VirtualDir parent;
+ std::string name;
+};
+
+} // namespace FileSys
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
index 82d19cefc..c63f0ed90 100644
--- a/src/core/hle/kernel/timer.h
+++ b/src/core/hle/kernel/timer.h
@@ -32,13 +32,17 @@ public:
return HANDLE_TYPE;
}
- ResetType reset_type; ///< The ResetType of this timer
+ ResetType GetResetType() const {
+ return reset_type;
+ }
- bool signaled; ///< Whether the timer has been signaled or not
- std::string name; ///< Name of timer (optional)
+ u64 GetInitialDelay() const {
+ return initial_delay;
+ }
- u64 initial_delay; ///< The delay until the timer fires for the first time
- u64 interval_delay; ///< The delay until the timer fires after the first time
+ u64 GetIntervalDelay() const {
+ return interval_delay;
+ }
bool ShouldWait(Thread* thread) const override;
void Acquire(Thread* thread) override;
@@ -67,6 +71,14 @@ private:
Timer();
~Timer() override;
+ ResetType reset_type; ///< The ResetType of this timer
+
+ u64 initial_delay; ///< The delay until the timer fires for the first time
+ u64 interval_delay; ///< The delay until the timer fires after the first time
+
+ bool signaled; ///< Whether the timer has been signaled or not
+ std::string name; ///< Name of timer (optional)
+
/// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
Handle callback_handle;
};
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 97ef07bf9..94d2a973d 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -11,6 +11,9 @@
#include "core/hle/service/am/am.h"
#include "core/hle/service/am/applet_ae.h"
#include "core/hle/service/am/applet_oe.h"
+#include "core/hle/service/am/idle.h"
+#include "core/hle/service/am/omm.h"
+#include "core/hle/service/am/spsm.h"
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/nvflinger/nvflinger.h"
@@ -689,6 +692,9 @@ void InstallInterfaces(SM::ServiceManager& service_manager,
std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
std::make_shared<AppletAE>(nvflinger)->InstallAsService(service_manager);
std::make_shared<AppletOE>(nvflinger)->InstallAsService(service_manager);
+ std::make_shared<IdleSys>()->InstallAsService(service_manager);
+ std::make_shared<OMM>()->InstallAsService(service_manager);
+ std::make_shared<SPSM>()->InstallAsService(service_manager);
}
IHomeMenuFunctions::IHomeMenuFunctions() : ServiceFramework("IHomeMenuFunctions") {
diff --git a/src/core/hle/service/am/idle.cpp b/src/core/hle/service/am/idle.cpp
new file mode 100644
index 000000000..af46e9494
--- /dev/null
+++ b/src/core/hle/service/am/idle.cpp
@@ -0,0 +1,24 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/am/idle.h"
+
+namespace Service::AM {
+
+IdleSys::IdleSys() : ServiceFramework{"idle:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetAutoPowerDownEvent"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/idle.h b/src/core/hle/service/am/idle.h
new file mode 100644
index 000000000..1eb68d2c9
--- /dev/null
+++ b/src/core/hle/service/am/idle.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class IdleSys final : public ServiceFramework<IdleSys> {
+public:
+ explicit IdleSys();
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/omm.cpp b/src/core/hle/service/am/omm.cpp
new file mode 100644
index 000000000..447fe8669
--- /dev/null
+++ b/src/core/hle/service/am/omm.cpp
@@ -0,0 +1,42 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/am/omm.h"
+
+namespace Service::AM {
+
+OMM::OMM() : ServiceFramework{"omm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetOperationMode"},
+ {1, nullptr, "GetOperationModeChangeEvent"},
+ {2, nullptr, "EnableAudioVisual"},
+ {3, nullptr, "DisableAudioVisual"},
+ {4, nullptr, "EnterSleepAndWait"},
+ {5, nullptr, "GetCradleStatus"},
+ {6, nullptr, "FadeInDisplay"},
+ {7, nullptr, "FadeOutDisplay"},
+ {8, nullptr, "Unknown1"},
+ {9, nullptr, "Unknown2"},
+ {10, nullptr, "Unknown3"},
+ {11, nullptr, "Unknown4"},
+ {12, nullptr, "Unknown5"},
+ {13, nullptr, "Unknown6"},
+ {14, nullptr, "Unknown7"},
+ {15, nullptr, "Unknown8"},
+ {16, nullptr, "Unknown9"},
+ {17, nullptr, "Unknown10"},
+ {18, nullptr, "Unknown11"},
+ {19, nullptr, "Unknown12"},
+ {20, nullptr, "Unknown13"},
+ {21, nullptr, "Unknown14"},
+ {22, nullptr, "Unknown15"},
+ {23, nullptr, "Unknown16"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/omm.h b/src/core/hle/service/am/omm.h
new file mode 100644
index 000000000..49e5d331c
--- /dev/null
+++ b/src/core/hle/service/am/omm.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class OMM final : public ServiceFramework<OMM> {
+public:
+ explicit OMM();
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp
new file mode 100644
index 000000000..a05d433d0
--- /dev/null
+++ b/src/core/hle/service/am/spsm.cpp
@@ -0,0 +1,30 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/am/spsm.h"
+
+namespace Service::AM {
+
+SPSM::SPSM() : ServiceFramework{"spsm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetState"},
+ {1, nullptr, "SleepSystemAndWaitAwake"},
+ {2, nullptr, "Unknown1"},
+ {3, nullptr, "Unknown2"},
+ {4, nullptr, "GetNotificationMessageEventHandle"},
+ {5, nullptr, "Unknown3"},
+ {6, nullptr, "Unknown4"},
+ {7, nullptr, "Unknown5"},
+ {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"},
+ {9, nullptr, "ChangeHomeButtonLongPressingTime"},
+ {10, nullptr, "Unknown6"},
+ {11, nullptr, "Unknown7"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/am/spsm.h b/src/core/hle/service/am/spsm.h
new file mode 100644
index 000000000..57dde62e1
--- /dev/null
+++ b/src/core/hle/service/am/spsm.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::AM {
+
+class SPSM final : public ServiceFramework<SPSM> {
+public:
+ explicit SPSM();
+};
+
+} // namespace Service::AM
diff --git a/src/core/hle/service/audio/audout_u.cpp b/src/core/hle/service/audio/audout_u.cpp
index 1dcd84d98..ab37c2a69 100644
--- a/src/core/hle/service/audio/audout_u.cpp
+++ b/src/core/hle/service/audio/audout_u.cpp
@@ -5,8 +5,7 @@
#include <array>
#include <vector>
#include "common/logging/log.h"
-#include "core/core_timing.h"
-#include "core/core_timing_util.h"
+#include "core/core.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/hle_ipc.h"
@@ -14,17 +13,21 @@
namespace Service::Audio {
-/// Switch sample rate frequency
-constexpr u32 sample_rate{48000};
-/// TODO(st4rk): dynamic number of channels, as I think Switch has support
-/// to more audio channels (probably when Docked I guess)
-constexpr u32 audio_channels{2};
-/// TODO(st4rk): find a proper value for the audio_ticks
-constexpr u64 audio_ticks{static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / 500)};
+namespace ErrCodes {
+enum {
+ ErrorUnknown = 2,
+ BufferCountExceeded = 8,
+};
+}
+
+constexpr std::array<char, 10> DefaultDevice{{"DeviceOut"}};
+constexpr int DefaultSampleRate{48000};
class IAudioOut final : public ServiceFramework<IAudioOut> {
public:
- IAudioOut() : ServiceFramework("IAudioOut"), audio_out_state(AudioState::Stopped) {
+ IAudioOut(AudoutParams audio_params, AudioCore::AudioOut& audio_core)
+ : ServiceFramework("IAudioOut"), audio_params(audio_params), audio_core(audio_core) {
+
static const FunctionInfo functions[] = {
{0, &IAudioOut::GetAudioOutState, "GetAudioOutState"},
{1, &IAudioOut::StartAudioOut, "StartAudioOut"},
@@ -32,66 +35,65 @@ public:
{3, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBuffer"},
{4, &IAudioOut::RegisterBufferEvent, "RegisterBufferEvent"},
{5, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBuffer"},
- {6, nullptr, "ContainsAudioOutBuffer"},
+ {6, &IAudioOut::ContainsAudioOutBuffer, "ContainsAudioOutBuffer"},
{7, &IAudioOut::AppendAudioOutBufferImpl, "AppendAudioOutBufferAuto"},
{8, &IAudioOut::GetReleasedAudioOutBufferImpl, "GetReleasedAudioOutBufferAuto"},
- {9, nullptr, "GetAudioOutBufferCount"},
+ {9, &IAudioOut::GetAudioOutBufferCount, "GetAudioOutBufferCount"},
{10, nullptr, "GetAudioOutPlayedSampleCount"},
{11, nullptr, "FlushAudioOutBuffers"},
};
RegisterHandlers(functions);
// This is the event handle used to check if the audio buffer was released
- buffer_event =
- Kernel::Event::Create(Kernel::ResetType::OneShot, "IAudioOutBufferReleasedEvent");
-
- // Register event callback to update the Audio Buffer
- audio_event = CoreTiming::RegisterEvent(
- "IAudioOut::UpdateAudioBuffersCallback", [this](u64 userdata, int cycles_late) {
- UpdateAudioBuffersCallback();
- CoreTiming::ScheduleEvent(audio_ticks - cycles_late, audio_event);
- });
-
- // Start the audio event
- CoreTiming::ScheduleEvent(audio_ticks, audio_event);
- }
+ buffer_event = Kernel::Event::Create(Kernel::ResetType::Sticky, "IAudioOutBufferReleased");
- ~IAudioOut() {
- CoreTiming::UnscheduleEvent(audio_event, 0);
+ stream = audio_core.OpenStream(audio_params.sample_rate, audio_params.channel_count,
+ [=]() { buffer_event->Signal(); });
}
private:
+ struct AudioBuffer {
+ u64_le next;
+ u64_le buffer;
+ u64_le buffer_capacity;
+ u64_le buffer_size;
+ u64_le offset;
+ };
+ static_assert(sizeof(AudioBuffer) == 0x28, "AudioBuffer is an invalid size");
+
void GetAudioOutState(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- rb.Push(static_cast<u32>(audio_out_state));
+ rb.Push(static_cast<u32>(stream->IsPlaying() ? AudioState::Started : AudioState::Stopped));
}
void StartAudioOut(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
+
+ if (stream->IsPlaying()) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::ErrorUnknown));
+ return;
+ }
- // Start audio
- audio_out_state = AudioState::Started;
+ audio_core.StartStream(stream);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void StopAudioOut(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
-
- // Stop audio
- audio_out_state = AudioState::Stopped;
+ LOG_DEBUG(Service_Audio, "called");
- queue_keys.clear();
+ audio_core.StopStream(stream);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void RegisterBufferEvent(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
IPC::ResponseBuilder rb{ctx, 2, 1};
rb.Push(RESULT_SUCCESS);
@@ -99,101 +101,107 @@ private:
}
void AppendAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "(STUBBED) called {}", ctx.Description());
IPC::RequestParser rp{ctx};
- const u64 key{rp.Pop<u64>()};
- queue_keys.insert(queue_keys.begin(), key);
+ const auto& input_buffer{ctx.ReadBuffer()};
+ ASSERT_MSG(input_buffer.size() == sizeof(AudioBuffer),
+ "AudioBuffer input is an invalid size!");
+ AudioBuffer audio_buffer{};
+ std::memcpy(&audio_buffer, input_buffer.data(), sizeof(AudioBuffer));
+ const u64 tag{rp.Pop<u64>()};
+
+ std::vector<u8> data(audio_buffer.buffer_size);
+ Memory::ReadBlock(audio_buffer.buffer, data.data(), data.size());
+
+ if (!audio_core.QueueBuffer(stream, tag, std::move(data))) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ResultCode(ErrorModule::Audio, ErrCodes::BufferCountExceeded));
+ }
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
}
void GetReleasedAudioOutBufferImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
-
- // TODO(st4rk): This is how libtransistor currently implements the
- // GetReleasedAudioOutBuffer, it should return the key (a VAddr) to the app and this address
- // is used to know which buffer should be filled with data and send again to the service
- // through AppendAudioOutBuffer. Check if this is the proper way to do it.
- u64 key{0};
-
- if (queue_keys.size()) {
- key = queue_keys.back();
- queue_keys.pop_back();
- }
+ LOG_DEBUG(Service_Audio, "called {}", ctx.Description());
+ IPC::RequestParser rp{ctx};
+ const u64 max_count{ctx.GetWriteBufferSize() / sizeof(u64)};
+ const auto released_buffers{audio_core.GetTagsAndReleaseBuffers(stream, max_count)};
- ctx.WriteBuffer(&key, sizeof(u64));
+ std::vector<u64> tags{released_buffers};
+ tags.resize(max_count);
+ ctx.WriteBuffer(tags);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- // TODO(st4rk): This might be the total of released buffers, needs to be verified on
- // hardware
- rb.Push<u32>(static_cast<u32>(queue_keys.size()));
+ rb.Push<u32>(static_cast<u32>(released_buffers.size()));
}
- void UpdateAudioBuffersCallback() {
- if (audio_out_state != AudioState::Started) {
- return;
- }
-
- if (queue_keys.empty()) {
- return;
- }
+ void ContainsAudioOutBuffer(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+ IPC::RequestParser rp{ctx};
+ const u64 tag{rp.Pop<u64>()};
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(stream->ContainsBuffer(tag));
+ }
- buffer_event->Signal();
+ void GetAudioOutBufferCount(Kernel::HLERequestContext& ctx) {
+ LOG_DEBUG(Service_Audio, "called");
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(static_cast<u32>(stream->GetQueueSize()));
}
- enum class AudioState : u32 {
- Started,
- Stopped,
- };
+ AudioCore::AudioOut& audio_core;
+ AudioCore::StreamPtr stream;
- /// This is used to trigger the audio event callback that is going to read the samples from the
- /// audio_buffer list and enqueue the samples using the sink (audio_core).
- CoreTiming::EventType* audio_event;
+ AudoutParams audio_params{};
/// This is the evend handle used to check if the audio buffer was released
Kernel::SharedPtr<Kernel::Event> buffer_event;
-
- /// (st4rk): This is just a temporary workaround for the future implementation. Libtransistor
- /// uses the key as an address in the App, so we need to return when the
- /// GetReleasedAudioOutBuffer_1 is called, otherwise we'll run in problems, because
- /// libtransistor uses the key returned as an pointer.
- std::vector<u64> queue_keys;
-
- AudioState audio_out_state;
};
void AudOutU::ListAudioOutsImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
IPC::RequestParser rp{ctx};
- constexpr std::array<char, 15> audio_interface{{"AudioInterface"}};
- ctx.WriteBuffer(audio_interface);
+ ctx.WriteBuffer(DefaultDevice);
IPC::ResponseBuilder rb = rp.MakeBuilder(3, 0, 0);
rb.Push(RESULT_SUCCESS);
- // TODO(st4rk): We're currently returning only one audio interface (stringlist size). However,
- // it's highly possible to have more than one interface (despite that libtransistor requires
- // only one).
- rb.Push<u32>(1);
+ rb.Push<u32>(1); // Amount of audio devices
}
void AudOutU::OpenAudioOutImpl(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ LOG_DEBUG(Service_Audio, "called");
- if (!audio_out_interface) {
- audio_out_interface = std::make_shared<IAudioOut>();
+ ctx.WriteBuffer(DefaultDevice);
+ IPC::RequestParser rp{ctx};
+ auto params{rp.PopRaw<AudoutParams>()};
+ if (params.channel_count <= 2) {
+ // Mono does not exist for audout
+ params.channel_count = 2;
+ } else {
+ params.channel_count = 6;
}
+ if (!params.sample_rate) {
+ params.sample_rate = DefaultSampleRate;
+ }
+
+ // TODO(bunnei): Support more than one IAudioOut interface. When we add this, ListAudioOutsImpl
+ // will likely need to be updated as well.
+ ASSERT_MSG(!audio_out_interface, "Unimplemented");
+ audio_out_interface = std::make_shared<IAudioOut>(std::move(params), *audio_core);
IPC::ResponseBuilder rb{ctx, 6, 0, 1};
rb.Push(RESULT_SUCCESS);
- rb.Push<u32>(sample_rate);
- rb.Push<u32>(audio_channels);
+ rb.Push<u32>(DefaultSampleRate);
+ rb.Push<u32>(params.channel_count);
rb.Push<u32>(static_cast<u32>(PcmFormat::Int16));
- rb.Push<u32>(0); // This field is unknown
+ rb.Push<u32>(static_cast<u32>(AudioState::Stopped));
rb.PushIpcInterface<Audio::IAudioOut>(audio_out_interface);
}
@@ -203,6 +211,7 @@ AudOutU::AudOutU() : ServiceFramework("audout:u") {
{2, &AudOutU::ListAudioOutsImpl, "ListAudioOutsAuto"},
{3, &AudOutU::OpenAudioOutImpl, "OpenAudioOutAuto"}};
RegisterHandlers(functions);
+ audio_core = std::make_unique<AudioCore::AudioOut>();
}
} // namespace Service::Audio
diff --git a/src/core/hle/service/audio/audout_u.h b/src/core/hle/service/audio/audout_u.h
index 847d86aa6..e5c2184d5 100644
--- a/src/core/hle/service/audio/audout_u.h
+++ b/src/core/hle/service/audio/audout_u.h
@@ -4,6 +4,7 @@
#pragma once
+#include "audio_core/audio_out.h"
#include "core/hle/service/service.h"
namespace Kernel {
@@ -12,6 +13,18 @@ class HLERequestContext;
namespace Service::Audio {
+struct AudoutParams {
+ s32_le sample_rate;
+ u16_le channel_count;
+ INSERT_PADDING_BYTES(2);
+};
+static_assert(sizeof(AudoutParams) == 0x8, "AudoutParams is an invalid size");
+
+enum class AudioState : u32 {
+ Started,
+ Stopped,
+};
+
class IAudioOut;
class AudOutU final : public ServiceFramework<AudOutU> {
@@ -21,6 +34,7 @@ public:
private:
std::shared_ptr<IAudioOut> audio_out_interface;
+ std::unique_ptr<AudioCore::AudioOut> audio_core;
void ListAudioOutsImpl(Kernel::HLERequestContext& ctx);
void OpenAudioOutImpl(Kernel::HLERequestContext& ctx);
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index 844df382c..371cd4997 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cstring>
+#include <opus.h>
#include "common/logging/log.h"
#include "core/hle/ipc_helpers.h"
#include "core/hle/kernel/hle_ipc.h"
@@ -9,19 +11,142 @@
namespace Service::Audio {
+struct OpusDeleter {
+ void operator()(void* ptr) const {
+ operator delete(ptr);
+ }
+};
+
+class IHardwareOpusDecoderManager final : public ServiceFramework<IHardwareOpusDecoderManager> {
+public:
+ IHardwareOpusDecoderManager(std::unique_ptr<OpusDecoder, OpusDeleter> decoder, u32 sample_rate,
+ u32 channel_count)
+ : ServiceFramework("IHardwareOpusDecoderManager"), decoder(std::move(decoder)),
+ sample_rate(sample_rate), channel_count(channel_count) {
+ static const FunctionInfo functions[] = {
+ {0, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
+ {1, nullptr, "SetContext"},
+ {2, nullptr, "DecodeInterleavedForMultiStream"},
+ {3, nullptr, "SetContextForMultiStream"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ };
+ RegisterHandlers(functions);
+ }
+
+private:
+ void DecodeInterleaved(Kernel::HLERequestContext& ctx) {
+ u32 consumed = 0;
+ u32 sample_count = 0;
+ std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
+ if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples)) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ // TODO(ogniK): Use correct error code
+ rb.Push(ResultCode(-1));
+ return;
+ }
+ IPC::ResponseBuilder rb{ctx, 4};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(consumed);
+ rb.Push<u32>(sample_count);
+ ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
+ }
+
+ bool Decoder_DecodeInterleaved(u32& consumed, u32& sample_count, const std::vector<u8>& input,
+ std::vector<opus_int16>& output) {
+ size_t raw_output_sz = output.size() * sizeof(opus_int16);
+ if (sizeof(OpusHeader) > input.size())
+ return false;
+ OpusHeader hdr{};
+ std::memcpy(&hdr, input.data(), sizeof(OpusHeader));
+ if (sizeof(OpusHeader) + static_cast<u32>(hdr.sz) > input.size()) {
+ return false;
+ }
+ auto frame = input.data() + sizeof(OpusHeader);
+ auto decoded_sample_count = opus_packet_get_nb_samples(
+ frame, static_cast<opus_int32>(input.size() - sizeof(OpusHeader)),
+ static_cast<opus_int32>(sample_rate));
+ if (decoded_sample_count * channel_count * sizeof(u16) > raw_output_sz)
+ return false;
+ auto out_sample_count =
+ opus_decode(decoder.get(), frame, hdr.sz, output.data(),
+ (static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)), 0);
+ if (out_sample_count < 0)
+ return false;
+ sample_count = out_sample_count;
+ consumed = static_cast<u32>(sizeof(OpusHeader) + hdr.sz);
+ return true;
+ }
+
+ struct OpusHeader {
+ u32_be sz; // Needs to be BE for some odd reason
+ INSERT_PADDING_WORDS(1);
+ };
+ static_assert(sizeof(OpusHeader) == 0x8, "OpusHeader is an invalid size");
+
+ std::unique_ptr<OpusDecoder, OpusDeleter> decoder;
+ u32 sample_rate;
+ u32 channel_count;
+};
+
+static size_t WorkerBufferSize(u32 channel_count) {
+ ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
+ return opus_decoder_get_size(static_cast<int>(channel_count));
+}
+
void HwOpus::GetWorkBufferSize(Kernel::HLERequestContext& ctx) {
- LOG_WARNING(Service_Audio, "(STUBBED) called");
+ IPC::RequestParser rp{ctx};
+ auto sample_rate = rp.Pop<u32>();
+ auto channel_count = rp.Pop<u32>();
+ ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
+ sample_rate == 12000 || sample_rate == 8000,
+ "Invalid sample rate");
+ ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
+ u32 worker_buffer_sz = static_cast<u32>(WorkerBufferSize(channel_count));
+ LOG_DEBUG(Audio, "called worker_buffer_sz={}", worker_buffer_sz);
+
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- rb.Push<u32>(0x4000);
+ rb.Push<u32>(worker_buffer_sz);
+}
+
+void HwOpus::OpenOpusDecoder(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ auto sample_rate = rp.Pop<u32>();
+ auto channel_count = rp.Pop<u32>();
+ auto buffer_sz = rp.Pop<u32>();
+ LOG_DEBUG(Audio, "called sample_rate={}, channel_count={}, buffer_size={}", sample_rate,
+ channel_count, buffer_sz);
+ ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
+ sample_rate == 12000 || sample_rate == 8000,
+ "Invalid sample rate");
+ ASSERT_MSG(channel_count == 1 || channel_count == 2, "Invalid channel count");
+
+ size_t worker_sz = WorkerBufferSize(channel_count);
+ ASSERT_MSG(buffer_sz < worker_sz, "Worker buffer too large");
+ std::unique_ptr<OpusDecoder, OpusDeleter> decoder{
+ static_cast<OpusDecoder*>(operator new(worker_sz))};
+ if (opus_decoder_init(decoder.get(), sample_rate, channel_count)) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ // TODO(ogniK): Use correct error code
+ rb.Push(ResultCode(-1));
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IHardwareOpusDecoderManager>(std::move(decoder), sample_rate,
+ channel_count);
}
HwOpus::HwOpus() : ServiceFramework("hwopus") {
static const FunctionInfo functions[] = {
- {0, nullptr, "Initialize"},
+ {0, &HwOpus::OpenOpusDecoder, "OpenOpusDecoder"},
{1, &HwOpus::GetWorkBufferSize, "GetWorkBufferSize"},
- {2, nullptr, "InitializeMultiStream"},
- {3, nullptr, "GetWorkBufferSizeMultiStream"},
+ {2, nullptr, "OpenOpusDecoderForMultiStream"},
+ {3, nullptr, "GetWorkBufferSizeForMultiStream"},
};
RegisterHandlers(functions);
}
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
index 090b8c825..5258d59f3 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hwopus.h
@@ -14,6 +14,7 @@ public:
~HwOpus() = default;
private:
+ void OpenOpusDecoder(Kernel::HLERequestContext& ctx);
void GetWorkBufferSize(Kernel::HLERequestContext& ctx);
};
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
new file mode 100644
index 000000000..d0a15cc4c
--- /dev/null
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -0,0 +1,72 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/btdrv/btdrv.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::BtDrv {
+
+class BtDrv final : public ServiceFramework<BtDrv> {
+public:
+ explicit BtDrv() : ServiceFramework{"btdrv"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown"},
+ {1, nullptr, "Init"},
+ {2, nullptr, "Enable"},
+ {3, nullptr, "Disable"},
+ {4, nullptr, "CleanupAndShutdown"},
+ {5, nullptr, "GetAdapterProperties"},
+ {6, nullptr, "GetAdapterProperty"},
+ {7, nullptr, "SetAdapterProperty"},
+ {8, nullptr, "StartDiscovery"},
+ {9, nullptr, "CancelDiscovery"},
+ {10, nullptr, "CreateBond"},
+ {11, nullptr, "RemoveBond"},
+ {12, nullptr, "CancelBond"},
+ {13, nullptr, "PinReply"},
+ {14, nullptr, "SspReply"},
+ {15, nullptr, "Unknown2"},
+ {16, nullptr, "InitInterfaces"},
+ {17, nullptr, "HidHostInterface_Connect"},
+ {18, nullptr, "HidHostInterface_Disconnect"},
+ {19, nullptr, "HidHostInterface_SendData"},
+ {20, nullptr, "HidHostInterface_SendData2"},
+ {21, nullptr, "HidHostInterface_SetReport"},
+ {22, nullptr, "HidHostInterface_GetReport"},
+ {23, nullptr, "HidHostInterface_WakeController"},
+ {24, nullptr, "HidHostInterface_AddPairedDevice"},
+ {25, nullptr, "HidHostInterface_GetPairedDevice"},
+ {26, nullptr, "HidHostInterface_CleanupAndShutdown"},
+ {27, nullptr, "Unknown3"},
+ {28, nullptr, "ExtInterface_SetTSI"},
+ {29, nullptr, "ExtInterface_SetBurstMode"},
+ {30, nullptr, "ExtInterface_SetZeroRetran"},
+ {31, nullptr, "ExtInterface_SetMcMode"},
+ {32, nullptr, "ExtInterface_StartLlrMode"},
+ {33, nullptr, "ExtInterface_ExitLlrMode"},
+ {34, nullptr, "ExtInterface_SetRadio"},
+ {35, nullptr, "ExtInterface_SetVisibility"},
+ {36, nullptr, "Unknown4"},
+ {37, nullptr, "Unknown5"},
+ {38, nullptr, "HidHostInterface_GetLatestPlr"},
+ {39, nullptr, "ExtInterface_GetPendingConnections"},
+ {40, nullptr, "HidHostInterface_GetChannelMap"},
+ {41, nullptr, "SetIsBluetoothBoostEnabled"},
+ {42, nullptr, "GetIsBluetoothBoostEnabled"},
+ {43, nullptr, "SetIsBluetoothAfhEnabled"},
+ {44, nullptr, "GetIsBluetoothAfhEnabled"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<BtDrv>()->InstallAsService(sm);
+}
+
+} // namespace Service::BtDrv
diff --git a/src/core/hle/service/btdrv/btdrv.h b/src/core/hle/service/btdrv/btdrv.h
new file mode 100644
index 000000000..164e56f43
--- /dev/null
+++ b/src/core/hle/service/btdrv/btdrv.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::BtDrv {
+
+/// Registers all BtDrv services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::BtDrv
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
new file mode 100644
index 000000000..b949bfabd
--- /dev/null
+++ b/src/core/hle/service/btm/btm.cpp
@@ -0,0 +1,121 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/btm/btm.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::BTM {
+
+class BTM final : public ServiceFramework<BTM> {
+public:
+ explicit BTM() : ServiceFramework{"btm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "RegisterSystemEventForConnectedDeviceConditionImpl"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ {8, nullptr, "RegisterSystemEventForRegisteredDeviceInfoImpl"},
+ {9, nullptr, "Unknown8"},
+ {10, nullptr, "Unknown9"},
+ {11, nullptr, "Unknown10"},
+ {12, nullptr, "Unknown11"},
+ {13, nullptr, "Unknown12"},
+ {14, nullptr, "EnableRadioImpl"},
+ {15, nullptr, "DisableRadioImpl"},
+ {16, nullptr, "Unknown13"},
+ {17, nullptr, "Unknown14"},
+ {18, nullptr, "Unknown15"},
+ {19, nullptr, "Unknown16"},
+ {20, nullptr, "Unknown17"},
+ {21, nullptr, "Unknown18"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class BTM_DBG final : public ServiceFramework<BTM_DBG> {
+public:
+ explicit BTM_DBG() : ServiceFramework{"btm:dbg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RegisterSystemEventForDiscoveryImpl"},
+ {1, nullptr, "Unknown1"},
+ {2, nullptr, "Unknown2"},
+ {3, nullptr, "Unknown3"},
+ {4, nullptr, "Unknown4"},
+ {5, nullptr, "Unknown5"},
+ {6, nullptr, "Unknown6"},
+ {7, nullptr, "Unknown7"},
+ {8, nullptr, "Unknown8"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class IBtmSystemCore final : public ServiceFramework<IBtmSystemCore> {
+public:
+ explicit IBtmSystemCore() : ServiceFramework{"IBtmSystemCore"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "StartGamepadPairingImpl"},
+ {1, nullptr, "CancelGamepadPairingImpl"},
+ {2, nullptr, "ClearGamepadPairingDatabaseImpl"},
+ {3, nullptr, "GetPairedGamepadCountImpl"},
+ {4, nullptr, "EnableRadioImpl"},
+ {5, nullptr, "DisableRadioImpl"},
+ {6, nullptr, "GetRadioOnOffImpl"},
+ {7, nullptr, "AcquireRadioEventImpl"},
+ {8, nullptr, "AcquireGamepadPairingEventImpl"},
+ {9, nullptr, "IsGamepadPairingStartedImpl"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class BTM_SYS final : public ServiceFramework<BTM_SYS> {
+public:
+ explicit BTM_SYS() : ServiceFramework{"btm:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &BTM_SYS::GetCoreImpl, "GetCoreImpl"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetCoreImpl(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IBtmSystemCore>();
+
+ LOG_DEBUG(Service_BTM, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<BTM>()->InstallAsService(sm);
+ std::make_shared<BTM_DBG>()->InstallAsService(sm);
+ std::make_shared<BTM_SYS>()->InstallAsService(sm);
+}
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/btm/btm.h b/src/core/hle/service/btm/btm.h
new file mode 100644
index 000000000..e6425a7e3
--- /dev/null
+++ b/src/core/hle/service/btm/btm.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::BTM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::BTM
diff --git a/src/core/hle/service/fgm/fgm.cpp b/src/core/hle/service/fgm/fgm.cpp
new file mode 100644
index 000000000..566fbf924
--- /dev/null
+++ b/src/core/hle/service/fgm/fgm.cpp
@@ -0,0 +1,75 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/fgm/fgm.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::FGM {
+
+class IRequest final : public ServiceFramework<IRequest> {
+public:
+ explicit IRequest() : ServiceFramework{"IRequest"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Set"},
+ {2, nullptr, "Get"},
+ {3, nullptr, "Cancel"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class FGM final : public ServiceFramework<FGM> {
+public:
+ explicit FGM(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &FGM::Initialize, "Initialize"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void Initialize(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IRequest>();
+
+ LOG_DEBUG(Service_FGM, "called");
+ }
+};
+
+class FGM_DBG final : public ServiceFramework<FGM_DBG> {
+public:
+ explicit FGM_DBG() : ServiceFramework{"fgm:dbg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Read"},
+ {2, nullptr, "Cancel"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<FGM>("fgm")->InstallAsService(sm);
+ std::make_shared<FGM>("fgm:0")->InstallAsService(sm);
+ std::make_shared<FGM>("fgm:9")->InstallAsService(sm);
+ std::make_shared<FGM_DBG>()->InstallAsService(sm);
+}
+
+} // namespace Service::FGM
diff --git a/src/core/hle/service/fgm/fgm.h b/src/core/hle/service/fgm/fgm.h
new file mode 100644
index 000000000..e59691264
--- /dev/null
+++ b/src/core/hle/service/fgm/fgm.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::FGM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::FGM
diff --git a/src/core/hle/service/grc/grc.cpp b/src/core/hle/service/grc/grc.cpp
new file mode 100644
index 000000000..24910ac6c
--- /dev/null
+++ b/src/core/hle/service/grc/grc.cpp
@@ -0,0 +1,31 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/grc/grc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::GRC {
+
+class GRC final : public ServiceFramework<GRC> {
+public:
+ explicit GRC() : ServiceFramework{"grc:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, nullptr, "OpenContinuousRecorder"},
+ {2, nullptr, "OpenGameMovieTrimmer"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<GRC>()->InstallAsService(sm);
+}
+
+} // namespace Service::GRC
diff --git a/src/core/hle/service/grc/grc.h b/src/core/hle/service/grc/grc.h
new file mode 100644
index 000000000..e0d29e70d
--- /dev/null
+++ b/src/core/hle/service/grc/grc.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::GRC {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::GRC
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 9a02ba686..ed53f96c5 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -14,6 +14,8 @@
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/hid/hid.h"
+#include "core/hle/service/hid/irs.h"
+#include "core/hle/service/hid/xcd.h"
#include "core/hle/service/service.h"
namespace Service::HID {
@@ -324,7 +326,7 @@ public:
{79, &Hid::SetGyroscopeZeroDriftMode, "SetGyroscopeZeroDriftMode"},
{80, nullptr, "GetGyroscopeZeroDriftMode"},
{81, nullptr, "ResetGyroscopeZeroDriftMode"},
- {82, nullptr, "IsSixAxisSensorAtRest"},
+ {82, &Hid::IsSixAxisSensorAtRest, "IsSixAxisSensorAtRest"},
{91, nullptr, "ActivateGesture"},
{100, &Hid::SetSupportedNpadStyleSet, "SetSupportedNpadStyleSet"},
{101, &Hid::GetSupportedNpadStyleSet, "GetSupportedNpadStyleSet"},
@@ -341,7 +343,7 @@ public:
"SetNpadJoyAssignmentModeSingleByDefault"},
{123, nullptr, "SetNpadJoyAssignmentModeSingleByDefault"},
{124, &Hid::SetNpadJoyAssignmentModeDual, "SetNpadJoyAssignmentModeDual"},
- {125, nullptr, "MergeSingleJoyAsDualJoy"},
+ {125, &Hid::MergeSingleJoyAsDualJoy, "MergeSingleJoyAsDualJoy"},
{126, nullptr, "StartLrAssignmentMode"},
{127, nullptr, "StopLrAssignmentMode"},
{128, &Hid::SetNpadHandheldActivationMode, "SetNpadHandheldActivationMode"},
@@ -453,6 +455,14 @@ private:
LOG_WARNING(Service_HID, "(STUBBED) called");
}
+ void IsSixAxisSensorAtRest(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ // TODO (Hexagon12): Properly implement reading gyroscope values from controllers.
+ rb.Push(true);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
+
void SetSupportedNpadStyleSet(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -528,6 +538,12 @@ private:
LOG_WARNING(Service_HID, "(STUBBED) called");
}
+ void MergeSingleJoyAsDualJoy(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ LOG_WARNING(Service_HID, "(STUBBED) called");
+ }
+
void SetNpadHandheldActivationMode(Kernel::HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(RESULT_SUCCESS);
@@ -555,10 +571,233 @@ private:
}
};
+class HidDbg final : public ServiceFramework<HidDbg> {
+public:
+ explicit HidDbg() : ServiceFramework{"hid:dbg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "DeactivateDebugPad"},
+ {1, nullptr, "SetDebugPadAutoPilotState"},
+ {2, nullptr, "UnsetDebugPadAutoPilotState"},
+ {10, nullptr, "DeactivateTouchScreen"},
+ {11, nullptr, "SetTouchScreenAutoPilotState"},
+ {12, nullptr, "UnsetTouchScreenAutoPilotState"},
+ {20, nullptr, "DeactivateMouse"},
+ {21, nullptr, "SetMouseAutoPilotState"},
+ {22, nullptr, "UnsetMouseAutoPilotState"},
+ {30, nullptr, "DeactivateKeyboard"},
+ {31, nullptr, "SetKeyboardAutoPilotState"},
+ {32, nullptr, "UnsetKeyboardAutoPilotState"},
+ {50, nullptr, "DeactivateXpad"},
+ {51, nullptr, "SetXpadAutoPilotState"},
+ {52, nullptr, "UnsetXpadAutoPilotState"},
+ {60, nullptr, "DeactivateJoyXpad"},
+ {91, nullptr, "DeactivateGesture"},
+ {110, nullptr, "DeactivateHomeButton"},
+ {111, nullptr, "SetHomeButtonAutoPilotState"},
+ {112, nullptr, "UnsetHomeButtonAutoPilotState"},
+ {120, nullptr, "DeactivateSleepButton"},
+ {121, nullptr, "SetSleepButtonAutoPilotState"},
+ {122, nullptr, "UnsetSleepButtonAutoPilotState"},
+ {123, nullptr, "DeactivateInputDetector"},
+ {130, nullptr, "DeactivateCaptureButton"},
+ {131, nullptr, "SetCaptureButtonAutoPilotState"},
+ {132, nullptr, "UnsetCaptureButtonAutoPilotState"},
+ {133, nullptr, "SetShiftAccelerometerCalibrationValue"},
+ {134, nullptr, "GetShiftAccelerometerCalibrationValue"},
+ {135, nullptr, "SetShiftGyroscopeCalibrationValue"},
+ {136, nullptr, "GetShiftGyroscopeCalibrationValue"},
+ {140, nullptr, "DeactivateConsoleSixAxisSensor"},
+ {141, nullptr, "GetConsoleSixAxisSensorSamplingFrequency"},
+ {142, nullptr, "DeactivateSevenSixAxisSensor"},
+ {201, nullptr, "ActivateFirmwareUpdate"},
+ {202, nullptr, "DeactivateFirmwareUpdate"},
+ {203, nullptr, "StartFirmwareUpdate"},
+ {204, nullptr, "GetFirmwareUpdateStage"},
+ {205, nullptr, "GetFirmwareVersion"},
+ {206, nullptr, "GetDestinationFirmwareVersion"},
+ {207, nullptr, "DiscardFirmwareInfoCacheForRevert"},
+ {208, nullptr, "StartFirmwareUpdateForRevert"},
+ {209, nullptr, "GetAvailableFirmwareVersionForRevert"},
+ {210, nullptr, "IsFirmwareUpdatingDevice"},
+ {221, nullptr, "UpdateControllerColor"},
+ {222, nullptr, "ConnectUsbPadsAsync"},
+ {223, nullptr, "DisconnectUsbPadsAsync"},
+ {224, nullptr, "UpdateDesignInfo"},
+ {225, nullptr, "GetUniquePadDriverState"},
+ {226, nullptr, "GetSixAxisSensorDriverStates"},
+ {301, nullptr, "GetAbstractedPadHandles"},
+ {302, nullptr, "GetAbstractedPadState"},
+ {303, nullptr, "GetAbstractedPadsState"},
+ {321, nullptr, "SetAutoPilotVirtualPadState"},
+ {322, nullptr, "UnsetAutoPilotVirtualPadState"},
+ {323, nullptr, "UnsetAllAutoPilotVirtualPadState"},
+ {350, nullptr, "AddRegisteredDevice"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class HidSys final : public ServiceFramework<HidSys> {
+public:
+ explicit HidSys() : ServiceFramework{"hid:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {31, nullptr, "SendKeyboardLockKeyEvent"},
+ {101, nullptr, "AcquireHomeButtonEventHandle"},
+ {111, nullptr, "ActivateHomeButton"},
+ {121, nullptr, "AcquireSleepButtonEventHandle"},
+ {131, nullptr, "ActivateSleepButton"},
+ {141, nullptr, "AcquireCaptureButtonEventHandle"},
+ {151, nullptr, "ActivateCaptureButton"},
+ {210, nullptr, "AcquireNfcDeviceUpdateEventHandle"},
+ {211, nullptr, "GetNpadsWithNfc"},
+ {212, nullptr, "AcquireNfcActivateEventHandle"},
+ {213, nullptr, "ActivateNfc"},
+ {214, nullptr, "GetXcdHandleForNpadWithNfc"},
+ {215, nullptr, "IsNfcActivated"},
+ {230, nullptr, "AcquireIrSensorEventHandle"},
+ {231, nullptr, "ActivateIrSensor"},
+ {301, nullptr, "ActivateNpadSystem"},
+ {303, nullptr, "ApplyNpadSystemCommonPolicy"},
+ {304, nullptr, "EnableAssigningSingleOnSlSrPress"},
+ {305, nullptr, "DisableAssigningSingleOnSlSrPress"},
+ {306, nullptr, "GetLastActiveNpad"},
+ {307, nullptr, "GetNpadSystemExtStyle"},
+ {308, nullptr, "ApplyNpadSystemCommonPolicyFull"},
+ {309, nullptr, "GetNpadFullKeyGripColor"},
+ {311, nullptr, "SetNpadPlayerLedBlinkingDevice"},
+ {321, nullptr, "GetUniquePadsFromNpad"},
+ {322, nullptr, "GetIrSensorState"},
+ {323, nullptr, "GetXcdHandleForNpadWithIrSensor"},
+ {500, nullptr, "SetAppletResourceUserId"},
+ {501, nullptr, "RegisterAppletResourceUserId"},
+ {502, nullptr, "UnregisterAppletResourceUserId"},
+ {503, nullptr, "EnableAppletToGetInput"},
+ {504, nullptr, "SetAruidValidForVibration"},
+ {505, nullptr, "EnableAppletToGetSixAxisSensor"},
+ {510, nullptr, "SetVibrationMasterVolume"},
+ {511, nullptr, "GetVibrationMasterVolume"},
+ {512, nullptr, "BeginPermitVibrationSession"},
+ {513, nullptr, "EndPermitVibrationSession"},
+ {520, nullptr, "EnableHandheldHids"},
+ {521, nullptr, "DisableHandheldHids"},
+ {540, nullptr, "AcquirePlayReportControllerUsageUpdateEvent"},
+ {541, nullptr, "GetPlayReportControllerUsages"},
+ {542, nullptr, "AcquirePlayReportRegisteredDeviceUpdateEvent"},
+ {543, nullptr, "GetRegisteredDevicesOld"},
+ {544, nullptr, "AcquireConnectionTriggerTimeoutEvent"},
+ {545, nullptr, "SendConnectionTrigger"},
+ {546, nullptr, "AcquireDeviceRegisteredEventForControllerSupport"},
+ {547, nullptr, "GetAllowedBluetoothLinksCount"},
+ {548, nullptr, "GetRegisteredDevices"},
+ {700, nullptr, "ActivateUniquePad"},
+ {702, nullptr, "AcquireUniquePadConnectionEventHandle"},
+ {703, nullptr, "GetUniquePadIds"},
+ {751, nullptr, "AcquireJoyDetachOnBluetoothOffEventHandle"},
+ {800, nullptr, "ListSixAxisSensorHandles"},
+ {801, nullptr, "IsSixAxisSensorUserCalibrationSupported"},
+ {802, nullptr, "ResetSixAxisSensorCalibrationValues"},
+ {803, nullptr, "StartSixAxisSensorUserCalibration"},
+ {804, nullptr, "CancelSixAxisSensorUserCalibration"},
+ {805, nullptr, "GetUniquePadBluetoothAddress"},
+ {806, nullptr, "DisconnectUniquePad"},
+ {807, nullptr, "GetUniquePadType"},
+ {808, nullptr, "GetUniquePadInterface"},
+ {809, nullptr, "GetUniquePadSerialNumber"},
+ {810, nullptr, "GetUniquePadControllerNumber"},
+ {811, nullptr, "GetSixAxisSensorUserCalibrationStage"},
+ {821, nullptr, "StartAnalogStickManualCalibration"},
+ {822, nullptr, "RetryCurrentAnalogStickManualCalibrationStage"},
+ {823, nullptr, "CancelAnalogStickManualCalibration"},
+ {824, nullptr, "ResetAnalogStickManualCalibration"},
+ {825, nullptr, "GetAnalogStickState"},
+ {826, nullptr, "GetAnalogStickManualCalibrationStage"},
+ {827, nullptr, "IsAnalogStickButtonPressed"},
+ {828, nullptr, "IsAnalogStickInReleasePosition"},
+ {829, nullptr, "IsAnalogStickInCircumference"},
+ {850, nullptr, "IsUsbFullKeyControllerEnabled"},
+ {851, nullptr, "EnableUsbFullKeyController"},
+ {852, nullptr, "IsUsbConnected"},
+ {900, nullptr, "ActivateInputDetector"},
+ {901, nullptr, "NotifyInputDetector"},
+ {1000, nullptr, "InitializeFirmwareUpdate"},
+ {1001, nullptr, "GetFirmwareVersion"},
+ {1002, nullptr, "GetAvailableFirmwareVersion"},
+ {1003, nullptr, "IsFirmwareUpdateAvailable"},
+ {1004, nullptr, "CheckFirmwareUpdateRequired"},
+ {1005, nullptr, "StartFirmwareUpdate"},
+ {1006, nullptr, "AbortFirmwareUpdate"},
+ {1007, nullptr, "GetFirmwareUpdateState"},
+ {1008, nullptr, "ActivateAudioControl"},
+ {1009, nullptr, "AcquireAudioControlEventHandle"},
+ {1010, nullptr, "GetAudioControlStates"},
+ {1011, nullptr, "DeactivateAudioControl"},
+ {1050, nullptr, "IsSixAxisSensorAccurateUserCalibrationSupported"},
+ {1051, nullptr, "StartSixAxisSensorAccurateUserCalibration"},
+ {1052, nullptr, "CancelSixAxisSensorAccurateUserCalibration"},
+ {1053, nullptr, "GetSixAxisSensorAccurateUserCalibrationState"},
+ {1100, nullptr, "GetHidbusSystemServiceObject"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class HidTmp final : public ServiceFramework<HidTmp> {
+public:
+ explicit HidTmp() : ServiceFramework{"hid:tmp"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetConsoleSixAxisSensorCalibrationValues"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class HidBus final : public ServiceFramework<HidBus> {
+public:
+ explicit HidBus() : ServiceFramework{"hidbus"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {1, nullptr, "GetBusHandle"},
+ {2, nullptr, "IsExternalDeviceConnected"},
+ {3, nullptr, "Initialize"},
+ {4, nullptr, "Finalize"},
+ {5, nullptr, "EnableExternalDevice"},
+ {6, nullptr, "GetExternalDeviceId"},
+ {7, nullptr, "SendCommandAsync"},
+ {8, nullptr, "GetSendCommandAsynceResult"},
+ {9, nullptr, "SetEventForSendCommandAsycResult"},
+ {10, nullptr, "GetSharedMemoryHandle"},
+ {11, nullptr, "EnableJoyPollingReceiveMode"},
+ {12, nullptr, "DisableJoyPollingReceiveMode"},
+ {13, nullptr, "GetPollingData"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
void ReloadInputDevices() {}
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<Hid>()->InstallAsService(service_manager);
+ std::make_shared<HidBus>()->InstallAsService(service_manager);
+ std::make_shared<HidDbg>()->InstallAsService(service_manager);
+ std::make_shared<HidSys>()->InstallAsService(service_manager);
+ std::make_shared<HidTmp>()->InstallAsService(service_manager);
+
+ std::make_shared<IRS>()->InstallAsService(service_manager);
+ std::make_shared<IRS_SYS>()->InstallAsService(service_manager);
+
+ std::make_shared<XCD_SYS>()->InstallAsService(service_manager);
}
} // namespace Service::HID
diff --git a/src/core/hle/service/hid/irs.cpp b/src/core/hle/service/hid/irs.cpp
new file mode 100644
index 000000000..aaf311912
--- /dev/null
+++ b/src/core/hle/service/hid/irs.cpp
@@ -0,0 +1,49 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/hid/irs.h"
+
+namespace Service::HID {
+
+IRS::IRS() : ServiceFramework{"irs"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {302, nullptr, "ActivateIrsensor"},
+ {303, nullptr, "DeactivateIrsensor"},
+ {304, nullptr, "GetIrsensorSharedMemoryHandle"},
+ {305, nullptr, "StopImageProcessor"},
+ {306, nullptr, "RunMomentProcessor"},
+ {307, nullptr, "RunClusteringProcessor"},
+ {308, nullptr, "RunImageTransferProcessor"},
+ {309, nullptr, "GetImageTransferProcessorState"},
+ {310, nullptr, "RunTeraPluginProcessor"},
+ {311, nullptr, "GetNpadIrCameraHandle"},
+ {312, nullptr, "RunPointingProcessor"},
+ {313, nullptr, "SuspendImageProcessor"},
+ {314, nullptr, "CheckFirmwareVersion"},
+ {315, nullptr, "SetFunctionLevel"},
+ {316, nullptr, "RunImageTransferExProcessor"},
+ {317, nullptr, "RunIrLedProcessor"},
+ {318, nullptr, "StopImageProcessorAsync"},
+ {319, nullptr, "ActivateIrsensorWithFunctionLevel"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+IRS_SYS::IRS_SYS() : ServiceFramework{"irs:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {500, nullptr, "SetAppletResourceUserId"},
+ {501, nullptr, "RegisterAppletResourceUserId"},
+ {502, nullptr, "UnregisterAppletResourceUserId"},
+ {503, nullptr, "EnableAppletToGetInput"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/irs.h b/src/core/hle/service/hid/irs.h
new file mode 100644
index 000000000..a8be701c7
--- /dev/null
+++ b/src/core/hle/service/hid/irs.h
@@ -0,0 +1,21 @@
+// 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::HID {
+
+class IRS final : public ServiceFramework<IRS> {
+public:
+ explicit IRS();
+};
+
+class IRS_SYS final : public ServiceFramework<IRS_SYS> {
+public:
+ explicit IRS_SYS();
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/xcd.cpp b/src/core/hle/service/hid/xcd.cpp
new file mode 100644
index 000000000..49f733f60
--- /dev/null
+++ b/src/core/hle/service/hid/xcd.cpp
@@ -0,0 +1,37 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/hid/xcd.h"
+
+namespace Service::HID {
+
+XCD_SYS::XCD_SYS() : ServiceFramework{"xcd:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetDataFormat"},
+ {1, nullptr, "SetDataFormat"},
+ {2, nullptr, "GetMcuState"},
+ {3, nullptr, "SetMcuState"},
+ {4, nullptr, "GetMcuVersionForNfc"},
+ {5, nullptr, "CheckNfcDevicePower"},
+ {10, nullptr, "SetNfcEvent"},
+ {11, nullptr, "GetNfcInfo"},
+ {12, nullptr, "StartNfcDiscovery"},
+ {13, nullptr, "StopNfcDiscovery"},
+ {14, nullptr, "StartNtagRead"},
+ {15, nullptr, "StartNtagWrite"},
+ {16, nullptr, "SendNfcRawData"},
+ {17, nullptr, "RegisterMifareKey"},
+ {18, nullptr, "ClearMifareKey"},
+ {19, nullptr, "StartMifareRead"},
+ {20, nullptr, "StartMifareWrite"},
+ {101, nullptr, "GetAwakeTriggerReasonForLeftRail"},
+ {102, nullptr, "GetAwakeTriggerReasonForRightRail"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/hid/xcd.h b/src/core/hle/service/hid/xcd.h
new file mode 100644
index 000000000..232a044df
--- /dev/null
+++ b/src/core/hle/service/hid/xcd.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+namespace Service::HID {
+
+class XCD_SYS final : public ServiceFramework<XCD_SYS> {
+public:
+ explicit XCD_SYS();
+};
+
+} // namespace Service::HID
diff --git a/src/core/hle/service/lbl/lbl.cpp b/src/core/hle/service/lbl/lbl.cpp
new file mode 100644
index 000000000..8fc8b1057
--- /dev/null
+++ b/src/core/hle/service/lbl/lbl.cpp
@@ -0,0 +1,90 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/lbl/lbl.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::LBL {
+
+class LBL final : public ServiceFramework<LBL> {
+public:
+ explicit LBL() : ServiceFramework{"lbl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "TurnOffBacklight"},
+ {7, nullptr, "TurnOnBacklight"},
+ {8, nullptr, "GetBacklightStatus"},
+ {9, nullptr, "Unknown7"},
+ {10, nullptr, "Unknown8"},
+ {11, nullptr, "Unknown9"},
+ {12, nullptr, "Unknown10"},
+ {13, nullptr, "Unknown11"},
+ {14, nullptr, "Unknown12"},
+ {15, nullptr, "Unknown13"},
+ {16, nullptr, "ReadRawLightSensor"},
+ {17, nullptr, "Unknown14"},
+ {18, nullptr, "Unknown15"},
+ {19, nullptr, "Unknown16"},
+ {20, nullptr, "Unknown17"},
+ {21, nullptr, "Unknown18"},
+ {22, nullptr, "Unknown19"},
+ {23, nullptr, "Unknown20"},
+ {24, nullptr, "Unknown21"},
+ {25, nullptr, "Unknown22"},
+ {26, &LBL::EnableVrMode, "EnableVrMode"},
+ {27, &LBL::DisableVrMode, "DisableVrMode"},
+ {28, &LBL::GetVrMode, "GetVrMode"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void EnableVrMode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+
+ vr_mode_enabled = true;
+
+ LOG_DEBUG(Service_LBL, "called");
+ }
+
+ void DisableVrMode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+
+ vr_mode_enabled = false;
+
+ LOG_DEBUG(Service_LBL, "called");
+ }
+
+ void GetVrMode(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 3};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push(vr_mode_enabled);
+
+ LOG_DEBUG(Service_LBL, "called");
+ }
+
+ bool vr_mode_enabled = false;
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<LBL>()->InstallAsService(sm);
+}
+
+} // namespace Service::LBL
diff --git a/src/core/hle/service/lbl/lbl.h b/src/core/hle/service/lbl/lbl.h
new file mode 100644
index 000000000..bf6f400f8
--- /dev/null
+++ b/src/core/hle/service/lbl/lbl.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::LBL {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::LBL
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
new file mode 100644
index 000000000..167f2c66a
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -0,0 +1,142 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/result.h"
+#include "core/hle/service/ldn/ldn.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::LDN {
+
+class IMonitorService final : public ServiceFramework<IMonitorService> {
+public:
+ explicit IMonitorService() : ServiceFramework{"IMonitorService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetStateForMonitor"},
+ {1, nullptr, "GetNetworkInfoForMonitor"},
+ {2, nullptr, "GetIpv4AddressForMonitor"},
+ {3, nullptr, "GetDisconnectReasonForMonitor"},
+ {4, nullptr, "GetSecurityParameterForMonitor"},
+ {5, nullptr, "GetNetworkConfigForMonitor"},
+ {100, nullptr, "InitializeMonitor"},
+ {101, nullptr, "FinalizeMonitor"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class LDNM final : public ServiceFramework<LDNM> {
+public:
+ explicit LDNM() : ServiceFramework{"ldn:m"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LDNM::CreateMonitorService, "CreateMonitorService"}
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateMonitorService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IMonitorService>();
+
+ LOG_DEBUG(Service_LDN, "called");
+ }
+};
+
+class ILocalCommunicationService final : public ServiceFramework<ILocalCommunicationService> {
+public:
+ explicit ILocalCommunicationService(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetState"},
+ {1, nullptr, "GetNetworkInfo"},
+ {2, nullptr, "GetIpv4Address"},
+ {3, nullptr, "GetDisconnectReason"},
+ {4, nullptr, "GetSecurityParameter"},
+ {5, nullptr, "GetNetworkConfig"},
+ {100, nullptr, "AttachStateChangeEvent"},
+ {101, nullptr, "GetNetworkInfoLatestUpdate"},
+ {102, nullptr, "Scan"},
+ {103, nullptr, "ScanPrivate"},
+ {200, nullptr, "OpenAccessPoint"},
+ {201, nullptr, "CloseAccessPoint"},
+ {202, nullptr, "CreateNetwork"},
+ {203, nullptr, "CreateNetworkPrivate"},
+ {204, nullptr, "DestroyNetwork"},
+ {205, nullptr, "Reject"},
+ {206, nullptr, "SetAdvertiseData"},
+ {207, nullptr, "SetStationAcceptPolicy"},
+ {208, nullptr, "AddAcceptFilterEntry"},
+ {209, nullptr, "ClearAcceptFilter"},
+ {300, nullptr, "OpenStation"},
+ {301, nullptr, "CloseStation"},
+ {302, nullptr, "Connect"},
+ {303, nullptr, "ConnectPrivate"},
+ {304, nullptr, "Disconnect"},
+ {400, nullptr, "InitializeSystem"},
+ {401, nullptr, "FinalizeSystem"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class LDNS final : public ServiceFramework<LDNS> {
+public:
+ explicit LDNS() : ServiceFramework{"ldn:s"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LDNS::CreateSystemLocalCommunicationService, "CreateSystemLocalCommunicationService"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateSystemLocalCommunicationService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ILocalCommunicationService>("ISystemLocalCommunicationService");
+
+ LOG_DEBUG(Service_LDN, "called");
+ }
+};
+
+class LDNU final : public ServiceFramework<LDNU> {
+public:
+ explicit LDNU() : ServiceFramework{"ldn:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LDNU::CreateUserLocalCommunicationService, "CreateUserLocalCommunicationService"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateUserLocalCommunicationService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ILocalCommunicationService>("IUserLocalCommunicationService");
+
+ LOG_DEBUG(Service_LDN, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<LDNM>()->InstallAsService(sm);
+ std::make_shared<LDNS>()->InstallAsService(sm);
+ std::make_shared<LDNU>()->InstallAsService(sm);
+}
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/ldn/ldn.h b/src/core/hle/service/ldn/ldn.h
new file mode 100644
index 000000000..6b2a3c2b2
--- /dev/null
+++ b/src/core/hle/service/ldn/ldn.h
@@ -0,0 +1,16 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::LDN {
+
+/// Registers all LDN services with the specified service manager.
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::LDN
diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp
new file mode 100644
index 000000000..a6197124a
--- /dev/null
+++ b/src/core/hle/service/mii/mii.cpp
@@ -0,0 +1,107 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/mii/mii.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::Mii {
+
+class IDatabaseService final : public ServiceFramework<IDatabaseService> {
+public:
+ explicit IDatabaseService() : ServiceFramework{"IDatabaseService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "IsUpdated"},
+ {1, nullptr, "IsFullDatabase"},
+ {2, nullptr, "GetCount"},
+ {3, nullptr, "Get"},
+ {4, nullptr, "Get1"},
+ {5, nullptr, "UpdateLatest"},
+ {6, nullptr, "BuildRandom"},
+ {7, nullptr, "BuildDefault"},
+ {8, nullptr, "Get2"},
+ {9, nullptr, "Get3"},
+ {10, nullptr, "UpdateLatest1"},
+ {11, nullptr, "FindIndex"},
+ {12, nullptr, "Move"},
+ {13, nullptr, "AddOrReplace"},
+ {14, nullptr, "Delete"},
+ {15, nullptr, "DestroyFile"},
+ {16, nullptr, "DeleteFile"},
+ {17, nullptr, "Format"},
+ {18, nullptr, "Import"},
+ {19, nullptr, "Export"},
+ {20, nullptr, "IsBrokenDatabaseWithClearFlag"},
+ {21, nullptr, "GetIndex"},
+ {22, nullptr, "SetInterfaceVersion"},
+ {23, nullptr, "Convert"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class MiiDBModule final : public ServiceFramework<MiiDBModule> {
+public:
+ explicit MiiDBModule(const char* name) : ServiceFramework{name} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &MiiDBModule::GetDatabaseService, "GetDatabaseService"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void GetDatabaseService(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IDatabaseService>();
+
+ LOG_DEBUG(Service_Mii, "called");
+ }
+};
+
+class MiiImg final : public ServiceFramework<MiiImg> {
+public:
+ explicit MiiImg() : ServiceFramework{"miiimg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {10, nullptr, "Reload"},
+ {11, nullptr, "GetCount"},
+ {12, nullptr, "IsEmpty"},
+ {13, nullptr, "IsFull"},
+ {14, nullptr, "GetAttribute"},
+ {15, nullptr, "LoadImage"},
+ {16, nullptr, "AddOrUpdateImage"},
+ {17, nullptr, "DeleteImages"},
+ {100, nullptr, "DeleteFile"},
+ {101, nullptr, "DestroyFile"},
+ {102, nullptr, "ImportFile"},
+ {103, nullptr, "ExportFile"},
+ {104, nullptr, "ForceInitialize"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<MiiDBModule>("mii:e")->InstallAsService(sm);
+ std::make_shared<MiiDBModule>("mii:u")->InstallAsService(sm);
+
+ std::make_shared<MiiImg>()->InstallAsService(sm);
+}
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/mii/mii.h b/src/core/hle/service/mii/mii.h
new file mode 100644
index 000000000..7ce9be50e
--- /dev/null
+++ b/src/core/hle/service/mii/mii.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::Mii {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::Mii
diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp
new file mode 100644
index 000000000..0297edca0
--- /dev/null
+++ b/src/core/hle/service/ncm/ncm.cpp
@@ -0,0 +1,59 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/ncm/ncm.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::NCM {
+
+class LocationResolver final : public ServiceFramework<LocationResolver> {
+public:
+ explicit LocationResolver() : ServiceFramework{"lr"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "OpenLocationResolver"},
+ {1, nullptr, "OpenRegisteredLocationResolver"},
+ {2, nullptr, "RefreshLocationResolver"},
+ {3, nullptr, "OpenAddOnContentLocationResolver"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NCM final : public ServiceFramework<NCM> {
+public:
+ explicit NCM() : ServiceFramework{"ncm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateContentStorage"},
+ {1, nullptr, "CreateContentMetaDatabase"},
+ {2, nullptr, "VerifyContentStorage"},
+ {3, nullptr, "VerifyContentMetaDatabase"},
+ {4, nullptr, "OpenContentStorage"},
+ {5, nullptr, "OpenContentMetaDatabase"},
+ {6, nullptr, "CloseContentStorageForcibly"},
+ {7, nullptr, "CloseContentMetaDatabaseForcibly"},
+ {8, nullptr, "CleanupContentMetaDatabase"},
+ {9, nullptr, "OpenContentStorage2"},
+ {10, nullptr, "CloseContentStorage"},
+ {11, nullptr, "OpenContentMetaDatabase2"},
+ {12, nullptr, "CloseContentMetaDatabase"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<LocationResolver>()->InstallAsService(sm);
+ std::make_shared<NCM>()->InstallAsService(sm);
+}
+
+} // namespace Service::NCM
diff --git a/src/core/hle/service/ncm/ncm.h b/src/core/hle/service/ncm/ncm.h
new file mode 100644
index 000000000..7bc8518a6
--- /dev/null
+++ b/src/core/hle/service/ncm/ncm.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::NCM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::NCM
diff --git a/src/core/hle/service/nfc/nfc.cpp b/src/core/hle/service/nfc/nfc.cpp
new file mode 100644
index 000000000..8fec97db8
--- /dev/null
+++ b/src/core/hle/service/nfc/nfc.cpp
@@ -0,0 +1,222 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "common/logging/log.h"
+#include "core/hle/ipc_helpers.h"
+#include "core/hle/kernel/hle_ipc.h"
+#include "core/hle/service/nfc/nfc.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::NFC {
+
+class IAm final : public ServiceFramework<IAm> {
+public:
+ explicit IAm() : ServiceFramework{"IAm"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "NotifyForegroundApplet"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_AM final : public ServiceFramework<NFC_AM> {
+public:
+ explicit NFC_AM() : ServiceFramework{"nfc:am"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_AM::CreateAmInterface, "CreateAmInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateAmInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IAm>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+class MFIUser final : public ServiceFramework<MFIUser> {
+public:
+ explicit MFIUser() : ServiceFramework{"IUser"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "ListDevices"},
+ {3, nullptr, "StartDetection"},
+ {4, nullptr, "StopDetection"},
+ {5, nullptr, "Read"},
+ {6, nullptr, "Write"},
+ {7, nullptr, "GetTagInfo"},
+ {8, nullptr, "GetActivateEventHandle"},
+ {9, nullptr, "GetDeactivateEventHandle"},
+ {10, nullptr, "GetState"},
+ {11, nullptr, "GetDeviceState"},
+ {12, nullptr, "GetNpadId"},
+ {13, nullptr, "GetAvailabilityChangeEventHandle"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_MF_U final : public ServiceFramework<NFC_MF_U> {
+public:
+ explicit NFC_MF_U() : ServiceFramework{"nfc:mf:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_MF_U::CreateUserInterface, "CreateUserInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateUserInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<MFIUser>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+class IUser final : public ServiceFramework<IUser> {
+public:
+ explicit IUser() : ServiceFramework{"IUser"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "GetState"},
+ {3, nullptr, "IsNfcEnabled"},
+ {400, nullptr, "Initialize"},
+ {401, nullptr, "Finalize"},
+ {402, nullptr, "GetState"},
+ {403, nullptr, "IsNfcEnabled"},
+ {404, nullptr, "ListDevices"},
+ {405, nullptr, "GetDeviceState"},
+ {406, nullptr, "GetNpadId"},
+ {407, nullptr, "AttachAvailabilityChangeEvent"},
+ {408, nullptr, "StartDetection"},
+ {409, nullptr, "StopDetection"},
+ {410, nullptr, "GetTagInfo"},
+ {411, nullptr, "AttachActivateEvent"},
+ {412, nullptr, "AttachDeactivateEvent"},
+ {1000, nullptr, "ReadMifare"},
+ {1001, nullptr, "WriteMifare"},
+ {1300, nullptr, "SendCommandByPassThrough"},
+ {1301, nullptr, "KeepPassThroughSession"},
+ {1302, nullptr, "ReleasePassThroughSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_U final : public ServiceFramework<NFC_U> {
+public:
+ explicit NFC_U() : ServiceFramework{"nfc:u"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_U::CreateUserInterface, "CreateUserInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateUserInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<IUser>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+class ISystem final : public ServiceFramework<ISystem> {
+public:
+ explicit ISystem() : ServiceFramework{"ISystem"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Finalize"},
+ {2, nullptr, "GetState"},
+ {3, nullptr, "IsNfcEnabled"},
+ {100, nullptr, "SetNfcEnabled"},
+ {400, nullptr, "InitializeSystem"},
+ {401, nullptr, "FinalizeSystem"},
+ {402, nullptr, "GetState"},
+ {403, nullptr, "IsNfcEnabled"},
+ {404, nullptr, "ListDevices"},
+ {405, nullptr, "GetDeviceState"},
+ {406, nullptr, "GetNpadId"},
+ {407, nullptr, "AttachAvailabilityChangeEvent"},
+ {408, nullptr, "StartDetection"},
+ {409, nullptr, "StopDetection"},
+ {410, nullptr, "GetTagInfo"},
+ {411, nullptr, "AttachActivateEvent"},
+ {412, nullptr, "AttachDeactivateEvent"},
+ {500, nullptr, "SetNfcEnabled"},
+ {1000, nullptr, "ReadMifare"},
+ {1001, nullptr, "WriteMifare"},
+ {1300, nullptr, "SendCommandByPassThrough"},
+ {1301, nullptr, "KeepPassThroughSession"},
+ {1302, nullptr, "ReleasePassThroughSession"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NFC_SYS final : public ServiceFramework<NFC_SYS> {
+public:
+ explicit NFC_SYS() : ServiceFramework{"nfc:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &NFC_SYS::CreateSystemInterface, "CreateSystemInterface"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+private:
+ void CreateSystemInterface(Kernel::HLERequestContext& ctx) {
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<ISystem>();
+
+ LOG_DEBUG(Service_NFC, "called");
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<NFC_AM>()->InstallAsService(sm);
+ std::make_shared<NFC_MF_U>()->InstallAsService(sm);
+ std::make_shared<NFC_U>()->InstallAsService(sm);
+ std::make_shared<NFC_SYS>()->InstallAsService(sm);
+}
+
+} // namespace Service::NFC
diff --git a/src/core/hle/service/nfc/nfc.h b/src/core/hle/service/nfc/nfc.h
new file mode 100644
index 000000000..4d2d815f9
--- /dev/null
+++ b/src/core/hle/service/nfc/nfc.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::NFC {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::NFC
diff --git a/src/core/hle/service/nim/nim.cpp b/src/core/hle/service/nim/nim.cpp
new file mode 100644
index 000000000..bd05b0a70
--- /dev/null
+++ b/src/core/hle/service/nim/nim.cpp
@@ -0,0 +1,124 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/nim/nim.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::NIM {
+
+class NIM final : public ServiceFramework<NIM> {
+public:
+ explicit NIM() : ServiceFramework{"nim"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "CreateSystemUpdateTask"},
+ {1, nullptr, "DestroySystemUpdateTask"},
+ {2, nullptr, "ListSystemUpdateTask"},
+ {3, nullptr, "RequestSystemUpdateTaskRun"},
+ {4, nullptr, "GetSystemUpdateTaskInfo"},
+ {5, nullptr, "CommitSystemUpdateTask"},
+ {6, nullptr, "CreateNetworkInstallTask"},
+ {7, nullptr, "DestroyNetworkInstallTask"},
+ {8, nullptr, "ListNetworkInstallTask"},
+ {9, nullptr, "RequestNetworkInstallTaskRun"},
+ {10, nullptr, "GetNetworkInstallTaskInfo"},
+ {11, nullptr, "CommitNetworkInstallTask"},
+ {12, nullptr, "RequestLatestSystemUpdateMeta"},
+ {14, nullptr, "ListApplicationNetworkInstallTask"},
+ {15, nullptr, "ListNetworkInstallTaskContentMeta"},
+ {16, nullptr, "RequestLatestVersion"},
+ {17, nullptr, "SetNetworkInstallTaskAttribute"},
+ {18, nullptr, "AddNetworkInstallTaskContentMeta"},
+ {19, nullptr, "GetDownloadedSystemDataPath"},
+ {20, nullptr, "CalculateNetworkInstallTaskRequiredSize"},
+ {21, nullptr, "IsExFatDriverIncluded"},
+ {22, nullptr, "GetBackgroundDownloadStressTaskInfo"},
+ {23, nullptr, "RequestDeviceAuthenticationToken"},
+ {24, nullptr, "RequestGameCardRegistrationStatus"},
+ {25, nullptr, "RequestRegisterGameCard"},
+ {26, nullptr, "RequestRegisterNotificationToken"},
+ {27, nullptr, "RequestDownloadTaskList"},
+ {28, nullptr, "RequestApplicationControl"},
+ {29, nullptr, "RequestLatestApplicationControl"},
+ {30, nullptr, "RequestVersionList"},
+ {31, nullptr, "CreateApplyDeltaTask"},
+ {32, nullptr, "DestroyApplyDeltaTask"},
+ {33, nullptr, "ListApplicationApplyDeltaTask"},
+ {34, nullptr, "RequestApplyDeltaTaskRun"},
+ {35, nullptr, "GetApplyDeltaTaskInfo"},
+ {36, nullptr, "ListApplyDeltaTask"},
+ {37, nullptr, "CommitApplyDeltaTask"},
+ {38, nullptr, "CalculateApplyDeltaTaskRequiredSize"},
+ {39, nullptr, "PrepareShutdown"},
+ {40, nullptr, "ListApplyDeltaTask"},
+ {41, nullptr, "ClearNotEnoughSpaceStateOfApplyDeltaTask"},
+ {42, nullptr, "Unknown1"},
+ {43, nullptr, "Unknown2"},
+ {44, nullptr, "Unknown3"},
+ {45, nullptr, "Unknown4"},
+ {46, nullptr, "Unknown5"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NIM_SHP final : public ServiceFramework<NIM_SHP> {
+public:
+ explicit NIM_SHP() : ServiceFramework{"nim:shp"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RequestDeviceAuthenticationToken"},
+ {1, nullptr, "RequestCachedDeviceAuthenticationToken"},
+ {100, nullptr, "RequestRegisterDeviceAccount"},
+ {101, nullptr, "RequestUnregisterDeviceAccount"},
+ {102, nullptr, "RequestDeviceAccountStatus"},
+ {103, nullptr, "GetDeviceAccountInfo"},
+ {104, nullptr, "RequestDeviceRegistrationInfo"},
+ {105, nullptr, "RequestTransferDeviceAccount"},
+ {106, nullptr, "RequestSyncRegistration"},
+ {107, nullptr, "IsOwnDeviceId"},
+ {200, nullptr, "RequestRegisterNotificationToken"},
+ {300, nullptr, "RequestUnlinkDevice"},
+ {301, nullptr, "RequestUnlinkDeviceIntegrated"},
+ {302, nullptr, "RequestLinkDevice"},
+ {303, nullptr, "HasDeviceLink"},
+ {304, nullptr, "RequestUnlinkDeviceAll"},
+ {305, nullptr, "RequestCreateVirtualAccount"},
+ {306, nullptr, "RequestDeviceLinkStatus"},
+ {400, nullptr, "GetAccountByVirtualAccount"},
+ {500, nullptr, "RequestSyncTicket"},
+ {501, nullptr, "RequestDownloadTicket"},
+ {502, nullptr, "RequestDownloadTicketForPrepurchasedContents"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class NTC final : public ServiceFramework<NTC> {
+public:
+ explicit NTC() : ServiceFramework{"ntc"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "OpenEnsureNetworkClockAvailabilityService"},
+ {100, nullptr, "SuspendAutonomicTimeCorrection"},
+ {101, nullptr, "ResumeAutonomicTimeCorrection"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<NIM>()->InstallAsService(sm);
+ std::make_shared<NIM_SHP>()->InstallAsService(sm);
+ std::make_shared<NTC>()->InstallAsService(sm);
+}
+
+} // namespace Service::NIM
diff --git a/src/core/hle/service/nim/nim.h b/src/core/hle/service/nim/nim.h
new file mode 100644
index 000000000..2a2a92df0
--- /dev/null
+++ b/src/core/hle/service/nim/nim.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::NIM {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::NIM
diff --git a/src/core/hle/service/pcie/pcie.cpp b/src/core/hle/service/pcie/pcie.cpp
new file mode 100644
index 000000000..39cf05eba
--- /dev/null
+++ b/src/core/hle/service/pcie/pcie.cpp
@@ -0,0 +1,64 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/pcie/pcie.h"
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+
+namespace Service::PCIe {
+
+class ISession final : public ServiceFramework<ISession> {
+public:
+ explicit ISession() : ServiceFramework{"ISession"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "QueryFunctions"},
+ {1, nullptr, "AcquireFunction"},
+ {2, nullptr, "ReleaseFunction"},
+ {3, nullptr, "GetFunctionState"},
+ {4, nullptr, "GetBarProfile"},
+ {5, nullptr, "ReadConfig"},
+ {6, nullptr, "WriteConfig"},
+ {7, nullptr, "ReadBarRegion"},
+ {8, nullptr, "WriteBarRegion"},
+ {9, nullptr, "FindCapability"},
+ {10, nullptr, "FindExtendedCapability"},
+ {11, nullptr, "MapDma"},
+ {12, nullptr, "UnmapDma"},
+ {13, nullptr, "UnmapDmaBusAddress"},
+ {14, nullptr, "GetDmaBusAddress"},
+ {15, nullptr, "GetDmaBusAddressRange"},
+ {16, nullptr, "SetDmaEnable"},
+ {17, nullptr, "AcquireIrq"},
+ {18, nullptr, "ReleaseIrq"},
+ {19, nullptr, "SetIrqEnable"},
+ {20, nullptr, "SetAspmEnable"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class PCIe final : public ServiceFramework<PCIe> {
+public:
+ explicit PCIe() : ServiceFramework{"pcie"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "RegisterClassDriver"},
+ {1, nullptr, "QueryFunctionsUnregistered"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<PCIe>()->InstallAsService(sm);
+}
+
+} // namespace Service::PCIe
diff --git a/src/core/hle/service/pcie/pcie.h b/src/core/hle/service/pcie/pcie.h
new file mode 100644
index 000000000..59c22ca45
--- /dev/null
+++ b/src/core/hle/service/pcie/pcie.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::PCIe {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::PCIe
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 482989ea7..fccc4c461 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -21,20 +21,31 @@
#include "core/hle/service/apm/apm.h"
#include "core/hle/service/audio/audio.h"
#include "core/hle/service/bcat/bcat.h"
+#include "core/hle/service/btdrv/btdrv.h"
+#include "core/hle/service/btm/btm.h"
#include "core/hle/service/erpt/erpt.h"
#include "core/hle/service/es/es.h"
#include "core/hle/service/eupld/eupld.h"
#include "core/hle/service/fatal/fatal.h"
+#include "core/hle/service/fgm/fgm.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "core/hle/service/friend/friend.h"
+#include "core/hle/service/grc/grc.h"
#include "core/hle/service/hid/hid.h"
+#include "core/hle/service/lbl/lbl.h"
+#include "core/hle/service/ldn/ldn.h"
#include "core/hle/service/ldr/ldr.h"
#include "core/hle/service/lm/lm.h"
+#include "core/hle/service/mii/mii.h"
#include "core/hle/service/mm/mm_u.h"
+#include "core/hle/service/ncm/ncm.h"
+#include "core/hle/service/nfc/nfc.h"
#include "core/hle/service/nfp/nfp.h"
#include "core/hle/service/nifm/nifm.h"
+#include "core/hle/service/nim/nim.h"
#include "core/hle/service/ns/ns.h"
#include "core/hle/service/nvdrv/nvdrv.h"
+#include "core/hle/service/pcie/pcie.h"
#include "core/hle/service/pctl/pctl.h"
#include "core/hle/service/pm/pm.h"
#include "core/hle/service/prepo/prepo.h"
@@ -47,6 +58,7 @@
#include "core/hle/service/ssl/ssl.h"
#include "core/hle/service/time/time.h"
#include "core/hle/service/vi/vi.h"
+#include "core/hle/service/wlan/wlan.h"
using Kernel::ClientPort;
using Kernel::ServerPort;
@@ -190,31 +202,43 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm) {
AM::InstallInterfaces(*sm, nv_flinger);
AOC::InstallInterfaces(*sm);
APM::InstallInterfaces(*sm);
- BCAT::InstallInterfaces(*sm);
Audio::InstallInterfaces(*sm);
+ BCAT::InstallInterfaces(*sm);
+ BtDrv::InstallInterfaces(*sm);
+ BTM::InstallInterfaces(*sm);
ERPT::InstallInterfaces(*sm);
ES::InstallInterfaces(*sm);
EUPLD::InstallInterfaces(*sm);
Fatal::InstallInterfaces(*sm);
+ FGM::InstallInterfaces(*sm);
FileSystem::InstallInterfaces(*sm);
Friend::InstallInterfaces(*sm);
+ GRC::InstallInterfaces(*sm);
HID::InstallInterfaces(*sm);
+ LBL::InstallInterfaces(*sm);
+ LDN::InstallInterfaces(*sm);
LDR::InstallInterfaces(*sm);
LM::InstallInterfaces(*sm);
+ Mii::InstallInterfaces(*sm);
MM::InstallInterfaces(*sm);
+ NCM::InstallInterfaces(*sm);
+ NFC::InstallInterfaces(*sm);
NFP::InstallInterfaces(*sm);
NIFM::InstallInterfaces(*sm);
+ NIM::InstallInterfaces(*sm);
NS::InstallInterfaces(*sm);
Nvidia::InstallInterfaces(*sm);
+ PCIe::InstallInterfaces(*sm);
PCTL::InstallInterfaces(*sm);
PlayReport::InstallInterfaces(*sm);
PM::InstallInterfaces(*sm);
+ Set::InstallInterfaces(*sm);
Sockets::InstallInterfaces(*sm);
SPL::InstallInterfaces(*sm);
SSL::InstallInterfaces(*sm);
Time::InstallInterfaces(*sm);
VI::InstallInterfaces(*sm, nv_flinger);
- Set::InstallInterfaces(*sm);
+ WLAN::InstallInterfaces(*sm);
LOG_DEBUG(Service, "initialized OK");
}
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 6aa1e2511..3211a8346 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -109,4 +109,26 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
RegisterHandlers(functions);
}
+BSDCFG::BSDCFG() : ServiceFramework{"bsdcfg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "SetIfUp"},
+ {1, nullptr, "SetIfUpWithEvent"},
+ {2, nullptr, "CancelIf"},
+ {3, nullptr, "SetIfDown"},
+ {4, nullptr, "GetIfState"},
+ {5, nullptr, "DhcpRenew"},
+ {6, nullptr, "AddStaticArpEntry"},
+ {7, nullptr, "RemoveArpEntry"},
+ {8, nullptr, "LookupArpEntry"},
+ {9, nullptr, "LookupArpEntry2"},
+ {10, nullptr, "ClearArpEntries"},
+ {11, nullptr, "ClearArpEntries2"},
+ {12, nullptr, "PrintArpEntries"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index a6b1ca7d0..c1da59b24 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -26,4 +26,9 @@ private:
u32 next_fd = 1;
};
+class BSDCFG final : public ServiceFramework<BSDCFG> {
+public:
+ explicit BSDCFG();
+};
+
} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/ethc.cpp b/src/core/hle/service/sockets/ethc.cpp
new file mode 100644
index 000000000..d53c25eec
--- /dev/null
+++ b/src/core/hle/service/sockets/ethc.cpp
@@ -0,0 +1,38 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/service/sockets/ethc.h"
+
+namespace Service::Sockets {
+
+ETHC_C::ETHC_C() : ServiceFramework{"ethc:c"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {1, nullptr, "Cancel"},
+ {2, nullptr, "GetResult"},
+ {3, nullptr, "GetMediaList"},
+ {4, nullptr, "SetMediaType"},
+ {5, nullptr, "GetMediaType"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+ETHC_I::ETHC_I() : ServiceFramework{"ethc:i"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "GetReadableHandle"},
+ {1, nullptr, "Cancel"},
+ {2, nullptr, "GetResult"},
+ {3, nullptr, "GetInterfaceList"},
+ {4, nullptr, "GetInterfaceCount"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+}
+
+} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/ethc.h b/src/core/hle/service/sockets/ethc.h
new file mode 100644
index 000000000..9a3c88100
--- /dev/null
+++ b/src/core/hle/service/sockets/ethc.h
@@ -0,0 +1,21 @@
+// 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::Sockets {
+
+class ETHC_C final : public ServiceFramework<ETHC_C> {
+public:
+ explicit ETHC_C();
+};
+
+class ETHC_I final : public ServiceFramework<ETHC_I> {
+public:
+ explicit ETHC_I();
+};
+
+} // namespace Service::Sockets
diff --git a/src/core/hle/service/sockets/sockets.cpp b/src/core/hle/service/sockets/sockets.cpp
index 05bd10d35..08d2d306a 100644
--- a/src/core/hle/service/sockets/sockets.cpp
+++ b/src/core/hle/service/sockets/sockets.cpp
@@ -3,6 +3,7 @@
// Refer to the license.txt file included.
#include "core/hle/service/sockets/bsd.h"
+#include "core/hle/service/sockets/ethc.h"
#include "core/hle/service/sockets/nsd.h"
#include "core/hle/service/sockets/sfdnsres.h"
#include "core/hle/service/sockets/sockets.h"
@@ -12,8 +13,14 @@ namespace Service::Sockets {
void InstallInterfaces(SM::ServiceManager& service_manager) {
std::make_shared<BSD>("bsd:s")->InstallAsService(service_manager);
std::make_shared<BSD>("bsd:u")->InstallAsService(service_manager);
+ std::make_shared<BSDCFG>()->InstallAsService(service_manager);
+
+ std::make_shared<ETHC_C>()->InstallAsService(service_manager);
+ std::make_shared<ETHC_I>()->InstallAsService(service_manager);
+
std::make_shared<NSD>("nsd:a")->InstallAsService(service_manager);
std::make_shared<NSD>("nsd:u")->InstallAsService(service_manager);
+
std::make_shared<SFDNSRES>()->InstallAsService(service_manager);
}
diff --git a/src/core/hle/service/wlan/wlan.cpp b/src/core/hle/service/wlan/wlan.cpp
new file mode 100644
index 000000000..2654594c1
--- /dev/null
+++ b/src/core/hle/service/wlan/wlan.cpp
@@ -0,0 +1,172 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+
+#include "core/hle/service/service.h"
+#include "core/hle/service/sm/sm.h"
+#include "core/hle/service/wlan/wlan.h"
+
+namespace Service::WLAN {
+
+class WLANInfra final : public ServiceFramework<WLANInfra> {
+public:
+ explicit WLANInfra() : ServiceFramework{"wlan:inf"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "GetMacAddress"},
+ {3, nullptr, "StartScan"},
+ {4, nullptr, "StopScan"},
+ {5, nullptr, "Connect"},
+ {6, nullptr, "CancelConnect"},
+ {7, nullptr, "Disconnect"},
+ {8, nullptr, "Unknown3"},
+ {9, nullptr, "Unknown4"},
+ {10, nullptr, "GetState"},
+ {11, nullptr, "GetScanResult"},
+ {12, nullptr, "GetRssi"},
+ {13, nullptr, "ChangeRxAntenna"},
+ {14, nullptr, "Unknown5"},
+ {15, nullptr, "Unknown6"},
+ {16, nullptr, "RequestWakeUp"},
+ {17, nullptr, "RequestIfUpDown"},
+ {18, nullptr, "Unknown7"},
+ {19, nullptr, "Unknown8"},
+ {20, nullptr, "Unknown9"},
+ {21, nullptr, "Unknown10"},
+ {22, nullptr, "Unknown11"},
+ {23, nullptr, "Unknown12"},
+ {24, nullptr, "Unknown13"},
+ {25, nullptr, "Unknown14"},
+ {26, nullptr, "Unknown15"},
+ {27, nullptr, "Unknown16"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANLocal final : public ServiceFramework<WLANLocal> {
+public:
+ explicit WLANLocal() : ServiceFramework{"wlan:lcl"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "GetMacAddress"},
+ {7, nullptr, "CreateBss"},
+ {8, nullptr, "DestroyBss"},
+ {9, nullptr, "StartScan"},
+ {10, nullptr, "StopScan"},
+ {11, nullptr, "Connect"},
+ {12, nullptr, "CancelConnect"},
+ {13, nullptr, "Join"},
+ {14, nullptr, "CancelJoin"},
+ {15, nullptr, "Disconnect"},
+ {16, nullptr, "SetBeaconLostCount"},
+ {17, nullptr, "Unknown7"},
+ {18, nullptr, "Unknown8"},
+ {19, nullptr, "Unknown9"},
+ {20, nullptr, "GetBssIndicationEvent"},
+ {21, nullptr, "GetBssIndicationInfo"},
+ {22, nullptr, "GetState"},
+ {23, nullptr, "GetAllowedChannels"},
+ {24, nullptr, "AddIe"},
+ {25, nullptr, "DeleteIe"},
+ {26, nullptr, "Unknown10"},
+ {27, nullptr, "Unknown11"},
+ {28, nullptr, "CreateRxEntry"},
+ {29, nullptr, "DeleteRxEntry"},
+ {30, nullptr, "Unknown12"},
+ {31, nullptr, "Unknown13"},
+ {32, nullptr, "AddMatchingDataToRxEntry"},
+ {33, nullptr, "RemoveMatchingDataFromRxEntry"},
+ {34, nullptr, "GetScanResult"},
+ {35, nullptr, "Unknown14"},
+ {36, nullptr, "SetActionFrameWithBeacon"},
+ {37, nullptr, "CancelActionFrameWithBeacon"},
+ {38, nullptr, "CreateRxEntryForActionFrame"},
+ {39, nullptr, "DeleteRxEntryForActionFrame"},
+ {40, nullptr, "Unknown15"},
+ {41, nullptr, "Unknown16"},
+ {42, nullptr, "CancelGetActionFrame"},
+ {43, nullptr, "GetRssi"},
+ {44, nullptr, "Unknown17"},
+ {45, nullptr, "Unknown18"},
+ {46, nullptr, "Unknown19"},
+ {47, nullptr, "Unknown20"},
+ {48, nullptr, "Unknown21"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANLocalGetFrame final : public ServiceFramework<WLANLocalGetFrame> {
+public:
+ explicit WLANLocalGetFrame() : ServiceFramework{"wlan:lg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANSocketGetFrame final : public ServiceFramework<WLANSocketGetFrame> {
+public:
+ explicit WLANSocketGetFrame() : ServiceFramework{"wlan:sg"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class WLANSocketManager final : public ServiceFramework<WLANSocketManager> {
+public:
+ explicit WLANSocketManager() : ServiceFramework{"wlan:soc"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Unknown1"},
+ {1, nullptr, "Unknown2"},
+ {2, nullptr, "Unknown3"},
+ {3, nullptr, "Unknown4"},
+ {4, nullptr, "Unknown5"},
+ {5, nullptr, "Unknown6"},
+ {6, nullptr, "GetMacAddress"},
+ {7, nullptr, "SwitchTsfTimerFunction"},
+ {8, nullptr, "Unknown7"},
+ {9, nullptr, "Unknown8"},
+ {10, nullptr, "Unknown9"},
+ {11, nullptr, "Unknown10"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+void InstallInterfaces(SM::ServiceManager& sm) {
+ std::make_shared<WLANInfra>()->InstallAsService(sm);
+ std::make_shared<WLANLocal>()->InstallAsService(sm);
+ std::make_shared<WLANLocalGetFrame>()->InstallAsService(sm);
+ std::make_shared<WLANSocketGetFrame>()->InstallAsService(sm);
+ std::make_shared<WLANSocketManager>()->InstallAsService(sm);
+}
+
+} // namespace Service::WLAN
diff --git a/src/core/hle/service/wlan/wlan.h b/src/core/hle/service/wlan/wlan.h
new file mode 100644
index 000000000..054ea928a
--- /dev/null
+++ b/src/core/hle/service/wlan/wlan.h
@@ -0,0 +1,15 @@
+// Copyright 2018 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+namespace Service::SM {
+class ServiceManager;
+}
+
+namespace Service::WLAN {
+
+void InstallInterfaces(SM::ServiceManager& sm);
+
+} // namespace Service::WLAN