mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-30 21:30:04 +00:00 
			
		
		
		
	Merge pull request #3462 from wwylele/am-new-framework
Service/AM: convert to ServiceFramework
This commit is contained in:
		
						commit
						001ad9da3b
					
				
					 13 changed files with 845 additions and 912 deletions
				
			
		|  | @ -117,10 +117,7 @@ public: | ||||||
| 
 | 
 | ||||||
|     // TODO : ensure that translate params are added after all regular params
 |     // TODO : ensure that translate params are added after all regular params
 | ||||||
|     template <typename... H> |     template <typename... H> | ||||||
|     void PushCopyHandles(H... handles); |     [[deprecated]] void PushCopyHandles(H... handles); | ||||||
| 
 |  | ||||||
|     template <typename... H> |  | ||||||
|     void PushMoveHandles(H... handles); |  | ||||||
| 
 | 
 | ||||||
|     template <typename... O> |     template <typename... O> | ||||||
|     void PushCopyObjects(Kernel::SharedPtr<O>... pointers); |     void PushCopyObjects(Kernel::SharedPtr<O>... pointers); | ||||||
|  | @ -131,11 +128,15 @@ public: | ||||||
|     [[deprecated]] void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id); |     [[deprecated]] void PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id); | ||||||
|     void PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id); |     void PushStaticBuffer(const std::vector<u8>& buffer, u8 buffer_id); | ||||||
| 
 | 
 | ||||||
|     [[deprecated]] void PushMappedBuffer(VAddr buffer_vaddr, size_t size, |  | ||||||
|                                          MappedBufferPermissions perms); |  | ||||||
| 
 |  | ||||||
|     /// Pushes an HLE MappedBuffer interface back to unmapped the buffer.
 |     /// Pushes an HLE MappedBuffer interface back to unmapped the buffer.
 | ||||||
|     void PushMappedBuffer(const Kernel::MappedBuffer& mapped_buffer); |     void PushMappedBuffer(const Kernel::MappedBuffer& mapped_buffer); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     template <typename... H> | ||||||
|  |     void PushCopyHLEHandles(H... handles); | ||||||
|  | 
 | ||||||
|  |     template <typename... H> | ||||||
|  |     void PushMoveHLEHandles(H... handles); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Push ///
 | /// Push ///
 | ||||||
