diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile
index 9d0408a23..161caed02 100644
--- a/stratosphere/tma/Makefile
+++ b/stratosphere/tma/Makefile
@@ -19,7 +19,7 @@ include $(DEVKITPRO)/libnx/switch_rules
#---------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
-SOURCES := source source/test
+SOURCES := source source/test source/settings
DATA := data
INCLUDES := include ../../common/include
EXEFS_SRC := exefs_src
diff --git a/stratosphere/tma/client/Main.py b/stratosphere/tma/client/Main.py
index 3ea150608..0a81509c6 100644
--- a/stratosphere/tma/client/Main.py
+++ b/stratosphere/tma/client/Main.py
@@ -20,9 +20,16 @@ def main(argc, argv):
print 'Waiting for connection...'
c.wait_connected()
print 'Connected!'
- c.intf.send_packet(Packet().set_service(ServiceId.ATMOSPHERE_TEST_SERVICE).set_task(0x01000000).write_u32(0x40))
+ c.intf.send_packet(Packet().set_service(ServiceId.SETTINGS_SERVICE).set_task(0x01000000).set_cmd(0).write_str('lm').write_str('sd_card_log_output_directory'))
resp = c.intf.read_packet()
- print resp.body
+ success = resp.read_u8() != 0
+ print 'Succeeded: %s' % str(success)
+ if success:
+ size = resp.read_u32()
+ value = resp.body[resp.offset:resp.offset+size]
+ print 'Value Size: 0x%x' % size
+ print 'Value: %s' % repr(value)
+
return 0
if __name__ == '__main__':
diff --git a/stratosphere/tma/client/Packet.py b/stratosphere/tma/client/Packet.py
index 465be93e8..9f623b28d 100644
--- a/stratosphere/tma/client/Packet.py
+++ b/stratosphere/tma/client/Packet.py
@@ -70,6 +70,8 @@ class Packet():
self.offset = 0
return self
def write_str(self, s):
+ if s[-1] != '\x00':
+ s += '\x00'
self.body += s
self.body_len += len(s)
return self
@@ -94,6 +96,8 @@ class Packet():
while self.body[self.offset] != '\x00' and self.offset < self.body_len:
s += self.body[self.offset]
self.offset += 1
+ if self.offset < self.body_len and self.body[self.offset] == '\x00':
+ self.offset += 1
def read_u8(self):
x, = up('.
+ */
+
+#include
+#include
+
+#include "settings_service.hpp"
+#include "settings_task.hpp"
+
+TmaTask *SettingsService::NewTask(TmaPacket *packet) {
+ TmaTask *new_task = nullptr;
+ switch (packet->GetCommand()) {
+ case SettingsServiceCmd_GetSetting:
+ {
+ new_task = new GetSettingTask(this->manager);
+ }
+ break;
+ default:
+ new_task = nullptr;
+ break;
+ }
+ if (new_task != nullptr) {
+ new_task->SetServiceId(this->GetServiceId());
+ new_task->SetTaskId(packet->GetTaskId());
+ new_task->OnStart(packet);
+ new_task->SetNeedsPackets(true);
+ }
+
+ return new_task;
+}
diff --git a/stratosphere/tma/source/settings/settings_service.hpp b/stratosphere/tma/source/settings/settings_service.hpp
new file mode 100644
index 000000000..3b21c891b
--- /dev/null
+++ b/stratosphere/tma/source/settings/settings_service.hpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+
+#include "../tma_conn_service_ids.hpp"
+#include "../tma_service.hpp"
+
+enum SettingsServiceCmd : u32 {
+ SettingsServiceCmd_GetSetting = 0,
+};
+
+class SettingsService : public TmaService {
+ public:
+ SettingsService(TmaServiceManager *m) : TmaService(m, "SettingsService") { }
+ virtual ~SettingsService() { }
+
+ virtual TmaTask *NewTask(TmaPacket *packet) override;
+};
\ No newline at end of file
diff --git a/stratosphere/tma/source/settings/settings_task.cpp b/stratosphere/tma/source/settings/settings_task.cpp
new file mode 100644
index 000000000..650cc6c15
--- /dev/null
+++ b/stratosphere/tma/source/settings/settings_task.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+#include
+
+#include "settings_task.hpp"
+
+void GetSettingTask::OnStart(TmaPacket *packet) {
+ size_t length;
+ packet->ReadString(this->name, sizeof(this->name), &length);
+ packet->ReadString(this->item_key, sizeof(this->item_key), &length);
+
+ if (R_SUCCEEDED(setsysGetSettingsItemValueSize(this->name, this->item_key, &this->value_size))) {
+ if (this->value_size <= sizeof(this->value)) {
+ if (R_SUCCEEDED(setsysGetSettingsItemValue(this->name, this->item_key, this->value, this->value_size))) {
+ this->succeeded = true;
+ }
+ }
+ }
+}
+
+void GetSettingTask::OnReceivePacket(TmaPacket *packet) {
+ std::abort();
+}
+
+void GetSettingTask::OnSendPacket(TmaPacket *packet) {
+ packet->Write((u8)this->succeeded);
+ packet->Write((u32)this->value_size);
+ packet->Write(this->value, this->value_size);
+
+ this->Complete();
+}
\ No newline at end of file
diff --git a/stratosphere/tma/source/settings/settings_task.hpp b/stratosphere/tma/source/settings/settings_task.hpp
new file mode 100644
index 000000000..5d2bd13be
--- /dev/null
+++ b/stratosphere/tma/source/settings/settings_task.hpp
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2018 Atmosphère-NX
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#pragma once
+#include
+#include
+
+#include "../tma_task.hpp"
+
+class GetSettingTask : public TmaTask {
+ private:
+ char name[0x40] = {0};
+ char item_key[0x40] = {0};
+ u8 value[0x40] = {0};
+ u64 value_size = 0;
+ bool succeeded = false;
+
+ public:
+ GetSettingTask(TmaServiceManager *m) : TmaTask(m) { }
+ virtual ~GetSettingTask() { }
+
+ virtual void OnStart(TmaPacket *packet) override;
+ virtual void OnReceivePacket(TmaPacket *packet) override;
+ virtual void OnSendPacket(TmaPacket *packet) override;
+};
diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp
index fb1491cc3..d314ed16a 100644
--- a/stratosphere/tma/source/tma_main.cpp
+++ b/stratosphere/tma/source/tma_main.cpp
@@ -65,11 +65,17 @@ void __appInit(void) {
fatalSimple(rc);
}
+ rc = setsysInitialize();
+ if (R_FAILED(rc)) {
+ fatalSimple(rc);
+ }
+
CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION);
}
void __appExit(void) {
/* Cleanup services. */
+ setsysExit();
pscExit();
smExit();
}
diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp
index 9873d952d..9cfcb335f 100644
--- a/stratosphere/tma/source/tma_target.cpp
+++ b/stratosphere/tma/source/tma_target.cpp
@@ -26,6 +26,7 @@
#include "tma_target.hpp"
#include "test/atmosphere_test_service.hpp"
+#include "settings/settings_service.hpp"
struct TmaTargetConfig {
char configuration_id1[0x80];
@@ -208,6 +209,7 @@ void TmaTarget::Initialize() {
g_service_manager = new TmaServiceManager();
/* TODO: Make this better. */
g_service_manager->AddService(new AtmosphereTestService(g_service_manager));
+ g_service_manager->AddService(new SettingsService(g_service_manager));
RefreshTargetConfig();