summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dyncom/arm_dyncom.cpp7
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp96
-rw-r--r--src/core/core.cpp5
-rw-r--r--src/core/file_sys/archive_extsavedata.cpp4
-rw-r--r--src/core/file_sys/archive_romfs.cpp3
-rw-r--r--src/core/file_sys/archive_savedata.cpp4
-rw-r--r--src/core/file_sys/archive_savedatacheck.cpp4
-rw-r--r--src/core/file_sys/archive_sdmc.cpp4
-rw-r--r--src/core/file_sys/archive_systemsavedata.cpp4
-rw-r--r--src/core/file_sys/disk_archive.cpp8
-rw-r--r--src/core/file_sys/ivfc_archive.cpp5
-rw-r--r--src/core/gdbstub/gdbstub.cpp108
-rw-r--r--src/core/hle/config_mem.cpp7
-rw-r--r--src/core/hle/hle.cpp2
-rw-r--r--src/core/hle/kernel/process.cpp3
-rw-r--r--src/core/hle/result.h1
-rw-r--r--src/core/hle/service/am/am.cpp140
-rw-r--r--src/core/hle/service/am/am.h126
-rw-r--r--src/core/hle/service/am/am_app.cpp16
-rw-r--r--src/core/hle/service/am/am_net.cpp18
-rw-r--r--src/core/hle/service/am/am_sys.cpp22
-rw-r--r--src/core/hle/service/am/am_u.cpp18
-rw-r--r--src/core/hle/service/apt/apt.cpp17
-rw-r--r--src/core/hle/service/apt/apt.h17
-rw-r--r--src/core/hle/service/apt/apt_a.cpp9
-rw-r--r--src/core/hle/service/apt/apt_s.cpp10
-rw-r--r--src/core/hle/service/apt/apt_u.cpp2
-rw-r--r--src/core/hle/service/cecd/cecd.cpp38
-rw-r--r--src/core/hle/service/cecd/cecd.h41
-rw-r--r--src/core/hle/service/cecd/cecd_u.cpp6
-rw-r--r--src/core/hle/service/cfg/cfg_i.cpp12
-rw-r--r--src/core/hle/service/cfg/cfg_s.cpp8
-rw-r--r--src/core/hle/service/cfg/cfg_u.cpp1
-rw-r--r--src/core/hle/service/dlp_srvr.cpp36
-rw-r--r--src/core/hle/service/dlp_srvr.h23
-rw-r--r--src/core/hle/service/frd/frd.cpp91
-rw-r--r--src/core/hle/service/frd/frd.h88
-rw-r--r--src/core/hle/service/frd/frd_u.cpp107
-rw-r--r--src/core/hle/service/fs/archive.cpp13
-rw-r--r--src/core/hle/service/gsp_gpu.cpp221
-rw-r--r--src/core/hle/service/gsp_gpu.h2
-rw-r--r--src/core/hle/service/service.cpp5
-rw-r--r--src/core/hle/shared_page.cpp3
-rw-r--r--src/core/hle/shared_page.h6
-rw-r--r--src/core/hw/y2r.cpp2
-rw-r--r--src/core/loader/3dsx.cpp6
-rw-r--r--src/core/loader/loader.cpp5
-rw-r--r--src/core/loader/ncch.cpp5
-rw-r--r--src/core/settings.cpp14
-rw-r--r--src/core/settings.h2
51 files changed, 1080 insertions, 317 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3473e2f5b..a8d891689 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -68,6 +68,7 @@ set(SRCS
hle/service/cfg/cfg_s.cpp
hle/service/cfg/cfg_u.cpp
hle/service/csnd_snd.cpp
+ hle/service/dlp_srvr.cpp
hle/service/dsp_dsp.cpp
hle/service/err_f.cpp
hle/service/frd/frd.cpp
@@ -200,6 +201,7 @@ set(HEADERS
hle/service/cfg/cfg_s.h
hle/service/cfg/cfg_u.h
hle/service/csnd_snd.h
+ hle/service/dlp_srvr.h
hle/service/dsp_dsp.h
hle/service/err_f.h
hle/service/frd/frd.h
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index f3be2c857..a3581132c 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -3,8 +3,7 @@
// Refer to the license.txt file included.
#include <cstring>
-
-#include "common/make_unique.h"
+#include <memory>
#include "core/arm/skyeye_common/armstate.h"
#include "core/arm/skyeye_common/armsupp.h"
@@ -18,7 +17,7 @@
#include "core/core_timing.h"
ARM_DynCom::ARM_DynCom(PrivilegeMode initial_mode) {
- state = Common::make_unique<ARMul_State>(initial_mode);
+ state = std::make_unique<ARMul_State>(initial_mode);
}
ARM_DynCom::~ARM_DynCom() {
@@ -94,7 +93,7 @@ void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 e
context.cpu_registers[0] = arg;
context.pc = entry_point;
context.sp = stack_top;
- context.cpsr = 0x1F; // Usermode
+ context.cpsr = 0x1F | ((entry_point & 1) << 5); // Usermode and THUMB mode
}
void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index 5f8826034..647784208 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -36,7 +36,8 @@ enum {
CALL = (1 << 4),
RET = (1 << 5),
END_OF_PAGE = (1 << 6),
- THUMB = (1 << 7)
+ THUMB = (1 << 7),
+ SINGLE_STEP = (1 << 8)
};
#define RM BITS(sht_oper, 0, 3)
@@ -3466,7 +3467,35 @@ enum {
MICROPROFILE_DEFINE(DynCom_Decode, "DynCom", "Decode", MP_RGB(255, 64, 64));
-static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
+static unsigned int InterpreterTranslateInstruction(const ARMul_State* cpu, const u32 phys_addr, ARM_INST_PTR& inst_base) {
+ unsigned int inst_size = 4;
+ unsigned int inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
+
+ // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
+ if (cpu->TFlag) {
+ u32 arm_inst;
+ ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
+
+ // We have translated the Thumb branch instruction in the Thumb decoder
+ if (state == ThumbDecodeStatus::BRANCH) {
+ return inst_size;
+ }
+ inst = arm_inst;
+ }
+
+ int idx;
+ if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
+ std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
+ LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst);
+ LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
+ CITRA_IGNORE_EXIT(-1);
+ }
+ inst_base = arm_instruction_trans[idx](inst, idx);
+
+ return inst_size;
+}
+
+static int InterpreterTranslateBlock(ARMul_State* cpu, int& bb_start, u32 addr) {
Common::Profiling::ScopeTimer timer_decode(profile_decode);
MICROPROFILE_SCOPE(DynCom_Decode);
@@ -3475,8 +3504,6 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
// Go on next, until terminal instruction
// Save start addr of basicblock in CreamCache
ARM_INST_PTR inst_base = nullptr;
- unsigned int inst, inst_size = 4;
- int idx;
int ret = NON_BRANCH;
int size = 0; // instruction size of basic block
bb_start = top;
@@ -3485,30 +3512,10 @@ static int InterpreterTranslate(ARMul_State* cpu, int& bb_start, u32 addr) {
u32 pc_start = cpu->Reg[15];
while (ret == NON_BRANCH) {
- inst = Memory::Read32(phys_addr & 0xFFFFFFFC);
+ unsigned int inst_size = InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
size++;
- // If we are in Thumb mode, we'll translate one Thumb instruction to the corresponding ARM instruction
- if (cpu->TFlag) {
- u32 arm_inst;
- ThumbDecodeStatus state = DecodeThumbInstruction(inst, phys_addr, &arm_inst, &inst_size, &inst_base);
-
- // We have translated the Thumb branch instruction in the Thumb decoder
- if (state == ThumbDecodeStatus::BRANCH) {
- goto translated;
- }
- inst = arm_inst;
- }
-
- if (DecodeARMInstruction(inst, &idx) == ARMDecodeStatus::FAILURE) {
- std::string disasm = ARM_Disasm::Disassemble(phys_addr, inst);
- LOG_ERROR(Core_ARM11, "Decode failure.\tPC : [0x%x]\tInstruction : %s [%x]", phys_addr, disasm.c_str(), inst);
- LOG_ERROR(Core_ARM11, "cpsr=0x%x, cpu->TFlag=%d, r15=0x%x", cpu->Cpsr, cpu->TFlag, cpu->Reg[15]);
- CITRA_IGNORE_EXIT(-1);
- }
- inst_base = arm_instruction_trans[idx](inst, idx);
-translated:
phys_addr += inst_size;
if ((phys_addr & 0xfff) == 0) {
@@ -3522,6 +3529,27 @@ translated:
return KEEP_GOING;
}
+static int InterpreterTranslateSingle(ARMul_State* cpu, int& bb_start, u32 addr) {
+ Common::Profiling::ScopeTimer timer_decode(profile_decode);
+ MICROPROFILE_SCOPE(DynCom_Decode);
+
+ ARM_INST_PTR inst_base = nullptr;
+ bb_start = top;
+
+ u32 phys_addr = addr;
+ u32 pc_start = cpu->Reg[15];
+
+ InterpreterTranslateInstruction(cpu, phys_addr, inst_base);
+
+ if (inst_base->br == NON_BRANCH) {
+ inst_base->br = SINGLE_STEP;
+ }
+
+ cpu->instruction_cache[pc_start] = bb_start;
+
+ return KEEP_GOING;
+}
+
static int clz(unsigned int x) {
int n;
if (x == 0) return (32);
@@ -3871,8 +3899,11 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
auto itr = cpu->instruction_cache.find(cpu->Reg[15]);
if (itr != cpu->instruction_cache.end()) {
ptr = itr->second;
+ } else if (cpu->NumInstrsToExecute != 1) {
+ if (InterpreterTranslateBlock(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
+ goto END;
} else {
- if (InterpreterTranslate(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
+ if (InterpreterTranslateSingle(cpu, ptr, cpu->Reg[15]) == FETCH_EXCEPTION)
goto END;
}
@@ -3924,9 +3955,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
add_inst* const inst_cream = (add_inst*)inst_base->component;
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
+ u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
bool carry;
bool overflow;
@@ -4051,11 +4080,12 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if ((inst_base->cond == ConditionCode::AL) || CondPassed(cpu, inst_base->cond)) {
unsigned int inst = inst_cream->inst;
if (BITS(inst, 20, 27) == 0x12 && BITS(inst, 4, 7) == 0x3) {
+ const u32 jump_address = cpu->Reg[inst_cream->val.Rm];
cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
if(cpu->TFlag)
cpu->Reg[14] |= 0x1;
- cpu->Reg[15] = cpu->Reg[inst_cream->val.Rm] & 0xfffffffe;
- cpu->TFlag = cpu->Reg[inst_cream->val.Rm] & 0x1;
+ cpu->Reg[15] = jump_address & 0xfffffffe;
+ cpu->TFlag = jump_address & 0x1;
} else {
cpu->Reg[14] = (cpu->Reg[15] + cpu->GetInstructionSize());
cpu->TFlag = 0x1;
@@ -6136,9 +6166,7 @@ unsigned InterpreterMainLoop(ARMul_State* cpu) {
if (inst_base->cond == ConditionCode::AL || CondPassed(cpu, inst_base->cond)) {
sub_inst* const inst_cream = (sub_inst*)inst_base->component;
- u32 rn_val = RN;
- if (inst_cream->Rn == 15)
- rn_val += 2 * cpu->GetInstructionSize();
+ u32 rn_val = CHECK_READ_REG15_WA(cpu, inst_cream->Rn);
bool carry;
bool overflow;
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 84d6c392e..3bb843aab 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -4,7 +4,6 @@
#include <memory>
-#include "common/make_unique.h"
#include "common/logging/log.h"
#include "core/core.h"
@@ -74,8 +73,8 @@ void Stop() {
/// Initialize the core
void Init() {
- g_sys_core = Common::make_unique<ARM_DynCom>(USER32MODE);
- g_app_core = Common::make_unique<ARM_DynCom>(USER32MODE);
+ g_sys_core = std::make_unique<ARM_DynCom>(USER32MODE);
+ g_app_core = std::make_unique<ARM_DynCom>(USER32MODE);
LOG_DEBUG(Core, "Initialized OK");
}
diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp
index 961264fe5..1d9eaefcb 100644
--- a/src/core/file_sys/archive_extsavedata.cpp
+++ b/src/core/file_sys/archive_extsavedata.cpp
@@ -3,12 +3,12 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <memory>
#include <vector>
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "common/string_util.h"
#include "core/file_sys/archive_extsavedata.h"
@@ -84,7 +84,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_ExtSaveData::Open(cons
ErrorSummary::InvalidState, ErrorLevel::Status);
}
}
- auto archive = Common::make_unique<DiskArchive>(fullpath);
+ auto archive = std::make_unique<DiskArchive>(fullpath);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
diff --git a/src/core/file_sys/archive_romfs.cpp b/src/core/file_sys/archive_romfs.cpp
index a9a29ebde..38828b546 100644
--- a/src/core/file_sys/archive_romfs.cpp
+++ b/src/core/file_sys/archive_romfs.cpp
@@ -7,7 +7,6 @@
#include "common/common_types.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "core/file_sys/archive_romfs.h"
#include "core/file_sys/ivfc_archive.h"
@@ -25,7 +24,7 @@ ArchiveFactory_RomFS::ArchiveFactory_RomFS(Loader::AppLoader& app_loader) {
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_RomFS::Open(const Path& path) {
- auto archive = Common::make_unique<IVFCArchive>(romfs_file, data_offset, data_size);
+ auto archive = std::make_unique<IVFCArchive>(romfs_file, data_offset, data_size);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
diff --git a/src/core/file_sys/archive_savedata.cpp b/src/core/file_sys/archive_savedata.cpp
index fe020d21c..fd5711e14 100644
--- a/src/core/file_sys/archive_savedata.cpp
+++ b/src/core/file_sys/archive_savedata.cpp
@@ -3,11 +3,11 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <memory>
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "common/string_util.h"
#include "core/file_sys/archive_savedata.h"
@@ -53,7 +53,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveData::Open(const P
ErrorSummary::InvalidState, ErrorLevel::Status);
}
- auto archive = Common::make_unique<DiskArchive>(std::move(concrete_mount_point));
+ auto archive = std::make_unique<DiskArchive>(std::move(concrete_mount_point));
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
diff --git a/src/core/file_sys/archive_savedatacheck.cpp b/src/core/file_sys/archive_savedatacheck.cpp
index 3db11c500..9f65e5455 100644
--- a/src/core/file_sys/archive_savedatacheck.cpp
+++ b/src/core/file_sys/archive_savedatacheck.cpp
@@ -3,12 +3,12 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <memory>
#include <vector>
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "common/string_util.h"
#include "core/file_sys/archive_savedatacheck.h"
@@ -44,7 +44,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SaveDataCheck::Open(co
}
auto size = file->GetSize();
- auto archive = Common::make_unique<IVFCArchive>(file, 0, size);
+ auto archive = std::make_unique<IVFCArchive>(file, 0, size);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
diff --git a/src/core/file_sys/archive_sdmc.cpp b/src/core/file_sys/archive_sdmc.cpp
index 657221cbf..9b218af58 100644
--- a/src/core/file_sys/archive_sdmc.cpp
+++ b/src/core/file_sys/archive_sdmc.cpp
@@ -3,10 +3,10 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <memory>
#include "common/file_util.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "core/file_sys/archive_sdmc.h"
#include "core/file_sys/disk_archive.h"
@@ -36,7 +36,7 @@ bool ArchiveFactory_SDMC::Initialize() {
}
ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SDMC::Open(const Path& path) {
- auto archive = Common::make_unique<DiskArchive>(sdmc_directory);
+ auto archive = std::make_unique<DiskArchive>(sdmc_directory);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
diff --git a/src/core/file_sys/archive_systemsavedata.cpp b/src/core/file_sys/archive_systemsavedata.cpp
index e1780de2f..1bcc228a1 100644
--- a/src/core/file_sys/archive_systemsavedata.cpp
+++ b/src/core/file_sys/archive_systemsavedata.cpp
@@ -3,11 +3,11 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <memory>
#include <vector>
#include "common/common_types.h"
#include "common/file_util.h"
-#include "common/make_unique.h"
#include "common/string_util.h"
#include "core/file_sys/archive_systemsavedata.h"
@@ -59,7 +59,7 @@ ResultVal<std::unique_ptr<ArchiveBackend>> ArchiveFactory_SystemSaveData::Open(c
return ResultCode(ErrorDescription::FS_NotFormatted, ErrorModule::FS,
ErrorSummary::InvalidState, ErrorLevel::Status);
}
- auto archive = Common::make_unique<DiskArchive>(fullpath);
+ auto archive = std::make_unique<DiskArchive>(fullpath);
return MakeResult<std::unique_ptr<ArchiveBackend>>(std::move(archive));
}
diff --git a/src/core/file_sys/disk_archive.cpp b/src/core/file_sys/disk_archive.cpp
index 8e4ea01c5..489cc96fb 100644
--- a/src/core/file_sys/disk_archive.cpp
+++ b/src/core/file_sys/disk_archive.cpp
@@ -4,11 +4,11 @@
#include <algorithm>
#include <cstdio>
+#include <memory>
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "core/file_sys/disk_archive.h"
@@ -19,7 +19,7 @@ namespace FileSys {
ResultVal<std::unique_ptr<FileBackend>> DiskArchive::OpenFile(const Path& path, const Mode mode) const {
LOG_DEBUG(Service_FS, "called path=%s mode=%01X", path.DebugStr().c_str(), mode.hex);
- auto file = Common::make_unique<DiskFile>(*this, path, mode);
+ auto file = std::make_unique<DiskFile>(*this, path, mode);
ResultCode result = file->Open();
if (result.IsError())
return result;
@@ -83,7 +83,7 @@ bool DiskArchive::RenameDirectory(const Path& src_path, const Path& dest_path) c
std::unique_ptr<DirectoryBackend> DiskArchive::OpenDirectory(const Path& path) const {
LOG_DEBUG(Service_FS, "called path=%s", path.DebugStr().c_str());
- auto directory = Common::make_unique<DiskDirectory>(*this, path);
+ auto directory = std::make_unique<DiskDirectory>(*this, path);
if (!directory->Open())
return nullptr;
return std::move(directory);
@@ -132,7 +132,7 @@ ResultCode DiskFile::Open() {
// Open the file in binary mode, to avoid problems with CR/LF on Windows systems
mode_string += "b";
- file = Common::make_unique<FileUtil::IOFile>(path, mode_string.c_str());
+ file = std::make_unique<FileUtil::IOFile>(path, mode_string.c_str());
if (file->IsOpen())
return RESULT_SUCCESS;
return ResultCode(ErrorDescription::FS_NotFound, ErrorModule::FS, ErrorSummary::NotFound, ErrorLevel::Status);
diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp
index a8e9a72ef..c61791ef7 100644
--- a/src/core/file_sys/ivfc_archive.cpp
+++ b/src/core/file_sys/ivfc_archive.cpp
@@ -7,7 +7,6 @@
#include "common/common_types.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "core/file_sys/ivfc_archive.h"
@@ -21,7 +20,7 @@ std::string IVFCArchive::GetName() const {
}
ResultVal<std::unique_ptr<FileBackend>> IVFCArchive::OpenFile(const Path& path, const Mode mode) const {
- return MakeResult<std::unique_ptr<FileBackend>>(Common::make_unique<IVFCFile>(romfs_file, data_offset, data_size));
+ return MakeResult<std::unique_ptr<FileBackend>>(std::make_unique<IVFCFile>(romfs_file, data_offset, data_size));
}
ResultCode IVFCArchive::DeleteFile(const Path& path) const {
@@ -58,7 +57,7 @@ bool IVFCArchive::RenameDirectory(const Path& src_path, const Path& dest_path) c
}
std::unique_ptr<DirectoryBackend> IVFCArchive::OpenDirectory(const Path& path) const {
- return Common::make_unique<IVFCDirectory>();
+ return std::make_unique<IVFCDirectory>();
}
u64 IVFCArchive::GetFreeBytes() const {
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 3a2445241..c1a7ec5bf 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -60,6 +60,59 @@ const u32 R15_REGISTER = 15;
const u32 CPSR_REGISTER = 25;
const u32 FPSCR_REGISTER = 58;
+// For sample XML files see the GDB source /gdb/features
+// GDB also wants the l character at the start
+// This XML defines what the registers are for this specific ARM device
+static const char* target_xml =
+R"(l<?xml version="1.0"?>
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
+<target version="1.0">
+ <feature name="org.gnu.gdb.arm.core">
+ <reg name="r0" bitsize="32"/>
+ <reg name="r1" bitsize="32"/>
+ <reg name="r2" bitsize="32"/>
+ <reg name="r3" bitsize="32"/>
+ <reg name="r4" bitsize="32"/>
+ <reg name="r5" bitsize="32"/>
+ <reg name="r6" bitsize="32"/>
+ <reg name="r7" bitsize="32"/>
+ <reg name="r8" bitsize="32"/>
+ <reg name="r9" bitsize="32"/>
+ <reg name="r10" bitsize="32"/>
+ <reg name="r11" bitsize="32"/>
+ <reg name="r12" bitsize="32"/>
+ <reg name="sp" bitsize="32" type="data_ptr"/>
+ <reg name="lr" bitsize="32"/>
+ <reg name="pc" bitsize="32" type="code_ptr"/>
+
+ <!-- The CPSR is register 25, rather than register 16, because
+ the FPA registers historically were placed between the PC
+ and the CPSR in the "g" packet. -->
+
+ <reg name="cpsr" bitsize="32" regnum="25"/>
+ </feature>
+ <feature name="org.gnu.gdb.arm.vfp">
+ <reg name="d0" bitsize="64" type="float"/>
+ <reg name="d1" bitsize="64" type="float"/>
+ <reg name="d2" bitsize="64" type="float"/>
+ <reg name="d3" bitsize="64" type="float"/>
+ <reg name="d4" bitsize="64" type="float"/>
+ <reg name="d5" bitsize="64" type="float"/>
+ <reg name="d6" bitsize="64" type="float"/>
+ <reg name="d7" bitsize="64" type="float"/>
+ <reg name="d8" bitsize="64" type="float"/>
+ <reg name="d9" bitsize="64" type="float"/>
+ <reg name="d10" bitsize="64" type="float"/>
+ <reg name="d11" bitsize="64" type="float"/>
+ <reg name="d12" bitsize="64" type="float"/>
+ <reg name="d13" bitsize="64" type="float"/>
+ <reg name="d14" bitsize="64" type="float"/>
+ <reg name="d15" bitsize="64" type="float"/>
+ <reg name="fpscr" bitsize="32" type="int" group="float"/>
+ </feature>
+</target>
+)";
+
namespace GDBStub {
static int gdbserver_socket = -1;
@@ -211,7 +264,7 @@ static u8 ReadByte() {
}
/// Calculate the checksum of the current command buffer.
-static u8 CalculateChecksum(u8 *buffer, u32 length) {
+static u8 CalculateChecksum(u8* buffer, u32 length) {
return static_cast<u8>(std::accumulate(buffer, buffer + length, 0, std::plus<u8>()));
}
@@ -353,8 +406,15 @@ static void SendReply(const char* reply) {
static void HandleQuery() {
LOG_DEBUG(Debug_GDBStub, "gdb: query '%s'\n", command_buffer + 1);
- if (!strcmp(reinterpret_cast<const char*>(command_buffer + 1), "TStatus")) {
+ const char* query = reinterpret_cast<const char*>(command_buffer + 1);
+
+ if (strcmp(query, "TStatus") == 0 ) {
SendReply("T0");
+ } else if (strncmp(query, "Supported:", strlen("Supported:")) == 0) {
+ // PacketSize needs to be large enough for target xml
+ SendReply("PacketSize=800;qXfer:features:read+");
+ } else if (strncmp(query, "Xfer:features:read:target.xml:", strlen("Xfer:features:read:target.xml:")) == 0) {
+ SendReply(target_xml);
} else {
SendReply("");
}
@@ -491,29 +551,25 @@ static void ReadRegisters() {
memset(buffer, 0, sizeof(buffer));
u8* bufptr = buffer;
- for (int i = 0, reg = 0; reg <= FPSCR_REGISTER; i++, reg++) {
- if (reg <= R15_REGISTER) {
- IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetReg(reg));
- } else if (reg == CPSR_REGISTER) {
- IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetCPSR());
- } else if (reg == CPSR_REGISTER - 1) {
- // Dummy FPA register, ignore
- IntToGdbHex(bufptr + i * CHAR_BIT, 0);
- } else if (reg < CPSR_REGISTER) {
- // Dummy FPA registers, ignore
- IntToGdbHex(bufptr + i * CHAR_BIT, 0);
- IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0);
- IntToGdbHex(bufptr + (i + 2) * CHAR_BIT, 0);
- i += 2;
- } else if (reg > CPSR_REGISTER && reg < FPSCR_REGISTER) {
- IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPReg(reg - CPSR_REGISTER - 1));
- IntToGdbHex(bufptr + (i + 1) * CHAR_BIT, 0);
- i++;
- } else if (reg == FPSCR_REGISTER) {
- IntToGdbHex(bufptr + i * CHAR_BIT, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR));
- }
+
+ for (int reg = 0; reg <= R15_REGISTER; reg++) {
+ IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetReg(reg));
}
+ bufptr += (16 * CHAR_BIT);
+
+ IntToGdbHex(bufptr, Core::g_app_core->GetCPSR());
+
+ bufptr += CHAR_BIT;
+
+ for (int reg = 0; reg <= 31; reg++) {
+ IntToGdbHex(bufptr + reg * CHAR_BIT, Core::g_app_core->GetVFPReg(reg));
+ }
+
+ bufptr += (32 * CHAR_BIT);
+
+ IntToGdbHex(bufptr, Core::g_app_core->GetVFPSystemReg(VFP_FPSCR));
+
SendReply(reinterpret_cast<char*>(buffer));
}
@@ -885,6 +941,12 @@ void Init(u16 port) {
LOG_ERROR(Debug_GDBStub, "Failed to create gdb socket");
}
+ // Set socket to SO_REUSEADDR so it can always bind on the same port
+ int reuse_enabled = 1;
+ if (setsockopt(tmpsock, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse_enabled, sizeof(reuse_enabled)) < 0) {
+ LOG_ERROR(Debug_GDBStub, "Failed to set gdb socket option");
+ }
+
const sockaddr* server_addr = reinterpret_cast<const sockaddr*>(&saddr_server);
socklen_t server_addrlen = sizeof(saddr_server);
if (bind(tmpsock, server_addr, server_addrlen) < 0) {
diff --git a/src/core/hle/config_mem.cpp b/src/core/hle/config_mem.cpp
index b1a72dc0c..ccd73cfcb 100644
--- a/src/core/hle/config_mem.cpp
+++ b/src/core/hle/config_mem.cpp
@@ -3,13 +3,6 @@
// Refer to the license.txt file included.
#include <cstring>
-
-#include "common/assert.h"
-#include "common/common_types.h"
-#include "common/common_funcs.h"
-
-#include "core/core.h"
-#include "core/memory.h"
#include "core/hle/config_mem.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/hle.cpp b/src/core/hle/hle.cpp
index 331b1b22a..e545de3b5 100644
--- a/src/core/hle/hle.cpp
+++ b/src/core/hle/hle.cpp
@@ -8,8 +8,6 @@
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/hle.h"
-#include "core/hle/config_mem.h"
-#include "core/hle/shared_page.h"
#include "core/hle/service/service.h"
////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 24b266eae..0546f6e16 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -2,10 +2,11 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <memory>
+
#include "common/assert.h"
#include "common/common_funcs.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "core/hle/kernel/memory.h"
#include "core/hle/kernel/process.h"
diff --git a/src/core/hle/result.h b/src/core/hle/result.h
index 0cb76ba1c..2d22652d9 100644
--- a/src/core/hle/result.h
+++ b/src/core/hle/result.h
@@ -24,6 +24,7 @@ enum class ErrorDescription : u32 {
FS_InvalidOpenFlags = 230,
FS_NotAFile = 250,
FS_NotFormatted = 340, ///< This is used by the FS service when creating a SaveData archive
+ OutofRangeOrMisalignedAddress = 513, // TODO(purpasmart): Check if this name fits its actual usage
FS_InvalidPath = 702,
InvalidSection = 1000,
TooLarge = 1001,
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp
index 06be9940e..9591522e5 100644
--- a/src/core/hle/service/am/am.cpp
+++ b/src/core/hle/service/am/am.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <cinttypes>
+
#include "common/logging/log.h"
#include "core/hle/service/service.h"
@@ -9,30 +11,119 @@
#include "core/hle/service/am/am_app.h"
#include "core/hle/service/am/am_net.h"
#include "core/hle/service/am/am_sys.h"
+#include "core/hle/service/am/am_u.h"
namespace Service {
namespace AM {
-void TitleIDListGetTotal(Service::Interface* self) {
+static std::array<u32, 3> am_content_count = { 0, 0, 0 };
+static std::array<u32, 3> am_titles_count = { 0, 0, 0 };
+static std::array<u32, 3> am_titles_list_count = { 0, 0, 0 };
+static u32 am_ticket_count = 0;
+static u32 am_ticket_list_count = 0;
+
+void GetTitleCount(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
+
u32 media_type = cmd_buff[1] & 0xFF;
cmd_buff[1] = RESULT_SUCCESS.raw;
- cmd_buff[2] = 0;
+ cmd_buff[2] = am_titles_count[media_type];
+ LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_count=0x%08x", media_type, am_titles_count[media_type]);
+}
+
+void FindContentInfos(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 media_type = cmd_buff[1] & 0xFF;
+ u64 title_id = (static_cast<u64>(cmd_buff[3]) << 32) | cmd_buff[2];
+ u32 content_ids_pointer = cmd_buff[6];
+ u32 content_info_pointer = cmd_buff[8];
+
+ am_content_count[media_type] = cmd_buff[4];
- LOG_WARNING(Service_AM, "(STUBBED) media_type %u", media_type);
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016lx, content_cound=%u, content_ids_pointer=0x%08x, content_info_pointer=0x%08x",
+ media_type, title_id, am_content_count[media_type], content_ids_pointer, content_info_pointer);
}
-void GetTitleIDList(Service::Interface* self) {
+void ListContentInfos(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
- u32 num_titles = cmd_buff[1];
+
u32 media_type = cmd_buff[2] & 0xFF;
- u32 addr = cmd_buff[4];
+ u64 title_id = (static_cast<u64>(cmd_buff[4]) << 32) | cmd_buff[3];
+ u32 start_index = cmd_buff[5];
+ u32 content_info_pointer = cmd_buff[7];
+
+ am_content_count[media_type] = cmd_buff[1];
cmd_buff[1] = RESULT_SUCCESS.raw;
- cmd_buff[2] = 0;
+ cmd_buff[2] = am_content_count[media_type];
+ LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, content_count=%u, title_id=0x%016" PRIx64 ", start_index=0x%08x, content_info_pointer=0x%08X",
+ media_type, am_content_count[media_type], title_id, start_index, content_info_pointer);
+}
+
+void DeleteContents(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 media_type = cmd_buff[1] & 0xFF;
+ u64 title_id = (static_cast<u64>(cmd_buff[3]) << 32) | cmd_buff[2];
+ u32 content_ids_pointer = cmd_buff[6];
- LOG_WARNING(Service_AM, "(STUBBED) Requested %u titles from media type %u. Address=0x%08X", num_titles, media_type, addr);
+ am_content_count[media_type] = cmd_buff[4];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 ", content_count=%u, content_ids_pointer=0x%08x",
+ media_type, title_id, am_content_count[media_type], content_ids_pointer);
+}
+
+void GetTitleList(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 media_type = cmd_buff[2] & 0xFF;
+ u32 title_ids_output_pointer = cmd_buff[4];
+
+ am_titles_list_count[media_type] = cmd_buff[1];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = am_titles_list_count[media_type];
+ LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, titles_list_count=0x%08X, title_ids_output_pointer=0x%08X",
+ media_type, am_titles_list_count[media_type], title_ids_output_pointer);
+}
+
+void GetTitleInfo(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 media_type = cmd_buff[1] & 0xFF;
+ u32 title_id_list_pointer = cmd_buff[4];
+ u32 title_list_pointer = cmd_buff[6];
+
+ am_titles_count[media_type] = cmd_buff[2];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, total_titles=0x%08X, title_id_list_pointer=0x%08X, title_list_pointer=0x%08X",
+ media_type, am_titles_count[media_type], title_id_list_pointer, title_list_pointer);
+}
+
+void GetDataTitleInfos(Service::Interface* self) {
+ GetTitleInfo(self);
+
+ LOG_WARNING(Service_AM, "(STUBBED) called");
+}
+
+void ListDataTitleTicketInfos(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u64 title_id = (static_cast<u64>(cmd_buff[3]) << 32) | cmd_buff[2];
+ u32 start_index = cmd_buff[4];
+ u32 ticket_info_pointer = cmd_buff[6];
+
+ am_ticket_count = cmd_buff[1];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = am_ticket_count;
+ LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 ", start_index=0x%08X, ticket_info_pointer=0x%08X",
+ am_ticket_count, title_id, start_index, ticket_info_pointer);
}
void GetNumContentInfos(Service::Interface* self) {
@@ -40,16 +131,47 @@ void GetNumContentInfos(Service::Interface* self) {
cmd_buff[1] = RESULT_SUCCESS.raw;
cmd_buff[2] = 1; // Number of content infos plus one
-
LOG_WARNING(Service_AM, "(STUBBED) called");
}
+void DeleteTicket(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u64 title_id = (static_cast<u64>(cmd_buff[2]) << 32) | cmd_buff[1];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "",title_id);
+}
+
+void GetTicketCount(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = am_ticket_count;
+ LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x",am_ticket_count);
+}
+
+void GetTicketList(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 num_of_skip = cmd_buff[2];
+ u32 ticket_list_pointer = cmd_buff[4];
+
+ am_ticket_list_count = cmd_buff[1];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = am_ticket_list_count;
+ LOG_WARNING(Service_AM, "(STUBBED) ticket_list_count=0x%08x, num_of_skip=0x%08x, ticket_list_pointer=0x%08x",
+ am_ticket_list_count, num_of_skip, ticket_list_pointer);
+}
+
void Init() {
using namespace Kernel;
AddService(new AM_APP_Interface);
AddService(new AM_NET_Interface);
AddService(new AM_SYS_Interface);
+ AddService(new AM_U_Interface);
}
void Shutdown() {
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h
index 15e63bc7b..5676cdd5f 100644
--- a/src/core/hle/service/am/am.h
+++ b/src/core/hle/service/am/am.h
@@ -11,7 +11,7 @@ class Interface;
namespace AM {
/**
- * AM::TitleIDListGetTotal service function
+ * AM::GetTitleCount service function
* Gets the number of installed titles in the requested media type
* Inputs:
* 0 : Command header (0x00010040)
@@ -20,36 +20,140 @@ namespace AM {
* 1 : Result, 0 on success, otherwise error code
* 2 : The number of titles in the requested media type
*/
-void TitleIDListGetTotal(Service::Interface* self);
+void GetTitleCount(Service::Interface* self);
/**
- * AM::GetTitleIDList service function
+ * AM::FindContentInfos service function
+ * Inputs:
+ * 1 : MediaType
+ * 2-3 : u64, Title ID
+ * 4 : Content count
+ * 6 : Content IDs pointer
+ * 8 : Content Infos pointer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ */
+void FindContentInfos(Service::Interface* self);
+
+/**
+ * AM::ListContentInfos service function
+ * Inputs:
+ * 1 : Content count
+ * 2 : MediaType
+ * 3-4 : u64, Title ID
+ * 5 : Start Index
+ * 7 : Content Infos pointer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ * 2 : Number of content infos returned
+ */
+void ListContentInfos(Service::Interface* self);
+
+/**
+ * AM::DeleteContents service function
+ * Inputs:
+ * 1 : MediaType
+ * 2-3 : u64, Title ID
+ * 4 : Content count
+ * 6 : Content IDs pointer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ */
+void DeleteContents(Service::Interface* self);
+
+/**
+ * AM::GetTitleList service function
* Loads information about the desired number of titles from the desired media type into an array
* Inputs:
- * 0 : Command header (0x00020082)
- * 1 : The maximum number of titles to load
+ * 1 : Title count
* 2 : Media type to load the titles from
- * 3 : Descriptor of the output buffer pointer
- * 4 : Address of the output buffer
+ * 4 : Title IDs output pointer
* Outputs:
* 1 : Result, 0 on success, otherwise error code
* 2 : The number of titles loaded from the requested media type
*/
-void GetTitleIDList(Service::Interface* self);
+void GetTitleList(Service::Interface* self);
+
+/**
+ * AM::GetTitleInfo service function
+ * Inputs:
+ * 1 : u8 Mediatype
+ * 2 : Total titles
+ * 4 : TitleIDList pointer
+ * 6 : TitleList pointer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ */
+void GetTitleInfo(Service::Interface* self);
+
+/**
+ * AM::GetDataTitleInfos service function
+ * Wrapper for AM::GetTitleInfo
+ * Inputs:
+ * 1 : u8 Mediatype
+ * 2 : Total titles
+ * 4 : TitleIDList pointer
+ * 6 : TitleList pointer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ */
+void GetDataTitleInfos(Service::Interface* self);
+
+/**
+ * AM::ListDataTitleTicketInfos service function
+ * Inputs:
+ * 1 : Ticket count
+ * 2-3 : u64, Title ID
+ * 4 : Start Index?
+ * 5 : (TicketCount * 24) << 8 | 0x4
+ * 6 : Ticket Infos pointer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ * 2 : Number of ticket infos returned
+ */
+void ListDataTitleTicketInfos(Service::Interface* self);
/**
* AM::GetNumContentInfos service function
* Inputs:
* 0 : Command header (0x100100C0)
- * 1 : Unknown
- * 2 : Unknown
- * 3 : Unknown
+ * 1 : MediaType
+ * 2-3 : u64, Title ID
* Outputs:
* 1 : Result, 0 on success, otherwise error code
* 2 : Number of content infos plus one
*/
void GetNumContentInfos(Service::Interface* self);
+/**
+ * AM::DeleteTicket service function
+ * Inputs:
+ * 1-2 : u64, Title ID
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ */
+void DeleteTicket(Service::Interface* self);
+
+/**
+ * AM::GetTicketCount service function
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ * 2 : Total titles
+ */
+void GetTicketCount(Service::Interface* self);
+
+/**
+ * AM::GetTicketList service function
+ * Inputs:
+ * 1 : Number of TicketList
+ * 2 : Number to skip
+ * 4 : TicketList pointer
+ * Outputs:
+ * 1 : Result, 0 on success, otherwise error code
+ * 2 : Total TicketList
+ */
+void GetTicketList(Service::Interface* self);
+
/// Initialize AM service
void Init();
diff --git a/src/core/hle/service/am/am_app.cpp b/src/core/hle/service/am/am_app.cpp
index 16c76a1eb..d27b3defd 100644
--- a/src/core/hle/service/am/am_app.cpp
+++ b/src/core/hle/service/am/am_app.cpp
@@ -9,14 +9,14 @@ namespace Service {
namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
- {0x100100C0, GetNumContentInfos, "GetNumContentInfos"},
- {0x10020104, nullptr, "FindContentInfos"},
- {0x10030142, nullptr, "ListContentInfos"},
- {0x10040102, nullptr, "DeleteContents"},
- {0x10050084, nullptr, "GetDataTitleInfos"},
- {0x10070102, nullptr, "ListDataTitleTicketInfos"},
- {0x100900C0, nullptr, "IsDataTitleInUse"},
- {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"},
+ {0x100100C0, GetNumContentInfos, "GetNumContentInfos"},
+ {0x10020104, FindContentInfos, "FindContentInfos"},
+ {0x10030142, ListContentInfos, "ListContentInfos"},
+ {0x10040102, DeleteContents, "DeleteContents"},
+ {0x10050084, GetDataTitleInfos, "GetDataTitleInfos"},
+ {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"},
+ {0x100900C0, nullptr, "IsDataTitleInUse"},
+ {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"},
};
AM_APP_Interface::AM_APP_Interface() {
diff --git a/src/core/hle/service/am/am_net.cpp b/src/core/hle/service/am/am_net.cpp
index 065e04118..e75755245 100644
--- a/src/core/hle/service/am/am_net.cpp
+++ b/src/core/hle/service/am/am_net.cpp
@@ -9,16 +9,20 @@ namespace Service {
namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
- {0x00020082, GetTitleIDList, "GetTitleIDList"},
- {0x00030084, nullptr, "ListTitles"},
+ {0x00010040, GetTitleCount, "GetTitleCount"},
+ {0x00020082, GetTitleList, "GetTitleList"},
+ {0x00030084, GetTitleInfo, "GetTitleInfo"},
{0x000400C0, nullptr, "DeleteApplicationTitle"},
{0x000500C0, nullptr, "GetTitleProductCode"},
- {0x00080000, nullptr, "TitleIDListGetTotal3"},
- {0x00090082, nullptr, "GetTitleIDList3"},
+ {0x000600C0, nullptr, "GetTitleExtDataId"},
+ {0x00070080, DeleteTicket, "DeleteTicket"},
+ {0x00080000, GetTicketCount, "GetTicketCount"},
+ {0x00090082, GetTicketList, "GetTicketList"},
{0x000A0000, nullptr, "GetDeviceID"},
- {0x000D0084, nullptr, "ListTitles2"},
- {0x00140040, nullptr, "FinishInstallToMedia"},
+ {0x000D0084, nullptr, "GetPendingTitleInfo"},
+ {0x000E00C0, nullptr, "DeletePendingTitle"},
+ {0x00140040, nullptr, "FinalizePendingTitles"},
+ {0x00150040, nullptr, "DeleteAllPendingTitles"},
{0x00180080, nullptr, "InitializeTitleDatabase"},
{0x00190040, nullptr, "ReloadDBS"},
{0x001A00C0, nullptr, "GetDSiWareExportSize"},
diff --git a/src/core/hle/service/am/am_sys.cpp b/src/core/hle/service/am/am_sys.cpp
index e38812297..8bad5e1c9 100644
--- a/src/core/hle/service/am/am_sys.cpp
+++ b/src/core/hle/service/am/am_sys.cpp
@@ -9,23 +9,27 @@ namespace Service {
namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
- {0x00020082, GetTitleIDList, "GetTitleIDList"},
- {0x00030084, nullptr, "ListTitles"},
+ {0x00010040, GetTitleCount, "GetTitleCount"},
+ {0x00020082, GetTitleList, "GetTitleList"},
+ {0x00030084, GetTitleInfo, "GetTitleInfo"},
{0x000400C0, nullptr, "DeleteApplicationTitle"},
{0x000500C0, nullptr, "GetTitleProductCode"},
- {0x00080000, nullptr, "TitleIDListGetTotal3"},
- {0x00090082, nullptr, "GetTitleIDList3"},
+ {0x000600C0, nullptr, "GetTitleExtDataId"},
+ {0x00070080, DeleteTicket, "DeleteTicket"},
+ {0x00080000, GetTicketCount, "GetTicketCount"},
+ {0x00090082, GetTicketList, "GetTicketList"},
{0x000A0000, nullptr, "GetDeviceID"},
- {0x000D0084, nullptr, "ListTitles2"},
- {0x00140040, nullptr, "FinishInstallToMedia"},
+ {0x000D0084, nullptr, "GetPendingTitleInfo"},
+ {0x000E00C0, nullptr, "DeletePendingTitle"},
+ {0x00140040, nullptr, "FinalizePendingTitles"},
+ {0x00150040, nullptr, "DeleteAllPendingTitles"},
{0x00180080, nullptr, "InitializeTitleDatabase"},
{0x00190040, nullptr, "ReloadDBS"},
{0x001A00C0, nullptr, "GetDSiWareExportSize"},
{0x001B0144, nullptr, "ExportDSiWare"},
{0x001C0084, nullptr, "ImportDSiWare"},
- {0x00230080, nullptr, "TitleIDListGetTotal2"},
- {0x002400C2, nullptr, "GetTitleIDList2"}
+ {0x00230080, nullptr, "GetPendingTitleCount"},
+ {0x002400C2, nullptr, "GetPendingTitleList"}
};
AM_SYS_Interface::AM_SYS_Interface() {
diff --git a/src/core/hle/service/am/am_u.cpp b/src/core/hle/service/am/am_u.cpp
index c0392b754..d583dd9e6 100644
--- a/src/core/hle/service/am/am_u.cpp
+++ b/src/core/hle/service/am/am_u.cpp
@@ -9,16 +9,20 @@ namespace Service {
namespace AM {
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010040, TitleIDListGetTotal, "TitleIDListGetTotal"},
- {0x00020082, GetTitleIDList, "GetTitleIDList"},
- {0x00030084, nullptr, "ListTitles"},
+ {0x00010040, GetTitleCount, "GetTitleCount"},
+ {0x00020082, GetTitleList, "GetTitleList"},
+ {0x00030084, GetTitleInfo, "GetTitleInfo"},
{0x000400C0, nullptr, "DeleteApplicationTitle"},
{0x000500C0, nullptr, "GetTitleProductCode"},
- {0x00080000, nullptr, "TitleIDListGetTotal3"},
- {0x00090082, nullptr, "GetTitleIDList3"},
+ {0x000600C0, nullptr, "GetTitleExtDataId"},
+ {0x00070080, DeleteTicket, "DeleteTicket"},
+ {0x00080000, GetTicketCount, "GetTicketCount"},
+ {0x00090082, GetTicketList, "GetTicketList"},
{0x000A0000, nullptr, "GetDeviceID"},
- {0x000D0084, nullptr, "ListTitles2"},
- {0x00140040, nullptr, "FinishInstallToMedia"},
+ {0x000D0084, nullptr, "GetPendingTitleInfo"},
+ {0x000E00C0, nullptr, "DeletePendingTitle"},
+ {0x00140040, nullptr, "FinalizePendingTitles"},
+ {0x00150040, nullptr, "DeleteAllPendingTitles"},
{0x00180080, nullptr, "InitializeTitleDatabase"},
{0x00190040, nullptr, "ReloadDBS"},
{0x001A00C0, nullptr, "GetDSiWareExportSize"},
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index a49365287..6d72e8188 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -397,6 +397,23 @@ void GetAppletInfo(Service::Interface* self) {
LOG_WARNING(Service_APT, "(stubbed) called appid=%u", app_id);
}
+void GetStartupArgument(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 parameter_size = cmd_buff[1];
+ StartupArgumentType startup_argument_type = static_cast<StartupArgumentType>(cmd_buff[2]);
+
+ if (parameter_size >= 0x300) {
+ LOG_ERROR(Service_APT, "Parameter size is outside the valid range (capped to 0x300): parameter_size=0x%08x", parameter_size);
+ return;
+ }
+
+ LOG_WARNING(Service_APT,"(stubbed) called startup_argument_type=%u , parameter_size=0x%08x , parameter_value=0x%08x",
+ startup_argument_type, parameter_size, Memory::Read32(cmd_buff[41]));
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = (parameter_size > 0) ? 1 : 0;
+}
+
void Init() {
AddService(new APT_A_Interface);
AddService(new APT_S_Interface);
diff --git a/src/core/hle/service/apt/apt.h b/src/core/hle/service/apt/apt.h
index 47a97c1a1..668b4a66f 100644
--- a/src/core/hle/service/apt/apt.h
+++ b/src/core/hle/service/apt/apt.h
@@ -67,6 +67,12 @@ enum class AppletId : u32 {
Ed2 = 0x402,
};
+enum class StartupArgumentType : u32 {
+ OtherApp = 0,
+ Restart = 1,
+ OtherMedia = 2,
+};
+
/// Send a parameter to the currently-running application, which will read it via ReceiveParameter
void SendParameter(const MessageParameter& parameter);
@@ -344,6 +350,17 @@ void PreloadLibraryApplet(Service::Interface* self);
*/
void StartLibraryApplet(Service::Interface* self);
+/**
+ * APT::GetStartupArgument service function
+ * Inputs:
+ * 1 : Parameter Size (capped to 0x300)
+ * 2 : StartupArgumentType
+ * Outputs:
+ * 0 : Return header
+ * 1 : u8, Exists (0 = does not exist, 1 = exists)
+ */
+void GetStartupArgument(Service::Interface* self);
+
/// Initialize the APT service
void Init();
diff --git a/src/core/hle/service/apt/apt_a.cpp b/src/core/hle/service/apt/apt_a.cpp
index 0c6a77305..9ff47701a 100644
--- a/src/core/hle/service/apt/apt_a.cpp
+++ b/src/core/hle/service/apt/apt_a.cpp
@@ -13,9 +13,10 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00020080, Initialize, "Initialize?"},
{0x00030040, Enable, "Enable?"},
{0x00040040, nullptr, "Finalize?"},
- {0x00050040, nullptr, "GetAppletManInfo?"},
- {0x00060040, nullptr, "GetAppletInfo?"},
+ {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
+ {0x00060040, GetAppletInfo, "GetAppletInfo"},
{0x00090040, IsRegistered, "IsRegistered"},
+ {0x000B0040, InquireNotification, "InquireNotification"},
{0x000C0104, SendParameter, "SendParameter"},
{0x000D0080, ReceiveParameter, "ReceiveParameter"},
{0x000E0080, GlanceParameter, "GlanceParameter"},
@@ -24,9 +25,13 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00180040, PrepareToStartLibraryApplet, "PrepareToStartLibraryApplet"},
{0x001E0084, StartLibraryApplet, "StartLibraryApplet"},
{0x003B0040, nullptr, "CancelLibraryApplet?"},
+ {0x003E0080, nullptr, "ReplySleepQuery"},
{0x00430040, NotifyToWait, "NotifyToWait?"},
{0x00440000, GetSharedFont, "GetSharedFont?"},
{0x004B00C2, AppletUtility, "AppletUtility?"},
+ {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
+ {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
+ {0x00510080, GetStartupArgument, "GetStartupArgument"},
{0x00550040, nullptr, "WriteInputToNsState?"},
};
diff --git a/src/core/hle/service/apt/apt_s.cpp b/src/core/hle/service/apt/apt_s.cpp
index 7f6e81a63..ca54e593c 100644
--- a/src/core/hle/service/apt/apt_s.cpp
+++ b/src/core/hle/service/apt/apt_s.cpp
@@ -13,8 +13,8 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x00020080, Initialize, "Initialize"},
{0x00030040, Enable, "Enable"},
{0x00040040, nullptr, "Finalize"},
- {0x00050040, nullptr, "GetAppletManInfo"},
- {0x00060040, nullptr, "GetAppletInfo"},
+ {0x00050040, GetAppletManInfo, "GetAppletManInfo"},
+ {0x00060040, GetAppletInfo, "GetAppletInfo"},
{0x00070000, nullptr, "GetLastSignaledAppletId"},
{0x00080000, nullptr, "CountRegisteredApplet"},
{0x00090040, nullptr, "IsRegistered"},
@@ -87,9 +87,9 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x004C0000, nullptr, "SetFatalErrDispMode"},
{0x004D0080, nullptr, "GetAppletProgramInfo"},
{0x004E0000, nullptr, "HardwareResetAsync"},
- {0x004F0080, nullptr, "SetApplicationCpuTimeLimit"},
- {0x00500040, nullptr, "GetApplicationCpuTimeLimit"},
- {0x00510080, nullptr, "GetStartupArgument"},
+ {0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
+ {0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
+ {0x00510080, GetStartupArgument, "GetStartupArgument"},
{0x00520104, nullptr, "Wrap1"},
{0x00530104, nullptr, "Unwrap1"},
{0x00580002, nullptr, "GetProgramID"},
diff --git a/src/core/hle/service/apt/apt_u.cpp b/src/core/hle/service/apt/apt_u.cpp
index b13b51549..0e85c6d08 100644
--- a/src/core/hle/service/apt/apt_u.cpp
+++ b/src/core/hle/service/apt/apt_u.cpp
@@ -89,7 +89,7 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x004E0000, nullptr, "HardwareResetAsync"},
{0x004F0080, SetAppCpuTimeLimit, "SetAppCpuTimeLimit"},
{0x00500040, GetAppCpuTimeLimit, "GetAppCpuTimeLimit"},
- {0x00510080, nullptr, "GetStartupArgument"},
+ {0x00510080, GetStartupArgument, "GetStartupArgument"},
{0x00520104, nullptr, "Wrap1"},
{0x00530104, nullptr, "Unwrap1"},
{0x00580002, nullptr, "GetProgramID"},
diff --git a/src/core/hle/service/cecd/cecd.cpp b/src/core/hle/service/cecd/cecd.cpp
index 6d79ce9b4..50c03495e 100644
--- a/src/core/hle/service/cecd/cecd.cpp
+++ b/src/core/hle/service/cecd/cecd.cpp
@@ -4,6 +4,7 @@
#include "common/logging/log.h"
+#include "core/hle/kernel/event.h"
#include "core/hle/service/service.h"
#include "core/hle/service/cecd/cecd.h"
#include "core/hle/service/cecd/cecd_s.h"
@@ -12,14 +13,47 @@
namespace Service {
namespace CECD {
-void Init() {
- using namespace Kernel;
+static Kernel::SharedPtr<Kernel::Event> cecinfo_event;
+static Kernel::SharedPtr<Kernel::Event> change_state_event;
+
+void GetCecStateAbbreviated(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = static_cast<u32>(CecStateAbbreviated::CEC_STATE_ABBREV_IDLE);
+
+ LOG_WARNING(Service_CECD, "(STUBBED) called");
+}
+
+void GetCecInfoEventHandle(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[3] = Kernel::g_handle_table.Create(cecinfo_event).MoveFrom(); // Event handle
+
+ LOG_WARNING(Service_CECD, "(STUBBED) called");
+}
+
+void GetChangeStateEventHandle(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[3] = Kernel::g_handle_table.Create(change_state_event).MoveFrom(); // Event handle
+
+ LOG_WARNING(Service_CECD, "(STUBBED) called");
+}
+
+void Init() {
AddService(new CECD_S_Interface);
AddService(new CECD_U_Interface);
+
+ cecinfo_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::cecinfo_event");
+ change_state_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "CECD_U::change_state_event");
}
void Shutdown() {
+ cecinfo_event = nullptr;
+ change_state_event = nullptr;
}
} // namespace CECD
diff --git a/src/core/hle/service/cecd/cecd.h b/src/core/hle/service/cecd/cecd.h
index 9e158521b..435611363 100644
--- a/src/core/hle/service/cecd/cecd.h
+++ b/src/core/hle/service/cecd/cecd.h
@@ -5,8 +5,49 @@
#pragma once
namespace Service {
+
+class Interface;
+
namespace CECD {
+enum class CecStateAbbreviated {
+ CEC_STATE_ABBREV_IDLE = 1, ///< Corresponds to CEC_STATE_IDLE
+ CEC_STATE_ABBREV_NOT_LOCAL = 2, ///< Corresponds to CEC_STATEs *FINISH*, *POST, and OVER_BOSS
+ CEC_STATE_ABBREV_SCANNING = 3, ///< Corresponds to CEC_STATE_SCANNING
+ CEC_STATE_ABBREV_WLREADY = 4, ///< Corresponds to CEC_STATE_WIRELESS_READY when some unknown bool is true
+ CEC_STATE_ABBREV_OTHER = 5, ///< Corresponds to CEC_STATEs besides *FINISH*, *POST, and OVER_BOSS and those listed here
+};
+
+/**
+ * GetCecStateAbbreviated service function
+ * Inputs:
+ * 0: 0x000E0000
+ * Outputs:
+ * 1: ResultCode
+ * 2: CecStateAbbreviated
+ */
+void GetCecStateAbbreviated(Service::Interface* self);
+
+/**
+ * GetCecInfoEventHandle service function
+ * Inputs:
+ * 0: 0x000F0000
+ * Outputs:
+ * 1: ResultCode
+ * 3: Event Handle
+ */
+void GetCecInfoEventHandle(Service::Interface* self);
+
+/**
+ * GetChangeStateEventHandle service function
+ * Inputs:
+ * 0: 0x00100000
+ * Outputs:
+ * 1: ResultCode
+ * 3: Event Handle
+ */
+void GetChangeStateEventHandle(Service::Interface* self);
+
/// Initialize CECD service(s)
void Init();
diff --git a/src/core/hle/service/cecd/cecd_u.cpp b/src/core/hle/service/cecd/cecd_u.cpp
index 9b720a738..be6d4d8f6 100644
--- a/src/core/hle/service/cecd/cecd_u.cpp
+++ b/src/core/hle/service/cecd/cecd_u.cpp
@@ -2,13 +2,17 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "core/hle/service/cecd/cecd.h"
#include "core/hle/service/cecd/cecd_u.h"
namespace Service {
namespace CECD {
static const Interface::FunctionInfo FunctionTable[] = {
- { 0x00120104, nullptr, "ReadSavedData" },
+ {0x000E0000, GetCecStateAbbreviated, "GetCecStateAbbreviated"},
+ {0x000F0000, GetCecInfoEventHandle, "GetCecInfoEventHandle"},
+ {0x00100000, GetChangeStateEventHandle, "GetChangeStateEventHandle"},
+ {0x00120104, nullptr, "ReadSavedData"},
};
CECD_U_Interface::CECD_U_Interface() {
diff --git a/src/core/hle/service/cfg/cfg_i.cpp b/src/core/hle/service/cfg/cfg_i.cpp
index 0559a07b2..b18060f6d 100644
--- a/src/core/hle/service/cfg/cfg_i.cpp
+++ b/src/core/hle/service/cfg/cfg_i.cpp
@@ -9,6 +9,18 @@ namespace Service {
namespace CFG {
const Interface::FunctionInfo FunctionTable[] = {
+ // cfg common
+ {0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
+ {0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
+ {0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
+ {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
+ {0x00050000, GetSystemModel, "GetSystemModel"},
+ {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
+ {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
+ {0x00080080, nullptr, "GoThroughTable"},
+ {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
+ {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
+ // cfg:i
{0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
{0x04020082, nullptr, "SetConfigInfoBlk4"},
{0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
diff --git a/src/core/hle/service/cfg/cfg_s.cpp b/src/core/hle/service/cfg/cfg_s.cpp
index b03d290e5..e001f7687 100644
--- a/src/core/hle/service/cfg/cfg_s.cpp
+++ b/src/core/hle/service/cfg/cfg_s.cpp
@@ -9,10 +9,18 @@ namespace Service {
namespace CFG {
const Interface::FunctionInfo FunctionTable[] = {
+ // cfg common
{0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
{0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
{0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
+ {0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
{0x00050000, GetSystemModel, "GetSystemModel"},
+ {0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
+ {0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
+ {0x00080080, nullptr, "GoThroughTable"},
+ {0x00090040, GetCountryCodeString, "GetCountryCodeString"},
+ {0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
+ // cfg:s
{0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
{0x04020082, nullptr, "SetConfigInfoBlk4"},
{0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 89ae96c9e..606f7b2eb 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -9,6 +9,7 @@ namespace Service {
namespace CFG {
const Interface::FunctionInfo FunctionTable[] = {
+ // cfg common
{0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
{0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
{0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
diff --git a/src/core/hle/service/dlp_srvr.cpp b/src/core/hle/service/dlp_srvr.cpp
new file mode 100644
index 000000000..1f30188da
--- /dev/null
+++ b/src/core/hle/service/dlp_srvr.cpp
@@ -0,0 +1,36 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "common/logging/log.h"
+#include "core/hle/hle.h"
+#include "core/hle/service/dlp_srvr.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace DLP_SRVR
+
+namespace DLP_SRVR {
+
+static void unk_0x000E0040(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+ cmd_buff[2] = 0;
+
+ LOG_WARNING(Service_DLP, "(STUBBED) called");
+}
+
+const Interface::FunctionInfo FunctionTable[] = {
+ {0x00010183, nullptr, "Initialize"},
+ {0x00020000, nullptr, "Finalize"},
+ {0x000E0040, unk_0x000E0040, "unk_0x000E0040"},
+};
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Interface class
+
+Interface::Interface() {
+ Register(FunctionTable);
+}
+
+} // namespace
diff --git a/src/core/hle/service/dlp_srvr.h b/src/core/hle/service/dlp_srvr.h
new file mode 100644
index 000000000..d65d00814
--- /dev/null
+++ b/src/core/hle/service/dlp_srvr.h
@@ -0,0 +1,23 @@
+// Copyright 2016 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "core/hle/service/service.h"
+
+////////////////////////////////////////////////////////////////////////////////////////////////////
+// Namespace DLP_SRVR
+
+namespace DLP_SRVR {
+
+class Interface : public Service::Interface {
+public:
+ Interface();
+
+ std::string GetPortName() const override {
+ return "dlp:SRVR";
+ }
+};
+
+} // namespace
diff --git a/src/core/hle/service/frd/frd.cpp b/src/core/hle/service/frd/frd.cpp
index c13ffd9d2..15d604bb6 100644
--- a/src/core/hle/service/frd/frd.cpp
+++ b/src/core/hle/service/frd/frd.cpp
@@ -2,6 +2,8 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "common/string_util.h"
+
#include "core/hle/service/service.h"
#include "core/hle/service/frd/frd.h"
#include "core/hle/service/frd/frd_a.h"
@@ -10,6 +12,95 @@
namespace Service {
namespace FRD {
+static FriendKey my_friend_key = {0, 0, 0ull};
+static MyPresence my_presence = {};
+
+void GetMyPresence(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 shifted_out_size = cmd_buff[64];
+ u32 my_presence_addr = cmd_buff[65];
+
+ ASSERT(shifted_out_size == ((sizeof(MyPresence) << 14) | 2));
+
+ Memory::WriteBlock(my_presence_addr, reinterpret_cast<const u8*>(&my_presence), sizeof(MyPresence));
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+ LOG_WARNING(Service_FRD, "(STUBBED) called");
+}
+
+void GetFriendKeyList(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 unknown = cmd_buff[1];
+ u32 frd_count = cmd_buff[2];
+ u32 frd_key_addr = cmd_buff[65];
+
+ FriendKey zero_key = {};
+ for (u32 i = 0; i < frd_count; ++i) {
+ Memory::WriteBlock(frd_key_addr + i * sizeof(FriendKey),
+ reinterpret_cast<const u8*>(&zero_key), sizeof(FriendKey));
+ }
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ cmd_buff[2] = 0; // 0 friends
+ LOG_WARNING(Service_FRD, "(STUBBED) called, unknown=%d, frd_count=%d, frd_key_addr=0x%08X",
+ unknown, frd_count, frd_key_addr);
+}
+
+void GetFriendProfile(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 count = cmd_buff[1];
+ u32 frd_key_addr = cmd_buff[3];
+ u32 profiles_addr = cmd_buff[65];
+
+ Profile zero_profile = {};
+ for (u32 i = 0; i < count; ++i) {
+ Memory::WriteBlock(profiles_addr + i * sizeof(Profile),
+ reinterpret_cast<const u8*>(&zero_profile), sizeof(Profile));
+ }
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, profiles_addr=0x%08X",
+ count, frd_key_addr, profiles_addr);
+}
+
+void GetFriendAttributeFlags(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ u32 count = cmd_buff[1];
+ u32 frd_key_addr = cmd_buff[3];
+ u32 attr_flags_addr = cmd_buff[65];
+
+ for (u32 i = 0; i < count; ++i) {
+ //TODO:(mailwl) figure out AttributeFlag size and zero all buffer. Assume 1 byte
+ Memory::Write8(attr_flags_addr + i, 0);
+ }
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ LOG_WARNING(Service_FRD, "(STUBBED) called, count=%d, frd_key_addr=0x%08X, attr_flags_addr=0x%08X",
+ count, frd_key_addr, attr_flags_addr);
+}
+
+void GetMyFriendKey(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ Memory::WriteBlock(cmd_buff[2], reinterpret_cast<const u8*>(&my_friend_key), sizeof(FriendKey));
+ LOG_WARNING(Service_FRD, "(STUBBED) called");
+}
+
+void GetMyScreenName(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+ // TODO: (mailwl) get the name from config
+ Common::UTF8ToUTF16("Citra").copy(reinterpret_cast<char16_t*>(&cmd_buff[2]), 11);
+ LOG_WARNING(Service_FRD, "(STUBBED) called");
+}
+
void Init() {
using namespace Kernel;
diff --git a/src/core/hle/service/frd/frd.h b/src/core/hle/service/frd/frd.h
index f9f88b444..c8283a7f3 100644
--- a/src/core/hle/service/frd/frd.h
+++ b/src/core/hle/service/frd/frd.h
@@ -4,9 +4,97 @@
#pragma once
+#include "common/common_types.h"
+
namespace Service {
+
+class Interface;
+
namespace FRD {
+struct FriendKey {
+ u32 friend_id;
+ u32 unknown;
+ u64 friend_code;
+};
+
+struct MyPresence {
+ u8 unknown[0x12C];
+};
+
+struct Profile {
+ u8 region;
+ u8 country;
+ u8 area;
+ u8 language;
+ u32 unknown;
+};
+
+/**
+ * FRD::GetMyPresence service function
+ * Inputs:
+ * 64 : sizeof (MyPresence) << 14 | 2
+ * 65 : Address of MyPresence structure
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void GetMyPresence(Service::Interface* self);
+
+/**
+ * FRD::GetFriendKeyList service function
+ * Inputs:
+ * 1 : Unknown
+ * 2 : Max friends count
+ * 65 : Address of FriendKey List
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : FriendKey count filled
+ */
+void GetFriendKeyList(Service::Interface* self);
+
+/**
+ * FRD::GetFriendProfile service function
+ * Inputs:
+ * 1 : Friends count
+ * 2 : Friends count << 18 | 2
+ * 3 : Address of FriendKey List
+ * 64 : (count * sizeof (Profile)) << 10 | 2
+ * 65 : Address of Profiles List
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void GetFriendProfile(Service::Interface* self);
+
+/**
+ * FRD::GetFriendAttributeFlags service function
+ * Inputs:
+ * 1 : Friends count
+ * 2 : Friends count << 18 | 2
+ * 3 : Address of FriendKey List
+ * 65 : Address of AttributeFlags
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+void GetFriendAttributeFlags(Service::Interface* self);
+
+/**
+ * FRD::GetMyFriendKey service function
+ * Inputs:
+ * none
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2-5 : FriendKey
+ */
+void GetMyFriendKey(Service::Interface* self);
+
+/**
+ * FRD::GetMyScreenName service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ * 2 : UTF16 encoded name (max 11 symbols)
+ */
+void GetMyScreenName(Service::Interface* self);
+
/// Initialize FRD service(s)
void Init();
diff --git a/src/core/hle/service/frd/frd_u.cpp b/src/core/hle/service/frd/frd_u.cpp
index 2c6885377..db8666416 100644
--- a/src/core/hle/service/frd/frd_u.cpp
+++ b/src/core/hle/service/frd/frd_u.cpp
@@ -2,65 +2,66 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include "core/hle/service/frd/frd.h"
#include "core/hle/service/frd/frd_u.h"
namespace Service {
namespace FRD {
const Interface::FunctionInfo FunctionTable[] = {
- {0x00010000, nullptr, "HasLoggedIn"},
- {0x00020000, nullptr, "IsOnline"},
- {0x00030000, nullptr, "Login"},
- {0x00040000, nullptr, "Logout"},
- {0x00050000, nullptr, "GetMyFriendKey"},
- {0x00060000, nullptr, "GetMyPreference"},
- {0x00070000, nullptr, "GetMyProfile"},
- {0x00080000, nullptr, "GetMyPresence"},
- {0x00090000, nullptr, "GetMyScreenName"},
- {0x000A0000, nullptr, "GetMyMii"},
- {0x000B0000, nullptr, "GetMyLocalAccountId"},
- {0x000C0000, nullptr, "GetMyPlayingGame"},
- {0x000D0000, nullptr, "GetMyFavoriteGame"},
- {0x000E0000, nullptr, "GetMyNcPrincipalId"},
- {0x000F0000, nullptr, "GetMyComment"},
- {0x00100040, nullptr, "GetMyPassword"},
- {0x00110080, nullptr, "GetFriendKeyList"},
- {0x00120042, nullptr, "GetFriendPresence"},
- {0x00130142, nullptr, "GetFriendScreenName"},
- {0x00140044, nullptr, "GetFriendMii"},
- {0x00150042, nullptr, "GetFriendProfile"},
- {0x00160042, nullptr, "GetFriendRelationship"},
- {0x00170042, nullptr, "GetFriendAttributeFlags"},
- {0x00180044, nullptr, "GetFriendPlayingGame"},
- {0x00190042, nullptr, "GetFriendFavoriteGame"},
- {0x001A00C4, nullptr, "GetFriendInfo"},
- {0x001B0080, nullptr, "IsIncludedInFriendList"},
- {0x001C0042, nullptr, "UnscrambleLocalFriendCode"},
- {0x001D0002, nullptr, "UpdateGameModeDescription"},
- {0x001E02C2, nullptr, "UpdateGameMode"},
- {0x001F0042, nullptr, "SendInvitation"},
- {0x00200002, nullptr, "AttachToEventNotification"},
- {0x00210040, nullptr, "SetNotificationMask"},
- {0x00220040, nullptr, "GetEventNotification"},
- {0x00230000, nullptr, "GetLastResponseResult"},
- {0x00240040, nullptr, "PrincipalIdToFriendCode"},
- {0x00250080, nullptr, "FriendCodeToPrincipalId"},
- {0x00260080, nullptr, "IsValidFriendCode"},
- {0x00270040, nullptr, "ResultToErrorCode"},
- {0x00280244, nullptr, "RequestGameAuthentication"},
- {0x00290000, nullptr, "GetGameAuthenticationData"},
- {0x002A0204, nullptr, "RequestServiceLocator"},
- {0x002B0000, nullptr, "GetServiceLocatorData"},
- {0x002C0002, nullptr, "DetectNatProperties"},
- {0x002D0000, nullptr, "GetNatProperties"},
- {0x002E0000, nullptr, "GetServerTimeInterval"},
- {0x002F0040, nullptr, "AllowHalfAwake"},
- {0x00300000, nullptr, "GetServerTypes"},
- {0x00310082, nullptr, "GetFriendComment"},
- {0x00320042, nullptr, "SetClientSdkVersion"},
- {0x00330000, nullptr, "GetMyApproachContext"},
- {0x00340046, nullptr, "AddFriendWithApproach"},
- {0x00350082, nullptr, "DecryptApproachContext"},
+ {0x00010000, nullptr, "HasLoggedIn"},
+ {0x00020000, nullptr, "IsOnline"},
+ {0x00030000, nullptr, "Login"},
+ {0x00040000, nullptr, "Logout"},
+ {0x00050000, GetMyFriendKey, "GetMyFriendKey"},
+ {0x00060000, nullptr, "GetMyPreference"},
+ {0x00070000, nullptr, "GetMyProfile"},
+ {0x00080000, GetMyPresence, "GetMyPresence"},
+ {0x00090000, GetMyScreenName, "GetMyScreenName"},
+ {0x000A0000, nullptr, "GetMyMii"},
+ {0x000B0000, nullptr, "GetMyLocalAccountId"},
+ {0x000C0000, nullptr, "GetMyPlayingGame"},
+ {0x000D0000, nullptr, "GetMyFavoriteGame"},
+ {0x000E0000, nullptr, "GetMyNcPrincipalId"},
+ {0x000F0000, nullptr, "GetMyComment"},
+ {0x00100040, nullptr, "GetMyPassword"},
+ {0x00110080, GetFriendKeyList, "GetFriendKeyList"},
+ {0x00120042, nullptr, "GetFriendPresence"},
+ {0x00130142, nullptr, "GetFriendScreenName"},
+ {0x00140044, nullptr, "GetFriendMii"},
+ {0x00150042, GetFriendProfile, "GetFriendProfile"},
+ {0x00160042, nullptr, "GetFriendRelationship"},
+ {0x00170042, GetFriendAttributeFlags, "GetFriendAttributeFlags"},
+ {0x00180044, nullptr, "GetFriendPlayingGame"},
+ {0x00190042, nullptr, "GetFriendFavoriteGame"},
+ {0x001A00C4, nullptr, "GetFriendInfo"},
+ {0x001B0080, nullptr, "IsIncludedInFriendList"},
+ {0x001C0042, nullptr, "UnscrambleLocalFriendCode"},
+ {0x001D0002, nullptr, "UpdateGameModeDescription"},
+ {0x001E02C2, nullptr, "UpdateGameMode"},
+ {0x001F0042, nullptr, "SendInvitation"},
+ {0x00200002, nullptr, "AttachToEventNotification"},
+ {0x00210040, nullptr, "SetNotificationMask"},
+ {0x00220040, nullptr, "GetEventNotification"},
+ {0x00230000, nullptr, "GetLastResponseResult"},
+ {0x00240040, nullptr, "PrincipalIdToFriendCode"},
+ {0x00250080, nullptr, "FriendCodeToPrincipalId"},
+ {0x00260080, nullptr, "IsValidFriendCode"},
+ {0x00270040, nullptr, "ResultToErrorCode"},
+ {0x00280244, nullptr, "RequestGameAuthentication"},
+ {0x00290000, nullptr, "GetGameAuthenticationData"},
+ {0x002A0204, nullptr, "RequestServiceLocator"},
+ {0x002B0000, nullptr, "GetServiceLocatorData"},
+ {0x002C0002, nullptr, "DetectNatProperties"},
+ {0x002D0000, nullptr, "GetNatProperties"},
+ {0x002E0000, nullptr, "GetServerTimeInterval"},
+ {0x002F0040, nullptr, "AllowHalfAwake"},
+ {0x00300000, nullptr, "GetServerTypes"},
+ {0x00310082, nullptr, "GetFriendComment"},
+ {0x00320042, nullptr, "SetClientSdkVersion"},
+ {0x00330000, nullptr, "GetMyApproachContext"},
+ {0x00340046, nullptr, "AddFriendWithApproach"},
+ {0x00350082, nullptr, "DecryptApproachContext"},
};
FRD_U_Interface::FRD_U_Interface() {
diff --git a/src/core/hle/service/fs/archive.cpp b/src/core/hle/service/fs/archive.cpp
index 590697e76..e9588cb72 100644
--- a/src/core/hle/service/fs/archive.cpp
+++ b/src/core/hle/service/fs/archive.cpp
@@ -15,7 +15,6 @@
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "core/file_sys/archive_backend.h"
#include "core/file_sys/archive_extsavedata.h"
@@ -521,23 +520,23 @@ void ArchiveInit() {
std::string sdmc_directory = FileUtil::GetUserPath(D_SDMC_IDX);
std::string nand_directory = FileUtil::GetUserPath(D_NAND_IDX);
- auto sdmc_factory = Common::make_unique<FileSys::ArchiveFactory_SDMC>(sdmc_directory);
+ auto sdmc_factory = std::make_unique<FileSys::ArchiveFactory_SDMC>(sdmc_directory);
if (sdmc_factory->Initialize())
RegisterArchiveType(std::move(sdmc_factory), ArchiveIdCode::SDMC);
else
LOG_ERROR(Service_FS, "Can't instantiate SDMC archive with path %s", sdmc_directory.c_str());
// Create the SaveData archive
- auto savedata_factory = Common::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
+ auto savedata_factory = std::make_unique<FileSys::ArchiveFactory_SaveData>(sdmc_directory);
RegisterArchiveType(std::move(savedata_factory), ArchiveIdCode::SaveData);
- auto extsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false);
+ auto extsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(sdmc_directory, false);
if (extsavedata_factory->Initialize())
RegisterArchiveType(std::move(extsavedata_factory), ArchiveIdCode::ExtSaveData);
else
LOG_ERROR(Service_FS, "Can't instantiate ExtSaveData archive with path %s", extsavedata_factory->GetMountPoint().c_str());
- auto sharedextsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true);
+ auto sharedextsavedata_factory = std::make_unique<FileSys::ArchiveFactory_ExtSaveData>(nand_directory, true);
if (sharedextsavedata_factory->Initialize())
RegisterArchiveType(std::move(sharedextsavedata_factory), ArchiveIdCode::SharedExtSaveData);
else
@@ -545,10 +544,10 @@ void ArchiveInit() {
sharedextsavedata_factory->GetMountPoint().c_str());
// Create the SaveDataCheck archive, basically a small variation of the RomFS archive
- auto savedatacheck_factory = Common::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
+ auto savedatacheck_factory = std::make_unique<FileSys::ArchiveFactory_SaveDataCheck>(nand_directory);
RegisterArchiveType(std::move(savedatacheck_factory), ArchiveIdCode::SaveDataCheck);
- auto systemsavedata_factory = Common::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
+ auto systemsavedata_factory = std::make_unique<FileSys::ArchiveFactory_SystemSaveData>(nand_directory);
RegisterArchiveType(std::move(systemsavedata_factory), ArchiveIdCode::SystemSaveData);
}
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 2ace2cade..0c655395e 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -31,6 +31,13 @@ const static u32 REGS_BEGIN = 0x1EB00000;
namespace GSP_GPU {
+const ResultCode ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED(ErrorDescription::OutofRangeOrMisalignedAddress, ErrorModule::GX,
+ ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02A01
+const ResultCode ERR_GSP_REGS_MISALIGNED(ErrorDescription::MisalignedSize, ErrorModule::GX,
+ ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BF2
+const ResultCode ERR_GSP_REGS_INVALID_SIZE(ErrorDescription::InvalidSize, ErrorModule::GX,
+ ErrorSummary::InvalidArgument, ErrorLevel::Usage); // 0xE0E02BEC
+
/// Event triggered when GSP interrupt has been signalled
Kernel::SharedPtr<Kernel::Event> g_interrupt_event;
/// GSP shared memoryings
@@ -59,47 +66,87 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) {
}
/**
- * Checks if the parameters in a register write call are valid and logs in the case that
- * they are not
- * @param base_address The first address in the sequence of registers that will be written
- * @param size_in_bytes The number of registers that will be written
- * @return true if the parameters are valid, false otherwise
+ * Writes sequential GSP GPU hardware registers using an array of source data
+ *
+ * @param base_address The address of the first register in the sequence
+ * @param size_in_bytes The number of registers to update (size of data)
+ * @param data A pointer to the source data
+ * @return RESULT_SUCCESS if the parameters are valid, error code otherwise
*/
-static bool CheckWriteParameters(u32 base_address, u32 size_in_bytes) {
- // TODO: Return proper error codes
- if (base_address + size_in_bytes >= 0x420000) {
- LOG_ERROR(Service_GSP, "Write address out of range! (address=0x%08x, size=0x%08x)",
+static ResultCode WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
+ // This magic number is verified to be done by the gsp module
+ const u32 max_size_in_bytes = 0x80;
+
+ if (base_address & 3 || base_address >= 0x420000) {
+ LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
base_address, size_in_bytes);
- return false;
- }
+ return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
+ } else if (size_in_bytes <= max_size_in_bytes) {
+ if (size_in_bytes & 3) {
+ LOG_ERROR(Service_GSP, "Misaligned size 0x%08x", size_in_bytes);
+ return ERR_GSP_REGS_MISALIGNED;
+ } else {
+ while (size_in_bytes > 0) {
+ HW::Write<u32>(base_address + REGS_BEGIN, *data);
+
+ size_in_bytes -= 4;
+ ++data;
+ base_address += 4;
+ }
+ return RESULT_SUCCESS;
+ }
- // size should be word-aligned
- if ((size_in_bytes % 4) != 0) {
- LOG_ERROR(Service_GSP, "Invalid size 0x%08x", size_in_bytes);
- return false;
+ } else {
+ LOG_ERROR(Service_GSP, "Out of range size 0x%08x", size_in_bytes);
+ return ERR_GSP_REGS_INVALID_SIZE;
}
-
- return true;
}
/**
- * Writes sequential GSP GPU hardware registers using an array of source data
+ * Updates sequential GSP GPU hardware registers using parallel arrays of source data and masks.
+ * For each register, the value is updated only where the mask is high
*
* @param base_address The address of the first register in the sequence
* @param size_in_bytes The number of registers to update (size of data)
- * @param data A pointer to the source data
+ * @param data A pointer to the source data to use for updates
+ * @param masks A pointer to the masks
+ * @return RESULT_SUCCESS if the parameters are valid, error code otherwise
*/
-static void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) {
- // TODO: Return proper error codes
- if (!CheckWriteParameters(base_address, size_in_bytes))
- return;
+static ResultCode WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) {
+ // This magic number is verified to be done by the gsp module
+ const u32 max_size_in_bytes = 0x80;
- while (size_in_bytes > 0) {
- HW::Write<u32>(base_address + REGS_BEGIN, *data);
+ if (base_address & 3 || base_address >= 0x420000) {
+ LOG_ERROR(Service_GSP, "Write address was out of range or misaligned! (address=0x%08x, size=0x%08x)",
+ base_address, size_in_bytes);
+ return ERR_GSP_REGS_OUTOFRANGE_OR_MISALIGNED;
+ } else if (size_in_bytes <= max_size_in_bytes) {
+ if (size_in_bytes & 3) {
+ LOG_ERROR(Service_GSP, "Misaligned size 0x%08x", size_in_bytes);
+ return ERR_GSP_REGS_MISALIGNED;
+ } else {
+ while (size_in_bytes > 0) {
+ const u32 reg_address = base_address + REGS_BEGIN;
+
+ u32 reg_value;
+ HW::Read<u32>(reg_value, reg_address);
+
+ // Update the current value of the register only for set mask bits
+ reg_value = (reg_value & ~*masks) | (*data | *masks);
+
+ HW::Write<u32>(reg_address, reg_value);
+
+ size_in_bytes -= 4;
+ ++data;
+ ++masks;
+ base_address += 4;
+ }
+ return RESULT_SUCCESS;
+ }
- size_in_bytes -= 4;
- ++data;
- base_address += 4;
+ } else {
+ LOG_ERROR(Service_GSP, "Out of range size 0x%08x", size_in_bytes);
+ return ERR_GSP_REGS_INVALID_SIZE;
}
}
@@ -120,39 +167,7 @@ static void WriteHWRegs(Service::Interface* self) {
u32* src = (u32*)Memory::GetPointer(cmd_buff[4]);
- WriteHWRegs(reg_addr, size, src);
-}
-
-/**
- * Updates sequential GSP GPU hardware registers using parallel arrays of source data and masks.
- * For each register, the value is updated only where the mask is high
- *
- * @param base_address The address of the first register in the sequence
- * @param size_in_bytes The number of registers to update (size of data)
- * @param data A pointer to the source data to use for updates
- * @param masks A pointer to the masks
- */
-static void WriteHWRegsWithMask(u32 base_address, u32 size_in_bytes, const u32* data, const u32* masks) {
- // TODO: Return proper error codes
- if (!CheckWriteParameters(base_address, size_in_bytes))
- return;
-
- while (size_in_bytes > 0) {
- const u32 reg_address = base_address + REGS_BEGIN;
-
- u32 reg_value;
- HW::Read<u32>(reg_value, reg_address);
-
- // Update the current value of the register only for set mask bits
- reg_value = (reg_value & ~*masks) | (*data | *masks);
-
- HW::Write<u32>(reg_address, reg_value);
-
- size_in_bytes -= 4;
- ++data;
- ++masks;
- base_address += 4;
- }
+ cmd_buff[1] = WriteHWRegs(reg_addr, size, src).raw;
}
/**
@@ -174,7 +189,7 @@ static void WriteHWRegsWithMask(Service::Interface* self) {
u32* src_data = (u32*)Memory::GetPointer(cmd_buff[4]);
u32* mask_data = (u32*)Memory::GetPointer(cmd_buff[6]);
- WriteHWRegsWithMask(reg_addr, size, src_data, mask_data);
+ cmd_buff[1] = WriteHWRegsWithMask(reg_addr, size, src_data, mask_data).raw;
}
/// Read a GSP GPU hardware register
@@ -206,27 +221,27 @@ static void ReadHWRegs(Service::Interface* self) {
}
}
-void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
+ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
u32 base_address = 0x400000;
PAddr phys_address_left = Memory::VirtualToPhysicalAddress(info.address_left);
PAddr phys_address_right = Memory::VirtualToPhysicalAddress(info.address_right);
if (info.active_fb == 0) {
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)), 4,
- &phys_address_left);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)), 4,
- &phys_address_right);
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left1)),
+ 4, &phys_address_left);
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right1)),
+ 4, &phys_address_right);
} else {
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)), 4,
- &phys_address_left);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)), 4,
- &phys_address_right);
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_left2)),
+ 4, &phys_address_left);
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].address_right2)),
+ 4, &phys_address_right);
}
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)), 4,
- &info.stride);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)), 4,
- &info.format);
- WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)), 4,
- &info.shown_fb);
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].stride)),
+ 4, &info.stride);
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].color_format)),
+ 4, &info.format);
+ WriteHWRegs(base_address + 4 * static_cast<u32>(GPU_REG_INDEX(framebuffer_config[screen_id].active_fb)),
+ 4, &info.shown_fb);
if (Pica::g_debug_context)
Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::BufferSwapped, nullptr);
@@ -234,6 +249,8 @@ void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
if (screen_id == 0) {
MicroProfileFlip();
}
+
+ return RESULT_SUCCESS;
}
/**
@@ -251,9 +268,8 @@ static void SetBufferSwap(Service::Interface* self) {
u32* cmd_buff = Kernel::GetCommandBuffer();
u32 screen_id = cmd_buff[1];
FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2];
- SetBufferSwap(screen_id, *fb_info);
- cmd_buff[1] = 0; // No error
+ cmd_buff[1] = SetBufferSwap(screen_id, *fb_info).raw;
}
/**
@@ -286,6 +302,22 @@ static void FlushDataCache(Service::Interface* self) {
}
/**
+ * GSP_GPU::SetAxiConfigQoSMode service function
+ * Inputs:
+ * 1 : Mode, unused in emulator
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void SetAxiConfigQoSMode(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+ u32 mode = cmd_buff[1];
+
+ cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+ LOG_WARNING(Service_GSP, "(STUBBED) called mode=0x%08X", mode);
+}
+
+/**
* GSP_GPU::RegisterInterruptRelayQueue service function
* Inputs:
* 1 : "Flags" field, purpose is unknown
@@ -302,6 +334,12 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
g_interrupt_event = Kernel::g_handle_table.Get<Kernel::Event>(cmd_buff[3]);
ASSERT_MSG((g_interrupt_event != nullptr), "handle is not valid!");
+ g_interrupt_event->name = "GSP_GPU::interrupt_event";
+
+ using Kernel::MemoryPermission;
+ g_shared_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite,
+ MemoryPermission::ReadWrite, "GSPSharedMem");
+
Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
// This specific code is required for a successful initialization, rather than 0
@@ -314,6 +352,22 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
}
/**
+ * GSP_GPU::UnregisterInterruptRelayQueue service function
+ * Outputs:
+ * 1 : Result of function, 0 on success, otherwise error code
+ */
+static void UnregisterInterruptRelayQueue(Service::Interface* self) {
+ u32* cmd_buff = Kernel::GetCommandBuffer();
+
+ g_shared_memory = nullptr;
+ g_interrupt_event = nullptr;
+
+ cmd_buff[1] = RESULT_SUCCESS.raw;
+
+ LOG_WARNING(Service_GSP, "called");
+}
+
+/**
* Signals that the specified interrupt type has occurred to userland code
* @param interrupt_id ID of interrupt that is being signalled
* @todo This should probably take a thread_id parameter and only signal this thread?
@@ -591,11 +645,11 @@ const Interface::FunctionInfo FunctionTable[] = {
{0x000D0140, nullptr, "SetDisplayTransfer"},
{0x000E0180, nullptr, "SetTextureCopy"},
{0x000F0200, nullptr, "SetMemoryFill"},
- {0x00100040, nullptr, "SetAxiConfigQoSMode"},
+ {0x00100040, SetAxiConfigQoSMode, "SetAxiConfigQoSMode"},
{0x00110040, nullptr, "SetPerfLogMode"},
{0x00120000, nullptr, "GetPerfLog"},
{0x00130042, RegisterInterruptRelayQueue, "RegisterInterruptRelayQueue"},
- {0x00140000, nullptr, "UnregisterInterruptRelayQueue"},
+ {0x00140000, UnregisterInterruptRelayQueue, "UnregisterInterruptRelayQueue"},
{0x00150002, nullptr, "TryAcquireRight"},
{0x00160042, nullptr, "AcquireRight"},
{0x00170000, nullptr, "ReleaseRight"},
@@ -616,10 +670,7 @@ Interface::Interface() {
Register(FunctionTable);
g_interrupt_event = nullptr;
-
- using Kernel::MemoryPermission;
- g_shared_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite,
- MemoryPermission::ReadWrite, "GSPSharedMem");
+ g_shared_memory = nullptr;
g_thread_id = 0;
}
diff --git a/src/core/hle/service/gsp_gpu.h b/src/core/hle/service/gsp_gpu.h
index 0e2f7a21e..55a993bb8 100644
--- a/src/core/hle/service/gsp_gpu.h
+++ b/src/core/hle/service/gsp_gpu.h
@@ -194,7 +194,7 @@ public:
*/
void SignalInterrupt(InterruptId interrupt_id);
-void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info);
+ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info);
/**
* Retrieves the framebuffer info stored in the GSP shared memory for the
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 35b648409..0fe3a4d7a 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -9,6 +9,7 @@
#include "core/hle/service/ac_u.h"
#include "core/hle/service/act_u.h"
#include "core/hle/service/csnd_snd.h"
+#include "core/hle/service/dlp_srvr.h"
#include "core/hle/service/dsp_dsp.h"
#include "core/hle/service/err_f.h"
#include "core/hle/service/gsp_gpu.h"
@@ -70,9 +71,8 @@ ResultVal<bool> Interface::SyncRequest() {
// TODO(bunnei): Hack - ignore error
cmd_buff[1] = 0;
return MakeResult<bool>(false);
- } else {
- LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
}
+ LOG_TRACE(Service, "%s", MakeFunctionString(itr->second.name, GetPortName().c_str(), cmd_buff).c_str());
itr->second.func(this);
@@ -121,6 +121,7 @@ void Init() {
AddService(new AC_U::Interface);
AddService(new ACT_U::Interface);
AddService(new CSND_SND::Interface);
+ AddService(new DLP_SRVR::Interface);
AddService(new DSP_DSP::Interface);
AddService(new GSP_GPU::Interface);
AddService(new GSP_LCD::Interface);
diff --git a/src/core/hle/shared_page.cpp b/src/core/hle/shared_page.cpp
index 50c5bc01b..2a1caeaac 100644
--- a/src/core/hle/shared_page.cpp
+++ b/src/core/hle/shared_page.cpp
@@ -16,6 +16,9 @@ void Init() {
std::memset(&shared_page, 0, sizeof(shared_page));
shared_page.running_hw = 0x1; // product
+
+ // Some games wait until this value becomes 0x1, before asking running_hw
+ shared_page.unknown_value = 0x1;
}
} // namespace
diff --git a/src/core/hle/shared_page.h b/src/core/hle/shared_page.h
index 379bb7b63..35a07c685 100644
--- a/src/core/hle/shared_page.h
+++ b/src/core/hle/shared_page.h
@@ -39,12 +39,14 @@ struct SharedPageDef {
DateTime date_time_0; // 20
DateTime date_time_1; // 40
u8 wifi_macaddr[6]; // 60
- u8 wifi_unknown1; // 66
+ u8 wifi_link_level; // 66
u8 wifi_unknown2; // 67
INSERT_PADDING_BYTES(0x80 - 0x68); // 68
float_le sliderstate_3d; // 80
u8 ledstate_3d; // 84
- INSERT_PADDING_BYTES(0xA0 - 0x85); // 85
+ INSERT_PADDING_BYTES(1); // 85
+ u8 unknown_value; // 86
+ INSERT_PADDING_BYTES(0xA0 - 0x87); // 87
u64_le menu_title_id; // A0
u64_le active_menu_title_id; // A8
INSERT_PADDING_BYTES(0x1000 - 0xB0); // B0
diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp
index 48c45564f..083391e83 100644
--- a/src/core/hw/y2r.cpp
+++ b/src/core/hw/y2r.cpp
@@ -261,7 +261,7 @@ void PerformConversion(ConversionConfiguration& cvt) {
ASSERT(cvt.block_alignment != BlockAlignment::Block8x8 || cvt.input_lines % 8 == 0);
// Tiles per row
size_t num_tiles = cvt.input_line_width / 8;
- ASSERT(num_tiles < MAX_TILES);
+ ASSERT(num_tiles <= MAX_TILES);
// Buffer used as a CDMA source/target.
std::unique_ptr<u8[]> data_buffer(new u8[cvt.input_line_width * 8 * 4]);
diff --git a/src/core/loader/3dsx.cpp b/src/core/loader/3dsx.cpp
index 8eed6a50a..5fb3b9e2b 100644
--- a/src/core/loader/3dsx.cpp
+++ b/src/core/loader/3dsx.cpp
@@ -10,13 +10,9 @@
#include "core/file_sys/archive_romfs.h"
#include "core/hle/kernel/process.h"
#include "core/hle/kernel/resource_limit.h"
-#include "core/hle/service/fs/archive.h"
-#include "core/loader/elf.h"
-#include "core/loader/ncch.h"
+#include "core/loader/3dsx.h"
#include "core/memory.h"
-#include "3dsx.h"
-
namespace Loader {
/*
diff --git a/src/core/loader/loader.cpp b/src/core/loader/loader.cpp
index b1907cd55..886501c41 100644
--- a/src/core/loader/loader.cpp
+++ b/src/core/loader/loader.cpp
@@ -6,7 +6,6 @@
#include <string>
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "common/string_util.h"
#include "core/file_sys/archive_romfs.h"
@@ -120,7 +119,7 @@ ResultStatus LoadFile(const std::string& filename) {
AppLoader_THREEDSX app_loader(std::move(file), filename_filename, filename);
// Load application and RomFS
if (ResultStatus::Success == app_loader.Load()) {
- Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
+ Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
return ResultStatus::Success;
}
break;
@@ -139,7 +138,7 @@ ResultStatus LoadFile(const std::string& filename) {
// Load application and RomFS
ResultStatus result = app_loader.Load();
if (ResultStatus::Success == result) {
- Service::FS::RegisterArchiveType(Common::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
+ Service::FS::RegisterArchiveType(std::make_unique<FileSys::ArchiveFactory_RomFS>(app_loader), Service::FS::ArchiveIdCode::RomFS);
}
return result;
}
diff --git a/src/core/loader/ncch.cpp b/src/core/loader/ncch.cpp
index 93f21bec2..a4b47ef8c 100644
--- a/src/core/loader/ncch.cpp
+++ b/src/core/loader/ncch.cpp
@@ -7,7 +7,6 @@
#include <memory>
#include "common/logging/log.h"
-#include "common/make_unique.h"
#include "common/string_util.h"
#include "common/swap.h"
@@ -175,7 +174,7 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>&
return ResultStatus::Error;
LOG_DEBUG(Loader, "%d sections:", kMaxSections);
- // Iterate through the ExeFs archive until we find the .code file...
+ // Iterate through the ExeFs archive until we find a section with the specified name...
for (unsigned section_number = 0; section_number < kMaxSections; section_number++) {
const auto& section = exefs_header.section[section_number];
@@ -187,7 +186,7 @@ ResultStatus AppLoader_NCCH::LoadSectionExeFS(const char* name, std::vector<u8>&
s64 section_offset = (section.offset + exefs_offset + sizeof(ExeFs_Header) + ncch_offset);
file.Seek(section_offset, SEEK_SET);
- if (is_compressed) {
+ if (strcmp(section.name, ".code") == 0 && is_compressed) {
// Section is compressed, read compressed .code section...
std::unique_ptr<u8[]> temp_buffer;
try {
diff --git a/src/core/settings.cpp b/src/core/settings.cpp
index 8a14f75aa..1aa26fbd2 100644
--- a/src/core/settings.cpp
+++ b/src/core/settings.cpp
@@ -4,8 +4,22 @@
#include "settings.h"
+#include "core/gdbstub/gdbstub.h"
+
+#include "video_core/video_core.h"
+
namespace Settings {
Values values = {};
+void Apply() {
+
+ GDBStub::SetServerPort(static_cast<u32>(values.gdbstub_port));
+ GDBStub::ToggleServer(values.use_gdbstub);
+
+ VideoCore::g_hw_renderer_enabled = values.use_hw_renderer;
+ VideoCore::g_shader_jit_enabled = values.use_shader_jit;
+
}
+
+} // namespace
diff --git a/src/core/settings.h b/src/core/settings.h
index 97ddcdff9..4933a516d 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -67,4 +67,6 @@ struct Values {
u16 gdbstub_port;
} extern values;
+void Apply();
+
}