summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/apt/apt.cpp11
-rw-r--r--src/core/hle/service/apt/apt.h34
-rw-r--r--src/core/hle/service/apt/apt_a.cpp2
-rw-r--r--src/core/hle/service/apt/apt_u.cpp2
-rw-r--r--src/core/hle/service/cfg/cfg.cpp19
-rw-r--r--src/core/hle/service/err_f.cpp316
-rw-r--r--src/core/hle/service/fs/archive.cpp58
-rw-r--r--src/core/hle/service/fs/archive.h2
-rw-r--r--src/core/hle/service/mic_u.cpp322
-rw-r--r--src/core/hle/service/mic_u.h1
-rw-r--r--src/core/hle/service/ptm/ptm.cpp2
11 files changed, 581 insertions, 188 deletions
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index c4bd65986..31e5e07b2 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -396,6 +396,15 @@ void StartLibraryApplet(Service::Interface* self) {
cmd_buff[1] = applet->Start(parameter).raw;
}
+void CancelLibraryApplet(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 exiting = cmd_buff[1] & 0xFF;
+
+ cmd_buff[1] = 1; // TODO: Find the return code meaning
+
+ LOG_WARNING(Service_APT, "(STUBBED) called exiting=%u", exiting);
+}
+
void SetScreenCapPostPermission(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
@@ -523,7 +532,7 @@ void Init() {
notification_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Notification");
parameter_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "APT_U:Start");
- next_parameter.signal = static_cast<u32>(SignalType::AppJustStarted);
+ next_parameter.signal = static_cast<u32>(SignalType::Wakeup);
next_parameter.destination_id = 0x300;
}
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index a118cda1f..44dbd8757 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -46,12 +46,23 @@ static_assert(sizeof(CaptureBufferInfo) == 0x20, "CaptureBufferInfo struct has i
/// Signals used by APT functions
enum class SignalType : u32 {
None = 0x0,
- AppJustStarted = 0x1,
- LibAppJustStarted = 0x2,
- LibAppFinished = 0x3,
- LibAppClosed = 0xA,
- ReturningToApp = 0xB,
- ExitingApp = 0xC,
+ Wakeup = 0x1,
+ Request = 0x2,
+ Response = 0x3,
+ Exit = 0x4,
+ Message = 0x5,
+ HomeButtonSingle = 0x6,
+ HomeButtonDouble = 0x7,
+ DspSleep = 0x8,
+ DspWakeup = 0x9,
+ WakeupByExit = 0xA,
+ WakeupByPause = 0xB,
+ WakeupByCancel = 0xC,
+ WakeupByCancelAll = 0xD,
+ WakeupByPowerButtonClick = 0xE,
+ WakeupToJumpHome = 0xF,
+ RequestForSysApplet = 0x10,
+ WakeupToLaunchApplication = 0x11,
};
/// App Id's used by APT functions
@@ -381,6 +392,17 @@ void PreloadLibraryApplet(Service::Interface* self);
void StartLibraryApplet(Service::Interface* self);
/**
+ * APT::CancelLibraryApplet service function
+ * Inputs:
+ * 0 : Command header [0x003B0040]
+ * 1 : u8, Application exiting (0 = not exiting, 1 = exiting)
+ * Outputs:
+ * 0 : Header code
+ * 1 : Result code
+ */
+void CancelLibraryApplet(Service::Interface* self);
+
+/**
* APT::GetStartupArgument service function
* Inputs:
* 1 : Parameter Size (capped to 0x300)
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index f27ad91b7..a7a0c8a41 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -25,7 +25,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00160040, PreloadLibraryApplet, "PreloadLibraryApplet"},
{0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
{0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
- {0x003B0040, nullptr, "CancelLibraryApplet?"},
+ {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"},
{0x003E0080, nullptr, "ReplySleepQuery"},
{0x00430040, NotifyToWait, "NotifyToWait?"},
{0x00440000, GetSharedFont, "GetSharedFont?"},
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index d6ad42e21..a731c39f6 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -67,7 +67,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00380040, nullptr, "PreloadResidentApplet"},
{0x00390040, nullptr, "PrepareToStartResidentApplet"},
{0x003A0044, nullptr, "StartResidentApplet"},
- {0x003B0040, nullptr, "CancelLibraryApplet"},
+ {0x003B0040, CancelLibraryApplet, "CancelLibraryApplet"},
{0x003C0042, nullptr, "SendDspSleep"},
{0x003D0042, nullptr, "SendDspWakeUp"},
{0x003E0080, nullptr, "ReplySleepQuery"},
diff --git a/src/core/hle/service/cfg/cfg.cpp b/src/core/hle/service/cfg/cfg.cpp
index 24eee6903..d554c3f54 100644
--- a/src/core/hle/service/cfg/cfg.cpp
+++ b/src/core/hle/service/cfg/cfg.cpp
@@ -45,7 +45,8 @@ static_assert(sizeof(SaveFileConfig) == 0x455C,
enum ConfigBlockID {
StereoCameraSettingsBlockID = 0x00050005,
SoundOutputModeBlockID = 0x00070001,
- ConsoleUniqueIDBlockID = 0x00090001,
+ ConsoleUniqueID1BlockID = 0x00090000,
+ ConsoleUniqueID2BlockID = 0x00090001,
UsernameBlockID = 0x000A0000,
BirthdayBlockID = 0x000A0001,
LanguageBlockID = 0x000A0002,
@@ -359,7 +360,7 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
}
ResultCode DeleteConfigNANDSaveFile() {
- FileSys::Path path("config");
+ FileSys::Path path("/config");
return Service::FS::DeleteFileFromArchive(cfg_system_save_data_archive, path);
}
@@ -368,7 +369,7 @@ ResultCode UpdateConfigNANDSavegame() {
mode.write_flag.Assign(1);
mode.create_flag.Assign(1);
- FileSys::Path path("config");
+ FileSys::Path path("/config");
auto config_result = Service::FS::OpenFileFromArchive(cfg_system_save_data_archive, path, mode);
ASSERT_MSG(config_result.Succeeded(), "could not open file");
@@ -382,8 +383,9 @@ ResultCode UpdateConfigNANDSavegame() {
ResultCode FormatConfig() {
ResultCode res = DeleteConfigNANDSaveFile();
// The delete command fails if the file doesn't exist, so we have to check that too
- if (!res.IsSuccess() && res.description != ErrorDescription::FS_NotFound)
+ if (!res.IsSuccess() && res.description != ErrorDescription::FS_FileNotFound) {
return res;
+ }
// Delete the old data
cfg_config_file_buffer.fill(0);
// Create the header
@@ -409,7 +411,12 @@ ResultCode FormatConfig() {
if (!res.IsSuccess())
return res;
- res = CreateConfigInfoBlk(ConsoleUniqueIDBlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
+ res = CreateConfigInfoBlk(ConsoleUniqueID1BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
+ &CONSOLE_UNIQUE_ID);
+ if (!res.IsSuccess())
+ return res;
+
+ res = CreateConfigInfoBlk(ConsoleUniqueID2BlockID, sizeof(CONSOLE_UNIQUE_ID), 0xE,
&CONSOLE_UNIQUE_ID);
if (!res.IsSuccess())
return res;
@@ -504,7 +511,7 @@ ResultCode LoadConfigNANDSaveFile() {
cfg_system_save_data_archive = *archive_result;
- FileSys::Path config_path("config");
+ FileSys::Path config_path("/config");
FileSys::Mode open_mode = {};
open_mode.read_flag.Assign(1);
diff --git a/src/core/hle/service/err_f.cpp b/src/core/hle/service/err_f.cpp
index 3ca4f98de..9905757c7 100644
--- a/src/core/hle/service/err_f.cpp
+++ b/src/core/hle/service/err_f.cpp
@@ -2,9 +2,15 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <array>
+#include <chrono>
+#include <iomanip>
+#include <sstream>
+
#include "common/bit_field.h"
#include "common/common_types.h"
#include "common/logging/log.h"
+#include "core/hle/result.h"
#include "core/hle/service/err_f.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -12,12 +18,45 @@
namespace ERR_F {
-enum {
- ErrSpecifier0 = 0,
- ErrSpecifier1 = 1,
- ErrSpecifier3 = 3,
- ErrSpecifier4 = 4,
+enum class FatalErrType : u32 {
+ Generic = 0,
+ Corrupted = 1,
+ CardRemoved = 2,
+ Exception = 3,
+ ResultFailure = 4,
+ Logged = 5,
+};
+
+enum class ExceptionType : u32 {
+ PrefetchAbort = 0,
+ DataAbort = 1,
+ Undefined = 2,
+ VectorFP = 3,
+};
+
+struct ExceptionInfo {
+ u8 exception_type;
+ INSERT_PADDING_BYTES(3);
+ u32 sr;
+ u32 ar;
+ u32 fpexc;
+ u32 fpinst;
+ u32 fpinst2;
+};
+static_assert(sizeof(ExceptionInfo) == 0x18, "ExceptionInfo struct has incorrect size");
+
+struct ExceptionContext final {
+ std::array<u32, 16> arm_regs;
+ u32 cpsr;
};
+static_assert(sizeof(ExceptionContext) == 0x44, "ExceptionContext struct has incorrect size");
+
+struct ExceptionData {
+ ExceptionInfo exception_info;
+ ExceptionContext exception_context;
+ INSERT_PADDING_WORDS(1);
+};
+static_assert(sizeof(ExceptionData) == 0x60, "ExceptionData struct has incorrect size");
// This is used instead of ResultCode from result.h
// because we can't have non-trivial data members in unions.
@@ -30,150 +69,191 @@ union RSL {
BitField<27, 5, u32> level;
};
-union ErrInfo {
- u8 specifier;
-
- struct {
- u8 specifier; // 0x0
- u8 rev_high; // 0x1
- u16 rev_low; // 0x2
- RSL result_code; // 0x4
- u32 address; // 0x8
- INSERT_PADDING_BYTES(4); // 0xC
- u32 pid_low; // 0x10
- u32 pid_high; // 0x14
- u32 aid_low; // 0x18
- u32 aid_high; // 0x1C
- } errtype1;
-
- struct {
- u8 specifier; // 0x0
- u8 rev_high; // 0x1
- u16 rev_low; // 0x2
- INSERT_PADDING_BYTES(0xC); // 0x4
- u32 pid_low; // 0x10
- u32 pid_high; // 0x14
- u32 aid_low; // 0x18
- u32 aid_high; // 0x1C
- u8 error_type; // 0x20
- INSERT_PADDING_BYTES(3); // 0x21
- u32 fault_status_reg; // 0x24
- u32 fault_addr; // 0x28
- u32 fpexc; // 0x2C
- u32 finst; // 0x30
- u32 finst2; // 0x34
- INSERT_PADDING_BYTES(0x34); // 0x38
- u32 sp; // 0x6C
- u32 pc; // 0x70
- u32 lr; // 0x74
- u32 cpsr; // 0x78
- } errtype3;
-
- struct {
- u8 specifier; // 0x0
- u8 rev_high; // 0x1
- u16 rev_low; // 0x2
- RSL result_code; // 0x4
- INSERT_PADDING_BYTES(8); // 0x8
- u32 pid_low; // 0x10
- u32 pid_high; // 0x14
- u32 aid_low; // 0x18
- u32 aid_high; // 0x1C
- char debug_string1[0x2E]; // 0x20
- char debug_string2[0x2E]; // 0x4E
- } errtype4;
+struct ErrInfo {
+ struct ErrInfoCommon {
+ u8 specifier; // 0x0
+ u8 rev_high; // 0x1
+ u16 rev_low; // 0x2
+ RSL result_code; // 0x4
+ u32 pc_address; // 0x8
+ u32 pid; // 0xC
+ u32 title_id_low; // 0x10
+ u32 title_id_high; // 0x14
+ u32 app_title_id_low; // 0x18
+ u32 app_title_id_high; // 0x1C
+ } errinfo_common;
+ static_assert(sizeof(ErrInfoCommon) == 0x20, "ErrInfoCommon struct has incorrect size");
+
+ union {
+ struct {
+ char data[0x60]; // 0x20
+ } generic;
+
+ struct {
+ ExceptionData exception_data; // 0x20
+ } exception;
+
+ struct {
+ char message[0x60]; // 0x20
+ } result_failure;
+ };
};
-enum { PrefetchAbort = 0, DataAbort = 1, UndefInstr = 2, VectorFP = 3 };
+static std::string GetErrType(u8 type_code) {
+ switch (static_cast<FatalErrType>(type_code)) {
+ case FatalErrType::Generic:
+ return "Generic";
+ case FatalErrType::Corrupted:
+ return "Corrupted";
+ case FatalErrType::CardRemoved:
+ return "CardRemoved";
+ case FatalErrType::Exception:
+ return "Exception";
+ case FatalErrType::ResultFailure:
+ return "ResultFailure";
+ case FatalErrType::Logged:
+ return "Logged";
+ default:
+ return "Unknown Error Type";
+ }
+}
-static std::string GetErrInfo3Type(u8 type_code) {
- switch (type_code) {
- case PrefetchAbort:
+static std::string GetExceptionType(u8 type_code) {
+ switch (static_cast<ExceptionType>(type_code)) {
+ case ExceptionType::PrefetchAbort:
return "Prefetch Abort";
- case DataAbort:
+ case ExceptionType::DataAbort:
return "Data Abort";
- case UndefInstr:
- return "Undefined Instruction";
- case VectorFP:
- return "Vector Floating Point";
+ case ExceptionType::Undefined:
+ return "Undefined Exception";
+ case ExceptionType::VectorFP:
+ return "Vector Floating Point Exception";
default:
- return "unknown";
+ return "Unknown Exception Type";
}
}
+static std::string GetCurrentSystemTime() {
+ auto now = std::chrono::system_clock::now();
+ auto time = std::chrono::system_clock::to_time_t(now);
+
+ std::stringstream time_stream;
+ time_stream << std::put_time(std::localtime(&time), "%Y/%m/%d %H:%M:%S");
+ return time_stream.str();
+}
+
+static void LogGenericInfo(const ErrInfo::ErrInfoCommon& errinfo_common) {
+ LOG_CRITICAL(Service_ERR, "PID: 0x%08X", errinfo_common.pid);
+ LOG_CRITICAL(Service_ERR, "REV: 0x%08X_0x%08X", errinfo_common.rev_high,
+ errinfo_common.rev_low);
+ LOG_CRITICAL(Service_ERR, "TID: 0x%08X_0x%08X", errinfo_common.title_id_high,
+ errinfo_common.title_id_low);
+ LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errinfo_common.app_title_id_high,
+ errinfo_common.app_title_id_low);
+ LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errinfo_common.pc_address);
+
+ LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errinfo_common.result_code.raw);
+ LOG_CRITICAL(Service_ERR, " Level: %u", errinfo_common.result_code.level.Value());
+ LOG_CRITICAL(Service_ERR, " Summary: %u", errinfo_common.result_code.summary.Value());
+ LOG_CRITICAL(Service_ERR, " Module: %u", errinfo_common.result_code.module.Value());
+ LOG_CRITICAL(Service_ERR, " Desc: %u", errinfo_common.result_code.description.Value());
+}
+
+/* ThrowFatalError function
+ * Inputs:
+ * 0 : Header code [0x00010800]
+ * 1-32 : FatalErrInfo
+ * Outputs:
+ * 0 : Header code
+ * 1 : Result code
+ */
static void ThrowFatalError(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- LOG_CRITICAL(Service_ERR, "Fatal error!");
+ LOG_CRITICAL(Service_ERR, "Fatal error");
const ErrInfo* errinfo = reinterpret_cast<ErrInfo*>(&cmd_buff[1]);
+ LOG_CRITICAL(Service_ERR, "Fatal error type: %s",
+ GetErrType(errinfo->errinfo_common.specifier).c_str());
- switch (errinfo->specifier) {
- case ErrSpecifier0:
- case ErrSpecifier1: {
- const auto& errtype = errinfo->errtype1;
- LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
- LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
- LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
- LOG_CRITICAL(Service_ERR, "ADR: 0x%08X", errtype.address);
-
- LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
- LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
- LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
- LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
- LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
+ // Generic Info
+ LogGenericInfo(errinfo->errinfo_common);
+
+ switch (static_cast<FatalErrType>(errinfo->errinfo_common.specifier)) {
+ case FatalErrType::Generic:
+ case FatalErrType::Corrupted:
+ case FatalErrType::CardRemoved:
+ case FatalErrType::Logged: {
+ LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str());
break;
}
+ case FatalErrType::Exception: {
+ const auto& errtype = errinfo->exception;
+
+ // Register Info
+ LOG_CRITICAL(Service_ERR, "ARM Registers:");
+ for (u32 index = 0; index < errtype.exception_data.exception_context.arm_regs.size();
+ ++index) {
+ if (index < 13) {
+ LOG_DEBUG(Service_ERR, "r%u=0x%08X", index,
+ errtype.exception_data.exception_context.arm_regs.at(index));
+ } else if (index == 13) {
+ LOG_CRITICAL(Service_ERR, "SP=0x%08X",
+ errtype.exception_data.exception_context.arm_regs.at(index));
+ } else if (index == 14) {
+ LOG_CRITICAL(Service_ERR, "LR=0x%08X",
+ errtype.exception_data.exception_context.arm_regs.at(index));
+ } else if (index == 15) {
+ LOG_CRITICAL(Service_ERR, "PC=0x%08X",
+ errtype.exception_data.exception_context.arm_regs.at(index));
+ }
+ }
+ LOG_CRITICAL(Service_ERR, "CPSR=0x%08X", errtype.exception_data.exception_context.cpsr);
- case ErrSpecifier3: {
- const auto& errtype = errinfo->errtype3;
- LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
- LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
- LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
- LOG_CRITICAL(Service_ERR, "TYPE: %s", GetErrInfo3Type(errtype.error_type).c_str());
-
- LOG_CRITICAL(Service_ERR, "PC: 0x%08X", errtype.pc);
- LOG_CRITICAL(Service_ERR, "LR: 0x%08X", errtype.lr);
- LOG_CRITICAL(Service_ERR, "SP: 0x%08X", errtype.sp);
- LOG_CRITICAL(Service_ERR, "CPSR: 0x%08X", errtype.cpsr);
-
- switch (errtype.error_type) {
- case PrefetchAbort:
- case DataAbort:
- LOG_CRITICAL(Service_ERR, "Fault Address: 0x%08X", errtype.fault_addr);
- LOG_CRITICAL(Service_ERR, "Fault Status Register: 0x%08X", errtype.fault_status_reg);
+ // Exception Info
+ LOG_CRITICAL(
+ Service_ERR, "EXCEPTION TYPE: %s",
+ GetExceptionType(errtype.exception_data.exception_info.exception_type).c_str());
+ switch (static_cast<ExceptionType>(errtype.exception_data.exception_info.exception_type)) {
+ case ExceptionType::PrefetchAbort:
+ LOG_CRITICAL(Service_ERR, "IFSR: 0x%08X", errtype.exception_data.exception_info.sr);
+ LOG_CRITICAL(Service_ERR, "r15: 0x%08X", errtype.exception_data.exception_info.ar);
+ case ExceptionType::DataAbort:
+ LOG_CRITICAL(Service_ERR, "DFSR: 0x%08X", errtype.exception_data.exception_info.sr);
+ LOG_CRITICAL(Service_ERR, "DFAR: 0x%08X", errtype.exception_data.exception_info.ar);
break;
- case VectorFP:
- LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X", errtype.fpexc);
- LOG_CRITICAL(Service_ERR, "FINST: 0x%08X", errtype.finst);
- LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X", errtype.finst2);
+ case ExceptionType::VectorFP:
+ LOG_CRITICAL(Service_ERR, "FPEXC: 0x%08X",
+ errtype.exception_data.exception_info.fpinst);
+ LOG_CRITICAL(Service_ERR, "FINST: 0x%08X",
+ errtype.exception_data.exception_info.fpinst);
+ LOG_CRITICAL(Service_ERR, "FINST2: 0x%08X",
+ errtype.exception_data.exception_info.fpinst2);
break;
}
+ LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str());
break;
}
- case ErrSpecifier4: {
- const auto& errtype = errinfo->errtype4;
- LOG_CRITICAL(Service_ERR, "PID: 0x%08X_0x%08X", errtype.pid_low, errtype.pid_high);
- LOG_CRITICAL(Service_ERR, "REV: %d", errtype.rev_low | (errtype.rev_high << 16));
- LOG_CRITICAL(Service_ERR, "AID: 0x%08X_0x%08X", errtype.aid_low, errtype.aid_high);
+ case FatalErrType::ResultFailure: {
+ const auto& errtype = errinfo->result_failure;
- LOG_CRITICAL(Service_ERR, "RSL: 0x%08X", errtype.result_code.raw);
- LOG_CRITICAL(Service_ERR, " Level: %u", errtype.result_code.level.Value());
- LOG_CRITICAL(Service_ERR, " Summary: %u", errtype.result_code.summary.Value());
- LOG_CRITICAL(Service_ERR, " Module: %u", errtype.result_code.module.Value());
- LOG_CRITICAL(Service_ERR, " Desc: %u", errtype.result_code.description.Value());
-
- LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string1);
- LOG_CRITICAL(Service_ERR, "%s", errtype.debug_string2);
+ // Failure Message
+ LOG_CRITICAL(Service_ERR, "Failure Message: %s", errtype.message);
+ LOG_CRITICAL(Service_ERR, "Datetime: %s", GetCurrentSystemTime().c_str());
break;
}
- }
- cmd_buff[1] = 0; // No error
+ } // switch FatalErrType
+
+ cmd_buff[0] = IPC::MakeHeader(0x1, 1, 0);
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
}
const Interface::FunctionInfo FunctionTable[] = {
+ // clang-format off
{0x00010800, ThrowFatalError, "ThrowFatalError"},
+ {0x00020042, nullptr, "SetUserString"},
+ // clang-format on
};
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 7f9696bfb..4c29784e8 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -15,9 +15,10 @@
#include "common/logging/log.h"
#include "core/file_sys/archive_backend.h"
#include "core/file_sys/archive_extsavedata.h"
+#include "core/file_sys/archive_ncch.h"
#include "core/file_sys/archive_savedata.h"
-#include "core/file_sys/archive_savedatacheck.h"
#include "core/file_sys/archive_sdmc.h"
+#include "core/file_sys/archive_sdmcwriteonly.h"
#include "core/file_sys/archive_systemsavedata.h"
#include "core/file_sys/directory_backend.h"
#include "core/file_sys/file_backend.h"
@@ -338,17 +339,11 @@ ResultCode RenameFileBetweenArchives(ArchiveHandle src_archive_handle,
return ERR_INVALID_ARCHIVE_HANDLE;
if (src_archive == dest_archive) {
- if (src_archive->RenameFile(src_path, dest_path))
- return RESULT_SUCCESS;
+ return src_archive->RenameFile(src_path, dest_path);
} else {
// TODO: Implement renaming across archives
return UnimplementedFunction(ErrorModule::FS);
}
-
- // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't
- // exist or similar. Verify.
- return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
- ErrorSummary::NothingHappened, ErrorLevel::Status);
}
ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSys::Path& path) {
@@ -356,10 +351,7 @@ ResultCode DeleteDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
if (archive == nullptr)
return ERR_INVALID_ARCHIVE_HANDLE;
- if (archive->DeleteDirectory(path))
- return RESULT_SUCCESS;
- return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
- ErrorSummary::Canceled, ErrorLevel::Status);
+ return archive->DeleteDirectory(path);
}
ResultCode DeleteDirectoryRecursivelyFromArchive(ArchiveHandle archive_handle,
@@ -368,10 +360,7 @@ ResultCode DeleteDirectoryRecursivelyFromArchive(ArchiveHandle archive_handle,
if (archive == nullptr)
return ERR_INVALID_ARCHIVE_HANDLE;
- if (archive->DeleteDirectoryRecursively(path))
- return RESULT_SUCCESS;
- return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
- ErrorSummary::Canceled, ErrorLevel::Status);
+ return archive->DeleteDirectoryRecursively(path);
}
ResultCode CreateFileInArchive(ArchiveHandle archive_handle, const FileSys::Path& path,
@@ -388,10 +377,7 @@ ResultCode CreateDirectoryFromArchive(ArchiveHandle archive_handle, const FileSy
if (archive == nullptr)
return ERR_INVALID_ARCHIVE_HANDLE;
- if (archive->CreateDirectory(path))
- return RESULT_SUCCESS;
- return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
- ErrorSummary::Canceled, ErrorLevel::Status);
+ return archive->CreateDirectory(path);
}
ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
@@ -404,17 +390,11 @@ ResultCode RenameDirectoryBetweenArchives(ArchiveHandle src_archive_handle,
return ERR_INVALID_ARCHIVE_HANDLE;
if (src_archive == dest_archive) {
- if (src_archive->RenameDirectory(src_path, dest_path))
- return RESULT_SUCCESS;
+ return src_archive->RenameDirectory(src_path, dest_path);
} else {
// TODO: Implement renaming across archives
return UnimplementedFunction(ErrorModule::FS);
}
-
- // TODO(yuriks): This code probably isn't right, it'll return a Status even if the file didn't
- // exist or similar. Verify.
- return ResultCode(ErrorDescription::NoData, ErrorModule::FS, // TODO: verify description
- ErrorSummary::NothingHappened, ErrorLevel::Status);
}
ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle archive_handle,
@@ -423,13 +403,11 @@ ResultVal<Kernel::SharedPtr<Directory>> OpenDirectoryFromArchive(ArchiveHandle a
if (archive == nullptr)
return ERR_INVALID_ARCHIVE_HANDLE;
- std::unique_ptr<FileSys::DirectoryBackend> backend = archive->OpenDirectory(path);
- if (backend == nullptr) {
- return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound,
- ErrorLevel::Permanent);
- }
+ auto backend = archive->OpenDirectory(path);
+ if (backend.Failed())
+ return backend.Code();
- auto directory = Kernel::SharedPtr<Directory>(new Directory(std::move(backend), path));
+ auto directory = Kernel::SharedPtr<Directory>(new Directory(backend.MoveFrom(), path));
return MakeResult<Kernel::SharedPtr<Directory>>(std::move(directory));
}
@@ -549,6 +527,13 @@ void RegisterArchiveTypes() {
LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s",
sdmc_directory.c_str());
+ auto sdmcwo_factory = std::make_unique<FileSys::ArchiveFactory_SDMCWriteOnly>(sdmc_directory);
+ if (sdmcwo_factory->Initialize())
+ RegisterArchiveType(std::move(sdmcwo_factory), ArchiveIdCode::SDMCWriteOnly);
+ else
+ LOG_ERROR(Service_FS, "Can't instantiate SDMCWriteOnly archive with path %s",
+ sdmc_directory.c_str());
+
// Create the SaveData archive
auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData);
@@ -569,10 +554,9 @@ void RegisterArchiveTypes() {
LOG_ERROR(Service_FS, "Can't instantiate SharedExtSaveData archive with path %s",
sharedextsavedata_factory->GetMountPoint().c_str());
- // Create the SaveDataCheck archive, basically a small variation of the RomFS archive
- auto savedatacheck_factory =
- std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
- RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck);
+ // Create the NCCH archive, basically a small variation of the RomFS archive
+ auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_NCCH>(nand_directory);
+ RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::NCCH);
auto systemsavedata_factory =
std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
diff --git a/src/core/hle/service/fs/archive.h b/src/core/hle/service/fs/archive.h
index 41a76285c..21ed9717b 100644
--- a/src/core/hle/service/fs/archive.h
+++ b/src/core/hle/service/fs/archive.h
@@ -33,7 +33,7 @@ enum class ArchiveIdCode : u32 {
SystemSaveData = 0x00000008,
SDMC = 0x00000009,
SDMCWriteOnly = 0x0000000A,
- SaveDataCheck = 0x2345678A,
+ NCCH = 0x2345678A,
};
/// Media types for the archives
diff --git a/src/core/hle/service/mic_u.cpp b/src/core/hle/service/mic_u.cpp
index edd1ea97b..563341504 100644
--- a/src/core/hle/service/mic_u.cpp
+++ b/src/core/hle/service/mic_u.cpp
@@ -2,6 +2,9 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/logging/log.h"
+#include "core/hle/kernel/event.h"
+#include "core/hle/kernel/shared_memory.h"
#include "core/hle/service/mic_u.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -9,23 +12,298 @@
namespace MIC_U {
+enum class Encoding : u8 {
+ PCM8 = 0,
+ PCM16 = 1,
+ PCM8Signed = 2,
+ PCM16Signed = 3,
+};
+
+enum class SampleRate : u8 {
+ SampleRate32730 = 0,
+ SampleRate16360 = 1,
+ SampleRate10910 = 2,
+ SampleRate8180 = 3
+};
+
+static Kernel::SharedPtr<Kernel::Event> buffer_full_event;
+static Kernel::SharedPtr<Kernel::SharedMemory> shared_memory;
+static u8 mic_gain = 0;
+static bool mic_power = false;
+static bool is_sampling = false;
+static bool allow_shell_closed;
+static bool clamp = false;
+static Encoding encoding;
+static SampleRate sample_rate;
+static s32 audio_buffer_offset;
+static u32 audio_buffer_size;
+static bool audio_buffer_loop;
+
+/**
+ * MIC::MapSharedMem service function
+ * Inputs:
+ * 0 : Header Code[0x00010042]
+ * 1 : Shared-mem size
+ * 2 : CopyHandleDesc
+ * 3 : Shared-mem handle
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void MapSharedMem(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 size = cmd_buff[1];
+ Handle mem_handle = cmd_buff[3];
+ shared_memory = Kernel::g_handle_table.Get<Kernel::SharedMemory>(mem_handle);
+ if (shared_memory) {
+ shared_memory->name = "MIC_U:shared_memory";
+ }
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "called, size=0x%X, mem_handle=0x%08X", size, mem_handle);
+}
+
+/**
+ * MIC::UnmapSharedMem service function
+ * Inputs:
+ * 0 : Header Code[0x00020000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void UnmapSharedMem(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "called");
+}
+
+/**
+ * MIC::StartSampling service function
+ * Inputs:
+ * 0 : Header Code[0x00030140]
+ * 1 : Encoding
+ * 2 : SampleRate
+ * 3 : Base offset for audio data in sharedmem
+ * 4 : Size of the audio data in sharedmem
+ * 5 : Loop at end of buffer
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void StartSampling(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ encoding = static_cast<Encoding>(cmd_buff[1] & 0xFF);
+ sample_rate = static_cast<SampleRate>(cmd_buff[2] & 0xFF);
+ audio_buffer_offset = cmd_buff[3];
+ audio_buffer_size = cmd_buff[4];
+ audio_buffer_loop = static_cast<bool>(cmd_buff[5] & 0xFF);
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ is_sampling = true;
+ LOG_WARNING(Service_MIC, "(STUBBED) called, encoding=%u, sample_rate=%u, "
+ "audio_buffer_offset=%d, audio_buffer_size=%u, audio_buffer_loop=%u",
+ encoding, sample_rate, audio_buffer_offset, audio_buffer_size, audio_buffer_loop);
+}
+
+/**
+ * MIC::AdjustSampling service function
+ * Inputs:
+ * 0 : Header Code[0x00040040]
+ * 1 : SampleRate
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void AdjustSampling(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ sample_rate = static_cast<SampleRate>(cmd_buff[1] & 0xFF);
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "(STUBBED) called, sample_rate=%u", sample_rate);
+}
+
+/**
+ * MIC::StopSampling service function
+ * Inputs:
+ * 0 : Header Code[0x00050000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void StopSampling(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ is_sampling = false;
+ LOG_WARNING(Service_MIC, "(STUBBED) called");
+}
+
+/**
+ * MIC::IsSampling service function
+ * Inputs:
+ * 0 : Header Code[0x00060000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : 0 = sampling, non-zero = sampling
+ */
+static void IsSampling(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = is_sampling;
+ LOG_WARNING(Service_MIC, "(STUBBED) called");
+}
+
+/**
+ * MIC::GetBufferFullEvent service function
+ * Inputs:
+ * 0 : Header Code[0x00070000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 3 : Event handle
+ */
+static void GetBufferFullEvent(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[3] = Kernel::g_handle_table.Create(buffer_full_event).MoveFrom();
+ LOG_WARNING(Service_MIC, "(STUBBED) called");
+}
+
+/**
+ * MIC::SetGain service function
+ * Inputs:
+ * 0 : Header Code[0x00080040]
+ * 1 : Gain
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetGain(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ mic_gain = cmd_buff[1] & 0xFF;
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "(STUBBED) called, mic_gain=%u", mic_gain);
+}
+
+/**
+ * MIC::GetGain service function
+ * Inputs:
+ * 0 : Header Code[0x00090000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Gain
+ */
+static void GetGain(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = mic_gain;
+ LOG_WARNING(Service_MIC, "(STUBBED) called");
+}
+
+/**
+ * MIC::SetPower service function
+ * Inputs:
+ * 0 : Header Code[0x000A0040]
+ * 1 : Power (0 = off, 1 = on)
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetPower(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ mic_power = static_cast<bool>(cmd_buff[1] & 0xFF);
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "(STUBBED) called, mic_power=%u", mic_power);
+}
+
+/**
+ * MIC::GetPower service function
+ * Inputs:
+ * 0 : Header Code[0x000B0000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Power
+ */
+static void GetPower(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = mic_power;
+ LOG_WARNING(Service_MIC, "(STUBBED) called");
+}
+
+/**
+ * MIC::SetIirFilterMic service function
+ * Inputs:
+ * 0 : Header Code[0x000C0042]
+ * 1 : Size
+ * 2 : (Size << 4) | 0xA
+ * 3 : Pointer to IIR Filter Data
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetIirFilterMic(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 size = cmd_buff[1];
+ VAddr buffer = cmd_buff[3];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "(STUBBED) called, size=0x%X, buffer=0x%08X", size, buffer);
+}
+
+/**
+ * MIC::SetClamp service function
+ * Inputs:
+ * 0 : Header Code[0x000D0040]
+ * 1 : Clamp (0 = don't clamp, non-zero = clamp)
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetClamp(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ clamp = static_cast<bool>(cmd_buff[1] & 0xFF);
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "(STUBBED) called, clamp=%u", clamp);
+}
+
+/**
+ * MIC::GetClamp service function
+ * Inputs:
+ * 0 : Header Code[0x000E0000]
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : Clamp (0 = don't clamp, non-zero = clamp)
+ */
+static void GetClamp(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = clamp;
+ LOG_WARNING(Service_MIC, "(STUBBED) called");
+}
+
+/**
+ * MIC::SetAllowShellClosed service function
+ * Inputs:
+ * 0 : Header Code[0x000D0040]
+ * 1 : Sampling allowed while shell closed (0 = disallow, non-zero = allow)
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetAllowShellClosed(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ allow_shell_closed = static_cast<bool>(cmd_buff[1] & 0xFF);
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_MIC, "(STUBBED) called, allow_shell_closed=%u", allow_shell_closed);
+}
+
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010042, nullptr, "MapSharedMem"},
- {0x00020000, nullptr, "UnmapSharedMem"},
- {0x00030140, nullptr, "Initialize"},
- {0x00040040, nullptr, "AdjustSampling"},
- {0x00050000, nullptr, "StopSampling"},
- {0x00060000, nullptr, "IsSampling"},
- {0x00070000, nullptr, "GetEventHandle"},
- {0x00080040, nullptr, "SetGain"},
- {0x00090000, nullptr, "GetGain"},
- {0x000A0040, nullptr, "SetPower"},
- {0x000B0000, nullptr, "GetPower"},
- {0x000C0042, nullptr, "size"},
- {0x000D0040, nullptr, "SetClamp"},
- {0x000E0000, nullptr, "GetClamp"},
- {0x000F0040, nullptr, "SetAllowShellClosed"},
- {0x00100040, nullptr, "unknown_input2"},
+ {0x00010042, MapSharedMem, "MapSharedMem"},
+ {0x00020000, UnmapSharedMem, "UnmapSharedMem"},
+ {0x00030140, StartSampling, "StartSampling"},
+ {0x00040040, AdjustSampling, "AdjustSampling"},
+ {0x00050000, StopSampling, "StopSampling"},
+ {0x00060000, IsSampling, "IsSampling"},
+ {0x00070000, GetBufferFullEvent, "GetBufferFullEvent"},
+ {0x00080040, SetGain, "SetGain"},
+ {0x00090000, GetGain, "GetGain"},
+ {0x000A0040, SetPower, "SetPower"},
+ {0x000B0000, GetPower, "GetPower"},
+ {0x000C0042, SetIirFilterMic, "SetIirFilterMic"},
+ {0x000D0040, SetClamp, "SetClamp"},
+ {0x000E0000, GetClamp, "GetClamp"},
+ {0x000F0040, SetAllowShellClosed, "SetAllowShellClosed"},
+ {0x00100040, nullptr, "SetClientSDKVersion"},
};
////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -33,6 +311,18 @@ const Interface::FunctionInfo FunctionTable[] = {
Interface::Interface() {
Register(FunctionTable);
+ shared_memory = nullptr;
+ buffer_full_event =
+ Kernel::Event::Create(Kernel::ResetType::OneShot, "MIC_U::buffer_full_event");
+ mic_gain = 0;
+ mic_power = false;
+ is_sampling = false;
+ clamp = false;
+}
+
+Interface::~Interface() {
+ shared_memory = nullptr;
+ buffer_full_event = nullptr;
}
} // namespace
diff --git a/src/core/hle/service/mic_u.h b/src/core/hle/service/mic_u.h
index dc795d14c..1cff7390e 100644
--- a/src/core/hle/service/mic_u.h
+++ b/src/core/hle/service/mic_u.h
@@ -16,6 +16,7 @@ namespace MIC_U {
class Interface : public Service::Interface {
public:
Interface();
+ ~Interface();
std::string GetPortName() const override {
return "mic:u";
diff --git a/src/core/hle/service/ptm/ptm.cpp b/src/core/hle/service/ptm/ptm.cpp
index 6e6b63329..cc859c14c 100644
--- a/src/core/hle/service/ptm/ptm.cpp
+++ b/src/core/hle/service/ptm/ptm.cpp
@@ -128,7 +128,7 @@ void Init() {
Service::FS::OpenArchive(Service::FS::ArchiveIdCode::SharedExtSaveData, archive_path);
ASSERT_MSG(archive_result.Succeeded(), "Could not open the PTM SharedExtSaveData archive!");
- FileSys::Path gamecoin_path("gamecoin.dat");
+ FileSys::Path gamecoin_path("/gamecoin.dat");
FileSys::Mode open_mode = {};
open_mode.write_flag.Assign(1);
open_mode.create_flag.Assign(1);