|  | @ -186,24 +187,29 @@ void RequestBuilder::Push(const First& first_value, const Other&... other_values | ||||||
| 
 | 
 | ||||||
| template <typename... H> | template <typename... H> | ||||||
| inline void RequestBuilder::PushCopyHandles(H... handles) { | inline void RequestBuilder::PushCopyHandles(H... handles) { | ||||||
|     Push(CopyHandleDesc(sizeof...(H))); |     PushCopyHLEHandles(handles...); | ||||||
|     Push(static_cast<Kernel::Handle>(handles)...); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename... H> | template <typename... H> | ||||||
| inline void RequestBuilder::PushMoveHandles(H... handles) { | inline void RequestBuilder::PushCopyHLEHandles(H... handles) { | ||||||
|  |     Push(CopyHandleDesc(sizeof...(H))); | ||||||
|  |     Push(static_cast<u32>(handles)...); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template <typename... H> | ||||||
|  | inline void RequestBuilder::PushMoveHLEHandles(H... handles) { | ||||||
|     Push(MoveHandleDesc(sizeof...(H))); |     Push(MoveHandleDesc(sizeof...(H))); | ||||||
|     Push(static_cast<Kernel::Handle>(handles)...); |     Push(static_cast<u32>(handles)...); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename... O> | template <typename... O> | ||||||
| inline void RequestBuilder::PushCopyObjects(Kernel::SharedPtr<O>... pointers) { | inline void RequestBuilder::PushCopyObjects(Kernel::SharedPtr<O>... pointers) { | ||||||
|     PushCopyHandles(context->AddOutgoingHandle(std::move(pointers))...); |     PushCopyHLEHandles(context->AddOutgoingHandle(std::move(pointers))...); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| template <typename... O> | template <typename... O> | ||||||
| inline void RequestBuilder::PushMoveObjects(Kernel::SharedPtr<O>... pointers) { | inline void RequestBuilder::PushMoveObjects(Kernel::SharedPtr<O>... pointers) { | ||||||
|     PushMoveHandles(context->AddOutgoingHandle(std::move(pointers))...); |     PushMoveHLEHandles(context->AddOutgoingHandle(std::move(pointers))...); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline void RequestBuilder::PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id) { | inline void RequestBuilder::PushStaticBuffer(VAddr buffer_vaddr, size_t size, u8 buffer_id) { | ||||||
|  | @ -221,12 +227,6 @@ inline void RequestBuilder::PushStaticBuffer(const std::vector<u8>& buffer, u8 b | ||||||
|     context->AddStaticBuffer(buffer_id, buffer); |     context->AddStaticBuffer(buffer_id, buffer); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline void RequestBuilder::PushMappedBuffer(VAddr buffer_vaddr, size_t size, |  | ||||||
|                                              MappedBufferPermissions perms) { |  | ||||||
|     Push(MappedBufferDesc(size, perms)); |  | ||||||
|     Push(buffer_vaddr); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline void RequestBuilder::PushMappedBuffer(const Kernel::MappedBuffer& mapped_buffer) { | inline void RequestBuilder::PushMappedBuffer(const Kernel::MappedBuffer& mapped_buffer) { | ||||||
|     Push(mapped_buffer.GenerateDescriptor()); |     Push(mapped_buffer.GenerateDescriptor()); | ||||||
|     Push(mapped_buffer.GetId()); |     Push(mapped_buffer.GetId()); | ||||||
|  | @ -284,24 +284,6 @@ public: | ||||||
|         return static_cast<T>(Pop<std::underlying_type_t<T>>()); |         return static_cast<T>(Pop<std::underlying_type_t<T>>()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /// Equivalent to calling `PopHandles<1>()[0]`.
 |  | ||||||
|     Kernel::Handle PopHandle(); |  | ||||||
| 
 |  | ||||||
|     /**
 |  | ||||||
|      * Pops a descriptor containing `N` handles. The handles are returned as an array. The |  | ||||||
|      * descriptor must contain exactly `N` handles, it is not permitted to, for example, call |  | ||||||
|      * PopHandles<1>() twice to read a multi-handle descriptor with 2 handles, or to make a single |  | ||||||
|      * PopHandles<2>() call to read 2 single-handle descriptors. |  | ||||||
|      */ |  | ||||||
|     template <unsigned int N> |  | ||||||
|     std::array<Kernel::Handle, N> PopHandles(); |  | ||||||
| 
 |  | ||||||
|     /// Convenience wrapper around PopHandles() which assigns the handles to the passed references.
 |  | ||||||
|     template <typename... H> |  | ||||||
|     void PopHandles(H&... handles) { |  | ||||||
|         std::tie(handles...) = PopHandles<sizeof...(H)>(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /// Equivalent to calling `PopGenericObjects<1>()[0]`.
 |     /// Equivalent to calling `PopGenericObjects<1>()[0]`.
 | ||||||
|     Kernel::SharedPtr<Kernel::Object> PopGenericObject(); |     Kernel::SharedPtr<Kernel::Object> PopGenericObject(); | ||||||
| 
 | 
 | ||||||
|  | @ -311,8 +293,10 @@ public: | ||||||
| 
 | 
 | ||||||
|     /**
 |     /**
 | ||||||
|      * Pop a descriptor containing `N` handles and resolves them to Kernel::Object pointers. If a |      * Pop a descriptor containing `N` handles and resolves them to Kernel::Object pointers. If a | ||||||
|      * handle is invalid, null is returned for that object instead. The same caveats from |      * handle is invalid, null is returned for that object instead. The descriptor must contain | ||||||
|      * PopHandles() apply regarding `N` matching the number of handles in the descriptor. |      * exactly `N` handles, it is not permitted to, for example, call PopGenericObjects<1>() twice | ||||||
|  |      * to read a multi-handle descriptor with 2 handles, or to make a single PopGenericObjects<2>() | ||||||
|  |      * call to read 2 single-handle descriptors. | ||||||
|      */ |      */ | ||||||
|     template <unsigned int N> |     template <unsigned int N> | ||||||
|     std::array<Kernel::SharedPtr<Kernel::Object>, N> PopGenericObjects(); |     std::array<Kernel::SharedPtr<Kernel::Object>, N> PopGenericObjects(); | ||||||
|  | @ -355,17 +339,6 @@ public: | ||||||
|      */ |      */ | ||||||
|     const std::vector<u8>& PopStaticBuffer(); |     const std::vector<u8>& PopStaticBuffer(); | ||||||
| 
 | 
 | ||||||
|     /**
 |  | ||||||
|      * @brief Pops the mapped buffer vaddr |  | ||||||
|      * @return                  The virtual address of the buffer |  | ||||||
|      * @param[out] data_size    If non-null, the pointed value will be set to the size of the data |  | ||||||
|      * given by the source process |  | ||||||
|      * @param[out] buffer_perms If non-null, the pointed value will be set to the permissions of the |  | ||||||
|      * buffer |  | ||||||
|      */ |  | ||||||
|     [[deprecated]] VAddr PopMappedBuffer(size_t* data_size, |  | ||||||
|                                          MappedBufferPermissions* buffer_perms = nullptr); |  | ||||||
| 
 |  | ||||||
|     /// Pops a mapped buffer descriptor with its vaddr and resolves it to an HLE interface
 |     /// Pops a mapped buffer descriptor with its vaddr and resolves it to an HLE interface
 | ||||||
|     Kernel::MappedBuffer& PopMappedBuffer(); |     Kernel::MappedBuffer& PopMappedBuffer(); | ||||||
| 
 | 
 | ||||||
|  | @ -382,6 +355,10 @@ public: | ||||||
|      */ |      */ | ||||||
|     template <typename T> |     template <typename T> | ||||||
|     T PopRaw(); |     T PopRaw(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |     template <unsigned int N> | ||||||
|  |     std::array<u32, N> PopHLEHandles(); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Pop ///
 | /// Pop ///
 | ||||||
|  | @ -443,32 +420,23 @@ void RequestParser::Pop(First& first_value, Other&... other_values) { | ||||||
|     Pop(other_values...); |     Pop(other_values...); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline Kernel::Handle RequestParser::PopHandle() { |  | ||||||
|     const u32 handle_descriptor = Pop<u32>(); |  | ||||||
|     DEBUG_ASSERT_MSG(IsHandleDescriptor(handle_descriptor), |  | ||||||
|                      "Tried to pop handle(s) but the descriptor is not a handle descriptor"); |  | ||||||
|     DEBUG_ASSERT_MSG(HandleNumberFromDesc(handle_descriptor) == 1, |  | ||||||
|                      "Descriptor indicates that there isn't exactly one handle"); |  | ||||||
|     return Pop<Kernel::Handle>(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| template <unsigned int N> | template <unsigned int N> | ||||||
| std::array<Kernel::Handle, N> RequestParser::PopHandles() { | std::array<u32, N> RequestParser::PopHLEHandles() { | ||||||
|     u32 handle_descriptor = Pop<u32>(); |     u32 handle_descriptor = Pop<u32>(); | ||||||
|     ASSERT_MSG(IsHandleDescriptor(handle_descriptor), |     ASSERT_MSG(IsHandleDescriptor(handle_descriptor), | ||||||
|                "Tried to pop handle(s) but the descriptor is not a handle descriptor"); |                "Tried to pop handle(s) but the descriptor is not a handle descriptor"); | ||||||
|     ASSERT_MSG(N == HandleNumberFromDesc(handle_descriptor), |     ASSERT_MSG(N == HandleNumberFromDesc(handle_descriptor), | ||||||
|                "Number of handles doesn't match the descriptor"); |                "Number of handles doesn't match the descriptor"); | ||||||
| 
 | 
 | ||||||
|     std::array<Kernel::Handle, N> handles{}; |     std::array<u32, N> handles{}; | ||||||
|     for (Kernel::Handle& handle : handles) { |     for (u32& handle : handles) { | ||||||
|         handle = Pop<Kernel::Handle>(); |         handle = Pop<u32>(); | ||||||
|     } |     } | ||||||
|     return handles; |     return handles; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline Kernel::SharedPtr<Kernel::Object> RequestParser::PopGenericObject() { | inline Kernel::SharedPtr<Kernel::Object> RequestParser::PopGenericObject() { | ||||||
|     Kernel::Handle handle = PopHandle(); |     auto[handle] = PopHLEHandles<1>(); | ||||||
|     return context->GetIncomingHandle(handle); |     return context->GetIncomingHandle(handle); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -479,7 +447,7 @@ Kernel::SharedPtr<T> RequestParser::PopObject() { | ||||||
| 
 | 
 | ||||||
| template <unsigned int N> | template <unsigned int N> | ||||||
| inline std::array<Kernel::SharedPtr<Kernel::Object>, N> RequestParser::PopGenericObjects() { | inline std::array<Kernel::SharedPtr<Kernel::Object>, N> RequestParser::PopGenericObjects() { | ||||||
|     std::array<Kernel::Handle, N> handles = PopHandles<N>(); |     std::array<u32, N> handles = PopHLEHandles<N>(); | ||||||
|     std::array<Kernel::SharedPtr<Kernel::Object>, N> pointers; |     std::array<Kernel::SharedPtr<Kernel::Object>, N> pointers; | ||||||
|     for (int i = 0; i < N; ++i) { |     for (int i = 0; i < N; ++i) { | ||||||
|         pointers[i] = context->GetIncomingHandle(handles[i]); |         pointers[i] = context->GetIncomingHandle(handles[i]); | ||||||
|  | @ -524,17 +492,6 @@ inline const std::vector<u8>& RequestParser::PopStaticBuffer() { | ||||||
|     return context->GetStaticBuffer(buffer_info.buffer_id); |     return context->GetStaticBuffer(buffer_info.buffer_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline VAddr RequestParser::PopMappedBuffer(size_t* data_size, |  | ||||||
|                                             MappedBufferPermissions* buffer_perms) { |  | ||||||
|     const u32 sbuffer_descriptor = Pop<u32>(); |  | ||||||
|     MappedBufferDescInfo bufferInfo{sbuffer_descriptor}; |  | ||||||
|     if (data_size != nullptr) |  | ||||||
|         *data_size = bufferInfo.size; |  | ||||||
|     if (buffer_perms != nullptr) |  | ||||||
|         *buffer_perms = bufferInfo.perms; |  | ||||||
|     return Pop<VAddr>(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| inline Kernel::MappedBuffer& RequestParser::PopMappedBuffer() { | inline Kernel::MappedBuffer& RequestParser::PopMappedBuffer() { | ||||||
|     u32 mapped_buffer_descriptor = Pop<u32>(); |     u32 mapped_buffer_descriptor = Pop<u32>(); | ||||||
|     ASSERT_MSG(GetDescriptorType(mapped_buffer_descriptor) == MappedBuffer, |     ASSERT_MSG(GetDescriptorType(mapped_buffer_descriptor) == MappedBuffer, | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <array> |  | ||||||
| #include <cinttypes> | #include <cinttypes> | ||||||
| #include <cstddef> | #include <cstddef> | ||||||
| #include <cstring> | #include <cstring> | ||||||
|  | @ -27,7 +26,6 @@ | ||||||
| #include "core/hle/service/am/am_sys.h" | #include "core/hle/service/am/am_sys.h" | ||||||
| #include "core/hle/service/am/am_u.h" | #include "core/hle/service/am/am_u.h" | ||||||
| #include "core/hle/service/fs/archive.h" | #include "core/hle/service/fs/archive.h" | ||||||
| #include "core/hle/service/service.h" |  | ||||||
| #include "core/loader/loader.h" | #include "core/loader/loader.h" | ||||||
| #include "core/loader/smdh.h" | #include "core/loader/smdh.h" | ||||||
| 
 | 
 | ||||||
|  | @ -41,12 +39,6 @@ constexpr u8 VARIATION_SYSTEM = 0x02; | ||||||
| constexpr u32 TID_HIGH_UPDATE = 0x0004000E; | constexpr u32 TID_HIGH_UPDATE = 0x0004000E; | ||||||
| constexpr u32 TID_HIGH_DLC = 0x0004008C; | constexpr u32 TID_HIGH_DLC = 0x0004008C; | ||||||
| 
 | 
 | ||||||
| // CIA installation static context variables
 |  | ||||||
| static bool cia_installing = false; |  | ||||||
| 
 |  | ||||||
| static bool lists_initialized = false; |  | ||||||
| static std::array<std::vector<u64_le>, 3> am_title_list; |  | ||||||
| 
 |  | ||||||
| struct TitleInfo { | struct TitleInfo { | ||||||
|     u64_le tid; |     u64_le tid; | ||||||
|     u64_le size; |     u64_le size; | ||||||
|  | @ -454,7 +446,7 @@ std::string GetMediaTitlePath(Service::FS::MediaType media_type) { | ||||||
|     return ""; |     return ""; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ScanForTitles(Service::FS::MediaType media_type) { | void Module::ScanForTitles(Service::FS::MediaType media_type) { | ||||||
|     am_title_list[static_cast<u32>(media_type)].clear(); |     am_title_list[static_cast<u32>(media_type)].clear(); | ||||||
| 
 | 
 | ||||||
|     std::string title_path = GetMediaTitlePath(media_type); |     std::string title_path = GetMediaTitlePath(media_type); | ||||||
|  | @ -473,31 +465,33 @@ void ScanForTitles(Service::FS::MediaType media_type) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ScanForAllTitles() { | void Module::ScanForAllTitles() { | ||||||
|     ScanForTitles(Service::FS::MediaType::NAND); |     ScanForTitles(Service::FS::MediaType::NAND); | ||||||
|     ScanForTitles(Service::FS::MediaType::SDMC); |     ScanForTitles(Service::FS::MediaType::SDMC); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetNumPrograms(Service::Interface* self) { | Module::Interface::Interface(std::shared_ptr<Module> am, const char* name, u32 max_session) | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1, 1, 0); // 0x00010040
 |     : ServiceFramework(name, max_session), am(std::move(am)) {} | ||||||
|  | 
 | ||||||
|  | Module::Interface::~Interface() = default; | ||||||
|  | 
 | ||||||
|  | void Module::Interface::GetNumPrograms(Kernel::HLERequestContext& ctx) { | ||||||
|  |     IPC::RequestParser rp(ctx, 0x0001, 1, 0); // 0x00010040
 | ||||||
|     u32 media_type = rp.Pop<u8>(); |     u32 media_type = rp.Pop<u8>(); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.Push<u32>(am_title_list[media_type].size()); |     rb.Push<u32>(am->am_title_list[media_type].size()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void FindDLCContentInfos(Service::Interface* self) { | void Module::Interface::FindDLCContentInfos(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1002, 4, 4); // 0x10020104
 |     IPC::RequestParser rp(ctx, 0x1002, 4, 4); // 0x10020104
 | ||||||
| 
 | 
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|     u64 title_id = rp.Pop<u64>(); |     u64 title_id = rp.Pop<u64>(); | ||||||
|     u32 content_count = rp.Pop<u32>(); |     u32 content_count = rp.Pop<u32>(); | ||||||
| 
 |     auto& content_requested_in = rp.PopMappedBuffer(); | ||||||
|     size_t input_buffer_size, output_buffer_size; |     auto& content_info_out = rp.PopMappedBuffer(); | ||||||
|     IPC::MappedBufferPermissions input_buffer_perms, output_buffer_perms; |  | ||||||
|     VAddr content_requested_in = rp.PopMappedBuffer(&input_buffer_size, &input_buffer_perms); |  | ||||||
|     VAddr content_info_out = rp.PopMappedBuffer(&output_buffer_size, &output_buffer_perms); |  | ||||||
| 
 | 
 | ||||||
|     // Validate that only DLC TIDs are passed in
 |     // Validate that only DLC TIDs are passed in
 | ||||||
|     u32 tid_high = static_cast<u32>(title_id >> 32); |     u32 tid_high = static_cast<u32>(title_id >> 32); | ||||||
|  | @ -505,19 +499,20 @@ void FindDLCContentInfos(Service::Interface* self) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); | ||||||
|         rb.Push(ResultCode(ErrCodes::InvalidTIDInList, ErrorModule::AM, |         rb.Push(ResultCode(ErrCodes::InvalidTIDInList, ErrorModule::AM, | ||||||
|                            ErrorSummary::InvalidArgument, ErrorLevel::Usage)); |                            ErrorSummary::InvalidArgument, ErrorLevel::Usage)); | ||||||
|         rb.PushMappedBuffer(content_requested_in, input_buffer_size, input_buffer_perms); |         rb.PushMappedBuffer(content_requested_in); | ||||||
|         rb.PushMappedBuffer(content_info_out, output_buffer_size, output_buffer_perms); |         rb.PushMappedBuffer(content_info_out); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     std::vector<u16_le> content_requested(content_count); |     std::vector<u16_le> content_requested(content_count); | ||||||
|     Memory::ReadBlock(content_requested_in, content_requested.data(), content_count * sizeof(u16)); |     content_requested_in.Read(content_requested.data(), 0, content_count * sizeof(u16)); | ||||||
| 
 | 
 | ||||||
|     std::string tmd_path = GetTitleMetadataPath(media_type, title_id); |     std::string tmd_path = GetTitleMetadataPath(media_type, title_id); | ||||||
| 
 | 
 | ||||||
|     u32 content_read = 0; |     u32 content_read = 0; | ||||||
|     FileSys::TitleMetadata tmd; |     FileSys::TitleMetadata tmd; | ||||||
|     if (tmd.Load(tmd_path) == Loader::ResultStatus::Success) { |     if (tmd.Load(tmd_path) == Loader::ResultStatus::Success) { | ||||||
|  |         std::size_t write_offset = 0; | ||||||
|         // Get info for each content index requested
 |         // Get info for each content index requested
 | ||||||
|         for (size_t i = 0; i < content_count; i++) { |         for (size_t i = 0; i < content_count; i++) { | ||||||
|             std::shared_ptr<FileUtil::IOFile> romfs_file; |             std::shared_ptr<FileUtil::IOFile> romfs_file; | ||||||
|  | @ -534,29 +529,26 @@ void FindDLCContentInfos(Service::Interface* self) { | ||||||
|             content_info.size = tmd.GetContentSizeByIndex(content_requested[i]); |             content_info.size = tmd.GetContentSizeByIndex(content_requested[i]); | ||||||
|             content_info.romfs_size = romfs_size; |             content_info.romfs_size = romfs_size; | ||||||
| 
 | 
 | ||||||
|             Memory::WriteBlock(content_info_out, &content_info, sizeof(ContentInfo)); |             content_info_out.Write(&content_info, write_offset, sizeof(ContentInfo)); | ||||||
|             content_info_out += sizeof(ContentInfo); |             write_offset += sizeof(ContentInfo); | ||||||
|             content_read++; |             content_read++; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushMappedBuffer(content_requested_in, input_buffer_size, input_buffer_perms); |     rb.PushMappedBuffer(content_requested_in); | ||||||
|     rb.PushMappedBuffer(content_info_out, output_buffer_size, output_buffer_perms); |     rb.PushMappedBuffer(content_info_out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ListDLCContentInfos(Service::Interface* self) { | void Module::Interface::ListDLCContentInfos(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1003, 5, 2); // 0x10030142
 |     IPC::RequestParser rp(ctx, 0x1003, 5, 2); // 0x10030142
 | ||||||
| 
 | 
 | ||||||
|     u32 content_count = rp.Pop<u32>(); |     u32 content_count = rp.Pop<u32>(); | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|     u64 title_id = rp.Pop<u64>(); |     u64 title_id = rp.Pop<u64>(); | ||||||
|     u32 start_index = rp.Pop<u32>(); |     u32 start_index = rp.Pop<u32>(); | ||||||
| 
 |     auto& content_info_out = rp.PopMappedBuffer(); | ||||||
|     size_t output_buffer_size; |  | ||||||
|     IPC::MappedBufferPermissions output_buffer_perms; |  | ||||||
|     VAddr content_info_out = rp.PopMappedBuffer(&output_buffer_size, &output_buffer_perms); |  | ||||||
| 
 | 
 | ||||||
|     // Validate that only DLC TIDs are passed in
 |     // Validate that only DLC TIDs are passed in
 | ||||||
|     u32 tid_high = static_cast<u32>(title_id >> 32); |     u32 tid_high = static_cast<u32>(title_id >> 32); | ||||||
|  | @ -565,7 +557,7 @@ void ListDLCContentInfos(Service::Interface* self) { | ||||||
|         rb.Push(ResultCode(ErrCodes::InvalidTIDInList, ErrorModule::AM, |         rb.Push(ResultCode(ErrCodes::InvalidTIDInList, ErrorModule::AM, | ||||||
|                            ErrorSummary::InvalidArgument, ErrorLevel::Usage)); |                            ErrorSummary::InvalidArgument, ErrorLevel::Usage)); | ||||||
|         rb.Push<u32>(0); |         rb.Push<u32>(0); | ||||||
|         rb.PushMappedBuffer(content_info_out, output_buffer_size, output_buffer_perms); |         rb.PushMappedBuffer(content_info_out); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -575,6 +567,7 @@ void ListDLCContentInfos(Service::Interface* self) { | ||||||
|     FileSys::TitleMetadata tmd; |     FileSys::TitleMetadata tmd; | ||||||
|     if (tmd.Load(tmd_path) == Loader::ResultStatus::Success) { |     if (tmd.Load(tmd_path) == Loader::ResultStatus::Success) { | ||||||
|         copied = std::min(content_count, static_cast<u32>(tmd.GetContentCount())); |         copied = std::min(content_count, static_cast<u32>(tmd.GetContentCount())); | ||||||
|  |         std::size_t write_offset = 0; | ||||||
|         for (u32 i = start_index; i < copied; i++) { |         for (u32 i = start_index; i < copied; i++) { | ||||||
|             std::shared_ptr<FileUtil::IOFile> romfs_file; |             std::shared_ptr<FileUtil::IOFile> romfs_file; | ||||||
|             u64 romfs_offset = 0; |             u64 romfs_offset = 0; | ||||||
|  | @ -590,58 +583,61 @@ void ListDLCContentInfos(Service::Interface* self) { | ||||||
|             content_info.size = tmd.GetContentSizeByIndex(i); |             content_info.size = tmd.GetContentSizeByIndex(i); | ||||||
|             content_info.romfs_size = romfs_size; |             content_info.romfs_size = romfs_size; | ||||||
| 
 | 
 | ||||||
|             Memory::WriteBlock(content_info_out, &content_info, sizeof(ContentInfo)); |             content_info_out.Write(&content_info, write_offset, sizeof(ContentInfo)); | ||||||
|             content_info_out += sizeof(ContentInfo); |             write_offset += sizeof(ContentInfo); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.Push(copied); |     rb.Push(copied); | ||||||
|     rb.PushMappedBuffer(content_info_out, output_buffer_size, output_buffer_perms); |     rb.PushMappedBuffer(content_info_out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DeleteContents(Service::Interface* self) { | void Module::Interface::DeleteContents(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1004, 4, 2); // 0x10040102
 |     IPC::RequestParser rp(ctx, 0x1004, 4, 2); // 0x10040102
 | ||||||
|     u8 media_type = rp.Pop<u8>(); |     u8 media_type = rp.Pop<u8>(); | ||||||
|     u64 title_id = rp.Pop<u64>(); |     u64 title_id = rp.Pop<u64>(); | ||||||
|     u32 content_count = rp.Pop<u32>(); |     u32 content_count = rp.Pop<u32>(); | ||||||
|     VAddr content_ids_in = rp.PopMappedBuffer(nullptr); |     auto& content_ids_in = rp.PopMappedBuffer(); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 |     rb.PushMappedBuffer(content_ids_in); | ||||||
|                             ", content_count=%u, content_ids_in=0x%08x", |     LOG_WARNING(Service_AM, "(STUBBED) media_type=%u, title_id=0x%016" PRIx64 ", content_count=%u", | ||||||
|                 media_type, title_id, content_count, content_ids_in); |                 media_type, title_id, content_count); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetProgramList(Service::Interface* self) { | void Module::Interface::GetProgramList(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 2, 2, 2); // 0x00020082
 |     IPC::RequestParser rp(ctx, 0x0002, 2, 2); // 0x00020082
 | ||||||
| 
 | 
 | ||||||
|     u32 count = rp.Pop<u32>(); |     u32 count = rp.Pop<u32>(); | ||||||
|     u8 media_type = rp.Pop<u8>(); |     u8 media_type = rp.Pop<u8>(); | ||||||
|     VAddr title_ids_output_pointer = rp.PopMappedBuffer(nullptr); |     auto& title_ids_output = rp.PopMappedBuffer(); | ||||||
| 
 | 
 | ||||||
|     if (!Memory::IsValidVirtualAddress(title_ids_output_pointer) || media_type > 2) { |     if (media_type > 2) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); | ||||||
|         rb.Push<u32>(-1); // TODO(shinyquagsire23): Find the right error code
 |         rb.Push<u32>(-1); // TODO(shinyquagsire23): Find the right error code
 | ||||||
|         rb.Push<u32>(0); |         rb.Push<u32>(0); | ||||||
|  |         rb.PushMappedBuffer(title_ids_output); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     u32 media_count = static_cast<u32>(am_title_list[media_type].size()); |     u32 media_count = static_cast<u32>(am->am_title_list[media_type].size()); | ||||||
|     u32 copied = std::min(media_count, count); |     u32 copied = std::min(media_count, count); | ||||||
| 
 | 
 | ||||||
|     Memory::WriteBlock(title_ids_output_pointer, am_title_list[media_type].data(), |     title_ids_output.Write(am->am_title_list[media_type].data(), 0, copied * sizeof(u64)); | ||||||
|                        copied * sizeof(u64)); |  | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.Push(copied); |     rb.Push(copied); | ||||||
|  |     rb.PushMappedBuffer(title_ids_output); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultCode GetTitleInfoFromList(const std::vector<u64>& title_id_list, | ResultCode GetTitleInfoFromList(const std::vector<u64>& title_id_list, | ||||||
|                                 Service::FS::MediaType media_type, VAddr title_info_out) { |                                 Service::FS::MediaType media_type, | ||||||
|  |                                 Kernel::MappedBuffer& title_info_out) { | ||||||
|  |     std::size_t write_offset = 0; | ||||||
|     for (u32 i = 0; i < title_id_list.size(); i++) { |     for (u32 i = 0; i < title_id_list.size(); i++) { | ||||||
|         std::string tmd_path = GetTitleMetadataPath(media_type, title_id_list[i]); |         std::string tmd_path = GetTitleMetadataPath(media_type, title_id_list[i]); | ||||||
| 
 | 
 | ||||||
|  | @ -659,37 +655,34 @@ ResultCode GetTitleInfoFromList(const std::vector<u64>& title_id_list, | ||||||
|             return ResultCode(ErrorDescription::NotFound, ErrorModule::AM, |             return ResultCode(ErrorDescription::NotFound, ErrorModule::AM, | ||||||
|                               ErrorSummary::InvalidState, ErrorLevel::Permanent); |                               ErrorSummary::InvalidState, ErrorLevel::Permanent); | ||||||
|         } |         } | ||||||
|         Memory::WriteBlock(title_info_out, &title_info, sizeof(TitleInfo)); |         title_info_out.Write(&title_info, write_offset, sizeof(TitleInfo)); | ||||||
|         title_info_out += sizeof(TitleInfo); |         write_offset += sizeof(TitleInfo); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetProgramInfos(Service::Interface* self) { | void Module::Interface::GetProgramInfos(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 3, 2, 4); // 0x00030084
 |     IPC::RequestParser rp(ctx, 0x0003, 2, 4); // 0x00030084
 | ||||||
| 
 | 
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|     u32 title_count = rp.Pop<u32>(); |     u32 title_count = rp.Pop<u32>(); | ||||||
| 
 |     auto& title_id_list_buffer = rp.PopMappedBuffer(); | ||||||
|     size_t title_id_list_size, title_info_size; |     auto& title_info_out = rp.PopMappedBuffer(); | ||||||
|     IPC::MappedBufferPermissions title_id_list_perms, title_info_perms; |  | ||||||
|     VAddr title_id_list_pointer = rp.PopMappedBuffer(&title_id_list_size, &title_id_list_perms); |  | ||||||
|     VAddr title_info_out = rp.PopMappedBuffer(&title_info_size, &title_info_perms); |  | ||||||
| 
 | 
 | ||||||
|     std::vector<u64> title_id_list(title_count); |     std::vector<u64> title_id_list(title_count); | ||||||
|     Memory::ReadBlock(title_id_list_pointer, title_id_list.data(), title_count * sizeof(u64)); |     title_id_list_buffer.Read(title_id_list.data(), 0, title_count * sizeof(u64)); | ||||||
| 
 | 
 | ||||||
|     ResultCode result = GetTitleInfoFromList(title_id_list, media_type, title_info_out); |     ResultCode result = GetTitleInfoFromList(title_id_list, media_type, title_info_out); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
|     rb.PushMappedBuffer(title_id_list_pointer, title_id_list_size, title_id_list_perms); |     rb.PushMappedBuffer(title_id_list_buffer); | ||||||
|     rb.PushMappedBuffer(title_info_out, title_info_size, title_info_perms); |     rb.PushMappedBuffer(title_info_out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DeleteUserProgram(Service::Interface* self) { | void Module::Interface::DeleteUserProgram(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x000400, 3, 0); |     IPC::RequestParser rp(ctx, 0x0004, 3, 0); | ||||||
|     auto media_type = rp.PopEnum<FS::MediaType>(); |     auto media_type = rp.PopEnum<FS::MediaType>(); | ||||||
|     u32 low = rp.Pop<u32>(); |     u32 low = rp.Pop<u32>(); | ||||||
|     u32 high = rp.Pop<u32>(); |     u32 high = rp.Pop<u32>(); | ||||||
|  | @ -712,25 +705,22 @@ void DeleteUserProgram(Service::Interface* self) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     bool success = FileUtil::DeleteDirRecursively(path); |     bool success = FileUtil::DeleteDirRecursively(path); | ||||||
|     ScanForAllTitles(); |     am->ScanForAllTitles(); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     if (!success) |     if (!success) | ||||||
|         LOG_ERROR(Service_AM, "FileUtil::DeleteDirRecursively unexpectedly failed"); |         LOG_ERROR(Service_AM, "FileUtil::DeleteDirRecursively unexpectedly failed"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetDLCTitleInfos(Service::Interface* self) { | void Module::Interface::GetDLCTitleInfos(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1005, 2, 4); // 0x10050084
 |     IPC::RequestParser rp(ctx, 0x1005, 2, 4); // 0x10050084
 | ||||||
| 
 | 
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|     u32 title_count = rp.Pop<u32>(); |     u32 title_count = rp.Pop<u32>(); | ||||||
| 
 |     auto& title_id_list_buffer = rp.PopMappedBuffer(); | ||||||
|     size_t title_id_list_size, title_info_size; |     auto& title_info_out = rp.PopMappedBuffer(); | ||||||
|     IPC::MappedBufferPermissions title_id_list_perms, title_info_perms; |  | ||||||
|     VAddr title_id_list_pointer = rp.PopMappedBuffer(&title_id_list_size, &title_id_list_perms); |  | ||||||
|     VAddr title_info_out = rp.PopMappedBuffer(&title_info_size, &title_info_perms); |  | ||||||
| 
 | 
 | ||||||
|     std::vector<u64> title_id_list(title_count); |     std::vector<u64> title_id_list(title_count); | ||||||
|     Memory::ReadBlock(title_id_list_pointer, title_id_list.data(), title_count * sizeof(u64)); |     title_id_list_buffer.Read(title_id_list.data(), 0, title_count * sizeof(u64)); | ||||||
| 
 | 
 | ||||||
|     ResultCode result = RESULT_SUCCESS; |     ResultCode result = RESULT_SUCCESS; | ||||||
| 
 | 
 | ||||||
|  | @ -750,23 +740,20 @@ void GetDLCTitleInfos(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
|     rb.PushMappedBuffer(title_id_list_pointer, title_id_list_size, title_id_list_perms); |     rb.PushMappedBuffer(title_id_list_buffer); | ||||||
|     rb.PushMappedBuffer(title_info_out, title_info_size, title_info_perms); |     rb.PushMappedBuffer(title_info_out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetPatchTitleInfos(Service::Interface* self) { | void Module::Interface::GetPatchTitleInfos(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x100D, 2, 4); // 0x100D0084
 |     IPC::RequestParser rp(ctx, 0x100D, 2, 4); // 0x100D0084
 | ||||||
| 
 | 
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|     u32 title_count = rp.Pop<u32>(); |     u32 title_count = rp.Pop<u32>(); | ||||||
| 
 |     auto& title_id_list_buffer = rp.PopMappedBuffer(); | ||||||
|     size_t title_id_list_size, title_info_size; |     auto& title_info_out = rp.PopMappedBuffer(); | ||||||
|     IPC::MappedBufferPermissions title_id_list_perms, title_info_perms; |  | ||||||
|     VAddr title_id_list_pointer = rp.PopMappedBuffer(&title_id_list_size, &title_id_list_perms); |  | ||||||
|     VAddr title_info_out = rp.PopMappedBuffer(&title_info_size, &title_info_perms); |  | ||||||
| 
 | 
 | ||||||
|     std::vector<u64> title_id_list(title_count); |     std::vector<u64> title_id_list(title_count); | ||||||
|     Memory::ReadBlock(title_id_list_pointer, title_id_list.data(), title_count * sizeof(u64)); |     title_id_list_buffer.Read(title_id_list.data(), 0, title_count * sizeof(u64)); | ||||||
| 
 | 
 | ||||||
|     ResultCode result = RESULT_SUCCESS; |     ResultCode result = RESULT_SUCCESS; | ||||||
| 
 | 
 | ||||||
|  | @ -786,39 +773,40 @@ void GetPatchTitleInfos(Service::Interface* self) { | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 4); | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
|     rb.PushMappedBuffer(title_id_list_pointer, title_id_list_size, title_id_list_perms); |     rb.PushMappedBuffer(title_id_list_buffer); | ||||||
|     rb.PushMappedBuffer(title_info_out, title_info_size, title_info_perms); |     rb.PushMappedBuffer(title_info_out); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void ListDataTitleTicketInfos(Service::Interface* self) { | void Module::Interface::ListDataTitleTicketInfos(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1007, 4, 4); // 0x10070102
 |     IPC::RequestParser rp(ctx, 0x1007, 4, 2); // 0x10070102
 | ||||||
|     u32 ticket_count = rp.Pop<u32>(); |     u32 ticket_count = rp.Pop<u32>(); | ||||||
|     u64 title_id = rp.Pop<u64>(); |     u64 title_id = rp.Pop<u64>(); | ||||||
|     u32 start_index = rp.Pop<u32>(); |     u32 start_index = rp.Pop<u32>(); | ||||||
|     VAddr ticket_info_out = rp.PopMappedBuffer(nullptr); |     auto& ticket_info_out = rp.PopMappedBuffer(); | ||||||
|     VAddr ticket_info_write = ticket_info_out; |  | ||||||
| 
 | 
 | ||||||
|  |     std::size_t write_offset = 0; | ||||||
|     for (u32 i = 0; i < ticket_count; i++) { |     for (u32 i = 0; i < ticket_count; i++) { | ||||||
|         TicketInfo ticket_info = {}; |         TicketInfo ticket_info = {}; | ||||||
|         ticket_info.title_id = title_id; |         ticket_info.title_id = title_id; | ||||||
|         ticket_info.version = 0; // TODO
 |         ticket_info.version = 0; // TODO
 | ||||||
|         ticket_info.size = 0;    // TODO
 |         ticket_info.size = 0;    // TODO
 | ||||||
| 
 | 
 | ||||||
|         Memory::WriteBlock(ticket_info_write, &ticket_info, sizeof(TicketInfo)); |         ticket_info_out.Write(&ticket_info, write_offset, sizeof(TicketInfo)); | ||||||
|         ticket_info_write += sizeof(TicketInfo); |         write_offset += sizeof(TicketInfo); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.Push(ticket_count); |     rb.Push(ticket_count); | ||||||
|  |     rb.PushMappedBuffer(ticket_info_out); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 |     LOG_WARNING(Service_AM, | ||||||
|                             ", start_index=0x%08X, ticket_info_out=0x%08X", |                 "(STUBBED) ticket_count=0x%08X, title_id=0x%016" PRIx64 ", start_index=0x%08X", | ||||||
|                 ticket_count, title_id, start_index, ticket_info_out); |                 ticket_count, title_id, start_index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetDLCContentInfoCount(Service::Interface* self) { | void Module::Interface::GetDLCContentInfoCount(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x1001, 3, 0); // 0x100100C0
 |     IPC::RequestParser rp(ctx, 0x1001, 3, 0); // 0x100100C0
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|     u64 title_id = rp.Pop<u64>(); |     u64 title_id = rp.Pop<u64>(); | ||||||
| 
 | 
 | ||||||
|  | @ -847,8 +835,8 @@ void GetDLCContentInfoCount(Service::Interface* self) { | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DeleteTicket(Service::Interface* self) { | void Module::Interface::DeleteTicket(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 7, 2, 0); // 0x00070080
 |     IPC::RequestParser rp(ctx, 0x0007, 2, 0); // 0x00070080
 | ||||||
|     u64 title_id = rp.Pop<u64>(); |     u64 title_id = rp.Pop<u64>(); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|  | @ -856,8 +844,8 @@ void DeleteTicket(Service::Interface* self) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id); |     LOG_WARNING(Service_AM, "(STUBBED) called title_id=0x%016" PRIx64 "", title_id); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetNumTickets(Service::Interface* self) { | void Module::Interface::GetNumTickets(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 8, 0, 0); // 0x00080000
 |     IPC::RequestParser rp(ctx, 0x0008, 0, 0); // 0x00080000
 | ||||||
|     u32 ticket_count = 0; |     u32 ticket_count = 0; | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|  | @ -866,22 +854,22 @@ void GetNumTickets(Service::Interface* self) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x", ticket_count); |     LOG_WARNING(Service_AM, "(STUBBED) called ticket_count=0x%08x", ticket_count); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetTicketList(Service::Interface* self) { | void Module::Interface::GetTicketList(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 9, 2, 2); // 0x00090082
 |     IPC::RequestParser rp(ctx, 0x0009, 2, 2); // 0x00090082
 | ||||||
|     u32 ticket_list_count = rp.Pop<u32>(); |     u32 ticket_list_count = rp.Pop<u32>(); | ||||||
|     u32 ticket_index = rp.Pop<u32>(); |     u32 ticket_index = rp.Pop<u32>(); | ||||||
|     VAddr ticket_tids_out = rp.PopMappedBuffer(nullptr); |     auto& ticket_tids_out = rp.PopMappedBuffer(); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.Push(ticket_list_count); |     rb.Push(ticket_list_count); | ||||||
|     LOG_WARNING(Service_AM, |     rb.PushMappedBuffer(ticket_tids_out); | ||||||
|                 "(STUBBED) ticket_list_count=0x%08x, ticket_index=0x%08x, ticket_tids_out=0x%08x", |     LOG_WARNING(Service_AM, "(STUBBED) ticket_list_count=0x%08x, ticket_index=0x%08x", | ||||||
|                 ticket_list_count, ticket_index, ticket_tids_out); |                 ticket_list_count, ticket_index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void QueryAvailableTitleDatabase(Service::Interface* self) { | void Module::Interface::QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x19, 1, 0); // 0x190040
 |     IPC::RequestParser rp(ctx, 0x0019, 1, 0); // 0x190040
 | ||||||
|     u8 media_type = rp.Pop<u8>(); |     u8 media_type = rp.Pop<u8>(); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); | ||||||
|  | @ -891,8 +879,8 @@ void QueryAvailableTitleDatabase(Service::Interface* self) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) media_type=%u", media_type); |     LOG_WARNING(Service_AM, "(STUBBED) media_type=%u", media_type); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CheckContentRights(Service::Interface* self) { | void Module::Interface::CheckContentRights(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x25, 3, 0); // 0x2500C0
 |     IPC::RequestParser rp(ctx, 0x0025, 3, 0); // 0x2500C0
 | ||||||
|     u64 tid = rp.Pop<u64>(); |     u64 tid = rp.Pop<u64>(); | ||||||
|     u16 content_index = rp.Pop<u16>(); |     u16 content_index = rp.Pop<u16>(); | ||||||
| 
 | 
 | ||||||
|  | @ -907,8 +895,8 @@ void CheckContentRights(Service::Interface* self) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) tid=%016" PRIx64 ", content_index=%u", tid, content_index); |     LOG_WARNING(Service_AM, "(STUBBED) tid=%016" PRIx64 ", content_index=%u", tid, content_index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void CheckContentRightsIgnorePlatform(Service::Interface* self) { | void Module::Interface::CheckContentRightsIgnorePlatform(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x2D, 3, 0); // 0x2D00C0
 |     IPC::RequestParser rp(ctx, 0x002D, 3, 0); // 0x2D00C0
 | ||||||
|     u64 tid = rp.Pop<u64>(); |     u64 tid = rp.Pop<u64>(); | ||||||
|     u16 content_index = rp.Pop<u16>(); |     u16 content_index = rp.Pop<u16>(); | ||||||
| 
 | 
 | ||||||
|  | @ -923,11 +911,11 @@ void CheckContentRightsIgnorePlatform(Service::Interface* self) { | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) tid=%016" PRIx64 ", content_index=%u", tid, content_index); |     LOG_WARNING(Service_AM, "(STUBBED) tid=%016" PRIx64 ", content_index=%u", tid, content_index); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void BeginImportProgram(Service::Interface* self) { | void Module::Interface::BeginImportProgram(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0402, 1, 0); // 0x04020040
 |     IPC::RequestParser rp(ctx, 0x0402, 1, 0); // 0x04020040
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
| 
 | 
 | ||||||
|     if (cia_installing) { |     if (am->cia_installing) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|         rb.Push(ResultCode(ErrCodes::CIACurrentlyInstalling, ErrorModule::AM, |         rb.Push(ResultCode(ErrCodes::CIACurrentlyInstalling, ErrorModule::AM, | ||||||
|                            ErrorSummary::InvalidState, ErrorLevel::Permanent)); |                            ErrorSummary::InvalidState, ErrorLevel::Permanent)); | ||||||
|  | @ -940,33 +928,32 @@ void BeginImportProgram(Service::Interface* self) { | ||||||
|     auto file = |     auto file = | ||||||
|         std::make_shared<Service::FS::File>(std::make_unique<CIAFile>(media_type), cia_path); |         std::make_shared<Service::FS::File>(std::make_unique<CIAFile>(media_type), cia_path); | ||||||
| 
 | 
 | ||||||
|     cia_installing = true; |     am->cia_installing = true; | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); // No error
 |     rb.Push(RESULT_SUCCESS); // No error
 | ||||||
|     rb.PushCopyHandles(Kernel::g_handle_table.Create(file->Connect()).Unwrap()); |     rb.PushCopyObjects(file->Connect()); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) media_type=%u", static_cast<u32>(media_type)); |     LOG_WARNING(Service_AM, "(STUBBED) media_type=%u", static_cast<u32>(media_type)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void EndImportProgram(Service::Interface* self) { | void Module::Interface::EndImportProgram(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0405, 0, 2); // 0x04050002
 |     IPC::RequestParser rp(ctx, 0x0405, 0, 2); // 0x04050002
 | ||||||
|     auto cia_handle = rp.PopHandle(); |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
| 
 | 
 | ||||||
|     Kernel::g_handle_table.Close(cia_handle); |     am->ScanForAllTitles(); | ||||||
|     ScanForAllTitles(); |  | ||||||
| 
 | 
 | ||||||
|     cia_installing = false; |     am->cia_installing = false; | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ResultVal<std::shared_ptr<Service::FS::File>> GetFileFromHandle(Kernel::Handle handle) { | ResultVal<std::shared_ptr<Service::FS::File>> GetFileFromSession( | ||||||
|     // Step up the chain from Handle->ClientSession->ServerSession and then
 |     Kernel::SharedPtr<Kernel::ClientSession> file_session) { | ||||||
|  |     // Step up the chain from ClientSession->ServerSession and then
 | ||||||
|     // cast to File. For AM on 3DS, invalid handles actually hang the system.
 |     // cast to File. For AM on 3DS, invalid handles actually hang the system.
 | ||||||
|     auto file_session = Kernel::g_handle_table.Get<Kernel::ClientSession>(handle); |  | ||||||
| 
 | 
 | ||||||
|     if (file_session == nullptr || file_session->parent == nullptr) { |     if (file_session->parent == nullptr) { | ||||||
|         LOG_WARNING(Service_AM, "Invalid file handle!"); |         LOG_WARNING(Service_AM, "Invalid file handle!"); | ||||||
|         return Kernel::ERR_INVALID_HANDLE; |         return Kernel::ERR_INVALID_HANDLE; | ||||||
|     } |     } | ||||||
|  | @ -994,12 +981,12 @@ ResultVal<std::shared_ptr<Service::FS::File>> GetFileFromHandle(Kernel::Handle h | ||||||
|     return Kernel::ERR_NOT_IMPLEMENTED; |     return Kernel::ERR_NOT_IMPLEMENTED; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetProgramInfoFromCia(Service::Interface* self) { | void Module::Interface::GetProgramInfoFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0408, 1, 2); // 0x04080042
 |     IPC::RequestParser rp(ctx, 0x0408, 1, 2); // 0x04080042
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|  | @ -1032,65 +1019,61 @@ void GetProgramInfoFromCia(Service::Interface* self) { | ||||||
|     rb.PushRaw<TitleInfo>(title_info); |     rb.PushRaw<TitleInfo>(title_info); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetSystemMenuDataFromCia(Service::Interface* self) { | void Module::Interface::GetSystemMenuDataFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0409, 0, 4); // 0x04090004
 |     IPC::RequestParser rp(ctx, 0x0409, 0, 4); // 0x04090004
 | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
|  |     auto& output_buffer = rp.PopMappedBuffer(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|  |         rb.PushMappedBuffer(output_buffer); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     size_t output_buffer_size; |     std::size_t output_buffer_size = std::min(output_buffer.GetSize(), sizeof(Loader::SMDH)); | ||||||
|     IPC::MappedBufferPermissions output_buffer_perms; |  | ||||||
|     VAddr output_buffer = rp.PopMappedBuffer(&output_buffer_size, &output_buffer_perms); |  | ||||||
|     output_buffer_size = std::min(output_buffer_size, sizeof(Loader::SMDH)); |  | ||||||
| 
 | 
 | ||||||
|     auto file = file_res.Unwrap(); |     auto file = file_res.Unwrap(); | ||||||
|     FileSys::CIAContainer container; |     FileSys::CIAContainer container; | ||||||
|     if (container.Load(*file->backend) != Loader::ResultStatus::Success) { |     if (container.Load(*file->backend) != Loader::ResultStatus::Success) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|         rb.Push(ResultCode(ErrCodes::InvalidCIAHeader, ErrorModule::AM, |         rb.Push(ResultCode(ErrCodes::InvalidCIAHeader, ErrorModule::AM, | ||||||
|                            ErrorSummary::InvalidArgument, ErrorLevel::Permanent)); |                            ErrorSummary::InvalidArgument, ErrorLevel::Permanent)); | ||||||
|  |         rb.PushMappedBuffer(output_buffer); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     std::vector<u8> temp(output_buffer_size); |     std::vector<u8> temp(output_buffer_size); | ||||||
| 
 | 
 | ||||||
|     //  Read from the Meta offset + 0x400 for the 0x36C0-large SMDH
 |     //  Read from the Meta offset + 0x400 for the 0x36C0-large SMDH
 | ||||||
|     auto read_result = |     auto read_result = file->backend->Read( | ||||||
|         file->backend->Read(container.GetMetadataOffset() + FileSys::CIA_METADATA_SIZE, |         container.GetMetadataOffset() + FileSys::CIA_METADATA_SIZE, temp.size(), temp.data()); | ||||||
|                             output_buffer_size, temp.data()); |     if (read_result.Failed() || *read_result != temp.size()) { | ||||||
|     if (read_result.Failed() || *read_result != output_buffer_size) { |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |  | ||||||
|         rb.Push(ResultCode(ErrCodes::InvalidCIAHeader, ErrorModule::AM, |         rb.Push(ResultCode(ErrCodes::InvalidCIAHeader, ErrorModule::AM, | ||||||
|                            ErrorSummary::InvalidArgument, ErrorLevel::Permanent)); |                            ErrorSummary::InvalidArgument, ErrorLevel::Permanent)); | ||||||
|  |         rb.PushMappedBuffer(output_buffer); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Memory::WriteBlock(output_buffer, temp.data(), output_buffer_size); |     output_buffer.Write(temp.data(), 0, temp.size()); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.PushMappedBuffer(output_buffer, output_buffer_size, output_buffer_perms); |  | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|  |     rb.PushMappedBuffer(output_buffer); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetDependencyListFromCia(Service::Interface* self) { | void Module::Interface::GetDependencyListFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x040A, 0, 2); // 0x040A0002
 |     IPC::RequestParser rp(ctx, 0x040A, 0, 2); // 0x040A0002
 | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     size_t output_buffer_size; |  | ||||||
|     VAddr output_buffer = rp.PeekStaticBuffer(0, &output_buffer_size); |  | ||||||
|     output_buffer_size = std::min(output_buffer_size, FileSys::CIA_DEPENDENCY_SIZE); |  | ||||||
| 
 |  | ||||||
|     auto file = file_res.Unwrap(); |     auto file = file_res.Unwrap(); | ||||||
|     FileSys::CIAContainer container; |     FileSys::CIAContainer container; | ||||||
|     if (container.Load(*file->backend) != Loader::ResultStatus::Success) { |     if (container.Load(*file->backend) != Loader::ResultStatus::Success) { | ||||||
|  | @ -1100,18 +1083,19 @@ void GetDependencyListFromCia(Service::Interface* self) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Memory::WriteBlock(output_buffer, container.GetDependencies().data(), output_buffer_size); |     std::vector<u8> buffer(FileSys::CIA_DEPENDENCY_SIZE); | ||||||
|  |     std::memcpy(buffer.data(), container.GetDependencies().data(), buffer.size()); | ||||||
| 
 | 
 | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushStaticBuffer(output_buffer, output_buffer_size, 0); |     rb.PushStaticBuffer(buffer, 0); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetTransferSizeFromCia(Service::Interface* self) { | void Module::Interface::GetTransferSizeFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x040B, 0, 2); // 0x040B0002
 |     IPC::RequestParser rp(ctx, 0x040B, 0, 2); // 0x040B0002
 | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|  | @ -1132,11 +1116,11 @@ void GetTransferSizeFromCia(Service::Interface* self) { | ||||||
|     rb.Push(container.GetMetadataOffset()); |     rb.Push(container.GetMetadataOffset()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetCoreVersionFromCia(Service::Interface* self) { | void Module::Interface::GetCoreVersionFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x040C, 0, 2); // 0x040C0002
 |     IPC::RequestParser rp(ctx, 0x040C, 0, 2); // 0x040C0002
 | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|  | @ -1157,12 +1141,12 @@ void GetCoreVersionFromCia(Service::Interface* self) { | ||||||
|     rb.Push(container.GetCoreVersion()); |     rb.Push(container.GetCoreVersion()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetRequiredSizeFromCia(Service::Interface* self) { | void Module::Interface::GetRequiredSizeFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x040D, 1, 2); // 0x040D0042
 |     IPC::RequestParser rp(ctx, 0x040D, 1, 2); // 0x040D0042
 | ||||||
|     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); |     auto media_type = static_cast<Service::FS::MediaType>(rp.Pop<u8>()); | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|  | @ -1186,8 +1170,8 @@ void GetRequiredSizeFromCia(Service::Interface* self) { | ||||||
|     rb.Push(container.GetTitleMetadata().GetContentSizeByIndex(FileSys::TMDContentIndex::Main)); |     rb.Push(container.GetTitleMetadata().GetContentSizeByIndex(FileSys::TMDContentIndex::Main)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DeleteProgram(Service::Interface* self) { | void Module::Interface::DeleteProgram(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0410, 3, 0); |     IPC::RequestParser rp(ctx, 0x0410, 3, 0); | ||||||
|     auto media_type = rp.PopEnum<FS::MediaType>(); |     auto media_type = rp.PopEnum<FS::MediaType>(); | ||||||
|     u32 low = rp.Pop<u32>(); |     u32 low = rp.Pop<u32>(); | ||||||
|     u32 high = rp.Pop<u32>(); |     u32 high = rp.Pop<u32>(); | ||||||
|  | @ -1202,17 +1186,17 @@ void DeleteProgram(Service::Interface* self) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     bool success = FileUtil::DeleteDirRecursively(path); |     bool success = FileUtil::DeleteDirRecursively(path); | ||||||
|     ScanForAllTitles(); |     am->ScanForAllTitles(); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     if (!success) |     if (!success) | ||||||
|         LOG_ERROR(Service_AM, "FileUtil::DeleteDirRecursively unexpectedly failed"); |         LOG_ERROR(Service_AM, "FileUtil::DeleteDirRecursively unexpectedly failed"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetMetaSizeFromCia(Service::Interface* self) { | void Module::Interface::GetMetaSizeFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0413, 0, 2); // 0x04130002
 |     IPC::RequestParser rp(ctx, 0x0413, 0, 2); // 0x04130002
 | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|  | @ -1234,31 +1218,30 @@ void GetMetaSizeFromCia(Service::Interface* self) { | ||||||
|     rb.Push(container.GetMetadataSize()); |     rb.Push(container.GetMetadataSize()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void GetMetaDataFromCia(Service::Interface* self) { | void Module::Interface::GetMetaDataFromCia(Kernel::HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x0414, 0, 2); // 0x04140044
 |     IPC::RequestParser rp(ctx, 0x0414, 1, 4); // 0x04140044
 | ||||||
| 
 | 
 | ||||||
|     u32 output_size = rp.Pop<u32>(); |     u32 output_size = rp.Pop<u32>(); | ||||||
|  |     auto cia = rp.PopObject<Kernel::ClientSession>(); | ||||||
|  |     auto& output_buffer = rp.PopMappedBuffer(); | ||||||
| 
 | 
 | ||||||
|     // Get a File from our Handle
 |     auto file_res = GetFileFromSession(cia); | ||||||
|     auto file_res = GetFileFromHandle(rp.PopHandle()); |  | ||||||
|     if (!file_res.Succeeded()) { |     if (!file_res.Succeeded()) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|         rb.Push(file_res.Code()); |         rb.Push(file_res.Code()); | ||||||
|  |         rb.PushMappedBuffer(output_buffer); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     size_t output_buffer_size; |  | ||||||
|     VAddr output_buffer = rp.PeekStaticBuffer(0, &output_buffer_size); |  | ||||||
| 
 |  | ||||||
|     // Don't write beyond the actual static buffer size.
 |     // Don't write beyond the actual static buffer size.
 | ||||||
|     output_size = std::min(static_cast<u32>(output_buffer_size), output_size); |     output_size = std::min(static_cast<u32>(output_buffer.GetSize()), output_size); | ||||||
| 
 | 
 | ||||||
|     auto file = file_res.Unwrap(); |     auto file = file_res.Unwrap(); | ||||||
|     FileSys::CIAContainer container; |     FileSys::CIAContainer container; | ||||||
|     if (container.Load(*file->backend) != Loader::ResultStatus::Success) { |     if (container.Load(*file->backend) != Loader::ResultStatus::Success) { | ||||||
|         IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); |         IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|         rb.Push(ResultCode(ErrCodes::InvalidCIAHeader, ErrorModule::AM, |         rb.Push(ResultCode(ErrCodes::InvalidCIAHeader, ErrorModule::AM, | ||||||
|                            ErrorSummary::InvalidArgument, ErrorLevel::Permanent)); |                            ErrorSummary::InvalidArgument, ErrorLevel::Permanent)); | ||||||
|  |         rb.PushMappedBuffer(output_buffer); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -1272,23 +1255,24 @@ void GetMetaDataFromCia(Service::Interface* self) { | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     Memory::WriteBlock(output_buffer, temp.data(), output_size); |     output_buffer.Write(temp.data(), 0, output_size); | ||||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); |     IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); | ||||||
|     rb.Push(RESULT_SUCCESS); |     rb.Push(RESULT_SUCCESS); | ||||||
|     rb.PushStaticBuffer(output_buffer, output_buffer_size, 0); |     rb.PushMappedBuffer(output_buffer); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Init() { | Module::Module() { | ||||||
|     AddService(new AM_APP_Interface); |  | ||||||
|     AddService(new AM_NET_Interface); |  | ||||||
|     AddService(new AM_SYS_Interface); |  | ||||||
|     AddService(new AM_U_Interface); |  | ||||||
| 
 |  | ||||||
|     ScanForAllTitles(); |     ScanForAllTitles(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void Shutdown() { | Module::~Module() = default; | ||||||
|     cia_installing = false; | 
 | ||||||
|  | void InstallInterfaces(SM::ServiceManager& service_manager) { | ||||||
|  |     auto am = std::make_shared<Module>(); | ||||||
|  |     std::make_shared<AM_APP>(am)->InstallAsService(service_manager); | ||||||
|  |     std::make_shared<AM_NET>(am)->InstallAsService(service_manager); | ||||||
|  |     std::make_shared<AM_SYS>(am)->InstallAsService(service_manager); | ||||||
|  |     std::make_shared<AM_U>(am)->InstallAsService(service_manager); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -4,12 +4,15 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
|  | #include <array> | ||||||
| #include <functional> | #include <functional> | ||||||
| #include <string> | #include <string> | ||||||
|  | #include <vector> | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "core/file_sys/cia_container.h" | #include "core/file_sys/cia_container.h" | ||||||
| #include "core/file_sys/file_backend.h" | #include "core/file_sys/file_backend.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
|  | #include "core/hle/service/service.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace FS { | namespace FS { | ||||||
|  | @ -18,9 +21,6 @@ enum class MediaType : u32; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| 
 |  | ||||||
| class Interface; |  | ||||||
| 
 |  | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| namespace ErrCodes { | namespace ErrCodes { | ||||||
|  | @ -138,360 +138,377 @@ std::string GetTitlePath(Service::FS::MediaType media_type, u64 tid); | ||||||
|  */ |  */ | ||||||
| std::string GetMediaTitlePath(Service::FS::MediaType media_type); | std::string GetMediaTitlePath(Service::FS::MediaType media_type); | ||||||
| 
 | 
 | ||||||
| /**
 | class Module final { | ||||||
|  * Scans the for titles in a storage medium for listing. | public: | ||||||
|  * @param media_type the storage medium to scan |     Module(); | ||||||
|  */ |     ~Module(); | ||||||
| void ScanForTitles(Service::FS::MediaType media_type); |  | ||||||
| 
 | 
 | ||||||
| /**
 |     class Interface : public ServiceFramework<Interface> { | ||||||
|  * Scans all storage mediums for titles for listing. |     public: | ||||||
|  */ |         Interface(std::shared_ptr<Module> am, const char* name, u32 max_session); | ||||||
| void ScanForAllTitles(); |         ~Interface(); | ||||||
| 
 | 
 | ||||||
| /**
 |     protected: | ||||||
|  * AM::GetNumPrograms service function |         /**
 | ||||||
|  * Gets the number of installed titles in the requested media type |          * AM::GetNumPrograms service function | ||||||
|  *  Inputs: |          * Gets the number of installed titles in the requested media type | ||||||
|  *      0 : Command header (0x00010040) |          *  Inputs: | ||||||
|  *      1 : Media type to load the titles from |          *      0 : Command header (0x00010040) | ||||||
|  *  Outputs: |          *      1 : Media type to load the titles from | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *  Outputs: | ||||||
|  *      2 : The number of titles in the requested media type |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          *      2 : The number of titles in the requested media type | ||||||
| void GetNumPrograms(Service::Interface* self); |          */ | ||||||
|  |         void GetNumPrograms(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::FindDLCContentInfos service function |          * AM::FindDLCContentInfos service function | ||||||
|  * Explicitly checks that TID high value is 0004008C or an error is returned. |          * Explicitly checks that TID high value is 0004008C or an error is returned. | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : MediaType |          *      1 : MediaType | ||||||
|  *    2-3 : u64, Title ID |          *    2-3 : u64, Title ID | ||||||
|  *      4 : Content count |          *      4 : Content count | ||||||
|  *      6 : Content IDs pointer |          *      6 : Content IDs pointer | ||||||
|  *      8 : Content Infos pointer |          *      8 : Content Infos pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void FindDLCContentInfos(Service::Interface* self); |         void FindDLCContentInfos(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::ListDLCContentInfos service function |          * AM::ListDLCContentInfos service function | ||||||
|  * Explicitly checks that TID high value is 0004008C or an error is returned. |          * Explicitly checks that TID high value is 0004008C or an error is returned. | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : Content count |          *      1 : Content count | ||||||
|  *      2 : MediaType |          *      2 : MediaType | ||||||
|  *    3-4 : u64, Title ID |          *    3-4 : u64, Title ID | ||||||
|  *      5 : Start Index |          *      5 : Start Index | ||||||
|  *      7 : Content Infos pointer |          *      7 : Content Infos pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Number of content infos returned |          *      2 : Number of content infos returned | ||||||
|  */ |          */ | ||||||
| void ListDLCContentInfos(Service::Interface* self); |         void ListDLCContentInfos(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::DeleteContents service function |          * AM::DeleteContents service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : MediaType |          *      1 : MediaType | ||||||
|  *    2-3 : u64, Title ID |          *    2-3 : u64, Title ID | ||||||
|  *      4 : Content count |          *      4 : Content count | ||||||
|  *      6 : Content IDs pointer |          *      6 : Content IDs pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void DeleteContents(Service::Interface* self); |         void DeleteContents(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetProgramList service function |          * AM::GetProgramList service function | ||||||
|  * Loads information about the desired number of titles from the desired media type into an array |          * Loads information about the desired number of titles from the desired media type into an | ||||||
|  *  Inputs: |          * array | ||||||
|  *      1 : Title count |          *  Inputs: | ||||||
|  *      2 : Media type to load the titles from |          *      1 : Title count | ||||||
|  *      4 : Title IDs output pointer |          *      2 : Media type to load the titles from | ||||||
|  *  Outputs: |          *      4 : Title IDs output pointer | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *  Outputs: | ||||||
|  *      2 : The number of titles loaded from the requested media type |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          *      2 : The number of titles loaded from the requested media type | ||||||
| void GetProgramList(Service::Interface* self); |          */ | ||||||
|  |         void GetProgramList(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetProgramInfos service function |          * AM::GetProgramInfos service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : u8 Mediatype |          *      1 : u8 Mediatype | ||||||
|  *      2 : Total titles |          *      2 : Total titles | ||||||
|  *      4 : TitleIDList pointer |          *      4 : TitleIDList pointer | ||||||
|  *      6 : TitleList pointer |          *      6 : TitleList pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void GetProgramInfos(Service::Interface* self); |         void GetProgramInfos(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::DeleteUserProgram service function |          * AM::DeleteUserProgram service function | ||||||
|  * Deletes a user program |          * Deletes a user program | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : Media Type |          *      1 : Media Type | ||||||
|  *      2-3 : Title ID |          *      2-3 : Title ID | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void DeleteUserProgram(Service::Interface* self); |         void DeleteUserProgram(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetDLCTitleInfos service function |          * AM::GetDLCTitleInfos service function | ||||||
|  * Wrapper for AM::GetProgramInfos, explicitly checks that TID high value is 0004008C. |          * Wrapper for AM::GetProgramInfos, explicitly checks that TID high value is 0004008C. | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : u8 Mediatype |          *      1 : u8 Mediatype | ||||||
|  *      2 : Total titles |          *      2 : Total titles | ||||||
|  *      4 : TitleIDList pointer |          *      4 : TitleIDList pointer | ||||||
|  *      6 : TitleList pointer |          *      6 : TitleList pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void GetDLCTitleInfos(Service::Interface* self); |         void GetDLCTitleInfos(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetPatchTitleInfos service function |          * AM::GetPatchTitleInfos service function | ||||||
|  * Wrapper for AM::GetProgramInfos, explicitly checks that TID high value is 0004000E. |          * Wrapper for AM::GetProgramInfos, explicitly checks that TID high value is 0004000E. | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : u8 Mediatype |          *      1 : u8 Mediatype | ||||||
|  *      2 : Total titles |          *      2 : Total titles | ||||||
|  *      4 : TitleIDList input pointer |          *      4 : TitleIDList input pointer | ||||||
|  *      6 : TitleList output pointer |          *      6 : TitleList output pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : TitleIDList input pointer |          *      2 : TitleIDList input pointer | ||||||
|  *      4 : TitleList output pointer |          *      4 : TitleList output pointer | ||||||
|  */ |          */ | ||||||
| void GetPatchTitleInfos(Service::Interface* self); |         void GetPatchTitleInfos(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::ListDataTitleTicketInfos service function |          * AM::ListDataTitleTicketInfos service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : Ticket count |          *      1 : Ticket count | ||||||
|  *    2-3 : u64, Title ID |          *    2-3 : u64, Title ID | ||||||
|  *      4 : Start Index? |          *      4 : Start Index? | ||||||
|  *      5 : (TicketCount * 24) << 8 | 0x4 |          *      5 : (TicketCount * 24) << 8 | 0x4 | ||||||
|  *      6 : Ticket Infos pointer |          *      6 : Ticket Infos pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Number of ticket infos returned |          *      2 : Number of ticket infos returned | ||||||
|  */ |          */ | ||||||
| void ListDataTitleTicketInfos(Service::Interface* self); |         void ListDataTitleTicketInfos(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetDLCContentInfoCount service function |          * AM::GetDLCContentInfoCount service function | ||||||
|  * Explicitly checks that TID high value is 0004008C or an error is returned. |          * Explicitly checks that TID high value is 0004008C or an error is returned. | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x100100C0) |          *      0 : Command header (0x100100C0) | ||||||
|  *      1 : MediaType |          *      1 : MediaType | ||||||
|  *    2-3 : u64, Title ID |          *    2-3 : u64, Title ID | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Number of content infos plus one |          *      2 : Number of content infos plus one | ||||||
|  */ |          */ | ||||||
| void GetDLCContentInfoCount(Service::Interface* self); |         void GetDLCContentInfoCount(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::DeleteTicket service function |          * AM::DeleteTicket service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *    1-2 : u64, Title ID |          *    1-2 : u64, Title ID | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void DeleteTicket(Service::Interface* self); |         void DeleteTicket(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetNumTickets service function |          * AM::GetNumTickets service function | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Number of tickets |          *      2 : Number of tickets | ||||||
|  */ |          */ | ||||||
| void GetNumTickets(Service::Interface* self); |         void GetNumTickets(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetTicketList service function |          * AM::GetTicketList service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : Number of TicketList |          *      1 : Number of TicketList | ||||||
|  *      2 : Number to skip |          *      2 : Number to skip | ||||||
|  *      4 : TicketList pointer |          *      4 : TicketList pointer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Total TicketList |          *      2 : Total TicketList | ||||||
|  */ |          */ | ||||||
| void GetTicketList(Service::Interface* self); |         void GetTicketList(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::QueryAvailableTitleDatabase service function |          * AM::QueryAvailableTitleDatabase service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1 : Media Type |          *      1 : Media Type | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Boolean, database availability |          *      2 : Boolean, database availability | ||||||
|  */ |          */ | ||||||
| void QueryAvailableTitleDatabase(Service::Interface* self); |         void QueryAvailableTitleDatabase(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::CheckContentRights service function |          * AM::CheckContentRights service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1-2 : Title ID |          *      1-2 : Title ID | ||||||
|  *      3 : Content Index |          *      3 : Content Index | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Boolean, whether we have rights to this content |          *      2 : Boolean, whether we have rights to this content | ||||||
|  */ |          */ | ||||||
| void CheckContentRights(Service::Interface* self); |         void CheckContentRights(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::CheckContentRightsIgnorePlatform service function |          * AM::CheckContentRightsIgnorePlatform service function | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      1-2 : Title ID |          *      1-2 : Title ID | ||||||
|  *      3 : Content Index |          *      3 : Content Index | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Boolean, whether we have rights to this content |          *      2 : Boolean, whether we have rights to this content | ||||||
|  */ |          */ | ||||||
| void CheckContentRightsIgnorePlatform(Service::Interface* self); |         void CheckContentRightsIgnorePlatform(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::BeginImportProgram service function |          * AM::BeginImportProgram service function | ||||||
|  * Begin importing from a CTR Installable Archive |          * Begin importing from a CTR Installable Archive | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x04020040) |          *      0 : Command header (0x04020040) | ||||||
|  *      1 : Media type to install title to |          *      1 : Media type to install title to | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2-3 : CIAFile handle for application to write to |          *      2-3 : CIAFile handle for application to write to | ||||||
|  */ |          */ | ||||||
| void BeginImportProgram(Service::Interface* self); |         void BeginImportProgram(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::EndImportProgram service function |          * AM::EndImportProgram service function | ||||||
|  * Finish importing from a CTR Installable Archive |          * Finish importing from a CTR Installable Archive | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x04050002) |          *      0 : Command header (0x04050002) | ||||||
|  *      1-2 : CIAFile handle application wrote to |          *      1-2 : CIAFile handle application wrote to | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void EndImportProgram(Service::Interface* self); |         void EndImportProgram(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetProgramInfoFromCia service function |          * AM::GetProgramInfoFromCia service function | ||||||
|  * Get TitleInfo from a CIA file handle |          * Get TitleInfo from a CIA file handle | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x04080042) |          *      0 : Command header (0x04080042) | ||||||
|  *      1 : Media type of the title |          *      1 : Media type of the title | ||||||
|  *      2-3 : File handle CIA data can be read from |          *      2-3 : File handle CIA data can be read from | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2-8: TitleInfo structure |          *      2-8: TitleInfo structure | ||||||
|  */ |          */ | ||||||
| void GetProgramInfoFromCia(Service::Interface* self); |         void GetProgramInfoFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetSystemMenuDataFromCia service function |          * AM::GetSystemMenuDataFromCia service function | ||||||
|  * Loads a CIA file's SMDH data into a specified buffer |          * Loads a CIA file's SMDH data into a specified buffer | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x04090004) |          *      0 : Command header (0x04090004) | ||||||
|  *      1-2 : File handle CIA data can be read from |          *      1-2 : File handle CIA data can be read from | ||||||
|  *      3-4 : Output buffer |          *      3-4 : Output buffer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void GetSystemMenuDataFromCia(Service::Interface* self); |         void GetSystemMenuDataFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetDependencyListFromCia service function |          * AM::GetDependencyListFromCia service function | ||||||
|  * Loads a CIA's dependency list into a specified buffer |          * Loads a CIA's dependency list into a specified buffer | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x040A0002) |          *      0 : Command header (0x040A0002) | ||||||
|  *      1-2 : File handle CIA data can be read from |          *      1-2 : File handle CIA data can be read from | ||||||
|  *      64-65 : Output buffer |          *      64-65 : Output buffer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void GetDependencyListFromCia(Service::Interface* self); |         void GetDependencyListFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetTransferSizeFromCia service function |          * AM::GetTransferSizeFromCia service function | ||||||
|  * Returns the total expected transfer size up to the CIA meta offset from a CIA |          * Returns the total expected transfer size up to the CIA meta offset from a CIA | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x040B0002) |          *      0 : Command header (0x040B0002) | ||||||
|  *      1-2 : File handle CIA data can be read from |          *      1-2 : File handle CIA data can be read from | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2-3 : Transfer size |          *      2-3 : Transfer size | ||||||
|  */ |          */ | ||||||
| void GetTransferSizeFromCia(Service::Interface* self); |         void GetTransferSizeFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetCoreVersionFromCia service function |          * AM::GetCoreVersionFromCia service function | ||||||
|  * Returns the core version from a CIA |          * Returns the core version from a CIA | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x040C0002) |          *      0 : Command header (0x040C0002) | ||||||
|  *      1-2 : File handle CIA data can be read from |          *      1-2 : File handle CIA data can be read from | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Core version |          *      2 : Core version | ||||||
|  */ |          */ | ||||||
| void GetCoreVersionFromCia(Service::Interface* self); |         void GetCoreVersionFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetRequiredSizeFromCia service function |          * AM::GetRequiredSizeFromCia service function | ||||||
|  * Returns the required amount of free space required to install a given CIA file |          * Returns the required amount of free space required to install a given CIA file | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x040D0042) |          *      0 : Command header (0x040D0042) | ||||||
|  *      1 : Media type to install title to |          *      1 : Media type to install title to | ||||||
|  *      2-3 : File handle CIA data can be read from |          *      2-3 : File handle CIA data can be read from | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2-3 : Required free space for CIA |          *      2-3 : Required free space for CIA | ||||||
|  */ |          */ | ||||||
| void GetRequiredSizeFromCia(Service::Interface* self); |         void GetRequiredSizeFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::DeleteProgram service function |          * AM::DeleteProgram service function | ||||||
|  * Deletes a program |          * Deletes a program | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x041000C0) |          *      0 : Command header (0x041000C0) | ||||||
|  *      1 : Media type |          *      1 : Media type | ||||||
|  *      2-3 : Title ID |          *      2-3 : Title ID | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void DeleteProgram(Service::Interface* self); |         void DeleteProgram(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetMetaSizeFromCia service function |          * AM::GetMetaSizeFromCia service function | ||||||
|  * Returns the size of a given CIA's meta section |          * Returns the size of a given CIA's meta section | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x04130002) |          *      0 : Command header (0x04130002) | ||||||
|  *      1-2 : File handle CIA data can be read from |          *      1-2 : File handle CIA data can be read from | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  *      2 : Meta section size |          *      2 : Meta section size | ||||||
|  */ |          */ | ||||||
| void GetMetaSizeFromCia(Service::Interface* self); |         void GetMetaSizeFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /**
 |         /**
 | ||||||
|  * AM::GetMetaDataFromCia service function |          * AM::GetMetaDataFromCia service function | ||||||
|  * Loads meta section data from a CIA file into a given buffer |          * Loads meta section data from a CIA file into a given buffer | ||||||
|  *  Inputs: |          *  Inputs: | ||||||
|  *      0 : Command header (0x04140044) |          *      0 : Command header (0x04140044) | ||||||
|  *      1-2 : File handle CIA data can be read from |          *      1-2 : File handle CIA data can be read from | ||||||
|  *      3-4 : Output buffer |          *      3-4 : Output buffer | ||||||
|  *  Outputs: |          *  Outputs: | ||||||
|  *      1 : Result, 0 on success, otherwise error code |          *      1 : Result, 0 on success, otherwise error code | ||||||
|  */ |          */ | ||||||
| void GetMetaDataFromCia(Service::Interface* self); |         void GetMetaDataFromCia(Kernel::HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
| /// Initialize AM service
 |     private: | ||||||
| void Init(); |         std::shared_ptr<Module> am; | ||||||
|  |     }; | ||||||
| 
 | 
 | ||||||
| /// Shutdown AM service
 | private: | ||||||
| void Shutdown(); |     /**
 | ||||||
|  |      * Scans the for titles in a storage medium for listing. | ||||||
|  |      * @param media_type the storage medium to scan | ||||||
|  |      */ | ||||||
|  |     void ScanForTitles(Service::FS::MediaType media_type); | ||||||
|  | 
 | ||||||
|  |     /**
 | ||||||
|  |      * Scans all storage mediums for titles for listing. | ||||||
|  |      */ | ||||||
|  |     void ScanForAllTitles(); | ||||||
|  | 
 | ||||||
|  |     bool cia_installing = false; | ||||||
|  |     std::array<std::vector<u64_le>, 3> am_title_list; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | void InstallInterfaces(SM::ServiceManager& service_manager); | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
| } // namespace Service
 | } // namespace Service
 | ||||||
|  |  | ||||||
|  | @ -2,30 +2,28 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/am/am.h" |  | ||||||
| #include "core/hle/service/am/am_app.h" | #include "core/hle/service/am/am_app.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | AM_APP::AM_APP(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:app", 5) { | ||||||
|     {0x100100C0, GetDLCContentInfoCount, "GetDLCContentInfoCount"}, |     static const FunctionInfo functions[] = { | ||||||
|     {0x10020104, FindDLCContentInfos, "FindDLCContentInfos"}, |         {0x100100C0, &AM_APP::GetDLCContentInfoCount, "GetDLCContentInfoCount"}, | ||||||
|     {0x10030142, ListDLCContentInfos, "ListDLCContentInfos"}, |         {0x10020104, &AM_APP::FindDLCContentInfos, "FindDLCContentInfos"}, | ||||||
|     {0x10040102, DeleteContents, "DeleteContents"}, |         {0x10030142, &AM_APP::ListDLCContentInfos, "ListDLCContentInfos"}, | ||||||
|     {0x10050084, GetDLCTitleInfos, "GetDLCTitleInfos"}, |         {0x10040102, &AM_APP::DeleteContents, "DeleteContents"}, | ||||||
|     {0x10060080, nullptr, "GetNumDataTitleTickets"}, |         {0x10050084, &AM_APP::GetDLCTitleInfos, "GetDLCTitleInfos"}, | ||||||
|     {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, |         {0x10060080, nullptr, "GetNumDataTitleTickets"}, | ||||||
|     {0x100801C2, nullptr, "GetItemRights"}, |         {0x10070102, &AM_APP::ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, | ||||||
|     {0x100900C0, nullptr, "IsDataTitleInUse"}, |         {0x100801C2, nullptr, "GetItemRights"}, | ||||||
|     {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, |         {0x100900C0, nullptr, "IsDataTitleInUse"}, | ||||||
|     {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, |         {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, | ||||||
|     {0x100C0142, nullptr, "ListExistingContentInfos"}, |         {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, | ||||||
|     {0x100D0084, GetPatchTitleInfos, "GetPatchTitleInfos"}, |         {0x100C0142, nullptr, "ListExistingContentInfos"}, | ||||||
| }; |         {0x100D0084, &AM_APP::GetPatchTitleInfos, "GetPatchTitleInfos"}, | ||||||
| 
 |     }; | ||||||
| AM_APP_Interface::AM_APP_Interface() { |     RegisterHandlers(functions); | ||||||
|     Register(FunctionTable); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -4,18 +4,14 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/am/am.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| class AM_APP_Interface : public Service::Interface { | class AM_APP final : public Module::Interface { | ||||||
| public: | public: | ||||||
|     AM_APP_Interface(); |     explicit AM_APP(std::shared_ptr<Module> am); | ||||||
| 
 |  | ||||||
|     std::string GetPortName() const override { |  | ||||||
|         return "am:app"; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -2,127 +2,125 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/am/am.h" |  | ||||||
| #include "core/hle/service/am/am_net.h" | #include "core/hle/service/am/am_net.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | AM_NET::AM_NET(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:net", 5) { | ||||||
|     {0x00010040, GetNumPrograms, "GetNumPrograms"}, |     static const FunctionInfo functions[] = { | ||||||
|     {0x00020082, GetProgramList, "GetProgramList"}, |         {0x00010040, &AM_NET::GetNumPrograms, "GetNumPrograms"}, | ||||||
|     {0x00030084, GetProgramInfos, "GetProgramInfos"}, |         {0x00020082, &AM_NET::GetProgramList, "GetProgramList"}, | ||||||
|     {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, |         {0x00030084, &AM_NET::GetProgramInfos, "GetProgramInfos"}, | ||||||
|     {0x000500C0, nullptr, "GetProductCode"}, |         {0x000400C0, &AM_NET::DeleteUserProgram, "DeleteUserProgram"}, | ||||||
|     {0x000600C0, nullptr, "GetStorageId"}, |         {0x000500C0, nullptr, "GetProductCode"}, | ||||||
|     {0x00070080, DeleteTicket, "DeleteTicket"}, |         {0x000600C0, nullptr, "GetStorageId"}, | ||||||
|     {0x00080000, GetNumTickets, "GetNumTickets"}, |         {0x00070080, &AM_NET::DeleteTicket, "DeleteTicket"}, | ||||||
|     {0x00090082, GetTicketList, "GetTicketList"}, |         {0x00080000, &AM_NET::GetNumTickets, "GetNumTickets"}, | ||||||
|     {0x000A0000, nullptr, "GetDeviceID"}, |         {0x00090082, &AM_NET::GetTicketList, "GetTicketList"}, | ||||||
|     {0x000B0040, nullptr, "GetNumImportTitleContexts"}, |         {0x000A0000, nullptr, "GetDeviceID"}, | ||||||
|     {0x000C0082, nullptr, "GetImportTitleContextList"}, |         {0x000B0040, nullptr, "GetNumImportTitleContexts"}, | ||||||
|     {0x000D0084, nullptr, "GetImportTitleContexts"}, |         {0x000C0082, nullptr, "GetImportTitleContextList"}, | ||||||
|     {0x000E00C0, nullptr, "DeleteImportTitleContext"}, |         {0x000D0084, nullptr, "GetImportTitleContexts"}, | ||||||
|     {0x000F00C0, nullptr, "GetNumImportContentContexts"}, |         {0x000E00C0, nullptr, "DeleteImportTitleContext"}, | ||||||
|     {0x00100102, nullptr, "GetImportContentContextList"}, |         {0x000F00C0, nullptr, "GetNumImportContentContexts"}, | ||||||
|     {0x00110104, nullptr, "GetImportContentContexts"}, |         {0x00100102, nullptr, "GetImportContentContextList"}, | ||||||
|     {0x00120102, nullptr, "DeleteImportContentContexts"}, |         {0x00110104, nullptr, "GetImportContentContexts"}, | ||||||
|     {0x00130040, nullptr, "NeedsCleanup"}, |         {0x00120102, nullptr, "DeleteImportContentContexts"}, | ||||||
|     {0x00140040, nullptr, "DoCleanup"}, |         {0x00130040, nullptr, "NeedsCleanup"}, | ||||||
|     {0x00150040, nullptr, "DeleteAllImportContexts"}, |         {0x00140040, nullptr, "DoCleanup"}, | ||||||
|     {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, |         {0x00150040, nullptr, "DeleteAllImportContexts"}, | ||||||
|     {0x00170044, nullptr, "ImportTwlBackupLegacy"}, |         {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, | ||||||
|     {0x00180080, nullptr, "InitializeTitleDatabase"}, |         {0x00170044, nullptr, "ImportTwlBackupLegacy"}, | ||||||
|     {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, |         {0x00180080, nullptr, "InitializeTitleDatabase"}, | ||||||
|     {0x001A00C0, nullptr, "CalcTwlBackupSize"}, |         {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, | ||||||
|     {0x001B0144, nullptr, "ExportTwlBackup"}, |         {0x001A00C0, nullptr, "CalcTwlBackupSize"}, | ||||||
|     {0x001C0084, nullptr, "ImportTwlBackup"}, |         {0x001B0144, nullptr, "ExportTwlBackup"}, | ||||||
|     {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, |         {0x001C0084, nullptr, "ImportTwlBackup"}, | ||||||
|     {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, |         {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, | ||||||
|     {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, |         {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, | ||||||
|     {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, |         {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, | ||||||
|     {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, |         {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, | ||||||
|     {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, |         {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, | ||||||
|     {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, |         {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, | ||||||
|     {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, |         {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, | ||||||
|     {0x002500C0, nullptr, "CheckContentRights"}, |         {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, | ||||||
|     {0x00260044, nullptr, "GetTicketLimitInfos"}, |         {0x002500C0, nullptr, "CheckContentRights"}, | ||||||
|     {0x00270044, nullptr, "GetDemoLaunchInfos"}, |         {0x00260044, nullptr, "GetTicketLimitInfos"}, | ||||||
|     {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, |         {0x00270044, nullptr, "GetDemoLaunchInfos"}, | ||||||
|     {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, |         {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, | ||||||
|     {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, |         {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, | ||||||
|     {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, |         {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, | ||||||
|     {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, |         {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, | ||||||
|     {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, |         {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, | ||||||
|     {0x04010080, nullptr, "UpdateFirmwareTo"}, |         {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, | ||||||
|     {0x04020040, BeginImportProgram, "BeginImportProgram"}, |         {0x04010080, nullptr, "UpdateFirmwareTo"}, | ||||||
|     {0x04030000, nullptr, "BeginImportProgramTemporarily"}, |         {0x04020040, &AM_NET::BeginImportProgram, "BeginImportProgram"}, | ||||||
|     {0x04040002, nullptr, "CancelImportProgram"}, |         {0x04030000, nullptr, "BeginImportProgramTemporarily"}, | ||||||
|     {0x04050002, EndImportProgram, "EndImportProgram"}, |         {0x04040002, nullptr, "CancelImportProgram"}, | ||||||
|     {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, |         {0x04050002, &AM_NET::EndImportProgram, "EndImportProgram"}, | ||||||
|     {0x040700C2, nullptr, "CommitImportPrograms"}, |         {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, | ||||||
|     {0x04080042, GetProgramInfoFromCia, "GetProgramInfoFromCia"}, |         {0x040700C2, nullptr, "CommitImportPrograms"}, | ||||||
|     {0x04090004, GetSystemMenuDataFromCia, "GetSystemMenuDataFromCia"}, |         {0x04080042, &AM_NET::GetProgramInfoFromCia, "GetProgramInfoFromCia"}, | ||||||
|     {0x040A0002, GetDependencyListFromCia, "GetDependencyListFromCia"}, |         {0x04090004, &AM_NET::GetSystemMenuDataFromCia, "GetSystemMenuDataFromCia"}, | ||||||
|     {0x040B0002, GetTransferSizeFromCia, "GetTransferSizeFromCia"}, |         {0x040A0002, &AM_NET::GetDependencyListFromCia, "GetDependencyListFromCia"}, | ||||||
|     {0x040C0002, GetCoreVersionFromCia, "GetCoreVersionFromCia"}, |         {0x040B0002, &AM_NET::GetTransferSizeFromCia, "GetTransferSizeFromCia"}, | ||||||
|     {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, |         {0x040C0002, &AM_NET::GetCoreVersionFromCia, "GetCoreVersionFromCia"}, | ||||||
|     {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, |         {0x040D0042, &AM_NET::GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, | ||||||
|     {0x040F0000, nullptr, "UpdateFirmwareAuto"}, |         {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, | ||||||
|     {0x041000C0, DeleteProgram, "DeleteProgram"}, |         {0x040F0000, nullptr, "UpdateFirmwareAuto"}, | ||||||
|     {0x04110044, nullptr, "GetTwlProgramListForReboot"}, |         {0x041000C0, &AM_NET::DeleteProgram, "DeleteProgram"}, | ||||||
|     {0x04120000, nullptr, "GetSystemUpdaterMutex"}, |         {0x04110044, nullptr, "GetTwlProgramListForReboot"}, | ||||||
|     {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"}, |         {0x04120000, nullptr, "GetSystemUpdaterMutex"}, | ||||||
|     {0x04140044, GetMetaDataFromCia, "GetMetaDataFromCia"}, |         {0x04130002, &AM_NET::GetMetaSizeFromCia, "GetMetaSizeFromCia"}, | ||||||
|     {0x04150080, nullptr, "CheckDemoLaunchRights"}, |         {0x04140044, &AM_NET::GetMetaDataFromCia, "GetMetaDataFromCia"}, | ||||||
|     {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, |         {0x04150080, nullptr, "CheckDemoLaunchRights"}, | ||||||
|     {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, |         {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, | ||||||
|     {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, |         {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, | ||||||
|     {0x04190000, nullptr, "BeginImportSystemProgram"}, |         {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, | ||||||
|     {0x08010000, nullptr, "BeginImportTicket"}, |         {0x04190000, nullptr, "BeginImportSystemProgram"}, | ||||||
|     {0x08020002, nullptr, "CancelImportTicket"}, |         {0x08010000, nullptr, "BeginImportTicket"}, | ||||||
|     {0x08030002, nullptr, "EndImportTicket"}, |         {0x08020002, nullptr, "CancelImportTicket"}, | ||||||
|     {0x08040100, nullptr, "BeginImportTitle"}, |         {0x08030002, nullptr, "EndImportTicket"}, | ||||||
|     {0x08050000, nullptr, "StopImportTitle"}, |         {0x08040100, nullptr, "BeginImportTitle"}, | ||||||
|     {0x080600C0, nullptr, "ResumeImportTitle"}, |         {0x08050000, nullptr, "StopImportTitle"}, | ||||||
|     {0x08070000, nullptr, "CancelImportTitle"}, |         {0x080600C0, nullptr, "ResumeImportTitle"}, | ||||||
|     {0x08080000, nullptr, "EndImportTitle"}, |         {0x08070000, nullptr, "CancelImportTitle"}, | ||||||
|     {0x080900C2, nullptr, "CommitImportTitles"}, |         {0x08080000, nullptr, "EndImportTitle"}, | ||||||
|     {0x080A0000, nullptr, "BeginImportTmd"}, |         {0x080900C2, nullptr, "CommitImportTitles"}, | ||||||
|     {0x080B0002, nullptr, "CancelImportTmd"}, |         {0x080A0000, nullptr, "BeginImportTmd"}, | ||||||
|     {0x080C0042, nullptr, "EndImportTmd"}, |         {0x080B0002, nullptr, "CancelImportTmd"}, | ||||||
|     {0x080D0042, nullptr, "CreateImportContentContexts"}, |         {0x080C0042, nullptr, "EndImportTmd"}, | ||||||
|     {0x080E0040, nullptr, "BeginImportContent"}, |         {0x080D0042, nullptr, "CreateImportContentContexts"}, | ||||||
|     {0x080F0002, nullptr, "StopImportContent"}, |         {0x080E0040, nullptr, "BeginImportContent"}, | ||||||
|     {0x08100040, nullptr, "ResumeImportContent"}, |         {0x080F0002, nullptr, "StopImportContent"}, | ||||||
|     {0x08110002, nullptr, "CancelImportContent"}, |         {0x08100040, nullptr, "ResumeImportContent"}, | ||||||
|     {0x08120002, nullptr, "EndImportContent"}, |         {0x08110002, nullptr, "CancelImportContent"}, | ||||||
|     {0x08130000, nullptr, "GetNumCurrentImportContentContexts"}, |         {0x08120002, nullptr, "EndImportContent"}, | ||||||
|     {0x08140042, nullptr, "GetCurrentImportContentContextList"}, |         {0x08130000, nullptr, "GetNumCurrentImportContentContexts"}, | ||||||
|     {0x08150044, nullptr, "GetCurrentImportContentContexts"}, |         {0x08140042, nullptr, "GetCurrentImportContentContextList"}, | ||||||
|     {0x08160146, nullptr, "Sign"}, |         {0x08150044, nullptr, "GetCurrentImportContentContexts"}, | ||||||
|     {0x08170146, nullptr, "Verify"}, |         {0x08160146, nullptr, "Sign"}, | ||||||
|     {0x08180042, nullptr, "GetDeviceCert"}, |         {0x08170146, nullptr, "Verify"}, | ||||||
|     {0x08190108, nullptr, "ImportCertificates"}, |         {0x08180042, nullptr, "GetDeviceCert"}, | ||||||
|     {0x081A0042, nullptr, "ImportCertificate"}, |         {0x08190108, nullptr, "ImportCertificates"}, | ||||||
|     {0x081B00C2, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"}, |         {0x081A0042, nullptr, "ImportCertificate"}, | ||||||
|     {0x081C0100, nullptr, "DeleteTicketId"}, |         {0x081B00C2, nullptr, "CommitImportTitlesAndUpdateFirmwareAuto"}, | ||||||
|     {0x081D0080, nullptr, "GetNumTicketIds"}, |         {0x081C0100, nullptr, "DeleteTicketId"}, | ||||||
|     {0x081E0102, nullptr, "GetTicketIdList"}, |         {0x081D0080, nullptr, "GetNumTicketIds"}, | ||||||
|     {0x081F0080, nullptr, "GetNumTicketsOfProgram"}, |         {0x081E0102, nullptr, "GetTicketIdList"}, | ||||||
|     {0x08200102, nullptr, "ListTicketInfos"}, |         {0x081F0080, nullptr, "GetNumTicketsOfProgram"}, | ||||||
|     {0x08210142, nullptr, "GetRightsOnlyTicketData"}, |         {0x08200102, nullptr, "ListTicketInfos"}, | ||||||
|     {0x08220000, nullptr, "GetNumCurrentContentInfos"}, |         {0x08210142, nullptr, "GetRightsOnlyTicketData"}, | ||||||
|     {0x08230044, nullptr, "FindCurrentContentInfos"}, |         {0x08220000, nullptr, "GetNumCurrentContentInfos"}, | ||||||
|     {0x08240082, nullptr, "ListCurrentContentInfos"}, |         {0x08230044, nullptr, "FindCurrentContentInfos"}, | ||||||
|     {0x08250102, nullptr, "CalculateContextRequiredSize"}, |         {0x08240082, nullptr, "ListCurrentContentInfos"}, | ||||||
|     {0x08260042, nullptr, "UpdateImportContentContexts"}, |         {0x08250102, nullptr, "CalculateContextRequiredSize"}, | ||||||
|     {0x08270000, nullptr, "DeleteAllDemoLaunchInfos"}, |         {0x08260042, nullptr, "UpdateImportContentContexts"}, | ||||||
|     {0x082800C0, nullptr, "BeginImportTitleForOverWrite"}, |         {0x08270000, nullptr, "DeleteAllDemoLaunchInfos"}, | ||||||
| }; |         {0x082800C0, nullptr, "BeginImportTitleForOverWrite"}, | ||||||
| 
 |     }; | ||||||
| AM_NET_Interface::AM_NET_Interface() { |     RegisterHandlers(functions); | ||||||
|     Register(FunctionTable); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -4,18 +4,14 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/am/am.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| class AM_NET_Interface : public Service::Interface { | class AM_NET final : public Module::Interface { | ||||||
| public: | public: | ||||||
|     AM_NET_Interface(); |     explicit AM_NET(std::shared_ptr<Module> am); | ||||||
| 
 |  | ||||||
|     std::string GetPortName() const override { |  | ||||||
|         return "am:net"; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -2,75 +2,73 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/am/am.h" |  | ||||||
| #include "core/hle/service/am/am_sys.h" | #include "core/hle/service/am/am_sys.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | AM_SYS::AM_SYS(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:sys", 5) { | ||||||
|     {0x00010040, GetNumPrograms, "GetNumPrograms"}, |     static const FunctionInfo functions[] = { | ||||||
|     {0x00020082, GetProgramList, "GetProgramList"}, |         {0x00010040, &AM_SYS::GetNumPrograms, "GetNumPrograms"}, | ||||||
|     {0x00030084, GetProgramInfos, "GetProgramInfos"}, |         {0x00020082, &AM_SYS::GetProgramList, "GetProgramList"}, | ||||||
|     {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, |         {0x00030084, &AM_SYS::GetProgramInfos, "GetProgramInfos"}, | ||||||
|     {0x000500C0, nullptr, "GetProductCode"}, |         {0x000400C0, &AM_SYS::DeleteUserProgram, "DeleteUserProgram"}, | ||||||
|     {0x000600C0, nullptr, "GetStorageId"}, |         {0x000500C0, nullptr, "GetProductCode"}, | ||||||
|     {0x00070080, DeleteTicket, "DeleteTicket"}, |         {0x000600C0, nullptr, "GetStorageId"}, | ||||||
|     {0x00080000, GetNumTickets, "GetNumTickets"}, |         {0x00070080, &AM_SYS::DeleteTicket, "DeleteTicket"}, | ||||||
|     {0x00090082, GetTicketList, "GetTicketList"}, |         {0x00080000, &AM_SYS::GetNumTickets, "GetNumTickets"}, | ||||||
|     {0x000A0000, nullptr, "GetDeviceID"}, |         {0x00090082, &AM_SYS::GetTicketList, "GetTicketList"}, | ||||||
|     {0x000B0040, nullptr, "GetNumImportTitleContexts"}, |         {0x000A0000, nullptr, "GetDeviceID"}, | ||||||
|     {0x000C0082, nullptr, "GetImportTitleContextList"}, |         {0x000B0040, nullptr, "GetNumImportTitleContexts"}, | ||||||
|     {0x000D0084, nullptr, "GetImportTitleContexts"}, |         {0x000C0082, nullptr, "GetImportTitleContextList"}, | ||||||
|     {0x000E00C0, nullptr, "DeleteImportTitleContext"}, |         {0x000D0084, nullptr, "GetImportTitleContexts"}, | ||||||
|     {0x000F00C0, nullptr, "GetNumImportContentContexts"}, |         {0x000E00C0, nullptr, "DeleteImportTitleContext"}, | ||||||
|     {0x00100102, nullptr, "GetImportContentContextList"}, |         {0x000F00C0, nullptr, "GetNumImportContentContexts"}, | ||||||
|     {0x00110104, nullptr, "GetImportContentContexts"}, |         {0x00100102, nullptr, "GetImportContentContextList"}, | ||||||
|     {0x00120102, nullptr, "DeleteImportContentContexts"}, |         {0x00110104, nullptr, "GetImportContentContexts"}, | ||||||
|     {0x00130040, nullptr, "NeedsCleanup"}, |         {0x00120102, nullptr, "DeleteImportContentContexts"}, | ||||||
|     {0x00140040, nullptr, "DoCleanup"}, |         {0x00130040, nullptr, "NeedsCleanup"}, | ||||||
|     {0x00150040, nullptr, "DeleteAllImportContexts"}, |         {0x00140040, nullptr, "DoCleanup"}, | ||||||
|     {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, |         {0x00150040, nullptr, "DeleteAllImportContexts"}, | ||||||
|     {0x00170044, nullptr, "ImportTwlBackupLegacy"}, |         {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, | ||||||
|     {0x00180080, nullptr, "InitializeTitleDatabase"}, |         {0x00170044, nullptr, "ImportTwlBackupLegacy"}, | ||||||
|     {0x00190040, QueryAvailableTitleDatabase, "QueryAvailableTitleDatabase"}, |         {0x00180080, nullptr, "InitializeTitleDatabase"}, | ||||||
|     {0x001A00C0, nullptr, "CalcTwlBackupSize"}, |         {0x00190040, &AM_SYS::QueryAvailableTitleDatabase, "QueryAvailableTitleDatabase"}, | ||||||
|     {0x001B0144, nullptr, "ExportTwlBackup"}, |         {0x001A00C0, nullptr, "CalcTwlBackupSize"}, | ||||||
|     {0x001C0084, nullptr, "ImportTwlBackup"}, |         {0x001B0144, nullptr, "ExportTwlBackup"}, | ||||||
|     {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, |         {0x001C0084, nullptr, "ImportTwlBackup"}, | ||||||
|     {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, |         {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, | ||||||
|     {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, |         {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, | ||||||
|     {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, |         {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, | ||||||
|     {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, |         {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, | ||||||
|     {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, |         {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, | ||||||
|     {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, |         {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, | ||||||
|     {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, |         {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, | ||||||
|     {0x002500C0, CheckContentRights, "CheckContentRights"}, |         {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, | ||||||
|     {0x00260044, nullptr, "GetTicketLimitInfos"}, |         {0x002500C0, &AM_SYS::CheckContentRights, "CheckContentRights"}, | ||||||
|     {0x00270044, nullptr, "GetDemoLaunchInfos"}, |         {0x00260044, nullptr, "GetTicketLimitInfos"}, | ||||||
|     {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, |         {0x00270044, nullptr, "GetDemoLaunchInfos"}, | ||||||
|     {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, |         {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, | ||||||
|     {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, |         {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, | ||||||
|     {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, |         {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, | ||||||
|     {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, |         {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, | ||||||
|     {0x002D00C0, CheckContentRightsIgnorePlatform, "CheckContentRightsIgnorePlatform"}, |         {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, | ||||||
|     {0x100100C0, GetDLCContentInfoCount, "GetDLCContentInfoCount"}, |         {0x002D00C0, &AM_SYS::CheckContentRightsIgnorePlatform, "CheckContentRightsIgnorePlatform"}, | ||||||
|     {0x10020104, FindDLCContentInfos, "FindDLCContentInfos"}, |         {0x100100C0, &AM_SYS::GetDLCContentInfoCount, "GetDLCContentInfoCount"}, | ||||||
|     {0x10030142, ListDLCContentInfos, "ListDLCContentInfos"}, |         {0x10020104, &AM_SYS::FindDLCContentInfos, "FindDLCContentInfos"}, | ||||||
|     {0x10040102, DeleteContents, "DeleteContents"}, |         {0x10030142, &AM_SYS::ListDLCContentInfos, "ListDLCContentInfos"}, | ||||||
|     {0x10050084, GetDLCTitleInfos, "GetDLCTitleInfos"}, |         {0x10040102, &AM_SYS::DeleteContents, "DeleteContents"}, | ||||||
|     {0x10060080, nullptr, "GetNumDataTitleTickets"}, |         {0x10050084, &AM_SYS::GetDLCTitleInfos, "GetDLCTitleInfos"}, | ||||||
|     {0x10070102, ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, |         {0x10060080, nullptr, "GetNumDataTitleTickets"}, | ||||||
|     {0x100801C2, nullptr, "GetItemRights"}, |         {0x10070102, &AM_SYS::ListDataTitleTicketInfos, "ListDataTitleTicketInfos"}, | ||||||
|     {0x100900C0, nullptr, "IsDataTitleInUse"}, |         {0x100801C2, nullptr, "GetItemRights"}, | ||||||
|     {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, |         {0x100900C0, nullptr, "IsDataTitleInUse"}, | ||||||
|     {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, |         {0x100A0000, nullptr, "IsExternalTitleDatabaseInitialized"}, | ||||||
|     {0x100C0142, nullptr, "ListExistingContentInfos"}, |         {0x100B00C0, nullptr, "GetNumExistingContentInfos"}, | ||||||
|     {0x100D0084, GetPatchTitleInfos, "GetPatchTitleInfos"}, |         {0x100C0142, nullptr, "ListExistingContentInfos"}, | ||||||
| }; |         {0x100D0084, &AM_SYS::GetPatchTitleInfos, "GetPatchTitleInfos"}, | ||||||
| 
 |     }; | ||||||
| AM_SYS_Interface::AM_SYS_Interface() { |     RegisterHandlers(functions); | ||||||
|     Register(FunctionTable); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -4,18 +4,14 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/am/am.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| class AM_SYS_Interface : public Service::Interface { | class AM_SYS final : public Module::Interface { | ||||||
| public: | public: | ||||||
|     AM_SYS_Interface(); |     explicit AM_SYS(std::shared_ptr<Module> am); | ||||||
| 
 |  | ||||||
|     std::string GetPortName() const override { |  | ||||||
|         return "am:sys"; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -2,87 +2,85 @@ | ||||||
| // Licensed under GPLv2 or any later version
 | // Licensed under GPLv2 or any later version
 | ||||||
| // Refer to the license.txt file included.
 | // Refer to the license.txt file included.
 | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/am/am.h" |  | ||||||
| #include "core/hle/service/am/am_u.h" | #include "core/hle/service/am/am_u.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| const Interface::FunctionInfo FunctionTable[] = { | AM_U::AM_U(std::shared_ptr<Module> am) : Module::Interface(std::move(am), "am:u", 5) { | ||||||
|     {0x00010040, GetNumPrograms, "GetNumPrograms"}, |     static const FunctionInfo functions[] = { | ||||||
|     {0x00020082, GetProgramList, "GetProgramList"}, |         {0x00010040, &AM_U::GetNumPrograms, "GetNumPrograms"}, | ||||||
|     {0x00030084, GetProgramInfos, "GetProgramInfos"}, |         {0x00020082, &AM_U::GetProgramList, "GetProgramList"}, | ||||||
|     {0x000400C0, DeleteUserProgram, "DeleteUserProgram"}, |         {0x00030084, &AM_U::GetProgramInfos, "GetProgramInfos"}, | ||||||
|     {0x000500C0, nullptr, "GetProductCode"}, |         {0x000400C0, &AM_U::DeleteUserProgram, "DeleteUserProgram"}, | ||||||
|     {0x000600C0, nullptr, "GetStorageId"}, |         {0x000500C0, nullptr, "GetProductCode"}, | ||||||
|     {0x00070080, DeleteTicket, "DeleteTicket"}, |         {0x000600C0, nullptr, "GetStorageId"}, | ||||||
|     {0x00080000, GetNumTickets, "GetNumTickets"}, |         {0x00070080, &AM_U::DeleteTicket, "DeleteTicket"}, | ||||||
|     {0x00090082, GetTicketList, "GetTicketList"}, |         {0x00080000, &AM_U::GetNumTickets, "GetNumTickets"}, | ||||||
|     {0x000A0000, nullptr, "GetDeviceID"}, |         {0x00090082, &AM_U::GetTicketList, "GetTicketList"}, | ||||||
|     {0x000B0040, nullptr, "GetNumImportTitleContexts"}, |         {0x000A0000, nullptr, "GetDeviceID"}, | ||||||
|     {0x000C0082, nullptr, "GetImportTitleContextList"}, |         {0x000B0040, nullptr, "GetNumImportTitleContexts"}, | ||||||
|     {0x000D0084, nullptr, "GetImportTitleContexts"}, |         {0x000C0082, nullptr, "GetImportTitleContextList"}, | ||||||
|     {0x000E00C0, nullptr, "DeleteImportTitleContext"}, |         {0x000D0084, nullptr, "GetImportTitleContexts"}, | ||||||
|     {0x000F00C0, nullptr, "GetNumImportContentContexts"}, |         {0x000E00C0, nullptr, "DeleteImportTitleContext"}, | ||||||
|     {0x00100102, nullptr, "GetImportContentContextList"}, |         {0x000F00C0, nullptr, "GetNumImportContentContexts"}, | ||||||
|     {0x00110104, nullptr, "GetImportContentContexts"}, |         {0x00100102, nullptr, "GetImportContentContextList"}, | ||||||
|     {0x00120102, nullptr, "DeleteImportContentContexts"}, |         {0x00110104, nullptr, "GetImportContentContexts"}, | ||||||
|     {0x00130040, nullptr, "NeedsCleanup"}, |         {0x00120102, nullptr, "DeleteImportContentContexts"}, | ||||||
|     {0x00140040, nullptr, "DoCleanup"}, |         {0x00130040, nullptr, "NeedsCleanup"}, | ||||||
|     {0x00150040, nullptr, "DeleteAllImportContexts"}, |         {0x00140040, nullptr, "DoCleanup"}, | ||||||
|     {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, |         {0x00150040, nullptr, "DeleteAllImportContexts"}, | ||||||
|     {0x00170044, nullptr, "ImportTwlBackupLegacy"}, |         {0x00160000, nullptr, "DeleteAllTemporaryPrograms"}, | ||||||
|     {0x00180080, nullptr, "InitializeTitleDatabase"}, |         {0x00170044, nullptr, "ImportTwlBackupLegacy"}, | ||||||
|     {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, |         {0x00180080, nullptr, "InitializeTitleDatabase"}, | ||||||
|     {0x001A00C0, nullptr, "CalcTwlBackupSize"}, |         {0x00190040, nullptr, "QueryAvailableTitleDatabase"}, | ||||||
|     {0x001B0144, nullptr, "ExportTwlBackup"}, |         {0x001A00C0, nullptr, "CalcTwlBackupSize"}, | ||||||
|     {0x001C0084, nullptr, "ImportTwlBackup"}, |         {0x001B0144, nullptr, "ExportTwlBackup"}, | ||||||
|     {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, |         {0x001C0084, nullptr, "ImportTwlBackup"}, | ||||||
|     {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, |         {0x001D0000, nullptr, "DeleteAllTwlUserPrograms"}, | ||||||
|     {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, |         {0x001E00C8, nullptr, "ReadTwlBackupInfo"}, | ||||||
|     {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, |         {0x001F0040, nullptr, "DeleteAllExpiredUserPrograms"}, | ||||||
|     {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, |         {0x00200000, nullptr, "GetTwlArchiveResourceInfo"}, | ||||||
|     {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, |         {0x00210042, nullptr, "GetPersonalizedTicketInfoList"}, | ||||||
|     {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, |         {0x00220080, nullptr, "DeleteAllImportContextsFiltered"}, | ||||||
|     {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, |         {0x00230080, nullptr, "GetNumImportTitleContextsFiltered"}, | ||||||
|     {0x002500C0, nullptr, "CheckContentRights"}, |         {0x002400C2, nullptr, "GetImportTitleContextListFiltered"}, | ||||||
|     {0x00260044, nullptr, "GetTicketLimitInfos"}, |         {0x002500C0, nullptr, "CheckContentRights"}, | ||||||
|     {0x00270044, nullptr, "GetDemoLaunchInfos"}, |         {0x00260044, nullptr, "GetTicketLimitInfos"}, | ||||||
|     {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, |         {0x00270044, nullptr, "GetDemoLaunchInfos"}, | ||||||
|     {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, |         {0x00280108, nullptr, "ReadTwlBackupInfoEx"}, | ||||||
|     {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, |         {0x00290082, nullptr, "DeleteUserProgramsAtomically"}, | ||||||
|     {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, |         {0x002A00C0, nullptr, "GetNumExistingContentInfosSystem"}, | ||||||
|     {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, |         {0x002B0142, nullptr, "ListExistingContentInfosSystem"}, | ||||||
|     {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, |         {0x002C0084, nullptr, "GetProgramInfosIgnorePlatform"}, | ||||||
|     {0x04010080, nullptr, "UpdateFirmwareTo"}, |         {0x002D00C0, nullptr, "CheckContentRightsIgnorePlatform"}, | ||||||
|     {0x04020040, BeginImportProgram, "BeginImportProgram"}, |         {0x04010080, nullptr, "UpdateFirmwareTo"}, | ||||||
|     {0x04030000, nullptr, "BeginImportProgramTemporarily"}, |         {0x04020040, &AM_U::BeginImportProgram, "BeginImportProgram"}, | ||||||
|     {0x04040002, nullptr, "CancelImportProgram"}, |         {0x04030000, nullptr, "BeginImportProgramTemporarily"}, | ||||||
|     {0x04050002, EndImportProgram, "EndImportProgram"}, |         {0x04040002, nullptr, "CancelImportProgram"}, | ||||||
|     {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, |         {0x04050002, &AM_U::EndImportProgram, "EndImportProgram"}, | ||||||
|     {0x040700C2, nullptr, "CommitImportPrograms"}, |         {0x04060002, nullptr, "EndImportProgramWithoutCommit"}, | ||||||
|     {0x04080042, GetProgramInfoFromCia, "GetProgramInfoFromCia"}, |         {0x040700C2, nullptr, "CommitImportPrograms"}, | ||||||
|     {0x04090004, GetSystemMenuDataFromCia, "GetSystemMenuDataFromCia"}, |         {0x04080042, &AM_U::GetProgramInfoFromCia, "GetProgramInfoFromCia"}, | ||||||
|     {0x040A0002, GetDependencyListFromCia, "GetDependencyListFromCia"}, |         {0x04090004, &AM_U::GetSystemMenuDataFromCia, "GetSystemMenuDataFromCia"}, | ||||||
|     {0x040B0002, GetTransferSizeFromCia, "GetTransferSizeFromCia"}, |         {0x040A0002, &AM_U::GetDependencyListFromCia, "GetDependencyListFromCia"}, | ||||||
|     {0x040C0002, GetCoreVersionFromCia, "GetCoreVersionFromCia"}, |         {0x040B0002, &AM_U::GetTransferSizeFromCia, "GetTransferSizeFromCia"}, | ||||||
|     {0x040D0042, GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, |         {0x040C0002, &AM_U::GetCoreVersionFromCia, "GetCoreVersionFromCia"}, | ||||||
|     {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, |         {0x040D0042, &AM_U::GetRequiredSizeFromCia, "GetRequiredSizeFromCia"}, | ||||||
|     {0x040F0000, nullptr, "UpdateFirmwareAuto"}, |         {0x040E00C2, nullptr, "CommitImportProgramsAndUpdateFirmwareAuto"}, | ||||||
|     {0x041000C0, DeleteProgram, "DeleteProgram"}, |         {0x040F0000, nullptr, "UpdateFirmwareAuto"}, | ||||||
|     {0x04110044, nullptr, "GetTwlProgramListForReboot"}, |         {0x041000C0, &AM_U::DeleteProgram, "DeleteProgram"}, | ||||||
|     {0x04120000, nullptr, "GetSystemUpdaterMutex"}, |         {0x04110044, nullptr, "GetTwlProgramListForReboot"}, | ||||||
|     {0x04130002, GetMetaSizeFromCia, "GetMetaSizeFromCia"}, |         {0x04120000, nullptr, "GetSystemUpdaterMutex"}, | ||||||
|     {0x04140044, GetMetaDataFromCia, "GetMetaDataFromCia"}, |         {0x04130002, &AM_U::GetMetaSizeFromCia, "GetMetaSizeFromCia"}, | ||||||
|     {0x04150080, nullptr, "CheckDemoLaunchRights"}, |         {0x04140044, &AM_U::GetMetaDataFromCia, "GetMetaDataFromCia"}, | ||||||
|     {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, |         {0x04150080, nullptr, "CheckDemoLaunchRights"}, | ||||||
|     {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, |         {0x041600C0, nullptr, "GetInternalTitleLocationInfo"}, | ||||||
|     {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, |         {0x041700C0, nullptr, "PerpetuateAgbSaveData"}, | ||||||
|     {0x04190000, nullptr, "BeginImportSystemProgram"}, |         {0x04180040, nullptr, "BeginImportProgramForOverWrite"}, | ||||||
| }; |         {0x04190000, nullptr, "BeginImportSystemProgram"}, | ||||||
| 
 |     }; | ||||||
| AM_U_Interface::AM_U_Interface() { |     RegisterHandlers(functions); | ||||||
|     Register(FunctionTable); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -4,18 +4,14 @@ | ||||||
| 
 | 
 | ||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| #include "core/hle/service/service.h" | #include "core/hle/service/am/am.h" | ||||||
| 
 | 
 | ||||||
| namespace Service { | namespace Service { | ||||||
| namespace AM { | namespace AM { | ||||||
| 
 | 
 | ||||||
| class AM_U_Interface : public Service::Interface { | class AM_U final : public Module::Interface { | ||||||
| public: | public: | ||||||
|     AM_U_Interface(); |     explicit AM_U(std::shared_ptr<Module> am); | ||||||
| 
 |  | ||||||
|     std::string GetPortName() const override { |  | ||||||
|         return "am:u"; |  | ||||||
|     } |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| } // namespace AM
 | } // namespace AM
 | ||||||
|  |  | ||||||
|  | @ -100,7 +100,7 @@ void FS_USER::OpenFileDirectly(Kernel::HLERequestContext& ctx) { | ||||||
|                   "Failed to get a handle for archive archive_id=0x%08X archive_path=%s", |                   "Failed to get a handle for archive archive_id=0x%08X archive_path=%s", | ||||||
|                   static_cast<u32>(archive_id), archive_path.DebugStr().c_str()); |                   static_cast<u32>(archive_id), archive_path.DebugStr().c_str()); | ||||||
|         rb.Push(archive_handle.Code()); |         rb.Push(archive_handle.Code()); | ||||||
|         rb.PushMoveHandles(0); |         rb.PushMoveObjects<Kernel::Object>(nullptr); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     SCOPE_EXIT({ Service::FS::CloseArchive(*archive_handle); }); |     SCOPE_EXIT({ Service::FS::CloseArchive(*archive_handle); }); | ||||||
|  |  | ||||||
|  | @ -237,7 +237,7 @@ void Init() { | ||||||
|     FS::InstallInterfaces(*SM::g_service_manager); |     FS::InstallInterfaces(*SM::g_service_manager); | ||||||
|     FS::ArchiveInit(); |     FS::ArchiveInit(); | ||||||
|     ACT::Init(); |     ACT::Init(); | ||||||
|     AM::Init(); |     AM::InstallInterfaces(*SM::g_service_manager); | ||||||
|     APT::InstallInterfaces(*SM::g_service_manager); |     APT::InstallInterfaces(*SM::g_service_manager); | ||||||
|     BOSS::Init(); |     BOSS::Init(); | ||||||
|     CAM::InstallInterfaces(*SM::g_service_manager); |     CAM::InstallInterfaces(*SM::g_service_manager); | ||||||
|  | @ -280,7 +280,6 @@ void Shutdown() { | ||||||
|     CFG::Shutdown(); |     CFG::Shutdown(); | ||||||
|     CECD::Shutdown(); |     CECD::Shutdown(); | ||||||
|     BOSS::Shutdown(); |     BOSS::Shutdown(); | ||||||
|     AM::Shutdown(); |  | ||||||
|     FS::ArchiveShutdown(); |     FS::ArchiveShutdown(); | ||||||
| 
 | 
 | ||||||
|     SM::g_service_manager = nullptr; |     SM::g_service_manager = nullptr; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue