diff --git a/stratosphere/dmnt/source/dmnt_service.hpp b/stratosphere/dmnt/source/dmnt_service.hpp index c35801680..ecb2f8f50 100644 --- a/stratosphere/dmnt/source/dmnt_service.hpp +++ b/stratosphere/dmnt/source/dmnt_service.hpp @@ -84,8 +84,8 @@ class DebugMonitorService final : public IServiceObject { Result TargetIO_FileOpen(OutBuffer out_hnd, InBuffer path, int open_mode, u32 create_mode); Result TargetIO_FileClose(InBuffer hnd); - Result TargetIO_FileRead(InBuffer hnd, OutBuffer out_data, Out out_read, u64 offset); - Result TargetIO_FileWrite(InBuffer hnd, InBuffer data, Out out_written, u64 offset); + Result TargetIO_FileRead(InBuffer hnd, OutBuffer out_data, Out out_read, u64 offset); + Result TargetIO_FileWrite(InBuffer hnd, InBuffer data, Out out_written, u64 offset); Result TargetIO_FileSetAttributes(InBuffer path, InBuffer attributes); Result TargetIO_FileGetInformation(InBuffer path, OutBuffer out_info, Out is_directory); Result TargetIO_FileSetTime(InBuffer path, u64 create, u64 access, u64 modify); diff --git a/stratosphere/dmnt/source/dmnt_service_target_io.cpp b/stratosphere/dmnt/source/dmnt_service_target_io.cpp index 6699ff3d0..ef56cfdbd 100644 --- a/stratosphere/dmnt/source/dmnt_service_target_io.cpp +++ b/stratosphere/dmnt/source/dmnt_service_target_io.cpp @@ -157,7 +157,7 @@ Result DebugMonitorService::TargetIO_FileClose(InBuffer hnd) { return CloseFileByHandle(hnd[0]); } -Result DebugMonitorService::TargetIO_FileRead(InBuffer hnd, OutBuffer out_data, Out out_read, u64 offset) { +Result DebugMonitorService::TargetIO_FileRead(InBuffer hnd, OutBuffer out_data, Out out_read, u64 offset) { if (hnd.num_elements != 1) { return 0xF601; } @@ -174,7 +174,7 @@ Result DebugMonitorService::TargetIO_FileRead(InBuffer hnd, OutBuffer o return rc; } -Result DebugMonitorService::TargetIO_FileWrite(InBuffer hnd, InBuffer data, Out out_written, u64 offset) { +Result DebugMonitorService::TargetIO_FileWrite(InBuffer hnd, InBuffer data, Out out_written, u64 offset) { if (hnd.num_elements != 1) { return 0xF601; } diff --git a/stratosphere/tma/Makefile b/stratosphere/tma/Makefile index 6b5faa89c..085537f4a 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 source/settings +SOURCES := source source/test source/settings source/target_io 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 4fabfc7b5..fe4687856 100644 --- a/stratosphere/tma/client/Main.py +++ b/stratosphere/tma/client/Main.py @@ -20,16 +20,15 @@ def main(argc, argv): print 'Waiting for connection...' c.wait_connected() print 'Connected!' - c.intf.send_packet(Packet().set_service(ServiceId.SETTINGS_SERVICE).set_task(0x01000000).set_cmd(0).write_str('platformconfig').write_str('platformtype')) + print 'Reading atmosphere/BCT.ini...' + c.intf.send_packet(Packet().set_service(ServiceId.TARGETIO_SERVICE).set_task(0x01000000).set_cmd(2).write_str('atmosphere/BCT.ini').write_u64(0x109).write_u64(0)) resp = c.intf.read_packet() - 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) - + res_packet = c.intf.read_packet() + read_res, size_read = resp.read_u32(), resp.read_u32() + print 'Final Result: 0x%x' % res_packet.read_u32() + print 'Size Read: 0x%x' % size_read + print 'Data:\n%s' % resp.body[resp.offset:] + return 0 if __name__ == '__main__': diff --git a/stratosphere/tma/client/ServiceId.py b/stratosphere/tma/client/ServiceId.py index e943313a6..4e4327f91 100644 --- a/stratosphere/tma/client/ServiceId.py +++ b/stratosphere/tma/client/ServiceId.py @@ -25,5 +25,6 @@ USB_CONNECT = hash("USBConnect") USB_DISCONNECT = hash("USBDisconnect") ATMOSPHERE_TEST_SERVICE = hash("AtmosphereTestService") -SETTINGS_SERVICE = hash ("SettingsService") +SETTINGS_SERVICE = hash("SettingsService") +TARGETIO_SERVICE = hash("TIOService") \ No newline at end of file diff --git a/stratosphere/tma/source/dmnt.c b/stratosphere/tma/source/dmnt.c new file mode 100644 index 000000000..c79f7765c --- /dev/null +++ b/stratosphere/tma/source/dmnt.c @@ -0,0 +1,188 @@ +/* + * 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 "dmnt.h" + +static Service g_dmntSrv; +static u64 g_refCnt; + +Result dmntInitialize(void) { + atomicIncrement64(&g_refCnt); + + if (serviceIsActive(&g_dmntSrv)) + return 0; + + return smGetService(&g_dmntSrv, "dmnt:-"); +} + +void dmntExit(void) { + if (atomicDecrement64(&g_refCnt) == 0) + serviceClose(&g_dmntSrv); +} + +Result dmntTargetIOFileOpen(DmntFile *out, const char *path, int flags, DmntTIOCreateOption create_option) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, path, FS_MAX_PATH, BufferType_Normal); + ipcAddRecvBuffer(&c, out, sizeof(*out), BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + int flags; + u32 create_option; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 29; + raw->flags = flags; + raw->create_option = create_option; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result dmntTargetIOFileClose(DmntFile *f) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, f, sizeof(*f), BufferType_Normal); + + struct { + u64 magic; + u64 cmd_id; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 30; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + } + + return rc; +} + +Result dmntTargetIOFileRead(DmntFile *f, u64 off, void* buf, size_t len, size_t *out_read) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, f, sizeof(*f), BufferType_Normal); + ipcAddRecvBuffer(&c, buf, len, BufferType_Type1); + + struct { + u64 magic; + u64 cmd_id; + u64 offset; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 31; + raw->offset = off; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 out_read; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out_read) { + *out_read = resp->out_read; + } + } + + return rc; +} + +Result dmntTargetIOFileWrite(DmntFile *f, u64 off, const void* buf, size_t len, size_t *out_written) { + IpcCommand c; + ipcInitialize(&c); + ipcAddSendBuffer(&c, f, sizeof(*f), BufferType_Normal); + ipcAddSendBuffer(&c, buf, len, BufferType_Type1); + + struct { + u64 magic; + u64 cmd_id; + u64 offset; + } *raw; + + raw = serviceIpcPrepareHeader(&g_dmntSrv, &c, sizeof(*raw)); + + raw->magic = SFCI_MAGIC; + raw->cmd_id = 32; + raw->offset = off; + + Result rc = serviceIpcDispatch(&g_dmntSrv); + + if (R_SUCCEEDED(rc)) { + IpcParsedCommand r; + struct { + u64 magic; + u64 result; + u32 out_written; + } *resp; + + serviceIpcParse(&g_dmntSrv, &r, sizeof(*resp)); + resp = r.Raw; + + rc = resp->result; + + if (R_SUCCEEDED(rc) && out_written) { + *out_written = resp->out_written; + } + } + + return rc; +} diff --git a/stratosphere/tma/source/dmnt.h b/stratosphere/tma/source/dmnt.h new file mode 100644 index 000000000..15382fb53 --- /dev/null +++ b/stratosphere/tma/source/dmnt.h @@ -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 . + */ + +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + u64 handle; +} DmntFile; + +typedef enum { + DmntTIOCreateOption_CreateNew = 1, + DmntTIOCreateOption_CreateAlways = 2, + DmntTIOCreateOption_OpenExisting = 3, + DmntTIOCreateOption_OpenAlways = 4, + DmntTIOCreateOption_ResetSize = 5, +} DmntTIOCreateOption; + +Result dmntInitialize(void); +void dmntExit(void); + +Result dmntTargetIOFileOpen(DmntFile *out, const char *path, int flags, DmntTIOCreateOption create_option); +Result dmntTargetIOFileClose(DmntFile *f); +Result dmntTargetIOFileRead(DmntFile *f, u64 off, void* buf, size_t len, size_t* out_read); +Result dmntTargetIOFileWrite(DmntFile *f, u64 off, const void* buf, size_t len, size_t* out_written); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/stratosphere/tma/source/target_io/tio_service.cpp b/stratosphere/tma/source/target_io/tio_service.cpp new file mode 100644 index 000000000..84edaba83 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_service.cpp @@ -0,0 +1,47 @@ +/* + * 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 "tio_service.hpp" +#include "tio_task.hpp" + +TmaTask *TIOService::NewTask(TmaPacket *packet) { + TmaTask *new_task = nullptr; + switch (packet->GetCommand()) { + case TIOServiceCmd_FileRead: + { + new_task = new TIOFileReadTask(this->manager); + } + break; + case TIOServiceCmd_FileWrite: + { + new_task = new TIOFileWriteTask(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); + } + + return new_task; +} diff --git a/stratosphere/tma/source/target_io/tio_service.hpp b/stratosphere/tma/source/target_io/tio_service.hpp new file mode 100644 index 000000000..110439468 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_service.hpp @@ -0,0 +1,35 @@ +/* + * 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 TIOServiceCmd : u32 { + TIOServiceCmd_FileRead = 2, + TIOServiceCmd_FileWrite = 3, +}; + +class TIOService : public TmaService { + public: + TIOService(TmaServiceManager *m) : TmaService(m, "TIOService") { } + virtual ~TIOService() { } + + virtual TmaTask *NewTask(TmaPacket *packet) override; +}; \ No newline at end of file diff --git a/stratosphere/tma/source/target_io/tio_task.cpp b/stratosphere/tma/source/target_io/tio_task.cpp new file mode 100644 index 000000000..528efeb99 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_task.cpp @@ -0,0 +1,152 @@ +/* + * 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 "tio_task.hpp" + + +void TIOFileReadTask::OnStart(TmaPacket *packet) { + char path[FS_MAX_PATH]; + + packet->ReadString(path, sizeof(path), nullptr); + packet->Read(this->size_remaining); + packet->Read(this->cur_offset); + + if (strlen(path) == 0) { + this->SendResult(0x202); + return; + } + + Result rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); + if (R_FAILED(rc)) { + this->SendResult(rc); + return; + } else { + auto packet = this->AllocateSendPacket(); + rc = this->ProcessPacket(packet); + if (R_SUCCEEDED(rc)) { + this->manager->SendPacket(packet); + if (this->size_remaining) { + this->SetNeedsPackets(true); + } else { + this->SendResult(rc); + } + } else { + this->manager->FreePacket(packet); + this->SendResult(rc); + } + } +} + +void TIOFileReadTask::OnSendPacket(TmaPacket *packet) { + Result rc = this->ProcessPacket(packet); + + if (this->size_remaining == 0 || R_FAILED(rc)) { + this->SendResult(rc); + } +} + +void TIOFileReadTask::SendResult(Result rc) { + dmntTargetIOFileClose(&this->handle); + this->SetNeedsPackets(false); + + auto packet = this->AllocateSendPacket(); + packet->Write(rc); + this->manager->SendPacket(packet); + Complete(); +} + +Result TIOFileReadTask::ProcessPacket(TmaPacket *packet) { + Result rc = 0x196002; + + size_t cur_read = static_cast((this->size_remaining > MaxDataSize) ? MaxDataSize : this->size_remaining); + + u8 *buf = new u8[cur_read]; + if (buf != nullptr) { + size_t actual_read = 0; + rc = dmntTargetIOFileRead(&this->handle, this->cur_offset, buf, cur_read, &actual_read); + if (R_SUCCEEDED(rc)) { + packet->Write(rc); + packet->Write(actual_read); + packet->Write(buf, actual_read); + this->cur_offset += actual_read; + this->size_remaining -= actual_read; + } + + delete buf; + } + + return rc; +} + +void TIOFileWriteTask::OnStart(TmaPacket *packet) { + char path[FS_MAX_PATH]; + + packet->ReadString(path, sizeof(path), nullptr); + packet->Read(this->size_remaining); + packet->Read(this->cur_offset); + + if (strlen(path) == 0) { + this->SendResult(0x202); + return; + } + + Result rc = dmntTargetIOFileOpen(&this->handle, path, FS_OPEN_READ, DmntTIOCreateOption_OpenExisting); + if (R_FAILED(rc)) { + this->SendResult(rc); + } +} + +void TIOFileWriteTask::OnReceivePacket(TmaPacket *packet) { + Result rc = this->ProcessPacket(packet); + + if (this->size_remaining == 0 || R_FAILED(rc)) { + this->SendResult(rc); + } +} + +void TIOFileWriteTask::SendResult(Result rc) { + dmntTargetIOFileClose(&this->handle); + + auto packet = this->AllocateSendPacket(); + packet->Write(rc); + this->manager->SendPacket(packet); + Complete(); +} + +Result TIOFileWriteTask::ProcessPacket(TmaPacket *packet) { + Result rc = 0x196002; + + /* Note: N does not bounds check this. We do. */ + u32 cur_write = 0; + packet->Read(cur_write); + + size_t actual_written = 0; + if (cur_write < MaxDataSize) { + if (cur_write > this->size_remaining) { + cur_write = this->size_remaining; + } + rc = dmntTargetIOFileWrite(&this->handle, this->cur_offset, packet->GetCurrentBodyPtr(), cur_write, &actual_written); + if (R_SUCCEEDED(rc)) { + this->size_remaining -= actual_written; + this->cur_offset += actual_written; + } + } + + return rc; +} \ No newline at end of file diff --git a/stratosphere/tma/source/target_io/tio_task.hpp b/stratosphere/tma/source/target_io/tio_task.hpp new file mode 100644 index 000000000..7a3307fd3 --- /dev/null +++ b/stratosphere/tma/source/target_io/tio_task.hpp @@ -0,0 +1,85 @@ +/* + * 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" +#include "../tma_service_manager.hpp" +#include "../dmnt.h" + +class TIOTask : public TmaTask { + public: + TIOTask(TmaServiceManager *m) : TmaTask(m) { } + virtual ~TIOTask() { } + + virtual void SendResult(Result rc) { + TmaPacket *packet = this->AllocateSendPacket(); + packet->Write(rc); + this->manager->SendPacket(packet); + this->Complete(); + } + + virtual void OnStart(TmaPacket *packet) = 0; + + virtual void OnReceivePacket(TmaPacket *packet) override { + this->Complete(); + } + + virtual void OnSendPacket(TmaPacket *packet) override { + this->Complete(); + } +}; + +class TIOFileReadTask : public TIOTask { + private: + static constexpr size_t HeaderSize = sizeof(Result) + sizeof(u32); + static constexpr size_t MaxDataSize = TmaPacket::MaxBodySize - HeaderSize; + private: + DmntFile handle = {0}; + u64 size_remaining = 0; + u64 cur_offset = 0; + public: + TIOFileReadTask(TmaServiceManager *m) : TIOTask(m) { } + virtual ~TIOFileReadTask() { } + + virtual void OnStart(TmaPacket *packet) override; + virtual void OnSendPacket(TmaPacket *packet) override; + virtual void SendResult(Result rc) override; + + Result ProcessPacket(TmaPacket *packet); +}; + +class TIOFileWriteTask : public TIOTask { + private: + static constexpr size_t HeaderSize = sizeof(u32); + static constexpr size_t MaxDataSize = TmaPacket::MaxBodySize - HeaderSize; + private: + DmntFile handle = {0}; + u64 size_remaining = 0; + u64 cur_offset = 0; + public: + TIOFileWriteTask(TmaServiceManager *m) : TIOTask(m) { } + virtual ~TIOFileWriteTask() { } + + virtual void OnStart(TmaPacket *packet) override; + virtual void OnReceivePacket(TmaPacket *packet) override; + virtual void SendResult(Result rc) override; + + Result ProcessPacket(TmaPacket *packet); +}; + diff --git a/stratosphere/tma/source/tma_conn_packet.hpp b/stratosphere/tma/source/tma_conn_packet.hpp index a3df7a3f3..20ccce265 100644 --- a/stratosphere/tma/source/tma_conn_packet.hpp +++ b/stratosphere/tma/source/tma_conn_packet.hpp @@ -166,6 +166,10 @@ class TmaPacket { return GetHeader()->version; } + u8 *GetCurrentBodyPtr() { + return GetBody(this->offset); + } + void ClearOffset() { this->offset = 0; } diff --git a/stratosphere/tma/source/tma_main.cpp b/stratosphere/tma/source/tma_main.cpp index d314ed16a..e0d16571e 100644 --- a/stratosphere/tma/source/tma_main.cpp +++ b/stratosphere/tma/source/tma_main.cpp @@ -25,6 +25,8 @@ #include "tma_target.hpp" +#include "dmnt.h" + extern "C" { extern u32 __start__; @@ -70,11 +72,17 @@ void __appInit(void) { fatalSimple(rc); } + rc = dmntInitialize(); + if (R_FAILED(rc)) { + fatalSimple(rc); + } + CheckAtmosphereVersion(CURRENT_ATMOSPHERE_VERSION); } void __appExit(void) { /* Cleanup services. */ + dmntExit(); setsysExit(); pscExit(); smExit(); diff --git a/stratosphere/tma/source/tma_target.cpp b/stratosphere/tma/source/tma_target.cpp index 9cfcb335f..2659c2636 100644 --- a/stratosphere/tma/source/tma_target.cpp +++ b/stratosphere/tma/source/tma_target.cpp @@ -27,6 +27,7 @@ #include "test/atmosphere_test_service.hpp" #include "settings/settings_service.hpp" +#include "target_io/tio_service.hpp" struct TmaTargetConfig { char configuration_id1[0x80]; @@ -210,6 +211,7 @@ void TmaTarget::Initialize() { /* TODO: Make this better. */ g_service_manager->AddService(new AtmosphereTestService(g_service_manager)); g_service_manager->AddService(new SettingsService(g_service_manager)); + g_service_manager->AddService(new TIOService(g_service_manager)); RefreshTargetConfig(); diff --git a/stratosphere/tma/source/tma_task.cpp b/stratosphere/tma/source/tma_task.cpp index 6133b5c5e..4fb10ad2d 100644 --- a/stratosphere/tma/source/tma_task.cpp +++ b/stratosphere/tma/source/tma_task.cpp @@ -24,6 +24,21 @@ void TmaTask::SetNeedsPackets(bool n) { this->manager->Tick(); } +TmaPacket *TmaTask::AllocateSendPacket(bool continuation) { + auto packet = this->manager->AllocateSendPacket(); + packet->SetServiceId(this->service_id); + packet->SetTaskId(this->task_id); + packet->SetCommand(this->command); + packet->SetContinuation(continuation); + + return packet; +} + + +void TmaTask::FreePacket(TmaPacket *packet) { + this->manager->FreePacket(packet); +} + void TmaTask::Complete() { SetNeedsPackets(false); this->state = TmaTaskState::Complete; diff --git a/stratosphere/tma/source/tma_task.hpp b/stratosphere/tma/source/tma_task.hpp index 686a7a50d..7f17ffc7b 100644 --- a/stratosphere/tma/source/tma_task.hpp +++ b/stratosphere/tma/source/tma_task.hpp @@ -68,6 +68,9 @@ class TmaTask { void Signal() { this->signal.Signal(); } void ResetSignal() { this->signal.Reset(); } + TmaPacket *AllocateSendPacket(bool continuation = true); + void FreePacket(TmaPacket *packet); + void Complete(); void Cancel();