diff --git a/libctru/include/3ds/services/am.h b/libctru/include/3ds/services/am.h index 1d83942b4..682ec63fc 100644 --- a/libctru/include/3ds/services/am.h +++ b/libctru/include/3ds/services/am.h @@ -1,6 +1,6 @@ /** * @file am.h - * @brief AM (Application Manager) service. + * @brief AM (Application Manager) services. */ #pragma once @@ -9,44 +9,102 @@ /// Contains basic information about a title. typedef struct { - u64 titleID; ///< The title's ID. - u64 size; ///< The title's installed size. - u16 version; ///< The title's version. - u8 unk[6]; ///< Unknown title data. -} AM_TitleEntry; - -/// Pending title status mask values. -enum + u64 titleID; ///< The title's ID. + u64 size; ///< The title's installed size. + u16 version; ///< The title's version. + u32 titleType; ///< The title's type from the TMD. +} AM_TitleInfo; + +/// Contains basic information about a title. +typedef AM_TitleInfo AM_TitleEntry; + +/// Contains information about a ticket. +typedef struct +{ + u64 titleId; ///< Title ID of the corresponding title. + u64 ticketId; ///< Ticket ID. + u16 titleVersion; ///< Title version at the time the ticket was issued. + u32 size; ///< Total size of the ticket. +} AM_TicketInfo; + +/// Ticket limit flags for ticket limit infos. +typedef enum +{ + TICKET_LIMIT_PLAY_COUNT = BIT(3) ///< Ticket limit for a maximum play count (used for demos). +} AM_TicketLimitFlag; + +/// Contains information about the limits section of a ticket. +typedef struct { - AM_STATUS_MASK_INSTALLING = BIT(0), ///< Titles currently installing. - AM_STATUS_MASK_AWAITING_FINALIZATION = BIT(1) ///< Titles awaiting finalization. -}; + u8 flags; ///< Enabled ticket limit types. @ref AM_TicketLimitFlag + u8 maxPlaycount; ///< The maximum play count when the ticket has a play count limit. + u8 reserved[14]; +} AM_TicketLimitInfo; + +/// Demo limit information. +typedef AM_TicketLimitInfo AM_DemoLaunchInfo; /// Pending title status values. typedef enum { - AM_STATUS_ABORTED = 0x0002, ///< Install aborted. - AM_STATUS_SAVED = 0x0003, ///< Title saved, but not installed. - AM_STATUS_INSTALL_IN_PROGRESS = 0x0802, ///< Install in progress. - AM_STATUS_AWAITING_FINALIZATION = 0x0803 ///< Awaiting finalization. -} AM_InstallStatus; + AM_INSTALL_NONE = 0, ///< No installation in progress. + AM_INSTALL_WAITING_FOR_IMPORT = 1, ///< Installation is pending. + AM_INSTALL_RESUMABLE = 2, ///< Installation is paused. + AM_INSTALL_WAITING_FOR_COMMIT = 3, ///< Installation is awaiting committing to the title database. + AM_INSTALL_ALREADY_EXISTS = 4, ///< The title already exists. + AM_INSTALL_DELETING = 5, ///< The title is pending removal. + AM_INSTALL_NEEDS_CLEANUP = 6, ///< Installation requires cleanup. +} AM_TitleInstallStatus; + +/// Content import status values. +typedef enum +{ + AM_CONTENT_IN_PROGRESS = 1, ///< Content installation is in progress. + AM_CONTENT_PAUSED = 2, ///< Content installation is paused. + AM_CONTENT_FINISHED = 3, ///< Content installation is complete. + AM_CONTENT_ALREADY_EXISTS = 4, ///< The content already exists. +} AM_ContentInstallStatus; + +// Contains basic information about a pending title. +typedef struct +{ + u64 titleId; ///< The title's title ID. + u16 version; ///< The title's title version. + u8 status; ///< The title's installation status. @ref AM_TitleInstallStatus + u32 titleType; ///< The title's title type from the TMD. + u64 titleSize; ///< The amount of storage space (in bytes) the title takes up. +} AM_PendingTitleInfo; // Contains basic information about a pending title. +typedef AM_PendingTitleInfo AM_PendingTitleEntry; + +// Contains information about a title's active content import. typedef struct { - u64 titleId; ///< Title ID - u16 version; ///< Version - u16 status; ///< @ref AM_InstallStatus - u32 titleType; ///< Title Type - u8 unk[0x8]; ///< Unknown -} AM_PendingTitleEntry; - -/// Pending title deletion flags. -enum + u32 contentId; ///< Content ID (from the TMD) of this content. + u16 contentIndex; ///< Content index (from the TMD) of this content. + u8 status; ///< Installation status of this content. @ref AM_ContentInstallStatus + u64 size; ///< Total size of this content. + u64 currentInstallOffset; ///< Current installation offset for this content. +} AM_ImportContentContext; + +/// Pending title flags. +typedef enum +{ + AM_PENDING_NON_SYSTEM = BIT(0), ///< Non-system titles. + AM_PENDING_SYSTEM = BIT(1) ///< System titles. +} AM_PendingTitleFlags; + +/// Information about an exported DSiWare title. +typedef struct AM_TWLBackupInfo { - AM_DELETE_PENDING_NON_SYSTEM = BIT(0), ///< Non-system titles. - AM_DELETE_PENDING_SYSTEM = BIT(1) ///< System titles. -}; + u64 titleId; ///< Title ID of the exported title. + u16 groupId; ///< Group ID (from the TMD). + u16 titleVersion; ///< Title version of the exported title. + u32 publicSaveSize; ///< public.sav size. + u32 privateSaveSize; ///< private.sav size. + u64 required_size; ///< Total size (in bytes) required to install the exported title. +} AM_TWLBackupInfo; /// Information about the TWL NAND partition. typedef struct { @@ -56,27 +114,49 @@ typedef struct { u64 titlesFreeSpace; ///< Free space for titles. } AM_TWLPartitionInfo; +/// Title ContentInfo flags. +typedef enum +{ + AM_CONTENT_INSTALLED = BIT(0), ///< The content is installed. + AM_CONTENT_OWNED = BIT(1) ///< The user has the right to use the content according to one or more of the title's tickets. +} AM_ContentInfoFlags; + +/// Title Content flags. +typedef enum +{ + AM_CONTENT_ENCRYPTED = BIT(0), ///< Content is encrypted (CDN crypto). + AM_CONTENT_DISC = BIT(1), + AM_CONTENT_HASHED = BIT(2), + AM_CONTENT_CFM = BIT(3), + AM_CONTENT_SHA1_HASH = BIT(13), + AM_CONTENT_OPTIONAL = BIT(14), ///< Content is optional (set for non-contentindex-0 DLC contents) + AM_CONTENT_SHARED = BIT(15) +} AM_ContentTypeFlags; + /// Contains information about a title's content. -typedef struct { - u16 index; ///< Index of the content in the title. - u16 type; ///< ? - u32 contentId; ///< ID of the content in the title. +typedef struct +{ + u16 index; ///< Content index from the TMD. + u16 type; ///< Content flags from the TMD. @ref AM_ContentTypeFlags + u32 contentId; ///< Content ID from the TMD. u64 size; ///< Size of the content in the title. u8 flags; ///< @ref AM_ContentInfoFlags u8 padding[7]; ///< Padding } AM_ContentInfo; -/// Title ContentInfo flags. -typedef enum +/// Contains internal information about a title's storage location. +typedef struct { - AM_CONTENT_DOWNLOADED = BIT(0), ///< ? - AM_CONTENT_OWNED = BIT(1) ///< ? -} AM_ContentInfoFlags; + u32 cmdFileId; ///< The ID of the currently active content metadata (CMD) file. + u32 saveFileId; ///< The ID of the currently active save data file. + u32 cmdFormatVersion; ///< The format version of the currently active content metadata (CMD) file. + u32 reserved[5]; +} AM_InternalTitleLocationInfo; /// Initializes AM. This doesn't initialize with "am:app", see amAppInit(). Result amInit(void); -/// Initializes AM with a service which has access to the amapp-commands. This should only be used when using the amapp commands, not non-amapp AM commands. +/// Initializes AM with a service which has access to the AMAPP-commands. This should only be used when using the AMAPP commands, as non-AMAPP commands will be inaccessible in this case. Result amAppInit(void); /// Exits AM. @@ -97,7 +177,7 @@ Result AM_GetTitleCount(FS_MediaType mediatype, u32 *count); * @param[out] titlesRead Pointer to output the number of read titles to. * @param mediatype Media type to get titles from. * @param titleCount Number of title IDs to get. - * @param titleIds Buffer to output the retrieved title IDs to. + * @param[out] titleIds Buffer to output the retrieved title IDs to. */ Result AM_GetTitleList(u32* titlesRead, FS_MediaType mediatype, u32 titleCount, u64 *titleIds); @@ -106,9 +186,38 @@ Result AM_GetTitleList(u32* titlesRead, FS_MediaType mediatype, u32 titleCount, * @param mediatype Media type to get titles from. * @param titleCount Number of titles to list. * @param titleIds List of title IDs to retrieve details for. - * @param titleInfo Buffer to write AM_TitleEntry's to. + * @param[out] titleInfo Buffer to write AM_TitleInfo's to. + */ +Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM_TitleInfo *titleInfo); + +/** + * @brief Deletes a title, provided that it is not a system title. + * @param mediatype Media type to delete from. + * @param titleID ID of the title to delete. + */ +Result AM_DeleteUserTitle(FS_MediaType mediatype, u64 titleID); + +/** + * @brief Gets the product code of a title. + * @param mediatype Media type of the title. + * @param titleID ID of the title. + * @param[out] productCode Pointer to output the product code to. (length = 16) + */ +Result AM_GetTitleProductCode(FS_MediaType mediatype, u64 titleId, char *productCode); + +/** + * @brief Gets the ext data ID of a title. + * @param[out] extDataId Pointer to output the ext data ID to. + * @param mediatype Media type of the title. + * @param titleID ID of the title. + */ +Result AM_GetTitleExtDataId(u64 *extDataId, FS_MediaType mediatype, u64 titleId); + +/** + * @brief Deletes all tickets for a specific title. + * @param titleId ID of the ticket to delete. */ -Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM_TitleEntry *titleInfo); +Result AM_DeleteTicket(u64 titleId); /** * @brief Gets the number of tickets installed on the system. @@ -117,78 +226,172 @@ Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM Result AM_GetTicketCount(u32 *count); /** - * @brief Gets a list of tickets installed on the system. - * @param[out] ticketsRead Pointer to output the number of read tickets to. - * @param ticketCount Number of tickets to read. - * @param skip Number of tickets to skip. - * @param ticketIds Buffer to output the retrieved ticket IDs to. + * @brief Gets a list of title IDs for which tickets are installed. + * @param[out] ticketsRead Pointer to output the number of read ticket title IDs to. + * @param ticketCount Number of ticket title IDs to read. + * @param skip Offset to start from in the entire ticket title ID list. + * @param[out] ticketTitleIds Buffer to output the retrieved ticket title IDs to. */ -Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticketIds); +Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticketTitleIds); /** - * @brief Gets the number of pending titles on this system. - * @param[out] count Pointer to output the pending title count to. - * @param mediatype Media type of pending titles to count. - * @param statusMask Bit mask of status values to include. + * @brief Gets a 32-bit device-specific ID. + * @param[out] outInternalResult Pointer to write an internal pxi:am9 result value to. + * @param[out] deviceID Pointer to write the device ID to. */ -Result AM_GetPendingTitleCount(u32 *count, FS_MediaType mediatype, u32 statusMask); +Result AM_GetDeviceId(s32 *outInternalResult, u32 *outDeviceId); /** - * @brief Gets a list of pending titles on this system. - * @param[out] titlesRead Pointer to output the number of read pending titles to. - * @param titleCount Number of pending titles to read. - * @param mediatype Media type of pending titles to list. - * @param statusMask Bit mask of status values to include. - * @param titleIds Buffer to output the retrieved pending title IDs to. + * @brief Returns the number of active title installation contexts (including system and user titles). + * @param[out] outNum Pointer to output the number of active title installation contexts to. + * @param mediaType Media type to check for title installation contexts. + */ +Result AM_GetNumPendingTitles(u32 *outNum, FS_MediaType mediaType); + +/** + * @brief Returns the title IDs of active title installation contexts (including system and user titles). + * @param[out] outNum Pointer to output the number of retrived title IDs to. + * @param[out] outTitleIds Pointer to output the retrieved title IDs to. + * @param count The maximum number of title IDs to retrieve. + * @param mediaType The media type to use for retrieving the title IDs for active title import contexts. */ -Result AM_GetPendingTitleList(u32 *titlesRead, u32 titleCount, FS_MediaType mediatype, u32 statusMask, u64 *titleIds); +Result AM_GetPendingTitleList(u32 *outNum, u64 *outTitleIds, u32 count, FS_MediaType mediaType); /** * @brief Gets information about pending titles on this system. * @param titleCount Number of pending titles to read. * @param mediatype Media type of pending titles to get information on. * @param titleIds IDs of the titles to get information about. - * @param titleInfo Buffer to output the retrieved pending title info to. + * @param[out] titleInfo Buffer to output the retrieved pending title infos to. */ -Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *titleIds, AM_PendingTitleEntry *titleInfo); +Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *titleIds, AM_PendingTitleInfo *titleInfo); /** - * @brief Gets a 32-bit device-specific ID. - * @param deviceID Pointer to write the device ID to. + * @brief Deletes a pending title (both user and system titles are allowed). + * @param mediatype Media type to delete from. + * @param titleId ID of the pending title to delete. + */ +Result AM_DeletePendingTitle(FS_MediaType mediatype, u64 titleId); + +/** + * @brief Gets the number of active content imports for a given title. + * @param[out] outNum Pointer to output the number of active content imports to. + * @param titleId The title ID of the corresponding title. + * @param mediaType The media type of the corresponding title. + */ +Result AM_GetNumImportContentContexts(u32 *outNum, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Gets the content indices of the active content imports for a given title. + * @param[out] outNum Pointer to output the number of read content indices to. + * @param[out] outContentIndices Pointer to output the content indices to. + * @param count The maximum number of content indices to retrieve. + * @param titleId The title ID of the corresponding title. + * @param mediaType The media type of the corresponding title. + */ +Result AM_GetImportContentContextList(u32 *outNum, u16 *outContentIndices, u32 count, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Gets import contexts for a title's active content imports. + * @param[out] outContexts Pointer to output the content import contexts to. + * @param contentIndices The content indices of the contents to get import contexts for. + * @param count The maximum number of import contexts to retrieve. + * @param titleId The title ID of the corresponding title. + * @param mediaType The media type of the corresponding title. + */ +Result AM_GetImportContentContexts(AM_ImportContentContext *outContexts, u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Deletes active content import contexts for a given title. + * @param contentIndices The content indices of the contents to delete import contexts for. + * @param count The number of given content indices, or the number of content indices to delete. + * @param titleId The title ID of the corresponding title. + * @param mediaType The media type of the corresponding title. + */ +Result AM_DeleteImportContentContexts(u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Checks if cleanup is required in the import database (when there are finalized titles left over in them). For NAND, this also returns true when nand:/data contains none or more than one directory, or when nand:/data/ does not exist. + * @param[out] outNeedsCleanup Pointer to write the status to. + * @param mediaType The media type to check. + */ +Result AM_NeedsCleanup(u8 *outNeedsCleanup, FS_MediaType mediaType); + +/** + * @brief Performs cleanup on the title import database, by deleting all titles found in the import.db that are marked as installed but haven't been transferred to the title.db. For NAND, if a file at nand:/data/disabled does not exist, this in addition removes any directory under nand:/data that doesn't match the system ID0. + * @param mediaType The media type to perform cleanup on. + */ +Result AM_DoCleanup(FS_MediaType mediaType); + +/** + * @brief Deletes all pending titles (including both user and system titles). + * @param mediatype Media type to delete from. + */ +Result AM_DeleteAllPendingTitles(FS_MediaType mediatype); + +/// Deletes temporary titles. +Result AM_DeleteAllTemporaryTitles(void); + +/** + * @brief Initializes the external (SD) title database. + * @param overwrite Overwrites the database if it already exists. + */ +Result AM_InitializeExternalTitleDatabase(bool overwrite); + +/** + * @brief Queries whether the external title database is available. + * @param[out] available Pointer to output the availability status to. + */ +Result AM_QueryAvailableExternalTitleDatabase(bool* available); + +/** + * @brief Calculates the total file size of a DSiWare export. + * @param[out] outSize Pointer to output the total file size to. + * @param titleId The title ID of the corresponding DSiWare title. + * @param exportType The export type to use when calculating the size. */ -Result AM_GetDeviceId(u32 *deviceID); +Result AM_CalculateTwlBackupSize(u64 *outSize, u64 titleId, u8 exportType); /** * @brief Exports DSiWare to the specified filepath. * @param titleID TWL titleID. - * @param operation DSiWare operation type. + * @param exportType DSiWare export type. * @param workbuf Work buffer. * @param workbuf_size Work buffer size, must be >=0x20000. * @param filepath UTF-8 filepath(converted to UTF-16 internally). */ -Result AM_ExportTwlBackup(u64 titleID, u8 operation, void* workbuf, u32 workbuf_size, const char *filepath); +Result AM_ExportTwlBackup(u64 titleID, u8 exportType, void* workbuf, u32 workbuf_size, const char *filepath); /** * @brief Imports DSiWare from the specified file. * @param filehandle FSUSER file handle. - * @param operation DSiWare operation type. + * @param exportType DSiWare export type. * @param buffer Work buffer. * @param size Buffer size, must be >=0x20000. */ -Result AM_ImportTwlBackup(Handle filehandle, u8 operation, void* buffer, u32 size); +Result AM_ImportTwlBackup(Handle filehandle, u8 exportType, void* buffer, u32 size); + +/// Deletes all DSiWare (TWL) user titles (not system titles). +Result AM_DeleteAllTwlUserTitles(void); /** - * @brief Reads info from the specified DSiWare export file. This can only be used with DSiWare exported with certain operation value(s). + * @brief Reads info from the specified DSiWare export file. This can only be used with DSiWare exported with certain export types. * @param filehandle FSUSER file handle. - * @param outinfo Output info buffer. + * @param[out] outinfo Output info buffer. * @param outinfo_size Output info buffer size. * @param workbuf Work buffer. * @param workbuf_size Work buffer size. - * @param banner Output banner buffer. + * @param[out] banner Output banner buffer. * @param banner_size Output banner buffer size. */ Result AM_ReadTwlBackupInfo(Handle filehandle, void* outinfo, u32 outinfo_size, void* workbuf, u32 workbuf_size, void* banner, u32 banner_size); +/** + * @brief Deletes all user titles (whether DSiWare or not) for which there are no tickets installed. + * @param mediatype Media type to delete from. + */ +Result AM_DeleteAllExpiredTitles(FS_MediaType mediatype); + /** * @brief Retrieves information about the NAND TWL partition. * @param[out] info Pointer to output the TWL partition info to. @@ -196,87 +399,116 @@ Result AM_ReadTwlBackupInfo(Handle filehandle, void* outinfo, u32 outinfo_size, Result AM_GetTWLPartitionInfo(AM_TWLPartitionInfo *info); /** - * @brief Initializes the CIA install process, returning a handle to write CIA data to. - * @param mediatype Media type to install the CIA to. - * @param[out] ciaHandle Pointer to write the CIA handle to. + * @brief Retrieves ticket information for user-installed (not system titles or DLP child titles) whose console ID matches that of the system. + * @param[out] outNum Pointer to output the number of retrieved ticket infos to. + * @param[out] outInfos Pointer to output the ticket infos to. + * @param count The maximum number of ticket infos to get. */ -Result AM_StartCiaInstall(FS_MediaType mediatype, Handle *ciaHandle); +Result AM_GetPersonalizedTicketInfos(u32 *outNum, AM_TicketInfo *outInfos, u32 count); /** - * @brief Initializes the CIA install process for Download Play CIAs, returning a handle to write CIA data to. - * @param[out] ciaHandle Pointer to write the CIA handle to. + * @brief Deletes all pending titles matching specific criteria. + * @param mediaType The media type to delete the pending titles from. + * @param flags The criteria based on which the pending titles should be deleted. @ref AM_PendingTitleFlags */ -Result AM_StartDlpChildCiaInstall(Handle *ciaHandle); +Result AM_DeleteAllImportTitleContexts(FS_MediaType mediaType, u32 flags); /** - * @brief Aborts the CIA install process. - * @param ciaHandle CIA handle to cancel. + * @brief Gets the number of pending titles matching specific criteria. + * @param[out] outNum Pointer to output the number of pending titles to. + * @param mediaType The media type to count the titles from. + * @param flags The criteria based on which the pending titles should be counted. @ref AM_PendingTitleFlags */ -Result AM_CancelCIAInstall(Handle ciaHandle); +Result AM_GetNumImportTitleContexts(u32 *outNum, FS_MediaType mediaType, u32 flags); /** - * @brief Finalizes the CIA install process. - * @param ciaHandle CIA handle to finalize. + * @brief Gets a list of title IDs for pending titles matching specific criteria. + * @param[out] outNum Pointer to output the number of pending titles to. + * @param count The maximum number of title IDs to get. + * @param flags The criteria based on which the title IDs should be retrieved. @ref AM_PendingTitleFlags + * @param[out] titleIds Pointer to output the title IDs to. */ -Result AM_FinishCiaInstall(Handle ciaHandle); +Result AM_GetImportTitleContextList(u32 *outNum, u32 count, FS_MediaType mediaType, u32 flags, u64 *titleIds); /** - * @brief Finalizes the CIA install process without committing the title to title.db or tmp*.db. - * @param ciaHandle CIA handle to finalize. + * @brief Checks whether or not the user has the right to use a given content of a title. + * @param[out] outHasRights Pointer to output whether or not the user has the right. + * @param titleId Title ID of the title to perform the check for. + * @param contentIndex Content index of the content to check. */ -Result AM_FinishCiaInstallWithoutCommit(Handle ciaHandle); +Result AM_CheckContentRights(u8 *outHasRights, u64 titleId, u16 contentIndex); /** - * @brief Commits installed CIAs. - * @param mediaType Location of the titles to finalize. - * @param titleCount Number of titles to finalize. - * @param temp Whether the titles being finalized are in the temporary database. - * @param titleIds Title IDs to finalize. + * @brief Obtains information about the limits section in tickets for the given list of title IDs. + * @param[out] outInfos Pointer to output the ticket limit information to. + * @param titleIds Pointer to the title IDs to obtain ticket limit information for. + * @param count Maximum number of ticket limit infos to obtain. */ -Result AM_CommitImportPrograms(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds); +Result AM_GetTicketLimitInfo(AM_TicketLimitInfo *outInfos, u64 *titleIds, u32 count); /** - * @brief Deletes a title. - * @param mediatype Media type to delete from. - * @param titleID ID of the title to delete. + * @brief Obtains information about demo limits from AM's demo limit database. + * @param[out] outInfos Pointer to output the demo limit information to. + * @param titleIds Pointer to the title IDs to obtain demo limit information for. + * @param count Maximum number of demo limit infos to obtain. */ -Result AM_DeleteTitle(FS_MediaType mediatype, u64 titleID); +Result AM_GetDemoLaunchInfo(AM_DemoLaunchInfo *outInfos, u64 *titleIds, u32 count); /** - * @brief Deletes a title, provided that it is not a system title. - * @param mediatype Media type to delete from. - * @param titleID ID of the title to delete. + * @brief Reads information from a DSiWare export file. Only works with exports that have 12 content sections (export types 7-11). + * @param[out] outInfo Pointer to output the backup information to. + * @param infoSize Size of the backup information buffer. + * @param[out] outBanner Pointer to output the DSi banner to. + * @param bannerSize Size of the banner buffer. + * @param workingBuffer Pointer to use as a working buffer. + * @param workingBufferSize Size of the working buffer. + * @param backupFile File handle of the backup file. */ -Result AM_DeleteAppTitle(FS_MediaType mediatype, u64 titleID); +Result AM_ReadTwlBackupInfoEx(void *outInfo, u32 infoSize, void *outBanner, u32 bannerSize, void *workingBuffer, u32 workingBufferSize, Handle backupFile); /** - * @brief Deletes a ticket. - * @param titleID ID of the ticket to delete. + * @brief Deletes a batch of user titles (CTR or TWL system titles are not allowed here). The given title IDs must be installed to the same title database. + * @param titleIds The title IDs of the titles to delete. + * @param count The number of title IDs in the buffer. + * @param mediaType The media type the titles are stored on. */ -Result AM_DeleteTicket(u64 ticketId); +Result AM_DeleteUserTitles(u64 *titleIds, u32 count, FS_MediaType mediaType); /** - * @brief Deletes a pending title. - * @param mediatype Media type to delete from. - * @param titleId ID of the pending title to delete. + * @brief Returns the number of installed contents of a given title. + * @param[out] outNum Pointer to output the number of installed contents to. + * @param titleId Title ID of the corresponding title. + * @param mediaType Media type of the corresponding title. */ -Result AM_DeletePendingTitle(FS_MediaType mediatype, u64 titleId); +Result AM_GetNumExistingContentInfos(u32 *outNum, u64 titleId, FS_MediaType mediaType); /** - * @brief Deletes pending titles. - * @param mediatype Media type to delete from. - * @param flags Flags used to select pending titles. + * @brief Retrieves content information for installed contents of a given title. + * @param[out] outNum Pointer to output the number of retrieved title infos to. + * @param offset Offset of the title infos in the entire list. + * @param count Number of title infos to retrive in this batch. + * @param titleId Title ID of the corresponding title. + * @param mediaType Media type of the corresponding title. */ -Result AM_DeletePendingTitles(FS_MediaType mediatype, u32 flags); +Result AM_ListExistingContentInfos(u32 *outNum, AM_ContentInfo *outInfos, u32 offset, u32 count, u64 titleId, FS_MediaType mediaType); /** - * @brief Deletes all pending titles. - * @param mediatype Media type to delete from. + * @brief Retrieves title information for a title, checking both the New3DS bit variant and the given title ID. + * @param[out] outInfos Pointer to output the title information to. + * @param titleIds Pointer to the title IDs to retrieve title information for. + * @param count Number of given title IDs. + * @param mediaType Media type of the given titles. */ -Result AM_DeleteAllPendingTitles(FS_MediaType mediatype); +Result AM_GetTitleInfosIgnorePlatform(AM_TitleInfo *outInfos, u64 *titleIds, u32 count, FS_MediaType mediaType); + +/** + * @brief Checks whether or not the user has the rights to use a content from a title, checking both the New3DS bit variant and the given title ID. + * @param[out] outHasRights Pointer to output the status to. + * @param titleId Title ID of the corresponding title. + * @param contentIndex Content index of the content to check. + */ +Result AM_CheckContentRightsIgnorePlatform(u8 *outHasRights, u64 titleId, u16 contentIndex); -/// Installs the current NATIVE_FIRM title to NAND (firm0:/ & firm1:/) -Result AM_InstallNativeFirm(void); /** * @brief Installs a NATIVE_FIRM title to NAND. Accepts 0004013800000002 or 0004013820000002 (N3DS). @@ -285,39 +517,63 @@ Result AM_InstallNativeFirm(void); Result AM_InstallFirm(u64 titleID); /** - * @brief Gets the product code of a title. - * @param mediatype Media type of the title. - * @param titleID ID of the title. - * @param[out] productCode Pointer to output the product code to. (length = 16) + * @brief Initializes the CIA install process, returning a handle to write CIA data to. + * @param mediatype Media type to install the CIA to. + * @param[out] ciaHandle Pointer to write the CIA handle to. */ -Result AM_GetTitleProductCode(FS_MediaType mediatype, u64 titleId, char *productCode); +Result AM_StartCiaInstall(FS_MediaType mediatype, Handle *ciaHandle); /** - * @brief Gets the ext data ID of a title. - * @param[out] extDataId Pointer to output the ext data ID to. - * @param mediatype Media type of the title. - * @param titleID ID of the title. + * @brief Initializes the CIA install process for temporary NAND titles (e.g. DLP child titles), returning a handle to write CIA data to. + * @param[out] ciaHandle Pointer to write the CIA handle to. */ -Result AM_GetTitleExtDataId(u64 *extDataId, FS_MediaType mediatype, u64 titleId); +Result AM_StartTempCiaInstall(Handle *ciaHandle); + +/** + * @brief Aborts the CIA install process. + * @param ciaHandle CIA handle to cancel. + */ +Result AM_CancelCIAInstall(Handle ciaHandle); + +/** + * @brief Finalizes the CIA install process. + * @param ciaHandle CIA handle to finalize. + */ +Result AM_FinishCiaInstall(Handle ciaHandle); + +/** + * @brief Finalizes the CIA install process without committing the title to title.db or tmp*.db. + * @param ciaHandle CIA handle to finalize. + */ +Result AM_FinishCiaInstallWithoutCommit(Handle ciaHandle); + +/** + * @brief Commits installed titles to the title database. + * @param mediaType Location of the titles to commit. + * @param titleCount Number of titles to commit. + * @param temp Whether the titles being committed are in the temporary database. + * @param titleIds Title IDs of the titles to commit. + */ +Result AM_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds); /** - * @brief Gets an AM_TitleEntry instance for a CIA file. + * @brief Gets an AM_TitleInfo instance for a CIA file. * @param mediatype Media type that this CIA would be installed to. - * @param[out] titleEntry Pointer to write the AM_TitleEntry instance to. + * @param[out] titleEntry Pointer to write the AM_TitleInfo instance to. * @param fileHandle Handle of the CIA file. */ -Result AM_GetCiaFileInfo(FS_MediaType mediatype, AM_TitleEntry *titleEntry, Handle fileHandle); +Result AM_GetCiaFileInfo(FS_MediaType mediatype, AM_TitleInfo *titleEntry, Handle fileHandle); /** * @brief Gets the SMDH icon data of a CIA file. - * @param icon Buffer to store the icon data in. Must be of size 0x36C0 bytes. + * @param[out] icon Buffer to store the icon data in. Must be of size 0x36C0 bytes. * @param fileHandle Handle of the CIA file. */ Result AM_GetCiaIcon(void *icon, Handle fileHandle); /** * @brief Gets the title ID dependency list of a CIA file. - * @param dependencies Buffer to store dependency title IDs in. Must be of size 0x300 bytes. + * @param[out] dependencies Buffer to store dependency title IDs in. Must be of size 0x300 bytes. * @param fileHandle Handle of the CIA file. */ Result AM_GetCiaDependencies(u64 *dependencies, Handle fileHandle); @@ -344,67 +600,132 @@ Result AM_GetCiaCoreVersion(u32 *coreVersion, Handle fileHandle); */ Result AM_GetCiaRequiredSpace(u64 *requiredSpace, FS_MediaType mediaType, Handle fileHandle); +/** + * @brief Commits installed titles, and installs NATIVE_FIRM if necessary. + * @param mediaType Location of the titles to finalize. + * @param titleCount Number of titles to finalize. + * @param temp Whether the titles being finalized are in the temporary database. + * @param titleIds Title IDs to finalize. + */ +Result AM_CommitImportTitlesAndInstallFirmAuto(FS_MediaType mediaType, u32 titleCount, bool temp, u64* titleIds); + +/// Installs the current NATIVE_FIRM title to NAND (firm0:/ & firm1:/) +Result AM_InstallFirmAuto(void); + +/** + * @brief Deletes a title. + * @param mediatype Media type to delete from. + * @param titleID ID of the title to delete. + */ +Result AM_DeleteTitle(FS_MediaType mediatype, u64 titleId); + +/** + * @brief Returns a list of TWL title IDs (0003XXXXXXXXXXXX) alongside the content IDs of the content with content index 0 for each. + * @param[out] outNum Pointer to return the number of titles read. + * @param[out] titleIds Pointer to output the TWL title IDs to. + * @param[out] contentIds Pointer to output the content IDs to. + * @param count The maximum number of titles to retrieve. + */ +Result AM_GetTwlTitleListForReboot(u32 *outNum, u64 *titleIds, u32 *contentIds, u32 count); + +/** + * @brief Returns the system updater mutex. + * @param[out] outMutex Pointer to output the updater mutex handle to. + */ +Result AM_GetSystemUpdaterMutex(Handle *outMutex); + +/** + * @brief Returns the size of the metadata region in a CIA file. + * @param[out] outSize Pointer to output the metadata region size to. + * @param ciaFile Handle for the the CIA file. + */ +Result AM_GetCiaMetaSize(u32 *outSize, Handle ciaFile); + /** * @brief Gets the full meta section of a CIA file. - * @param meta Buffer to store the meta section in. + * @param[out] meta Buffer to store the meta section in. * @param size Size of the buffer. Must be greater than or equal to the actual section data's size. * @param fileHandle Handle of the CIA file. */ Result AM_GetCiaMetaSection(void *meta, u32 size, Handle fileHandle); /** - * @brief Initializes the external (SD) title database. - * @param overwrite Overwrites the database if it already exists. + * @brief Queries the AM demo launch database to check whether or not the user has the right to launch a demo. Note that this command will cause the demo play count to increase when there are remaining plays. + * @param[out] outHasRight Pointer to output the status to. + * @param titleId The title ID of the title to perform this check for. */ -Result AM_InitializeExternalTitleDatabase(bool overwrite); +Result AM_CheckDemoLaunchRight(u8 *outHasRight, u64 titleId); /** - * @brief Queries whether the external title database is available. - * @param[out] available Pointer to output the availability status to. + * @brief Returns internal title location info for a specific title. + * @param[out] outInfo Pointer to output the info to. + * @param titleId The title ID of the title to retrieve the info for. + * @param mediaType The media type of the corresponding title. */ -Result AM_QueryAvailableExternalTitleDatabase(bool* available); +Result AM_GetInternalTitleLocationInfo(AM_InternalTitleLocationInfo *outInfo, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Migrates the AGB_SAVE partition data to the .SAV format on the SD card. + * @param titleId Title ID of the AGB title. + * @param mediaType Media type of the AGB title. + */ +Result AM_MigrateAGBToSAV(u64 titleId, FS_MediaType mediaType); + +/** + * @brief Begins the installation of a CIA, set up to overwrite an existing title with the same title ID and media type. + * @param[out] outCiaHandle Pointer to output the virtual import file handle to. + * @param mediaType The target media of the title to be installed. + */ +Result AM_StartCiaInstallOverwrite(Handle *outCiaHandle, FS_MediaType mediaType); + +/** + * @brief Begins the installation of a CIA containing a system title. + * @param[out] outCiaHandle Pointer to output the virtual import file handle to. + */ +Result AM_StartSystemCiaInstall(Handle *outCiaHandle); + /** * @brief Begins installing a ticket. * @param[out] ticketHandle Pointer to output a handle to write ticket data to. */ -Result AM_InstallTicketBegin(Handle *ticketHandle); +Result AMNET_InstallTicketBegin(Handle *ticketHandle); /** * @brief Aborts installing a ticket. * @param ticketHandle Handle of the installation to abort. */ -Result AM_InstallTicketAbort(Handle ticketHandle); +Result AMNET_InstallTicketAbort(Handle ticketHandle); /** * @brief Finishes installing a ticket. * @param ticketHandle Handle of the installation to finalize. */ -Result AM_InstallTicketFinish(Handle ticketHandle); +Result AMNET_InstallTicketFinish(Handle ticketHandle); /** * @brief Begins installing a title. * @param mediaType Destination to install to. * @param titleId ID of the title to install. - * @param unk Unknown. (usually false) + * @param inTempDb Whether or not the title should be installed to the temporary title database. */ -Result AM_InstallTitleBegin(FS_MediaType mediaType, u64 titleId, bool unk); +Result AMNET_InstallTitleBegin(FS_MediaType mediaType, u64 titleId, bool inTempDb); -/// Stops installing a title, generally to be resumed later. -Result AM_InstallTitleStop(void); +/// Pauses the currently active title installation. +Result AMNET_InstallTitleStop(void); /** * @brief Resumes installing a title. * @param mediaType Destination to install to. * @param titleId ID of the title to install. */ -Result AM_InstallTitleResume(FS_MediaType mediaType, u64 titleId); +Result AMNET_InstallTitleResume(FS_MediaType mediaType, u64 titleId); /// Aborts installing a title. -Result AM_InstallTitleAbort(void); +Result AMNET_InstallTitleAbort(void); /// Finishes installing a title. -Result AM_InstallTitleFinish(void); +Result AMNET_InstallTitleFinish(void); /** * @brief Commits installed titles. @@ -413,69 +734,112 @@ Result AM_InstallTitleFinish(void); * @param temp Whether the titles being finalized are in the temporary database. * @param titleIds Title IDs to finalize. */ -Result AM_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds); +Result AMNET_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds); /** * @brief Begins installing a TMD. * @param[out] tmdHandle Pointer to output a handle to write TMD data to. */ -Result AM_InstallTmdBegin(Handle *tmdHandle); +Result AMNET_InstallTmdBegin(Handle *tmdHandle); /** * @brief Aborts installing a TMD. * @param tmdHandle Handle of the installation to abort. */ -Result AM_InstallTmdAbort(Handle tmdHandle); +Result AMNET_InstallTmdAbort(Handle tmdHandle); /** * @brief Finishes installing a TMD. * @param tmdHandle Handle of the installation to finalize. - * @param unk Unknown. (usually true) + * @param unk Unknown - not used by AM or AMPXI. */ -Result AM_InstallTmdFinish(Handle tmdHandle, bool unk); +Result AMNET_InstallTmdFinish(Handle tmdHandle, bool unk); /** * @brief Prepares to import title contents. * @param contentCount Number of contents to be imported. * @param contentIndices Indices of the contents to be imported. */ -Result AM_CreateImportContentContexts(u32 contentCount, u16* contentIndices); +Result AMNET_CreateImportContentContexts(u32 contentCount, u16 *contentIndices); /** * @brief Begins installing title content. * @param[out] contentHandle Pointer to output a handle to write content data to. * @param index Index of the content to install. */ -Result AM_InstallContentBegin(Handle *contentHandle, u16 index); +Result AMNET_InstallContentBegin(Handle *contentHandle, u16 index); /** - * @brief Stops installing title content, generally to be resumed later. - * @param contentHandle Handle of the installation to abort. + * @brief Pauses the current content installation. + * @param contentHandle Handle of the content installation to pause. */ -Result AM_InstallContentStop(Handle contentHandle); +Result AMNET_InstallContentStop(Handle contentHandle); /** - * @brief Resumes installing title content. + * @brief Resumes installing a content. * @param[out] contentHandle Pointer to output a handle to write content data to. * @param[out] resumeOffset Pointer to write the offset to resume content installation at to. * @param index Index of the content to install. */ -Result AM_InstallContentResume(Handle *contentHandle, u64* resumeOffset, u16 index); +Result AMNET_InstallContentResume(Handle *contentHandle, u64* resumeOffset, u16 index); /** * @brief Cancels installing title content. - * @param contentHandle Handle of the installation to finalize. + * @param contentHandle Handle of the content installation to cancel. */ -Result AM_InstallContentCancel(Handle contentHandle); +Result AMNET_InstallContentCancel(Handle contentHandle); /** * @brief Finishes installing title content. * @param contentHandle Handle of the installation to finalize. */ -Result AM_InstallContentFinish(Handle contentHandle); +Result AMNET_InstallContentFinish(Handle contentHandle); /** - * @brief Imports up to four certificates into the ticket certificate chain. + * @brief Returns the number active content imports for the current title installation. + * @param[out] outNum Pointer to output the number of content imports to. + */ +Result AMNET_GetNumCurrentImportContentContexts(u32 *outNum); + +/** + * @brief Returns the content indices of the active content imports for the current title installation. + * @param[out] outNum Pointer to output the number of read content indices to. + * @param[out] outIndices Pointer to output the content indices to. + * @param count The maximum number of content indices to get. + */ +Result AMNET_GetCurrentImportContentContextsList(u32 *outNum, u16 *outIndices, u32 count); + +/** + * @brief Retrieves import content contexts for the active content imports of the current title installation. + * @param[out] outContexts Pointer to output the import content contexts to. + * @param indices Pointer to the content indices to retrieve import content contexts for. + * @param count Number of content indices or maximum number of import content contexts to retrieve. + */ +Result AMNET_GetCurrentImportContentContexts(AM_ImportContentContext *outContexts, u16 *indices, u32 count); + +/** + * @brief Signs the given message with ECDSA with SHA256 using the device certificate (CTCert) using a randomly generated public key. + * @param[out] outInternalResult Pointer to output an internal pxi:am9 result value to. + * @param[out] outSignature Pointer to output the signature data to. + * @param signatureSize The size of the output signature. This is usually 0x3C. + * @param[out] outCertificate Pointer to output the certificate data to. + * @param certificateSize The size of the output certificate. This is usually 0x180. + * @param indata Pointer to the input message to sign. + * @param indataSize Size of the input data. + * @param titleId Title ID to use in the signing process. + */ +Result AMNET_Sign(s32 *outInternalResult, void *outSignature, u32 signatureSize, void *outCertificate, u32 certificateSize, void *indata, u32 indataSize, u64 titleId); + +/** + * @brief Returns the device certificate of the system (CTCert). + * @param[out] outInternalResult Pointer to output an internal pxi:am9 result value to. + * @param[out] outCert Pointer to output the device certificate data to. + * @param certSize Size of the certificate. Must be 0x180. + */ +Result AMNET_GetCTCert(s32 *outInternalResult, void *outCert, u32 certSize); + +/** + * @brief Imports up to four certificates. * @param cert1Size Size of the first certificate. * @param cert1 Data of the first certificate. * @param cert2Size Size of the second certificate. @@ -485,54 +849,252 @@ Result AM_InstallContentFinish(Handle contentHandle); * @param cert4Size Size of the fourth certificate. * @param cert4 Data of the fourth certificate. */ -Result AM_ImportCertificates(u32 cert1Size, void* cert1, u32 cert2Size, void* cert2, u32 cert3Size, void* cert3, u32 cert4Size, void* cert4); +Result AMNET_ImportCertificates(u32 cert1Size, void* cert1, u32 cert2Size, void* cert2, u32 cert3Size, void* cert3, u32 cert4Size, void* cert4); /** - * @brief Imports a certificate into the ticket certificate chain. + * @brief Imports a certificate. * @param certSize Size of the certificate. * @param cert Data of the certificate. */ -Result AM_ImportCertificate(u32 certSize, void* cert); +Result AMNET_ImportCertificate(u32 certSize, void* cert); /** - * @brief Commits installed titles, and updates FIRM if necessary. + * @brief Commits pending titles, and installs NATIVE_FIRM if necessary. * @param mediaType Location of the titles to finalize. * @param titleCount Number of titles to finalize. - * @param temp Whether the titles being finalized are in the temporary database. + * @param temp Whether the titles being finalized are in the temporary import database. * @param titleIds Title IDs to finalize. */ -Result AM_CommitImportTitlesAndUpdateFirmwareAuto(FS_MediaType mediaType, u32 titleCount, bool temp, u64* titleIds); +Result AMNET_CommitImportTitlesAndInstallFirmAuto(FS_MediaType mediaType, u32 titleCount, bool temp, u64 *titleIds); + +/** + * @brief Deletes a title's ticket matching a certain ticket ID. + * @param titleId Title ID of the title. + * @param ticketId The ticket ID of the ticket to delete for the title. + */ +Result AMNET_DeleteTicket(u64 titleId, u64 ticketId); + +/** + * @brief Gets the number of ticket IDs for a certain title (a given title can have more than one ticket ID). + * @param[out] outNum Pointer to output the number of ticket IDs to. + * @param titleId Title ID of the title to retrieve the number of ticket IDs for. + */ +Result AMNET_GetTitleNumTicketIds(u32 *outNum, u64 titleId); + +/** + * @brief Retrieves the ticket IDs for all installed tickets of a title. + * @param[out] outNum Pointer to output the number of read ticket IDs to. + * @param[out] outTicketIds Pointer to output the ticket IDs to. + * @param count The maximum number of ticket IDs to retrieve. + * @param titleId The title ID of the title to retrieve ticket IDs for. + * @param verifyTickets Whether or not to verify the installed tickets as they're being read. + */ +Result AMNET_GetTitleTicketIds(u32 *outNum, u64 *outTicketIds, u32 count, u64 titleId, bool verifyTickets); + +/** + * @brief Gets the number of tickets for a certain title (a given title can have more than one ticket). + * @param[out] outNum Pointer to output the number of tickets to. + * @param titleId Title ID of the title to retrieve the number of tickets for. + */ +Result AMNET_GetTitleNumTickets(u32 *outNum, u64 titleId); + +/** + * @brief Retrieves information about a title's installed tickets (for any titles). + * @param[out] outNum Pointer to output the number of retrieved ticket infos to. + * @param[out] outInfos Pointer to output the ticket infos to. + * @param offset Offset of the ticket infos to start from within the entire list. + * @param count Maximum number of ticket infos to retrieve. + * @param titleId Title ID of the corresponding title. + */ +Result AMNET_GetTicketInfos(u32 *outNum, AM_TicketInfo *outInfos, u32 offset, u32 count, u64 titleId); + +/** + * @brief Exports a license ticket's raw (non-encrypted) data. + * @param[out] outActualSize Pointer to output the actual ticket size to. + * @param[out] outdata Pointer to output the raw license ticket data to. + * @param outdataSize Size of the output data buffer. + * @param titleId Ticket title ID of the ticket to export. + * @param ticketId Ticket ID of the license ticket to export. + */ +Result AMNET_ExportLicenseTicket(u32 *outActualSize, void *outdata, u32 outdataSize, u64 titleId, u64 ticketId); + +/** + * @brief Returns the number of contents in the TMD of the currently active title installation. + * @param[out] outNum Pointer to output the number of contents to. + */ +Result AMNET_GetNumCurrentContentInfos(u32 *outNum); + +/** + * @brief Finds content infos of the current content installation's TMD using the given content indices. + * @param[out] outInfos Pointer to output the content infos to. + * @param contentIndices Pointer to the content indices to look for. + * @param count Number of content indices. + */ +Result AMNET_FindCurrentContentInfos(AM_ContentInfo *outInfos, u16 *contentIndices, u32 count); + +/** + * @brief Retrieves content infos from the current content installation's TMD. + * @param[out] outNum Pointer to output the number of retrieved content infos to. + * @param[out] outInfos Pointer to output the content infos to. + * @param offset Offset to start from in the entire content info list. + * @param count Maximum number of content infos to retrieve. + */ +Result AMNET_ListCurrentContentInfos(u32 *outNum, AM_ContentInfo *outInfos, u32 offset, u32 count); + +/** + * @brief Calculates the total storage space required to install the provided optional (@ref AM_ContentTypeFlags) contents (e.g. for DLC). + * @param[out] outRequiredSize Pointer to output the total required size (in bytes) to. + * @param contentIndices Pointer to the input content indices for the optional contents to include in the size calculation. + * @param count Number of content indices. + * @param titleId Title ID of the corresponding title. + * @param mediaType Media type of the corresponding title. + */ +Result AMNET_CalculateContextRequiredSize(u64 *outRequiredSize, u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Similar to @ref AMNET_CreateImportContentContexts, but this command must be called after finializing the TMD installation but not while a content import is active. This command recreates the current title installation's import.db entry, and then proceeds to create new import content contexts for the given content indices. + */ +Result AMNET_UpdateImportContentContexts(u16 *contentIndices, u32 count); /// Resets play count of all installed demos by deleting their launch info. -Result AM_DeleteAllDemoLaunchInfos(void); +Result AMNET_DeleteAllDemoLaunchInfos(void); -/// Deletes temporary titles. -Result AM_DeleteAllTemporaryTitles(void); +/** + * @brief Begins a new title installation in overwrite mode. + * @param titleId Title ID of the title. + * @param mediaType Media type of the title. + */ +Result AMNET_InstallTitleBeginForOverwrite(u64 titleId, FS_MediaType mediaType); /** - * @brief Deletes all expired titles. - * @param mediatype Media type to delete from. + * @brief Exports an encrypted buffer containing a ticket to be sent to the CDN for title downloads. + * @param[out] outWrappedTicketSize Pointer to output the actual size of the encrypted ticket data to. + * @param[out] outKeyIvSize Pointer to output the actual size of the encryption key and IV to. + * @param[out] outWrappedTicket Pointer to output the encrypted ticket data to. + * @param wrappedTicketSize Size of the output ticket data buffer. + * @param[out] outKeyIv Pointer to output the encryption key and IV to. + * @param keyIvSize Size of the encryption key and IV buffer. + * @param titleId Title ID of the corresponding title. + * @param ticketId Ticket ID of the ticket to export. */ -Result AM_DeleteAllExpiredTitles(FS_MediaType mediatype); +Result AMNET_ExportTicketWrapped(u32 *outWrappedTicketSize, u32 *outKeyIvSize, void *outWrappedTicket, u32 wrappedTicketSize, void *outKeyIv, u32 keyIvSize, u64 titleId, u64 ticketId); -/// Deletes all TWL titles. -Result AM_DeleteAllTwlTitles(void); /** - * @brief Gets the number of content index installed under the specified DLC title. - * @param[out] count Pointer to output the number of content indices to. + * @brief Gets the number of contents in the TMD of the specified DLC title. + * @param[out] count Pointer to output the number of contents to. * @param mediatype Media type of the title. - * @param titleID Title ID to retrieve the count for (high-id is 0x0004008C). + * @param titleID Title ID to retrieve the count for. */ Result AMAPP_GetDLCContentInfoCount(u32* count, FS_MediaType mediatype, u64 titleID); /** - * @brief Gets content infos installed under the specified DLC title. + * @brief Finds content infos from the TMD of an installed DLC title. + * @param[out] outInfos Pointer to output the found content infos to. + * @param contentIndices Pointer to the content indices to find content infos for. + * @param count Maximum number of content infos to retrieve. + * @param titleId Title ID of the DLC title. + * @param mediaType Media type of the DLC title. + */ +Result AMAPP_FindDLCContentInfos(AM_ContentInfo *outInfos, u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Gets content infos from the TMD of the specified DLC title. * @param[out] contentInfoRead Pointer to output the number of content infos read to. * @param mediatype Media type of the title. - * @param titleID Title ID to retrieve the content infos for (high-id is 0x0004008C). + * @param titleID Title ID to retrieve the content infos for. * @param contentInfoCount Number of content infos to retrieve. * @param offset Offset from the first content index the count starts at. * @param[out] contentInfos Pointer to output the content infos read to. */ Result AMAPP_ListDLCContentInfos(u32* contentInfoRead, FS_MediaType mediatype, u64 titleID, u32 contentInfoCount, u32 offset, AM_ContentInfo* contentInfos); + +/** + * @brief Deletes a range of contents from an installed DLC title. + * @param contentIndices Pointer to the content indices of the contents to delete. + * @param count Number of given content indices. + * @param titleId Title ID of the DLC title to delete the contents from. + * @param mediaType Media type of the DLC title. + */ +Result AMAPP_DeleteDLCContents(u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Retrieves title information about installed DLC titles. + * @param[out] outInfos Pointer to output the read title infos to. + * @param titleIds Pointer to the input title IDs of the DLC titles to retrieve title infos for. + * @param count Number of input DLC title IDs, or the maximum number of title infos to retrieve. + * @param mediaType Media type of the given DLC titles. + */ +Result AMAPP_GetDLCTitleInfos(AM_TitleInfo *outInfos, u64 *titleIds, u32 count, FS_MediaType mediaType); + +/** + * @brief Returns the number of tickets installed for a given DLC or license title ID. + * @param[out] outNum Pointer to output the number of installed tickets to. + * @param titleId The input DLC or license ticket title ID. + */ +Result AMAPP_GetDLCOrLicenseNumTickets(u32 *outNum, u64 titleId); + +/** + * @brief Returns information about installed DLC or license tickets. + * @param[out] outNum Pointer to output the number of retrieved ticket infos to. + * @param[out] outInfos Pointer to output the retrieved ticket infos to. + * @param offset Offset to start from in the entire ticket infos list. + * @param count Maximum number of ticket infos to retrieve. + * @param titleId The input DLC or license ticket title ID. + */ +Result AMAPP_ListDLCOrLicenseTicketInfos(u32 *outNum, AM_TicketInfo *outInfos, u32 offset, u32 count, u64 titleId); + +/** + * @brief Retrieves rights data from a DLC or license ticket. This always reads at most rightsSize / (size of one record depending on rightsType). + * @param[out] outNumRecords Pointer to output the total number of records in the ticket corresponding to the given rights type. + * @param[out] outNextOffset Pointer to output the next offset to for iterating through the records. + * @param[out] outRights Pointer to output the rights records to. + * @param rightsSize Size of the rights record buffer. + * @param rightsType The type of rights record to retrieve. Allowed values range from 1 to 6, inclusive. + * @param recordOffset The record offset to start from in the entire rights record list of the given type. + * @param titleId The ticket title ID of the ticket to read. + * @param ticketId The ticket ID of the ticket to read. + */ +Result AMAPP_GetDLCOrLicenseItemRights(u32 *outNumRecords, u32 *outNextOffset, void *outRights, u32 rightsSize, u32 rightsType, u32 recordOffset, u64 titleId, u64 ticketId); + +/** + * @brief Returns whether or not the given DLC title is being accessed by one or more processes. + * @param[out] outInUse Pointer to output the status to. + * @param titleId The title ID of the DLC title to check. + * @param mediaType The media type of the DLC title to check. + */ +Result AMAPP_IsDLCTitleInUse(u8 *outInUse, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Queries whether the SD title database is available. + * @param[out] available Pointer to output the availability status to. + */ +Result AMAPP_QueryAvailableExternalTitleDatabase(bool* available); + +/** + * @brief Returns the number of installed contents for a DLC title. + * @param[out] outNum Pointer to output the number of installed contents to. + * @param titleId The title ID of the DLC title. + * @param mediaType Media type of the DLC title. + */ +Result AMAPP_GetNumExistingDLCContentInfos(u32 *outNum, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Retrieves information about the installed contents for a DLC title. + * @param[out] outNum Pointer to output the number of retrieved content infos to. + * @param[out] outInfos Pointer to output the content infos to. + * @param offset Offset to start from in the entire content info list. + * @param count Maximum number of content infos to retrieve. + * @param titleId The title ID of the DLC title. + * @param mediaType The media type of the DLC title. + */ +Result AMAPP_ListExistingDLCContentInfos(u32 *outNum, AM_ContentInfo *outInfos, u32 offset, u32 count, u64 titleId, FS_MediaType mediaType); + +/** + * @brief Returns information about installed patch (update) titles. + * @param[out] outInfos Pointer to output the title infos to. + * @param titleIds The title IDs of the patch titles to retrieve title infos for. + * @param count The number of given title IDs. + * @param mediaType The media type of the given titles. + */ +Result AMAPP_GetPatchTitleInfos(AM_TitleInfo *outInfos, u64 *titleIds, u32 count, FS_MediaType mediaType); diff --git a/libctru/source/services/am.c b/libctru/source/services/am.c index 7e791ab26..13975c133 100644 --- a/libctru/source/services/am.c +++ b/libctru/source/services/am.c @@ -1,14 +1,15 @@ -#include -#include -#include -#include <3ds/types.h> +#include <3ds/synchronization.h> +#include <3ds/services/am.h> +#include <3ds/services/fs.h> +#include <3ds/util/utf.h> #include <3ds/result.h> +#include <3ds/types.h> #include <3ds/svc.h> #include <3ds/srv.h> -#include <3ds/synchronization.h> -#include <3ds/services/am.h> #include <3ds/ipc.h> -#include <3ds/util/utf.h> + +#include +#include static Handle amHandle; static int amRefCount; @@ -84,7 +85,7 @@ Result AM_GetTitleList(u32* titlesRead, FS_MediaType mediatype, u32 titleCount, return (Result)cmdbuf[1]; } -Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM_TitleEntry *titleInfo) +Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM_TitleInfo *titleInfo) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -94,7 +95,7 @@ Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM cmdbuf[2] = titleCount; cmdbuf[3] = IPC_Desc_Buffer(titleCount*sizeof(u64),IPC_BUFFER_R); cmdbuf[4] = (u32)titleIds; - cmdbuf[5] = IPC_Desc_Buffer(titleCount*sizeof(AM_TitleEntry),IPC_BUFFER_W); + cmdbuf[5] = IPC_Desc_Buffer(titleCount*sizeof(AM_TitleInfo),IPC_BUFFER_W); cmdbuf[6] = (u32)titleInfo; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -102,6 +103,70 @@ Result AM_GetTitleInfo(FS_MediaType mediatype, u32 titleCount, u64 *titleIds, AM return (Result)cmdbuf[1]; } +Result AM_DeleteUserTitle(FS_MediaType mediatype, u64 titleID) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x4,3,0); // 0x000400C0 + cmdbuf[1] = mediatype; + cmdbuf[2] = titleID & 0xffffffff; + cmdbuf[3] = (u32)(titleID >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_GetTitleProductCode(FS_MediaType mediatype, u64 titleId, char *productCode) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x5,3,0); // 0x000500C0 + cmdbuf[1] = mediatype; + cmdbuf[2] = titleId & 0xffffffff; + cmdbuf[3] = (u32)(titleId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + // The product code string can use the full 16 bytes without NULL terminator + if(productCode) strncpy(productCode, (char*)&cmdbuf[2], 16); + + return (Result)cmdbuf[1]; +} + +Result AM_GetTitleExtDataId(u64 *extDataId, FS_MediaType mediatype, u64 titleId) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x6,3,0); // 0x000600C0 + cmdbuf[1] = mediatype; + cmdbuf[2] = titleId & 0xffffffff; + cmdbuf[3] = (u32)(titleId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + if(extDataId) *extDataId = (u64)cmdbuf[2] | ((u64)cmdbuf[3] << 32); + + return (Result)cmdbuf[1]; +} + +Result AM_DeleteTicket(u64 titleId) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x7,2,0); // 0x00070080 + cmdbuf[1] = titleId & 0xffffffff; + cmdbuf[2] = (u32)(titleId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + Result AM_GetTicketCount(u32 *count) { Result ret = 0; @@ -116,7 +181,7 @@ Result AM_GetTicketCount(u32 *count) return (Result)cmdbuf[1]; } -Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticketIds) +Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticketTitleIds) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -125,7 +190,7 @@ Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticket cmdbuf[1] = ticketCount; cmdbuf[2] = skip; cmdbuf[3] = IPC_Desc_Buffer(ticketCount*sizeof(u64),IPC_BUFFER_W); - cmdbuf[4] = (u32)ticketIds; + cmdbuf[4] = (u32)ticketTitleIds; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -134,42 +199,55 @@ Result AM_GetTicketList(u32 *ticketsRead, u32 ticketCount, u32 skip, u64 *ticket return (Result)cmdbuf[1]; } -Result AM_GetPendingTitleCount(u32 *count, FS_MediaType mediatype, u32 statusMask) +Result AM_GetDeviceId(s32 *outInternalResult, u32 *outDeviceId) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x23,2,0); // 0x00230080 - cmdbuf[1] = mediatype; - cmdbuf[2] = statusMask; + cmdbuf[0] = IPC_MakeHeader(0xA,0,0); // 0x000A0000 if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - if(count) *count = cmdbuf[2]; + if (outInternalResult) *outInternalResult = (s32)cmdbuf[2]; + if (outDeviceId) *outDeviceId = cmdbuf[3]; return (Result)cmdbuf[1]; } -Result AM_GetPendingTitleList(u32 *titlesRead, u32 titleCount, FS_MediaType mediatype, u32 statusMask, u64 *titleIds) +Result AM_GetNumPendingTitles(u32 *outNum, FS_MediaType mediaType) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x24,3,2); // 0x002400C2 - cmdbuf[1] = titleCount; - cmdbuf[2] = mediatype; - cmdbuf[3] = statusMask; - cmdbuf[4] = IPC_Desc_Buffer(titleCount*sizeof(u64),IPC_BUFFER_W); - cmdbuf[5] = (u32)titleIds; + cmdbuf[0] = IPC_MakeHeader(0xB, 1, 0); // 0x000B0040 + cmdbuf[1] = (u32)mediaType; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); - if(titlesRead) *titlesRead = cmdbuf[2]; + if (R_FAILED(res)) return res; + if (outNum) *outNum = cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *titleIds, AM_PendingTitleEntry *titleInfo) +Result AM_GetPendingTitleList(u32 *outNum, u64 *outTitleIds, u32 count, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xC, 2, 2); // 0x000C0082 + cmdbuf[1] = count; + cmdbuf[2] = (u32)mediaType; + cmdbuf[3] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_W); + cmdbuf[4] = (u32)outTitleIds; + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *titleIds, AM_PendingTitleInfo *titleInfo) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -179,7 +257,7 @@ Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *title cmdbuf[2] = mediatype; cmdbuf[3] = IPC_Desc_Buffer(titleCount*sizeof(u64),IPC_BUFFER_R); cmdbuf[4] = (u32)titleIds; - cmdbuf[5] = IPC_Desc_Buffer(titleCount*sizeof(AM_TitleEntry),IPC_BUFFER_W); + cmdbuf[5] = IPC_Desc_Buffer(titleCount*sizeof(AM_TitleInfo),IPC_BUFFER_W); cmdbuf[6] = (u32)titleInfo; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -187,20 +265,195 @@ Result AM_GetPendingTitleInfo(u32 titleCount, FS_MediaType mediatype, u64 *title return (Result)cmdbuf[1]; } -Result AM_GetDeviceId(u32 *deviceID) +Result AM_DeletePendingTitle(FS_MediaType mediatype, u64 titleId) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0xA,0,0); // 0x000A0000 + cmdbuf[0] = IPC_MakeHeader(0xE,3,0); // 0x000E00C0 + cmdbuf[1] = mediatype; + cmdbuf[2] = titleId & 0xffffffff; + cmdbuf[3] = (u32)(titleId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_GetNumImportContentContexts(u32 *outNum, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0xF, 3, 0); // 0x000F00C0 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AM_GetImportContentContextList(u32 *outNum, u16 *outContentIndices, u32 count, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x10, 4, 2); // 0x00100102 + cmdbuf[1] = count; + cmdbuf[2] = (u32)mediaType; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_W); + cmdbuf[6] = (u32)outContentIndices; + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AM_GetImportContentContexts(AM_ImportContentContext *outContexts, u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x11, 4, 4); // 0x00110104 + cmdbuf[1] = count; + cmdbuf[2] = (u32)mediaType; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[6] = (u32)contentIndices; + cmdbuf[7] = IPC_Desc_Buffer(count * sizeof(AM_ImportContentContext), IPC_BUFFER_W); + cmdbuf[8] = (u32)outContexts; + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AM_DeleteImportContentContexts(u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x12, 4, 2); // 0x00120102 + cmdbuf[1] = count; + cmdbuf[2] = (u32)mediaType; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[6] = (u32)contentIndices; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + return (Result)cmdbuf[1]; +} + +Result AM_NeedsCleanup(u8 *outNeedsCleanup, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x13, 1, 0); // 0x00130040 + cmdbuf[1] = (u32)mediaType; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNeedsCleanup) *outNeedsCleanup = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AM_DoCleanup(FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x14, 1, 0); // 0x00140040 + cmdbuf[1] = (u32)mediaType; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AM_DeleteAllPendingTitles(FS_MediaType mediatype) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x15,1,0); // 0x00150040 + cmdbuf[1] = mediatype; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - if(deviceID) *deviceID = cmdbuf[3]; + return (Result)cmdbuf[1]; +} + +Result AM_DeleteAllTemporaryTitles(void) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x16,0,0); // 0x00160000 + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } +Result AM_InitializeExternalTitleDatabase(bool overwrite) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x18,2,0); // 0x00180080 + cmdbuf[1] = 1; // No other media type is accepted + cmdbuf[2] = overwrite; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_QueryAvailableExternalTitleDatabase(bool* available) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x19,1,0); // 0x00190040 + cmdbuf[1] = 1; // No other media type is accepted + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + if(R_FAILED(ret = (Result)cmdbuf[1])) return ret; + + // Only accept this if the command was a success + if(available) *available = cmdbuf[2] & 0xFF; + + return ret; +} + +Result AM_CalculateTwlBackupSize(u64 *outSize, u64 titleId, u8 exportType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1A, 3, 0); // 0x001A00C0 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); + cmdbuf[3] = (u32)exportType; + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + + if (outSize) *outSize = *(u64 *)(&cmdbuf[2]); + return (Result)cmdbuf[1]; +} + Result AM_ExportTwlBackup(u64 titleID, u8 operation, void* workbuf, u32 workbuf_size, const char *filepath) { Result ret = 0; @@ -249,6 +502,18 @@ Result AM_ImportTwlBackup(Handle filehandle, u8 operation, void* buffer, u32 siz return (Result)cmdbuf[1]; } +Result AM_DeleteAllTwlUserTitles(void) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1D,0,0); // 0x001D0000 + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + Result AM_ReadTwlBackupInfo(Handle filehandle, void* outinfo, u32 outinfo_size, void* workbuf, u32 workbuf_size, void* banner, u32 banner_size) { Result ret = 0; @@ -262,10 +527,23 @@ Result AM_ReadTwlBackupInfo(Handle filehandle, void* outinfo, u32 outinfo_size, cmdbuf[5] = filehandle; cmdbuf[6] = IPC_Desc_Buffer(outinfo_size,IPC_BUFFER_W); cmdbuf[7] = (u32)outinfo; - cmdbuf[8] = IPC_Desc_Buffer(workbuf_size,IPC_BUFFER_W); - cmdbuf[9] = (u32)workbuf; - cmdbuf[10] = IPC_Desc_Buffer(banner_size,IPC_BUFFER_W); - cmdbuf[11] = (u32)banner; + cmdbuf[8] = IPC_Desc_Buffer(banner_size,IPC_BUFFER_W); + cmdbuf[9] = (u32)banner; + cmdbuf[10] = IPC_Desc_Buffer(workbuf_size,IPC_BUFFER_W); + cmdbuf[11] = (u32)workbuf; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_DeleteAllExpiredTitles(FS_MediaType mediatype) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1F,1,0); // 0x001F0040 + cmdbuf[1] = mediatype; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -286,253 +564,349 @@ Result AM_GetTWLPartitionInfo(AM_TWLPartitionInfo *info) return (Result)cmdbuf[1]; } -Result AM_StartCiaInstall(FS_MediaType mediatype, Handle *ciaHandle) +Result AM_GetPersonalizedTicketInfos(u32 *outNum, AM_TicketInfo *outInfos, u32 count) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x402,1,0); // 0x04020040 - cmdbuf[1] = mediatype; + cmdbuf[0] = IPC_MakeHeader(0x21, 1, 2); // 0x00210042 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(AM_TicketInfo), IPC_BUFFER_W); + cmdbuf[3] = (u32)outInfos; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); - if(ciaHandle) *ciaHandle = cmdbuf[3]; + if (R_FAILED(res)) return res; + if (outNum) *outNum = cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_StartDlpChildCiaInstall(Handle *ciaHandle) +Result AM_DeleteAllImportTitleContexts(FS_MediaType mediaType, u32 flags) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x22, 2, 0); // 0x00220080 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = flags; + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AM_GetNumImportTitleContexts(u32 *outNum, FS_MediaType mediaType, u32 flags) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x403,0,0); // 0x04030000 + cmdbuf[0] = IPC_MakeHeader(0x23,2,0); // 0x00230080 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = flags; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - if(ciaHandle) *ciaHandle = cmdbuf[3]; + if(outNum) *outNum = cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_CancelCIAInstall(Handle ciaHandle) +Result AM_GetImportTitleContextList(u32 *outNum, u32 count, FS_MediaType mediaType, u32 flags, u64 *titleIds) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x404,0,2); // 0x04040002 - cmdbuf[1] = IPC_Desc_MoveHandles(1); - cmdbuf[2] = ciaHandle; + cmdbuf[0] = IPC_MakeHeader(0x24,3,2); // 0x002400C2 + cmdbuf[1] = count; + cmdbuf[2] = (u32)mediaType; + cmdbuf[3] = flags; + cmdbuf[4] = IPC_Desc_Buffer(count*sizeof(u64),IPC_BUFFER_W); + cmdbuf[5] = (u32)titleIds; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + if(outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; } -Result AM_FinishCiaInstall(Handle ciaHandle) +Result AM_CheckContentRights(u8 *outHasRights, u64 titleId, u16 contentIndex) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x405,0,2); // 0x04050002 - cmdbuf[1] = IPC_Desc_MoveHandles(1); - cmdbuf[2] = ciaHandle; + cmdbuf[0] = IPC_MakeHeader(0x25, 3, 0); // 0x002500C0 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); + cmdbuf[3] = (u32)contentIndex; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + if (outHasRights) *outHasRights = (u8)cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_FinishCiaInstallWithoutCommit(Handle ciaHandle) +Result AM_GetTicketLimitInfo(AM_TicketLimitInfo *outInfos, u64 *titleIds, u32 count) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x406,0,2); // 0x04060002 - cmdbuf[1] = IPC_Desc_MoveHandles(1); - cmdbuf[2] = ciaHandle; + cmdbuf[0] = IPC_MakeHeader(0x26, 1, 4); // 0x00260044 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_R); + cmdbuf[3] = (u32)titleIds; + cmdbuf[4] = IPC_Desc_Buffer(count * sizeof(AM_TicketLimitInfo), IPC_BUFFER_W); + cmdbuf[5] = (u32)outInfos; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; return (Result)cmdbuf[1]; } -Result AM_CommitImportPrograms(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds) +Result AM_GetDemoLaunchInfo(AM_DemoLaunchInfo *outInfos, u64 *titleIds, u32 count) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x407,3,2); // 0x040700C2 - cmdbuf[1] = mediaType; - cmdbuf[2] = titleCount; - cmdbuf[3] = temp ? 1 : 0; - cmdbuf[4] = IPC_Desc_Buffer(titleCount * 8, IPC_BUFFER_R); - cmdbuf[5] = (u32)titleIds; + cmdbuf[0] = IPC_MakeHeader(0x27, 1, 4); // 0x00270044 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_R); + cmdbuf[3] = (u32)titleIds; + cmdbuf[4] = IPC_Desc_Buffer(count * sizeof(AM_DemoLaunchInfo), IPC_BUFFER_W); + cmdbuf[5] = (u32)outInfos; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; return (Result)cmdbuf[1]; } -Result AM_DeleteTitle(FS_MediaType mediatype, u64 titleID) +Result AM_ReadTwlBackupInfoEx(void *outInfo, u32 infoSize, void *outBanner, u32 bannerSize, void *workingBuffer, u32 workingBufferSize, Handle backupFile) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x410,3,0); // 0x041000C0 - cmdbuf[1] = mediatype; - cmdbuf[2] = titleID & 0xffffffff; - cmdbuf[3] = (u32)(titleID >> 32); + cmdbuf[0] = IPC_MakeHeader(0x28, 4, 8); // 0x00280108 + cmdbuf[1] = infoSize; + cmdbuf[2] = bannerSize; + cmdbuf[3] = workingBufferSize; + cmdbuf[4] = 0; // not used + cmdbuf[5] = IPC_Desc_MoveHandles(1); + cmdbuf[6] = backupFile; + cmdbuf[7] = IPC_Desc_Buffer(infoSize, IPC_BUFFER_W); + cmdbuf[8] = (u32)outInfo; + cmdbuf[9] = IPC_Desc_Buffer(bannerSize, IPC_BUFFER_W); + cmdbuf[10] = (u32)outBanner; + cmdbuf[11] = IPC_Desc_Buffer(workingBufferSize, IPC_BUFFER_W); + cmdbuf[12] = (u32)workingBuffer; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AM_DeleteUserTitles(u64 *titleIds, u32 count, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(0x29, 2, 2); // 0x00290082 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = count; + cmdbuf[3] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_R); + cmdbuf[4] = (u32)titleIds; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; return (Result)cmdbuf[1]; } -Result AM_DeleteAppTitle(FS_MediaType mediatype, u64 titleID) +Result AM_GetNumExistingContentInfos(u32 *outNum, u64 titleId, FS_MediaType mediaType) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x4,3,0); // 0x000400C0 - cmdbuf[1] = mediatype; - cmdbuf[2] = titleID & 0xffffffff; - cmdbuf[3] = (u32)(titleID >> 32); + cmdbuf[0] = IPC_MakeHeader(0x2A, 3, 0); // 0x002A00C0 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_DeleteTicket(u64 ticketId) +Result AM_ListExistingContentInfos(u32 *outNum, AM_ContentInfo *outInfos, u32 offset, u32 count, u64 titleId, FS_MediaType mediaType) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x7,2,0); // 0x00070080 - cmdbuf[1] = ticketId & 0xffffffff; - cmdbuf[2] = (u32)(ticketId >> 32); + cmdbuf[0] = IPC_MakeHeader(0x2B, 5, 2); // 0x002B0142 + cmdbuf[1] = count; + cmdbuf[2] = (u32)mediaType; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = offset; + cmdbuf[6] = IPC_Desc_Buffer(count * sizeof(AM_ContentInfo), IPC_BUFFER_W); + cmdbuf[7] = (u32)outInfos; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_DeletePendingTitle(FS_MediaType mediatype, u64 titleId) +Result AM_GetTitleInfosIgnorePlatform(AM_TitleInfo *outInfos, u64 *titleIds, u32 count, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x2C, 2, 4); // 0x002C0084 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = count; + cmdbuf[3] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_R); + cmdbuf[4] = (u32)titleIds; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(AM_TitleInfo), IPC_BUFFER_W); + cmdbuf[6] = (u32)outInfos; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AM_CheckContentRightsIgnorePlatform(u8 *outHasRights, u64 titleId, u16 contentIndex) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x2D, 3, 0); // 0x002D00C0 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); + cmdbuf[3] = (u32)contentIndex; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outHasRights) *outHasRights = (u8)cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + + +Result AM_InstallFirm(u64 titleID) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0xE,3,0); // 0x000E00C0 - cmdbuf[1] = mediatype; - cmdbuf[2] = titleId & 0xffffffff; - cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[0] = IPC_MakeHeader(0x401,2,0); // 0x04010080 + cmdbuf[1] = titleID & 0xffffffff; + cmdbuf[2] = (u32)(titleID >> 32); if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } -Result AM_DeletePendingTitles(FS_MediaType mediatype, u32 flags) +Result AM_StartCiaInstall(FS_MediaType mediatype, Handle *ciaHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x22,2,0); // 0x00220080 + cmdbuf[0] = IPC_MakeHeader(0x402,1,0); // 0x04020040 cmdbuf[1] = mediatype; - cmdbuf[2] = flags; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + if(ciaHandle) *ciaHandle = cmdbuf[3]; + return (Result)cmdbuf[1]; } -Result AM_DeleteAllPendingTitles(FS_MediaType mediatype) +Result AM_StartTempCiaInstall(Handle *ciaHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x15,1,0); // 0x00150040 - cmdbuf[1] = mediatype; + cmdbuf[0] = IPC_MakeHeader(0x403,0,0); // 0x04030000 if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + if(ciaHandle) *ciaHandle = cmdbuf[3]; + return (Result)cmdbuf[1]; } -Result AM_InstallNativeFirm(void) +Result AM_CancelCIAInstall(Handle ciaHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x40F,0,0); // 0x040F0000 + cmdbuf[0] = IPC_MakeHeader(0x404,0,2); // 0x04040002 + cmdbuf[1] = IPC_Desc_MoveHandles(1); + cmdbuf[2] = ciaHandle; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } -Result AM_InstallFirm(u64 titleID){ +Result AM_FinishCiaInstall(Handle ciaHandle) +{ Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x401,2,0); // 0x04010080 - cmdbuf[1] = titleID & 0xffffffff; - cmdbuf[2] = (u32)(titleID >> 32); + cmdbuf[0] = IPC_MakeHeader(0x405,0,2); // 0x04050002 + cmdbuf[1] = IPC_Desc_MoveHandles(1); + cmdbuf[2] = ciaHandle; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } -Result AM_GetTitleProductCode(FS_MediaType mediatype, u64 titleId, char *productCode) +Result AM_FinishCiaInstallWithoutCommit(Handle ciaHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x5,3,0); // 0x000500C0 - cmdbuf[1] = mediatype; - cmdbuf[2] = titleId & 0xffffffff; - cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[0] = IPC_MakeHeader(0x406,0,2); // 0x04060002 + cmdbuf[1] = IPC_Desc_MoveHandles(1); + cmdbuf[2] = ciaHandle; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - // The product code string can use the full 16 bytes without NULL terminator - if(productCode) strncpy(productCode, (char*)&cmdbuf[2], 16); - return (Result)cmdbuf[1]; } -Result AM_GetTitleExtDataId(u64 *extDataId, FS_MediaType mediatype, u64 titleId) +Result AM_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x6,3,0); // 0x000600C0 - cmdbuf[1] = mediatype; - cmdbuf[2] = titleId & 0xffffffff; - cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[0] = IPC_MakeHeader(0x407,3,2); // 0x040700C2 + cmdbuf[1] = mediaType; + cmdbuf[2] = titleCount; + cmdbuf[3] = temp ? 1 : 0; + cmdbuf[4] = IPC_Desc_Buffer(titleCount * sizeof(u64), IPC_BUFFER_R); + cmdbuf[5] = (u32)titleIds; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - if(extDataId) *extDataId = (u64)cmdbuf[2] | ((u64)cmdbuf[3] << 32); - return (Result)cmdbuf[1]; } -Result AM_GetCiaFileInfo(FS_MediaType mediatype, AM_TitleEntry *titleEntry, Handle fileHandle) +Result AM_GetCiaFileInfo(FS_MediaType mediatype, AM_TitleInfo *titleEntry, Handle fileHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x408,1,2); // 0x04080042 - cmdbuf[1] = mediatype; + cmdbuf[1] = (u32)mediatype; cmdbuf[2] = IPC_Desc_SharedHandles(1); cmdbuf[3] = fileHandle; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - if(titleEntry) memcpy(titleEntry, &cmdbuf[2], sizeof(AM_TitleEntry)); + if(titleEntry) memcpy(titleEntry, &cmdbuf[2], sizeof(AM_TitleInfo)); return (Result)cmdbuf[1]; } @@ -548,7 +922,7 @@ Result AM_GetCiaIcon(void *icon, Handle fileHandle) cmdbuf[3] = IPC_Desc_Buffer(0x36C0, IPC_BUFFER_W); cmdbuf[4] = (u32)icon; - if(R_FAILED(ret = svcSendSyncRequest(*amGetSessionHandle()))) return ret; + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } @@ -567,7 +941,7 @@ Result AM_GetCiaDependencies(u64 *dependencies, Handle fileHandle) staticbuf[0] = IPC_Desc_StaticBuffer(0x300, 0); staticbuf[1] = (u32)dependencies; - if(R_FAILED(ret = svcSendSyncRequest(*amGetSessionHandle()))) return ret; + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } @@ -581,7 +955,7 @@ Result AM_GetCiaMetaOffset(u64 *metaOffset, Handle fileHandle) cmdbuf[1] = IPC_Desc_SharedHandles(1); cmdbuf[2] = fileHandle; - if(R_FAILED(ret = svcSendSyncRequest(*amGetSessionHandle()))) return ret; + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; if(metaOffset) *metaOffset = cmdbuf[2] | ((u64)cmdbuf[3] << 32); @@ -597,7 +971,7 @@ Result AM_GetCiaCoreVersion(u32 *coreVersion, Handle fileHandle) cmdbuf[1] = IPC_Desc_SharedHandles(1); cmdbuf[2] = fileHandle; - if(R_FAILED(ret = svcSendSyncRequest(*amGetSessionHandle()))) return ret; + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; if(coreVersion) *coreVersion = cmdbuf[2]; @@ -614,13 +988,106 @@ Result AM_GetCiaRequiredSpace(u64 *requiredSpace, FS_MediaType mediaType, Handle cmdbuf[2] = IPC_Desc_SharedHandles(1); cmdbuf[3] = fileHandle; - if(R_FAILED(ret = svcSendSyncRequest(*amGetSessionHandle()))) return ret; + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; if(requiredSpace) *requiredSpace = cmdbuf[2] | ((u64)cmdbuf[3] << 32); return (Result)cmdbuf[1]; } +Result AM_CommitImportTitlesAndInstallFirmAuto(FS_MediaType mediaType, u32 titleCount, bool temp, u64* titleIds) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x40E,3,2); // 0x040E00C2 + cmdbuf[1] = mediaType; + cmdbuf[2] = titleCount; + cmdbuf[3] = temp ? 1 : 0; + cmdbuf[4] = IPC_Desc_Buffer(titleCount * sizeof(u64), IPC_BUFFER_R); + cmdbuf[5] = (u32)titleIds; + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_InstallFirmAuto(void) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x40F,0,0); // 0x040F0000 + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_DeleteTitle(FS_MediaType mediatype, u64 titleId) +{ + Result ret = 0; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x410,3,0); // 0x041000C0 + cmdbuf[1] = mediatype; + cmdbuf[2] = titleId & 0xffffffff; + cmdbuf[3] = (u32)(titleId >> 32); + + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_GetTwlTitleListForReboot(u32 *outNum, u64 *titleIds, u32 *contentIds, u32 count) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x411, 1, 4); // 0x04110044 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_W); + cmdbuf[3] = (u32)titleIds; + cmdbuf[4] = IPC_Desc_Buffer(count * sizeof(u32), IPC_BUFFER_W); + cmdbuf[5] = (u32)contentIds; + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AM_GetSystemUpdaterMutex(Handle *outMutex) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x412, 0, 0); // 0x04120000 + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + + if (outMutex) *outMutex = (Handle)cmdbuf[3]; + return (Result)cmdbuf[1]; +} + +Result AM_GetCiaMetaSize(u32 *outSize, Handle ciaFile) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x413, 0, 2); // 0x04130002 + cmdbuf[1] = IPC_Desc_SharedHandles(1); + cmdbuf[2] = ciaFile; + + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + + if (outSize) *outSize = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + Result AM_GetCiaMetaSection(void *meta, u32 size, Handle fileHandle) { Result ret = 0; @@ -633,43 +1100,87 @@ Result AM_GetCiaMetaSection(void *meta, u32 size, Handle fileHandle) cmdbuf[4] = IPC_Desc_Buffer(size, IPC_BUFFER_W); cmdbuf[5] = (u32)meta; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + + return (Result)cmdbuf[1]; +} + +Result AM_CheckDemoLaunchRight(u8 *outHasRight, u64 titleId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x415, 2, 0); // 0x04150080 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outHasRight) *outHasRight = (u8)cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AM_GetInternalTitleLocationInfo(AM_InternalTitleLocationInfo *outInfo, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x416, 3, 0); // 0x41600C0 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outInfo) memcpy(outInfo, &cmdbuf[2], sizeof(AM_InternalTitleLocationInfo)); + return (Result)cmdbuf[1]; +} + +Result AM_MigrateAGBToSAV(u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + cmdbuf[0] = IPC_MakeHeader(0x417, 3, 0); // 0x041700C0 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; return (Result)cmdbuf[1]; } -Result AM_InitializeExternalTitleDatabase(bool overwrite) +Result AM_StartCiaInstallOverwrite(Handle *outCiaHandle, FS_MediaType mediaType) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x18,2,0); // 0x180080 - cmdbuf[1] = 1; // No other media type is accepted - cmdbuf[2] = overwrite; + cmdbuf[0] = IPC_MakeHeader(0x418, 1, 0); // 0x04180040 + cmdbuf[1] = (u32)mediaType; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + + if (R_FAILED(res)) return res; + if (outCiaHandle) *outCiaHandle = (Handle)cmdbuf[3]; return (Result)cmdbuf[1]; } -Result AM_QueryAvailableExternalTitleDatabase(bool* available) +Result AM_StartSystemCiaInstall(Handle *outCiaHandle) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x19,1,0); // 0x190040 - cmdbuf[1] = 1; // No other media type is accepted + cmdbuf[0] = IPC_MakeHeader(0x419, 0, 0); // 0x04190000 - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - if(R_FAILED(ret = (Result)cmdbuf[1])) return ret; + Result res = svcSendSyncRequest(amHandle); - // Only accept this if the command was a success - if(available) *available = cmdbuf[2] & 0xFF; + if (R_FAILED(res)) return res; - return ret; + if (outCiaHandle) *outCiaHandle = (Handle)cmdbuf[3]; + return (Result)cmdbuf[1]; } -Result AM_InstallTicketBegin(Handle *ticketHandle) + +Result AMNET_InstallTicketBegin(Handle *ticketHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -683,7 +1194,7 @@ Result AM_InstallTicketBegin(Handle *ticketHandle) return (Result)cmdbuf[1]; } -Result AM_InstallTicketAbort(Handle ticketHandle) +Result AMNET_InstallTicketAbort(Handle ticketHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -697,7 +1208,7 @@ Result AM_InstallTicketAbort(Handle ticketHandle) return (Result)cmdbuf[1]; } -Result AM_InstallTicketFinish(Handle ticketHandle) +Result AMNET_InstallTicketFinish(Handle ticketHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -711,7 +1222,7 @@ Result AM_InstallTicketFinish(Handle ticketHandle) return (Result)cmdbuf[1]; } -Result AM_InstallTitleBegin(FS_MediaType mediaType, u64 titleId, bool unk) +Result AMNET_InstallTitleBegin(FS_MediaType mediaType, u64 titleId, bool inTempDb) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -720,14 +1231,14 @@ Result AM_InstallTitleBegin(FS_MediaType mediaType, u64 titleId, bool unk) cmdbuf[1] = mediaType; cmdbuf[2] = (u32) (titleId & 0xFFFFFFFF); cmdbuf[3] = (u32) ((titleId >> 32) & 0xFFFFFFFF); - cmdbuf[4] = unk; + cmdbuf[4] = inTempDb ? 1 : 0; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } -Result AM_InstallTitleStop(void) +Result AMNET_InstallTitleStop(void) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -739,7 +1250,7 @@ Result AM_InstallTitleStop(void) return (Result)cmdbuf[1]; } -Result AM_InstallTitleResume(FS_MediaType mediaType, u64 titleId) +Result AMNET_InstallTitleResume(FS_MediaType mediaType, u64 titleId) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -754,8 +1265,7 @@ Result AM_InstallTitleResume(FS_MediaType mediaType, u64 titleId) return (Result)cmdbuf[1]; } - -Result AM_InstallTitleAbort(void) +Result AMNET_InstallTitleAbort(void) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -767,7 +1277,7 @@ Result AM_InstallTitleAbort(void) return (Result)cmdbuf[1]; } -Result AM_InstallTitleFinish(void) +Result AMNET_InstallTitleFinish(void) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -779,7 +1289,7 @@ Result AM_InstallTitleFinish(void) return (Result)cmdbuf[1]; } -Result AM_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds) +Result AMNET_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, const u64* titleIds) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -788,7 +1298,7 @@ Result AM_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, cmdbuf[1] = mediaType; cmdbuf[2] = titleCount; cmdbuf[3] = temp ? 1 : 0; - cmdbuf[4] = IPC_Desc_Buffer(titleCount * 8, IPC_BUFFER_R); + cmdbuf[4] = IPC_Desc_Buffer(titleCount * sizeof(u64), IPC_BUFFER_R); cmdbuf[5] = (u32)titleIds; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -796,7 +1306,7 @@ Result AM_CommitImportTitles(FS_MediaType mediaType, u32 titleCount, bool temp, return (Result)cmdbuf[1]; } -Result AM_InstallTmdBegin(Handle *tmdHandle) +Result AMNET_InstallTmdBegin(Handle *tmdHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -810,7 +1320,7 @@ Result AM_InstallTmdBegin(Handle *tmdHandle) return (Result)cmdbuf[1]; } -Result AM_InstallTmdAbort(Handle tmdHandle) +Result AMNET_InstallTmdAbort(Handle tmdHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -824,13 +1334,13 @@ Result AM_InstallTmdAbort(Handle tmdHandle) return (Result)cmdbuf[1]; } -Result AM_InstallTmdFinish(Handle tmdHandle, bool unk) +Result AMNET_InstallTmdFinish(Handle tmdHandle, bool unk) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x80C,1,2); // 0x080C0042 - cmdbuf[1] = unk; + cmdbuf[1] = unk; /* this value is not used */ cmdbuf[2] = IPC_Desc_MoveHandles(1); cmdbuf[3] = tmdHandle; @@ -839,14 +1349,14 @@ Result AM_InstallTmdFinish(Handle tmdHandle, bool unk) return (Result)cmdbuf[1]; } -Result AM_CreateImportContentContexts(u32 contentCount, u16* contentIndices) +Result AMNET_CreateImportContentContexts(u32 contentCount, u16* contentIndices) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x80D,1,2); // 0x080D0042 cmdbuf[1] = contentCount; - cmdbuf[2] = IPC_Desc_Buffer(contentCount * 2, IPC_BUFFER_R); + cmdbuf[2] = IPC_Desc_Buffer(contentCount * sizeof(u16), IPC_BUFFER_R); cmdbuf[3] = (u32)contentIndices; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -854,7 +1364,7 @@ Result AM_CreateImportContentContexts(u32 contentCount, u16* contentIndices) return (Result)cmdbuf[1]; } -Result AM_InstallContentBegin(Handle *contentHandle, u16 index) +Result AMNET_InstallContentBegin(Handle *contentHandle, u16 index) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -869,7 +1379,7 @@ Result AM_InstallContentBegin(Handle *contentHandle, u16 index) return (Result)cmdbuf[1]; } -Result AM_InstallContentStop(Handle contentHandle) +Result AMNET_InstallContentStop(Handle contentHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -883,7 +1393,7 @@ Result AM_InstallContentStop(Handle contentHandle) return (Result)cmdbuf[1]; } -Result AM_InstallContentResume(Handle *contentHandle, u64* resumeOffset, u16 index) +Result AMNET_InstallContentResume(Handle *contentHandle, u64* resumeOffset, u16 index) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -899,7 +1409,7 @@ Result AM_InstallContentResume(Handle *contentHandle, u64* resumeOffset, u16 ind return (Result)cmdbuf[1]; } -Result AM_InstallContentCancel(Handle contentHandle) +Result AMNET_InstallContentCancel(Handle contentHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -913,7 +1423,7 @@ Result AM_InstallContentCancel(Handle contentHandle) return (Result)cmdbuf[1]; } -Result AM_InstallContentFinish(Handle contentHandle) +Result AMNET_InstallContentFinish(Handle contentHandle) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -927,31 +1437,116 @@ Result AM_InstallContentFinish(Handle contentHandle) return (Result)cmdbuf[1]; } -Result AM_ImportCertificates(u32 cert1Size, void* cert1, u32 cert2Size, void* cert2, u32 cert3Size, void* cert3, u32 cert4Size, void* cert4) +Result AMNET_GetNumCurrentImportContentContexts(u32 *outNum) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x813, 0, 0); // 0x08130000 + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + + return (Result)cmdbuf[1]; +} + +Result AMNET_GetCurrentImportContentContextsList(u32 *outNum, u16 *outIndices, u32 count) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x814, 1, 2); // 0x08140040 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_W); + cmdbuf[3] = (u32)outIndices; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_GetCurrentImportContentContexts(AM_ImportContentContext *outContexts, u16 *indices, u32 count) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x815, 1, 4); // 0x08150044 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[3] = (u32)indices; + cmdbuf[4] = IPC_Desc_Buffer(count * sizeof(AM_ImportContentContext), IPC_BUFFER_W); + cmdbuf[5] = (u32)outContexts; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AMNET_Sign(s32 *outInternalResult, void *outSignature, u32 signatureSize, void *outCertificate, u32 certificateSize, void *indata, u32 indataSize, u64 titleId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x816, 5, 6); // 0x08160146 + cmdbuf[1] = signatureSize; + cmdbuf[2] = certificateSize; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = indataSize; + cmdbuf[6] = IPC_Desc_Buffer(indataSize, IPC_BUFFER_R); + cmdbuf[7] = (u32)indata; + cmdbuf[8] = IPC_Desc_Buffer(signatureSize, IPC_BUFFER_W); + cmdbuf[9] = (u32)outSignature; + cmdbuf[10] = IPC_Desc_Buffer(certificateSize, IPC_BUFFER_W); + cmdbuf[11] = (u32)outCertificate; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outInternalResult) *outInternalResult = (s32)cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_GetCTCert(s32 *outInternalResult, void *outCert, u32 certSize) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x818, 1, 2); // 0x08180042 + cmdbuf[1] = certSize; + cmdbuf[2] = IPC_Desc_Buffer(certSize, IPC_BUFFER_W); + cmdbuf[3] = (u32)outCert; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outInternalResult) *outInternalResult = (s32)cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_ImportCertificates(u32 cert1Size, void* cert1, u32 cert2Size, void* cert2, u32 cert3Size, void* cert3, u32 cert4Size, void* cert4) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x819,4,8); // 0x08190108 - cmdbuf[1] = cert1Size; - cmdbuf[2] = cert2Size; - cmdbuf[3] = cert3Size; - cmdbuf[4] = cert4Size; - cmdbuf[5] = IPC_Desc_Buffer(cert1Size, IPC_BUFFER_R); - cmdbuf[6] = (u32)cert1; - cmdbuf[7] = IPC_Desc_Buffer(cert2Size, IPC_BUFFER_R); - cmdbuf[8] = (u32)cert2; - cmdbuf[9] = IPC_Desc_Buffer(cert3Size, IPC_BUFFER_R); + cmdbuf[0] = IPC_MakeHeader(0x819,4,8); // 0x08190108 + cmdbuf[1] = cert1Size; + cmdbuf[2] = cert2Size; + cmdbuf[3] = cert3Size; + cmdbuf[4] = cert4Size; + cmdbuf[5] = IPC_Desc_Buffer(cert1Size, IPC_BUFFER_R); + cmdbuf[6] = (u32)cert1; + cmdbuf[7] = IPC_Desc_Buffer(cert2Size, IPC_BUFFER_R); + cmdbuf[8] = (u32)cert2; + cmdbuf[9] = IPC_Desc_Buffer(cert3Size, IPC_BUFFER_R); cmdbuf[10] = (u32)cert3; cmdbuf[11] = IPC_Desc_Buffer(cert4Size, IPC_BUFFER_R); cmdbuf[12] = (u32)cert4; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; - return (Result)cmdbuf[1]; } -Result AM_ImportCertificate(u32 certSize, void* cert) +Result AMNET_ImportCertificate(u32 certSize, void* cert) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -966,7 +1561,7 @@ Result AM_ImportCertificate(u32 certSize, void* cert) return (Result)cmdbuf[1]; } -Result AM_CommitImportTitlesAndUpdateFirmwareAuto(FS_MediaType mediaType, u32 titleCount, bool temp, u64* titleIds) +Result AMNET_CommitImportTitlesAndInstallFirmAuto(FS_MediaType mediaType, u32 titleCount, bool temp, u64* titleIds) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); @@ -975,7 +1570,7 @@ Result AM_CommitImportTitlesAndUpdateFirmwareAuto(FS_MediaType mediaType, u32 ti cmdbuf[1] = mediaType; cmdbuf[2] = titleCount; cmdbuf[3] = temp ? 1 : 0; - cmdbuf[4] = IPC_Desc_Buffer(titleCount * 8, IPC_BUFFER_R); + cmdbuf[4] = IPC_Desc_Buffer(titleCount * sizeof(u64), IPC_BUFFER_R); cmdbuf[5] = (u32)titleIds; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -983,55 +1578,242 @@ Result AM_CommitImportTitlesAndUpdateFirmwareAuto(FS_MediaType mediaType, u32 ti return (Result)cmdbuf[1]; } -Result AM_DeleteAllDemoLaunchInfos(void) +Result AMNET_DeleteTicket(u64 titleId, u64 ticketId) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x827,0,0); // 0x8270000 + cmdbuf[0] = IPC_MakeHeader(0x81C, 4, 0); // 0x081C0100 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); + cmdbuf[3] = ticketId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(ticketId >> 32); - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AMNET_GetTitleNumTicketIds(u32 *outNum, u64 titleId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81D, 2, 0); // 0x081D0080 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_DeleteAllTemporaryTitles(void) +Result AMNET_GetTitleTicketIds(u32 *outNum, u64 *outTicketIds, u32 count, u64 titleId, bool verifyTickets) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81E, 4, 2); // 0x081E0102 + cmdbuf[1] = count; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[4] = verifyTickets ? 1 : 0; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_W); + cmdbuf[6] = (u32)outTicketIds; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_GetTitleNumTickets(u32 *outNum, u64 titleId) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x16,0,0); // 0x160000 + cmdbuf[0] = IPC_MakeHeader(0x81F, 2, 0); // 0x081F0080 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; return (Result)cmdbuf[1]; } -Result AM_DeleteAllExpiredTitles(FS_MediaType mediatype) +Result AMNET_GetTicketInfos(u32 *outNum, AM_TicketInfo *outInfos, u32 offset, u32 count, u64 titleId) { - Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x1F,1,0); // 0x1F0040 - cmdbuf[1] = mediatype; + cmdbuf[0] = IPC_MakeHeader(0x820, 4, 2); // 0x08200102 + cmdbuf[1] = count; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[4] = offset; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(AM_TicketInfo), IPC_BUFFER_W); + cmdbuf[6] = (u32)outInfos; - if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_ExportLicenseTicket(u32 *outActualSize, void *outdata, u32 outdataSize, u64 titleId, u64 ticketId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x821, 5, 2); // 0x08210142 + cmdbuf[1] = outdataSize; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[4] = ticketId & 0xFFFFFFFF; + cmdbuf[5] = (u32)(ticketId >> 32); + cmdbuf[6] = IPC_Desc_Buffer(outdataSize, IPC_BUFFER_W); + cmdbuf[7] = (u32)outdata; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outActualSize) *outActualSize = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_GetNumCurrentContentInfos(u32 *outNum) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x822, 0, 0); // 0x08220000 + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_FindCurrentContentInfos(AM_ContentInfo *outInfos, u16 *contentIndices, u32 count) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x823, 1, 4); // 0x08230044 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[3] = (u32)contentIndices; + cmdbuf[4] = IPC_Desc_Buffer(count * sizeof(AM_ContentInfo), IPC_BUFFER_W); + cmdbuf[5] = (u32)outInfos; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + return (Result)cmdbuf[1]; +} + +Result AMNET_ListCurrentContentInfos(u32 *outNum, AM_ContentInfo *outInfos, u32 offset, u32 count) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x824, 2, 2); // 0x08240082 + cmdbuf[1] = count; + cmdbuf[2] = offset; + cmdbuf[3] = IPC_Desc_Buffer(count * sizeof(AM_ContentInfo), IPC_BUFFER_W); + cmdbuf[4] = (u32)outInfos; + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMNET_CalculateContextRequiredSize(u64 *outRequiredSize, u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x825, 4, 2); // 0x08250102 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[4] = count; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[6] = (u32)contentIndices; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outRequiredSize) *outRequiredSize = *((u64 *)(&cmdbuf[2])); + return (Result)cmdbuf[1]; +} + +Result AMNET_UpdateImportContentContexts(u16 *contentIndices, u32 count) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x826, 1, 2); // 0x08260042 + cmdbuf[1] = count; + cmdbuf[2] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[3] = (u32)contentIndices; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; return (Result)cmdbuf[1]; } -Result AM_DeleteAllTwlTitles(void) +Result AMNET_DeleteAllDemoLaunchInfos(void) { Result ret = 0; u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x1D,0,0); // 0x1D0000 + cmdbuf[0] = IPC_MakeHeader(0x827,0,0); // 0x8270000 if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; return (Result)cmdbuf[1]; } +Result AMNET_InstallTitleBeginForOverwrite(u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x828, 3, 0); // 0x082800C0 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AMNET_ExportTicketWrapped(u32 *outWrappedTicketSize, u32 *outKeyIvSize, void *outWrappedTicket, u32 wrappedTicketSize, void *outKeyIv, u32 keyIvSize, u64 titleId, u64 ticketId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x829, 6, 4); // 0x08290184 + cmdbuf[1] = wrappedTicketSize; + cmdbuf[2] = keyIvSize; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = ticketId & 0xFFFFFFFF; + cmdbuf[6] = (u32)(ticketId >> 32); + cmdbuf[7] = IPC_Desc_Buffer(wrappedTicketSize, IPC_BUFFER_W); + cmdbuf[8] = (u32)outWrappedTicket; + cmdbuf[9] = IPC_Desc_Buffer(keyIvSize, IPC_BUFFER_W); + cmdbuf[10] = (u32)outKeyIv; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outWrappedTicketSize) *outWrappedTicketSize = cmdbuf[2]; + if (outKeyIvSize) *outKeyIvSize = cmdbuf[3]; + return (Result)cmdbuf[1]; +} + + Result AMAPP_GetDLCContentInfoCount(u32* count, FS_MediaType mediatype, u64 titleID) { Result ret = 0; @@ -1049,6 +1831,25 @@ Result AMAPP_GetDLCContentInfoCount(u32* count, FS_MediaType mediatype, u64 titl return (Result)cmdbuf[1]; } +Result AMAPP_FindDLCContentInfos(AM_ContentInfo *outInfos, u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1002, 4, 4); // 0x10020104 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[4] = count; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[6] = (u32)contentIndices; + cmdbuf[7] = IPC_Desc_Buffer(count * sizeof(AM_ContentInfo), IPC_BUFFER_W); + cmdbuf[8] = (u32)outInfos; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + Result AMAPP_ListDLCContentInfos(u32* contentInfoRead, FS_MediaType mediatype, u64 titleID, u32 contentInfoCount, u32 offset, AM_ContentInfo* contentInfos) { Result ret = 0; @@ -1060,7 +1861,7 @@ Result AMAPP_ListDLCContentInfos(u32* contentInfoRead, FS_MediaType mediatype, u cmdbuf[3] = titleID & 0xffffffff; cmdbuf[4] = (u32)(titleID >> 32); cmdbuf[5] = offset; - cmdbuf[6] = IPC_Desc_Buffer(contentInfoCount * 0x18, IPC_BUFFER_W); + cmdbuf[6] = IPC_Desc_Buffer(contentInfoCount * sizeof(AM_ContentInfo), IPC_BUFFER_W); cmdbuf[7] = (u32)contentInfos; if(R_FAILED(ret = svcSendSyncRequest(amHandle))) return ret; @@ -1069,3 +1870,176 @@ Result AMAPP_ListDLCContentInfos(u32* contentInfoRead, FS_MediaType mediatype, u return (Result)cmdbuf[1]; } + +Result AMAPP_DeleteDLCContents(u16 *contentIndices, u32 count, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1004, 4, 2); // 0x10040102 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[4] = count; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(u16), IPC_BUFFER_R); + cmdbuf[6] = (u32)contentIndices; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AMAPP_GetDLCTitleInfos(AM_TitleInfo *outInfos, u64 *titleIds, u32 count, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1005, 2, 4); // 0x10050084 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = count; + cmdbuf[3] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_R); + cmdbuf[4] = (u32)titleIds; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(AM_TitleInfo), IPC_BUFFER_W); + cmdbuf[6] = (u32)outInfos; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +} + +Result AMAPP_GetDLCOrLicenseNumTickets(u32 *outNum, u64 titleId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1006, 2, 0); // 0x10060080 + cmdbuf[1] = titleId & 0xFFFFFFFF; + cmdbuf[2] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMAPP_ListDLCOrLicenseTicketInfos(u32 *outNum, AM_TicketInfo *outInfos, u32 offset, u32 count, u64 titleId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1007, 4, 2); // 0x10070102 + cmdbuf[1] = count; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + cmdbuf[4] = offset; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(AM_TicketInfo), IPC_BUFFER_W); + cmdbuf[6] = (u32)outInfos; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMAPP_GetDLCOrLicenseItemRights(u32 *outNumRecords, u32 *outNextOffset, void *outRights, u32 rightsSize, u32 rightsType, u32 recordOffset, u64 titleId, u64 ticketId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1008, 7, 2); // 0x100801C2 + cmdbuf[1] = rightsSize; + cmdbuf[2] = rightsType; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = ticketId & 0xFFFFFFFF; + cmdbuf[6] = (u32)(ticketId >> 32); + cmdbuf[7] = recordOffset; + cmdbuf[8] = IPC_Desc_Buffer(rightsSize, IPC_BUFFER_W); + cmdbuf[9] = (u32)outRights; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNumRecords) *outNumRecords = cmdbuf[2]; + if (outNextOffset) *outNextOffset = cmdbuf[3]; + return (Result)cmdbuf[1]; +} + +Result AMAPP_IsDLCTitleInUse(u8 *outInUse, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x1009, 3, 0); // 0x100900C0 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outInUse) *outInUse = (u8)cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMAPP_QueryAvailableExternalTitleDatabase(bool *available) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x100A, 0, 0); // 0x100A0000 + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (available) *available = (u8)cmdbuf[2] == 1; + return (Result)cmdbuf[1]; +} + +Result AMAPP_GetNumExistingDLCContentInfos(u32 *outNum, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x100B, 3, 0); // 0x100B00C0 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = titleId & 0xFFFFFFFF; + cmdbuf[3] = (u32)(titleId >> 32); + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMAPP_ListExistingDLCContentInfos(u32 *outNum, AM_ContentInfo *outInfos, u32 offset, u32 count, u64 titleId, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x100C, 5, 2); // 0x100C0142 + cmdbuf[1] = count; + cmdbuf[2] = (u32)mediaType; + cmdbuf[3] = titleId & 0xFFFFFFFF; + cmdbuf[4] = (u32)(titleId >> 32); + cmdbuf[5] = offset; + cmdbuf[6] = IPC_Desc_Buffer(count * sizeof(AM_ContentInfo), IPC_BUFFER_W); + cmdbuf[7] = (u32)outInfos; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + + if (outNum) *outNum = cmdbuf[2]; + return (Result)cmdbuf[1]; +} + +Result AMAPP_GetPatchTitleInfos(AM_TitleInfo *outInfos, u64 *titleIds, u32 count, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x100D, 2, 4); // 0x100D0084 + cmdbuf[1] = (u32)mediaType; + cmdbuf[2] = count; + cmdbuf[3] = IPC_Desc_Buffer(count * sizeof(u64), IPC_BUFFER_R); + cmdbuf[4] = (u32)titleIds; + cmdbuf[5] = IPC_Desc_Buffer(count * sizeof(AM_TitleInfo), IPC_BUFFER_W); + cmdbuf[6] = (u32)outInfos; + + Result res = svcSendSyncRequest(amHandle); + if (R_FAILED(res)) return res; + return (Result)cmdbuf[1]; +}