From 60ce36f721415a1be26eab838ed4196efd3e475f Mon Sep 17 00:00:00 2001
From: purpasmart96 <kanzoconfigz@hotmail.com>
Date: Sat, 31 Jan 2015 15:11:51 -0800
Subject: [PATCH] Services: Stub some functions

---
 src/citra/config.cpp               |  3 ++
 src/citra/default_ini.h            |  3 ++
 src/citra_qt/config.cpp            |  8 ++++
 src/common/logging/log.h           |  1 +
 src/core/hle/service/cfg/cfg_u.cpp | 66 ++++++++++++++++++++++++++++--
 src/core/hle/service/dsp_dsp.cpp   | 66 ++++++++++++++++++++++++++++--
 src/core/hle/service/ldr_ro.cpp    | 64 ++++++++++++++++++++++++++++-
 src/core/settings.h                |  3 ++
 8 files changed, 206 insertions(+), 8 deletions(-)

diff --git a/src/citra/config.cpp b/src/citra/config.cpp
index 2bf0dff35..50ed468d7 100644
--- a/src/citra/config.cpp
+++ b/src/citra/config.cpp
@@ -64,6 +64,9 @@ void Config::ReadValues() {
     // Data Storage
     Settings::values.use_virtual_sd = glfw_config->GetBoolean("Data Storage", "use_virtual_sd", true);
 
+    // System Region
+    Settings::values.region_value = glfw_config->GetInteger("System Region", "region_value", 1);
+
     // Miscellaneous
     Settings::values.log_filter = glfw_config->Get("Miscellaneous", "log_filter", "*:Info");
 }
diff --git a/src/citra/default_ini.h b/src/citra/default_ini.h
index ebe2e9767..005f3de23 100644
--- a/src/citra/default_ini.h
+++ b/src/citra/default_ini.h
@@ -34,6 +34,9 @@ frame_skip = ## 0: No frameskip (default), 1 : 2x frameskip, 2 : 4x frameskip, e
 [Data Storage]
 use_virtual_sd =
 
+[System Region]
+region_value = ## 0 : Japan, 1 : Usa (default), 2 : Europe, 3 : Australia, 4 : China, 5 : Korea, 6 : Taiwan.
+
 [Miscellaneous]
 log_filter = *:Info  ## Examples: *:Debug Kernel.SVC:Trace Service.*:Critical
 )";
diff --git a/src/citra_qt/config.cpp b/src/citra_qt/config.cpp
index 1596c08d7..b0ff5a37e 100644
--- a/src/citra_qt/config.cpp
+++ b/src/citra_qt/config.cpp
@@ -52,6 +52,10 @@ void Config::ReadValues() {
     Settings::values.use_virtual_sd = qt_config->value("use_virtual_sd", true).toBool();
     qt_config->endGroup();
 
+    qt_config->beginGroup("System Region");
+    Settings::values.region_value = qt_config->value("region_value", 1).toInt();
+    qt_config->endGroup();
+
     qt_config->beginGroup("Miscellaneous");
     Settings::values.log_filter = qt_config->value("log_filter", "*:Info").toString().toStdString();
     qt_config->endGroup();
@@ -88,6 +92,10 @@ void Config::SaveValues() {
     qt_config->setValue("use_virtual_sd", Settings::values.use_virtual_sd);
     qt_config->endGroup();
 
+    qt_config->beginGroup("System Region");
+    qt_config->setValue("region_value", Settings::values.region_value);
+    qt_config->endGroup();
+
     qt_config->beginGroup("Miscellaneous");
     qt_config->setValue("log_filter", QString::fromStdString(Settings::values.log_filter));
     qt_config->endGroup();
diff --git a/src/common/logging/log.h b/src/common/logging/log.h
index 3d94bf0d9..af931a7e8 100644
--- a/src/common/logging/log.h
+++ b/src/common/logging/log.h
@@ -57,6 +57,7 @@ enum class Class : ClassType {
     Service_GSP,                ///< The GSP (GPU control) service
     Service_AC,                 ///< The AC (WiFi status) service
     Service_PTM,                ///< The PTM (Power status & misc.) service
+    Service_LDR,                ///< The LDR (3ds dll loader) service
     Service_CFG,                ///< The CFG (Configuration) service
     Service_DSP,                ///< The DSP (DSP control) service
     Service_HID,                ///< The HID (User input) service
diff --git a/src/core/hle/service/cfg/cfg_u.cpp b/src/core/hle/service/cfg/cfg_u.cpp
index 835620909..5d212a9a2 100644
--- a/src/core/hle/service/cfg/cfg_u.cpp
+++ b/src/core/hle/service/cfg/cfg_u.cpp
@@ -5,6 +5,7 @@
 #include "common/file_util.h"
 #include "common/log.h"
 #include "common/string_util.h"
+#include "core/settings.h"
 #include "core/file_sys/archive_systemsavedata.h"
 #include "core/hle/hle.h"
 #include "core/hle/service/cfg/cfg.h"
@@ -128,6 +129,65 @@ static void GetConfigInfoBlk2(Service::Interface* self) {
     cmd_buffer[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data_pointer).raw;
 }
 
+/**
+ * CFG_User::SecureInfoGetRegion service function
+ *  Inputs:
+ *      1 : None
+ *  Outputs:
+ *      0 : Result Header code
+ *      1 : Result of function, 0 on success, otherwise error code
+ *      2 : Region value loaded from SecureInfo offset 0x100
+ */
+static void SecureInfoGetRegion(Service::Interface* self) {
+    u32* cmd_buffer = Kernel::GetCommandBuffer();
+
+    cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error
+    cmd_buffer[2] = Settings::values.region_value;
+}
+
+/**
+ * CFG_User::GenHashConsoleUnique service function
+ *  Inputs:
+ *      1 : 20 bit application ID salt
+ *  Outputs:
+ *      0 : Result Header code
+ *      1 : Result of function, 0 on success, otherwise error code
+ *      2 : Hash/"ID" lower word
+ *      3 : Hash/"ID" upper word
+ */
+static void GenHashConsoleUnique(Service::Interface* self) {
+    u32* cmd_buffer = Kernel::GetCommandBuffer();
+    u32 app_id_salt = cmd_buffer[1];
+
+    cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error
+    cmd_buffer[2] = 0x33646D6F ^ (app_id_salt & 0xFFFFF); // 3dmoo hash
+    cmd_buffer[3] = 0x6F534841 ^ (app_id_salt & 0xFFFFF);
+
+    LOG_WARNING(Service_CFG, "(STUBBED) called app_id_salt=0x%08X", app_id_salt);
+}
+
+/**
+ * CFG_User::GetRegionCanadaUSA service function
+ *  Inputs:
+ *      1 : None
+ *  Outputs:
+ *      0 : Result Header code
+ *      1 : Result of function, 0 on success, otherwise error code
+ *      2 : Output value
+ */
+static void GetRegionCanadaUSA(Service::Interface* self) {
+    u32* cmd_buffer = Kernel::GetCommandBuffer();
+
+    cmd_buffer[1] = RESULT_SUCCESS.raw; // No Error
+
+    u8 canada_or_usa = 1;
+    if (canada_or_usa == Settings::values.region_value) {
+        cmd_buffer[2] = 1;
+    } else {
+        cmd_buffer[2] = 0;
+    }
+}
+
 /**
  * CFG_User::GetSystemModel service function
  *  Inputs:
@@ -171,9 +231,9 @@ static void GetModelNintendo2DS(Service::Interface* self) {
 
 const Interface::FunctionInfo FunctionTable[] = {
     {0x00010082, GetConfigInfoBlk2,     "GetConfigInfoBlk2"},
-    {0x00020000, nullptr,               "SecureInfoGetRegion"},
-    {0x00030040, nullptr,               "GenHashConsoleUnique"},
-    {0x00040000, nullptr,               "GetRegionCanadaUSA"},
+    {0x00020000, SecureInfoGetRegion,   "SecureInfoGetRegion"},
+    {0x00030040, GenHashConsoleUnique,  "GenHashConsoleUnique"},
+    {0x00040000, GetRegionCanadaUSA,    "GetRegionCanadaUSA"},
     {0x00050000, GetSystemModel,        "GetSystemModel"},
     {0x00060000, GetModelNintendo2DS,   "GetModelNintendo2DS"},
     {0x00070040, nullptr,               "WriteToFirstByteCfgSavegame"},
diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp
index 9a38be393..f413c6f54 100644
--- a/src/core/hle/service/dsp_dsp.cpp
+++ b/src/core/hle/service/dsp_dsp.cpp
@@ -127,6 +127,31 @@ void WriteReg0x10(Service::Interface* self) {
     LOG_WARNING(Service_DSP, "(STUBBED) called");
 }
 
+/**
+ * DSP_DSP::WriteProcessPipe service function
+ *  Inputs:
+ *      1 : Number
+ *      2 : Size
+ *      3 : (size <<14) | 0x402
+ *      4 : Buffer
+ *  Outputs:
+ *      0 : Return header
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+void WriteProcessPipe(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    u32 number   = cmd_buff[1];
+    u32 size     = cmd_buff[2];
+    u32 new_size = cmd_buff[3];
+    u32 buffer   = cmd_buff[4];
+
+    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+    LOG_WARNING(Service_DSP, "(STUBBED) called number=%u, size=0x%08X, new_size=0x%08X, buffer=0x%08X",
+                number, size, new_size, buffer);
+}
+
 /**
  * DSP_DSP::ReadPipeIfPossible service function
  *  Inputs:
@@ -169,6 +194,41 @@ void ReadPipeIfPossible(Service::Interface* self) {
     LOG_WARNING(Service_DSP, "(STUBBED) called size=0x%08X, buffer=0x%08X", size, addr);
 }
 
+/**
+ * DSP_DSP::SetSemaphoreMask service function
+ *  Inputs:
+ *      1 : Mask
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+void SetSemaphoreMask(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    u32 mask = cmd_buff[1];
+
+    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+    LOG_WARNING(Service_DSP, "(STUBBED) called mask=0x%08X", mask);
+}
+
+/**
+ * DSP_DSP::GetHeadphoneStatus service function
+ *  Inputs:
+ *      1 : None
+ *  Outputs:
+ *      1 : Result of function, 0 on success, otherwise error code
+ *      2 : The headphone status response, 0 = Not using headphones?,
+ *          1 = using headphones?
+ */
+void GetHeadphoneStatus(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+
+    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+    cmd_buff[2] = 0; // Not using headphones?
+
+    LOG_WARNING(Service_DSP, "(STUBBED) called");
+}
+
 const Interface::FunctionInfo FunctionTable[] = {
     {0x00010040, nullptr,                          "RecvData"},
     {0x00020040, nullptr,                          "RecvDataIsReady"},
@@ -179,7 +239,7 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00090040, nullptr,                          "ClearSemaphore"},
     {0x000B0000, nullptr,                          "CheckSemaphoreRequest"},
     {0x000C0040, ConvertProcessAddressFromDspDram, "ConvertProcessAddressFromDspDram"},
-    {0x000D0082, nullptr,                          "WriteProcessPipe"},
+    {0x000D0082, WriteProcessPipe,                 "WriteProcessPipe"},
     {0x001000C0, ReadPipeIfPossible,               "ReadPipeIfPossible"},
     {0x001100C2, LoadComponent,                    "LoadComponent"},
     {0x00120000, nullptr,                          "UnloadComponent"},
@@ -187,13 +247,13 @@ const Interface::FunctionInfo FunctionTable[] = {
     {0x00140082, nullptr,                          "InvalidateDCache"},
     {0x00150082, RegisterInterruptEvents,          "RegisterInterruptEvents"},
     {0x00160000, GetSemaphoreEventHandle,          "GetSemaphoreEventHandle"},
-    {0x00170040, nullptr,                          "SetSemaphoreMask"},
+    {0x00170040, SetSemaphoreMask,                 "SetSemaphoreMask"},
     {0x00180040, nullptr,                          "GetPhysicalAddress"},
     {0x00190040, nullptr,                          "GetVirtualAddress"},
     {0x001A0042, nullptr,                          "SetIirFilterI2S1_cmd1"},
     {0x001B0042, nullptr,                          "SetIirFilterI2S1_cmd2"},
     {0x001C0082, nullptr,                          "SetIirFilterEQ"},
-    {0x001F0000, nullptr,                          "GetHeadphoneStatus"},
+    {0x001F0000, GetHeadphoneStatus,               "GetHeadphoneStatus"},
     {0x00210000, nullptr,                          "GetIsDspOccupied"},
 };
 
diff --git a/src/core/hle/service/ldr_ro.cpp b/src/core/hle/service/ldr_ro.cpp
index 7d6e2e8e8..83bb9eabe 100644
--- a/src/core/hle/service/ldr_ro.cpp
+++ b/src/core/hle/service/ldr_ro.cpp
@@ -11,9 +11,69 @@
 
 namespace LDR_RO {
 
+/**
+ * LDR_RO::Initialize service function
+ *  Inputs:
+ *      1 : CRS buffer pointer
+ *      2 : CRS Size
+ *      3 : Process memory address where the CRS will be mapped
+ *      4 : Value, must be zero
+ *      5 : KProcess handle
+ *  Outputs:
+ *      0 : Return header
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+static void Initialize(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+    u32 crs_buffer_ptr = cmd_buff[1];
+    u32 crs_size       = cmd_buff[2];
+    u32 address        = cmd_buff[3];
+    u32 value          = cmd_buff[4];
+    u32 process        = cmd_buff[5];
+
+    if (value != 0) {
+        LOG_ERROR(Service_LDR, "This value should be zero, but is actually %u!", value);
+    }
+
+    // TODO(purpasmart96): Verify return header on HW
+
+    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+    LOG_WARNING(Service_LDR, "(STUBBED) called");
+}
+
+/**
+ * LDR_RO::LoadCRR service function
+ *  Inputs:
+ *      1 : CRS buffer pointer
+ *      2 : CRS Size
+ *      3 : Value, must be zero
+ *      4 : KProcess handle
+ *  Outputs:
+ *      0 : Return header
+ *      1 : Result of function, 0 on success, otherwise error code
+ */
+static void LoadCRR(Service::Interface* self) {
+    u32* cmd_buff = Kernel::GetCommandBuffer();
+    u32 crs_buffer_ptr = cmd_buff[1];
+    u32 crs_size       = cmd_buff[2];
+    u32 value          = cmd_buff[3];
+    u32 process        = cmd_buff[4];
+
+    if (value != 0) {
+        LOG_ERROR(Service_LDR, "This value should be zero, but is actually %u!", value);
+    }
+
+    // TODO(purpasmart96): Verify return header on HW
+
+    cmd_buff[1] = RESULT_SUCCESS.raw; // No error
+
+    LOG_WARNING(Service_LDR, "(STUBBED) called");
+}
+
 const Interface::FunctionInfo FunctionTable[] = {
-    {0x000100C2, nullptr,               "Initialize"},
-    {0x00020082, nullptr,               "LoadCRR"},
+    {0x000100C2, Initialize,            "Initialize"},
+    {0x00020082, LoadCRR,               "LoadCRR"},
     {0x00030042, nullptr,               "UnloadCCR"},
     {0x000402C2, nullptr,               "LoadExeCRO"},
     {0x000500C2, nullptr,               "LoadCROSymbols"},
diff --git a/src/core/settings.h b/src/core/settings.h
index 4b8928847..9b52be259 100644
--- a/src/core/settings.h
+++ b/src/core/settings.h
@@ -36,6 +36,9 @@ struct Values {
     // Data Storage
     bool use_virtual_sd;
 
+    // System Region
+    int region_value;
+
     std::string log_filter;
 } extern values;