diff --git a/libctru/include/3ds.h b/libctru/include/3ds.h index 004ad78..44b91d2 100644 --- a/libctru/include/3ds.h +++ b/libctru/include/3ds.h @@ -49,6 +49,7 @@ extern "C" { #include <3ds/services/mvd.h> #include <3ds/services/news.h> #include <3ds/services/qtm.h> +#include <3ds/services/srvpm.h> #include <3ds/services/y2r.h> #include <3ds/services/hb.h> diff --git a/libctru/include/3ds/services/fs.h b/libctru/include/3ds/services/fs.h index 0e5bd3d..fc88c25 100644 --- a/libctru/include/3ds/services/fs.h +++ b/libctru/include/3ds/services/fs.h @@ -6,106 +6,231 @@ #include <3ds/types.h> -///@name FS Open Flags -///@{ -/// Open file for read. -#define FS_OPEN_READ (1<<0) -/// Open file for write. -#define FS_OPEN_WRITE (1<<1) -/// Create file if it doesn't exist. -#define FS_OPEN_CREATE (1<<2) -/// @} +/// Open flags. +enum +{ + FS_OPEN_READ = BIT(0), ///< Open for reading. + FS_OPEN_WRITE = BIT(1), ///< Open for writing. + FS_OPEN_CREATE = BIT(2), ///< Create file. +}; -///@name FS Create Attributes -///@{ -/// No attributes. -#define FS_ATTRIBUTE_NONE (0x00000000) -/// Create with read-only attribute. -#define FS_ATTRIBUTE_READONLY (0x00000001) -/// Create with archive attribute. -#define FS_ATTRIBUTE_ARCHIVE (0x00000100) -/// Create with hidden attribute. -#define FS_ATTRIBUTE_HIDDEN (0x00010000) -/// Create with directory attribute. -#define FS_ATTRIBUTE_DIRECTORY (0x01000000) -/// @} +/// Write flags. +enum +{ + FS_WRITE_FLUSH = BIT(0), ///< Flush. + FS_WRITE_UPDATE_TIME = BIT(8), ///< Update file timestamp. +}; -///@name FS Flush Flags -///@{ -/// Don't flush -#define FS_WRITE_NOFLUSH (0x00000000) -/// Flush -#define FS_WRITE_FLUSH (0x00010001) -/// @} +/// Attribute flags. +enum +{ + FS_ATTRIBUTE_READ_ONLY = BIT(0), ///< Read-only. + FS_ATTRIBUTE_ARCHIVE = BIT(8), ///< Archive. + FS_ATTRIBUTE_HIDDEN = BIT(16), ///< Hidden. + FS_ATTRIBUTE_DIRECTORY = BIT(24), ///< Directory. +}; -/// FS path type. +/// Media types. typedef enum { - PATH_INVALID = 0, ///< Specifies an invalid path. - PATH_EMPTY = 1, ///< Specifies an empty path. - PATH_BINARY = 2, ///< Specifies a binary path, which is non-text based. - PATH_CHAR = 3, ///< Specifies a text based path with a 8-bit byte per character. - PATH_WCHAR = 4, ///< Specifies a text based path with a 16-bit short per character. -} FS_pathType; + MEDIATYPE_NAND = 0, ///< NAND. + MEDIATYPE_SD = 1, ///< SD card. + MEDIATYPE_GAME_CARD = 2, ///< Game card. +} FS_MediaType; -/// FS archive IDs. +/// Archive IDs. typedef enum { - ARCH_ROMFS = 0x3, ///< RomFS archive. - ARCH_SAVEDATA = 0x4, ///< Save data archive. - ARCH_EXTDATA = 0x6, ///< Ext data archive. - ARCH_SHARED_EXTDATA = 0x7, ///< Shared ext data archive. - ARCH_SYSTEM_SAVEDATA = 0x8, ///< System save data archive. - ARCH_SDMC = 0x9, ///< SDMC archive. - ARCH_SDMC_WRITE_ONLY = 0xA, ///< Write-only SDMC archive. - ARCH_BOSS_EXTDATA = 0x12345678, ///< BOSS ext data archive. - ARCH_CARD_SPIFS = 0x12345679, ///< Card SPIFS archive. - ARCH_NAND_RW = 0x1234567D, ///< Read-write NAND archive. - ARCH_NAND_RO = 0x1234567E, ///< Read-only NAND archive. - ARCH_NAND_RO_WRITE_ACCESS = 0x1234567F, ///< Read-only write access NAND archive. -} FS_archiveIds; + ARCHIVE_ROMFS = 0x00000003, ///< RomFS archive. + ARCHIVE_SAVEDATA = 0x00000004, ///< Save data archive. + ARCHIVE_EXTDATA = 0x00000006, ///< Ext data archive. + ARCHIVE_SHARED_EXTDATA = 0x00000007, ///< Shared ext data archive. + ARCHIVE_SYSTEM_SAVEDATA = 0x00000008, ///< System save data archive. + ARCHIVE_SDMC = 0x00000009, ///< SDMC archive. + ARCHIVE_SDMC_WRITE_ONLY = 0x0000000A, ///< Write-only SDMC archive. + ARCHIVE_BOSS_EXTDATA = 0x12345678, ///< BOSS ext data archive. + ARCHIVE_CARD_SPIFS = 0x12345679, ///< Card SPI FS archive. + ARCHIVE_EXTDATA_AND_BOSS_EXTDATA = 0x1234567B, ///< Ext data and BOSS ext data archive. + ARCHIVE_SYSTEM_SAVEDATA2 = 0x1234567C, ///< System save data archive. + ARCHIVE_NAND_RW = 0x1234567D, ///< Read-write NAND archive. + ARCHIVE_NAND_RO = 0x1234567E, ///< Read-only NAND archive. + ARCHIVE_NAND_RO_WRITE_ACCESS = 0x1234567F, ///< Read-only write access NAND archive. + ARCHIVE_SAVEDATA_AND_CONTENT = 0x2345678A, ///< User save data and ExeFS/RomFS archive. + ARCHIVE_SAVEDATA_AND_CONTENT2 = 0x2345678E, ///< User save data and ExeFS/RomFS archive (only ExeFS for fs:LDR). + ARCHIVE_NAND_CTR_FS = 0x567890AB, ///< NAND CTR FS archive. + ARCHIVE_TWL_PHOTO = 0x567890AC, ///< TWL PHOTO archive. + ARCHIVE_NAND_TWL_FS = 0x567890AE, ///< NAND TWL FS archive. + ARCHIVE_NAND_W_FS = 0x567890AF, ///< NAND W FS archive. + ARCHIVE_GAMECARD_SAVEDATA = 0x567890B1, ///< Game card save data archive. + ARCHIVE_USER_SAVEDATA = 0x567890B2, ///< User save data archive. + ARCHIVE_DEMO_SAVEDATA = 0x567890B4, ///< Demo save data archive. +} FS_ArchiveID; -/// FS path. -typedef struct +/// Path types. +typedef enum { - FS_pathType type; ///< FS path type. - u32 size; ///< FS path size. - const u8 *data; ///< Pointer to FS path data. -} FS_path; + PATH_INVALID = 0, ///< Invalid path. + PATH_EMPTY = 1, ///< Empty path. + PATH_BINARY = 2, ///< Binary path. Meaning is per-archive. + PATH_ASCII = 3, ///< ASCII text path. + PATH_UTF16 = 4, ///< UTF-16 text path. +} FS_PathType; -/// FS archive. -typedef struct +/// Secure value slot. +typedef enum { - u32 id; ///< Archive ID. - FS_path lowPath; ///< FS path. - Handle handleLow; ///< High word of handle. - Handle handleHigh; ///< Low word of handle. -} FS_archive; + SECUREVALUE_SLOT_SD = 0x1000, ///< SD application. +} FS_SecureValueSlot; + +/// Card SPI baud rate. +typedef enum +{ + BAUDRATE_512KHZ = 0, ///< 512KHz. + BAUDRATE_1MHZ = 1, ///< 1MHz. + BAUDRATE_2MHZ = 2, ///< 2MHz. + BAUDRATE_4MHZ = 3, ///< 4MHz. + BAUDRATE_8MHZ = 4, ///< 8MHz. + BAUDRATE_16MHZ = 5, ///< 16MHz. +} FS_CardSpiBaudRate; + +/// Card SPI bus mode. +typedef enum +{ + BUSMODE_1BIT = 0, ///< 1-bit. + BUSMODE_4BIT = 1, ///< 4-bit. +} FS_CardSpiBusMode; + +/// Card SPI bus mode. +typedef enum +{ + SPECIALCONTENT_UPDATE = 1, ///< Update. + SPECIALCONTENT_MANUAL = 2, ///< Manual. + SPECIALCONTENT_DLP_CHILD = 3, ///< DLP child. +} FS_SpecialContentType; + +typedef enum +{ + CARD_CTR = 0, ///< CTR card. + CARD_TWL = 1, ///< TWL card. +} FS_CardType; + +/// FS control actions. +typedef enum +{ + FS_ACTION_UNKNOWN = 0, +} FS_Action; + +/// Archive control actions. +typedef enum +{ + ARCHIVE_ACTION_COMMIT_SAVE_DATA = 0, ///< Commits save data changes. No inputs/outputs. + ARCHIVE_ACTION_GET_TIMESTAMP = 1, ///< Retrieves a file's last-modified timestamp. In: "u16*, UTF-16 Path", Out: "u64, Time Stamp". +} FS_ArchiveAction; + +/// Secure save control actions. +typedef enum +{ + SECURESAVE_ACTION_DELETE = 0, ///< Deletes a save's secure value. In: "u64, ((SecureValueSlot << 32) | (TitleUniqueId << 8) | TitleVariation)", Out: "u8, Value Existed" + SECURESAVE_ACTION_FORMAT = 1, ///< Formats a save. No inputs/outputs. +} FS_SecureSaveAction; + +/// File control actions. +typedef enum +{ + FILE_ACTION_UNKNOWN = 0, +} FS_FileAction; + +/// Directory control actions. +typedef enum +{ + DIRECTORY_ACTION_UNKNOWN = 0, +} FS_DirectoryAction; /// Directory entry. typedef struct { - // 0x00 - u16 name[0x106]; ///< UTF-16 encoded name - // 0x20C - u8 shortName[0x0A]; ///< 8.3 File name - // 0x216 - u8 shortExt[0x04]; ///< 8.3 File extension (set to spaces for directories) - // 0x21A - u8 unknown2; ///< ??? - // 0x21B - u8 unknown3; ///< ??? - // 0x21C - u8 isDirectory; ///< Directory bit - // 0x21D - u8 isHidden; ///< Hidden bit - // 0x21E - u8 isArchive; ///< Archive bit - // 0x21F - u8 isReadOnly; ///< Read-only bit - // 0x220 - u64 fileSize; ///< File size -} FS_dirent; + u16 name[0x106]; ///< UTF-16 directory name. + char shortName[0x0A]; ///< File name. + char shortExt[0x04]; ///< File extension. + u8 valid; ///< Valid flag. (Always 1) + u8 reserved; ///< Reserved. + u32 attributes; ///< Attributes. + u64 fileSize; ///< File size. +} FS_DirectoryEntry; + +/// Archive resource information. +typedef struct +{ + u32 sectorSize; ///< Size of each sector, in bytes. + u32 clusterSize; ///< Size of each cluster, in bytes. + u32 totalClusters; ///< Total number of clusters. + u32 freeClusters; ///< Number of free clusters. +} FS_ArchiveResource; + +/// Program information. +typedef struct +{ + u64 programId; ///< Program ID. + FS_MediaType mediaType : 8; ///< Media type. + u8 padding[7]; ///< Padding. +} FS_ProgramInfo; + +/// Product information. +typedef struct +{ + char productCode[0x10]; ///< Product code. + char companyCode[0x2]; ///< Company code. + u16 remasterVersion; ///< Remaster version. +} FS_ProductInfo; + +/// Integrity verification seed. +typedef struct +{ + u8 aesCbcMac[0x10]; ///< AES-CBC MAC over a SHA256 hash, which hashes the first 0x110-bytes of the cleartext SEED. + u8 movableSed[0x120]; ///< The "nand/private/movable.sed", encrypted with AES-CTR using the above MAC for the counter. +} FS_IntegrityVerificationSeed; + +/// Ext save data information. +typedef struct PACKED +{ + FS_MediaType mediaType : 8; ///< Media type. + u8 unknown; ///< Unknown. + u16 reserved1; ///< Reserved. + u64 saveId; ///< Save ID. + u32 reserved2; ///< Reserved. +} FS_ExtSaveDataInfo; + +/// System save data information. +typedef struct +{ + FS_MediaType mediaType : 8; ///< Media type. + u8 unknown; ///< Unknown. + u16 reserved; ///< Reserved. + u32 saveId; ///< Save ID. +} FS_SystemSaveDataInfo; + +/// Device move context. +typedef struct +{ + u8 ivs[0x10]; ///< IVs. + u8 encryptParameter[0x10]; ///< Encrypt parameter. +} FS_DeviceMoveContext; + +/// FS path. +typedef struct +{ + FS_PathType type; ///< FS path type. + u32 size; ///< FS path size. + const u8* data; ///< Pointer to FS path data. +} FS_Path; + +/// FS archive. +typedef struct +{ + u32 id; ///< Archive ID. + FS_Path lowPath; ///< FS path. + u64 handle; ///< Handle. +} FS_Archive; /// Initializes FS. Result fsInit(void); @@ -117,224 +242,789 @@ void fsExit(void); * @brief Gets the current FS session handle. * @return The current FS session handle. */ -Handle *fsGetSessionHandle(void); +Handle* fsGetSessionHandle(void); /** - * Creates an FS_path instance. - * @param type Type of path. - * @param path Path to use. - * @return The created FS_path instance. + * @brief Performs a control operation on the filesystem. + * @param action Action to perform. + * @param input Buffer to read input from. + * @param inputSize Size of the input. + * @param output Buffer to write output to. + * @param outputSize Size of the output. */ -FS_path fsMakePath(FS_pathType type, const char *path); +Result FSUSER_Control(FS_Action action, void* input, u32 inputSize, void* output, u32 outputSize); + +/// Initializes the FSUSER session. +Result FSUSER_Initialize(void); /** - * @brief Initializes FSUSER. - * @param handle FS:USER service handle to use. + * @brief Opens a file. + * @param out Pointer to output the file handle to. + * @param archive Archive containing the file. + * @param path Path of the file. + * @param openFlags Flags to open the file with. + * @param attributes Attributes of the file. */ -Result FSUSER_Initialize(Handle handle); +Result FSUSER_OpenFile(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes); + +/** + * @brief Opens a file directly. + * @param out Pointer to output the file handle to. + * @param archive Archive containing the file. + * @param path Path of the file. + * @param openFlags Flags to open the file with. + * @param attributes Attributes of the file. + */ +Result FSUSER_OpenFileDirectly(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes); + +/** + * @brief Deletes a file. + * @param archive Archive containing the file. + * @param path Path of the file. + */ +Result FSUSER_DeleteFile(FS_Archive archive, FS_Path path); + +/** + * @brief Renames a file. + * @param srcArchive Archive containing the source file. + * @param srcPath Path of the source file. + * @param dstArchive Archive containing the destination file. + * @param dstPath Path of the destination file. + */ +Result FSUSER_RenameFile(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstArchive, FS_Path dstPath); + +/** + * @brief Deletes a directory, failing if it is not empty. + * @param archive Archive containing the directory. + * @param path Path of the directory. + */ +Result FSUSER_DeleteDirectory(FS_Archive archive, FS_Path path); + +/** + * @brief Deletes a directory, also deleting its contents. + * @param archive Archive containing the directory. + * @param path Path of the directory. + */ +Result FSUSER_DeleteDirectoryRecursively(FS_Archive archive, FS_Path path); + +/** + * @brief Creates a file. + * @param archive Archive containing the file. + * @param path Path of the file. + * @param attributes Attributes of the file. + * @param fileSize Size of the file. + */ +Result FSUSER_CreateFile(FS_Archive archive, FS_Path path, u32 attributes, u64 fileSize); + +/** + * @brief Creates a directory + * @param archive Archive containing the directory. + * @param path Path of the directory. + * @param attributes Attributes of the directory. + */ +Result FSUSER_CreateDirectory(FS_Archive archive, FS_Path path, u32 attributes); + +/** + * @brief Renames a directory. + * @param srcArchive Archive containing the source directory. + * @param srcPath Path of the source directory. + * @param dstArchive Archive containing the destination directory. + * @param dstPath Path of the destination directory. + */ +Result FSUSER_RenameDirectory(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstArchive, FS_Path dstPath); + +/** + * @brief Opens a directory. + * @param out Pointer to output the directory handle to. + * @param archive Archive containing the directory. + * @param path Path of the directory. + */ +Result FSUSER_OpenDirectory(Handle *out, FS_Archive archive, FS_Path path); /** * @brief Opens an archive. * @param archive Archive to open. */ -Result FSUSER_OpenArchive(FS_archive* archive); +Result FSUSER_OpenArchive(FS_Archive* archive); /** - * @brief Opens a directory. - * @param out Pointer to output the directory handle to. - * @param archive Archive to open the directory from. - * @param dirLowPath Path of the directory. + * @brief Performs a control operation on an archive. + * @param archive Archive to control. + * @param action Action to perform. + * @param input Buffer to read input from. + * @param inputSize Size of the input. + * @param output Buffer to write output to. + * @param outputSize Size of the output. */ -Result FSUSER_OpenDirectory(Handle* out, FS_archive archive, FS_path dirLowPath); - -/** - * @brief Opens a file. - * @param out Pointer to output the file handle to. - * @param archive Archive to open the file from. - * @param fileLowPath Path of the file. - * @param openflags Open flags to use. - * @param attributes Attributes to use. - */ -Result FSUSER_OpenFile(Handle* out, FS_archive archive, FS_path fileLowPath, u32 openflags, u32 attributes); - -/** - * @brief Opens a file directly. - * @param out Pointer to output the file handle to. - * @param archive Archive to open the file from. - * @param fileLowPath Path of the file. - * @param openflags Open flags to use. - * @param attributes Attributes to use. - */ -Result FSUSER_OpenFileDirectly(Handle* out, FS_archive archive, FS_path fileLowPath, u32 openflags, u32 attributes); +Result FSUSER_ControlArchive(FS_Archive archive, FS_ArchiveAction action, void* input, u32 inputSize, void* output, u32 outputSize); /** * @brief Closes an archive. * @param archive Archive to close. */ -Result FSUSER_CloseArchive(FS_archive* archive); +Result FSUSER_CloseArchive(FS_Archive* archive); /** - * @brief Creates a file. - * @param archive Archive to use. - * @param fileLowPath Path of the file. - * @param fileSize Initial size of the file. + * @brief Gets the number of free bytes within an archive. + * @param freeBytes Pointer to output the free bytes to. + * @param archive Archive to check. */ -Result FSUSER_CreateFile(FS_archive archive, FS_path fileLowPath, u32 fileSize); +Result FSUSER_GetFreeBytes(u64* freeBytes, FS_Archive archive); /** - * @brief Creates a directory. - * @param archive Archive to use. - * @param dirLowPath Path of the directory. + * @brief Gets the inserted card type. + * @param type Pointer to output the card type to. */ -Result FSUSER_CreateDirectory(FS_archive archive, FS_path dirLowPath); +Result FSUSER_GetCardType(FS_CardType* type); /** - * @brief Deletes a file. - * @param archive Archive to use. - * @param fileLowPath Path of the file. + * @brief Gets the SDMC archive resource information. + * @param archiveResource Pointer to output the archive resource information to. */ -Result FSUSER_DeleteFile(FS_archive archive, FS_path fileLowPath); +Result FSUSER_GetSdmcArchiveResource(FS_ArchiveResource* archiveResource); /** - * @brief Deletes a directory. - * @param archive Archive to use. - * @param dirLowPath Path of the directory. + * @brief Gets the NAND archive resource information. + * @param archiveResource Pointer to output the archive resource information to. */ -Result FSUSER_DeleteDirectory(FS_archive archive, FS_path dirLowPath); +Result FSUSER_GetNandArchiveResource(FS_ArchiveResource* archiveResource); /** - * @brief Deletes a directory recursively. - * @param archive Archive to use. - * @param dirLowPath Path of the directory. + * @brief Gets the last SDMC fatfs error. + * @param error Pointer to output the error to. */ -Result FSUSER_DeleteDirectoryRecursively(FS_archive archive, FS_path dirLowPath); - -/** - * @brief Renames a file. - * @param srcArchive Source archive. - * @param srcFileLowPath Source file. - * @param destArchive Destination archive. - * @param destFileLowPath Destination file. - */ -Result FSUSER_RenameFile(FS_archive srcArchive, FS_path srcFileLowPath, FS_archive destArchive, FS_path destFileLowPath); - -/** - * @brief Renames a directory. - * @param srcArchive Source archive. - * @param srcDirLowPath Source directory. - * @param destArchive Destination archive. - * @param destDirLowPath Destination directory. - */ -Result FSUSER_RenameDirectory(FS_archive srcArchive, FS_path srcDirLowPath, FS_archive destArchive, FS_path destDirLowPath); - -/** - * @brief Gets the SDMC resource info. - * @param sectorSize Pointer to output the sector size to. - * @param sectorSize Pointer to output the cluster size to. - * @param sectorSize Pointer to output the total number of clusters to. - * @param sectorSize Pointer to output the number of free clusters to. - */ -Result FSUSER_GetSdmcArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters); - -/** - * @brief Gets the NAND resource info. - * @param sectorSize Pointer to output the sector size to. - * @param sectorSize Pointer to output the cluster size to. - * @param sectorSize Pointer to output the total number of clusters to. - * @param sectorSize Pointer to output the number of free clusters to. - */ -Result FSUSER_GetNandArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters); +Result FSUSER_GetSdmcFatfsError(u32* error); /** * @brief Gets whether an SD card is detected. - * @param detected Pointer to output the SD detection state to. + * @param detected Pointer to output the detection status to. */ -Result FSUSER_IsSdmcDetected(u8 *detected); +Result FSUSER_IsSdmcDetected(bool *detected); /** * @brief Gets whether the SD card is writable. - * @param detected Pointer to output the SD writable state to. + * @param detected Pointer to output the writable status to. */ -Result FSUSER_IsSdmcWritable(u8 *writable); +Result FSUSER_IsSdmcWritable(bool *writable); + +/** + * @brief Gets the SDMC CID. + * @param out Pointer to output the CID to. + * @param length Length of the CID buffer. (should be 0x10) + */ +Result FSUSER_GetSdmcCid(u8* out, u32 length); + +/** + * @brief Gets the NAND CID. + * @param out Pointer to output the CID to. + * @param length Length of the CID buffer. (should be 0x10) + */ +Result FSUSER_GetNandCid(u8* out, u32 length); + +/** + * @brief Gets the SDMC speed info. + * @param speedInfo Pointer to output the speed info to. + */ +Result FSUSER_GetSdmcSpeedInfo(u32 *speedInfo); + +/** + * @brief Gets the NAND speed info. + * @param speedInfo Pointer to output the speed info to. + */ +Result FSUSER_GetNandSpeedInfo(u32 *speedInfo); + +/** + * @brief Gets the SDMC log. + * @param out Pointer to output the log to. + * @param length Length of the log buffer. + */ +Result FSUSER_GetSdmcLog(u8* out, u32 length); + +/** + * @brief Gets the NAND log. + * @param out Pointer to output the log to. + * @param length Length of the log buffer. + */ +Result FSUSER_GetNandLog(u8* out, u32 length); + +/// Clears the SDMC log. +Result FSUSER_ClearSdmcLog(void); + +/// Clears the NAND log. +Result FSUSER_ClearNandLog(void); + +/** + * @brief Gets whether a card is inserted. + * @param inserted Pointer to output the insertion status to. + */ +Result FSUSER_CardSlotIsInserted(bool* inserted); + +/** + * @brief Powers on the card slot. + * @param status Pointer to output the power status to. + */ +Result FSUSER_CardSlotPowerOn(bool* status); + +/** + * @brief Powers off the card slot. + * @param status Pointer to output the power status to. + */ +Result FSUSER_CardSlotPowerOff(bool* status); + +/** + * @brief Gets the card's power status. + * @param status Pointer to output the power status to. + */ +Result FSUSER_CardSlotGetCardIFPowerStatus(bool* status); + +/** + * @brief Executes a CARDNOR direct command. + * @param commandId ID of the command. + */ +Result FSUSER_CardNorDirectCommand(u8 commandId); + +/** + * @brief Executes a CARDNOR direct command with an address. + * @param commandId ID of the command. + * @param address Address to provide. + */ +Result FSUSER_CardNorDirectCommandWithAddress(u8 commandId, u32 address); + +/** + * @brief Executes a CARDNOR direct read. + * @param commandId ID of the command. + * @param size Size of the output buffer. + * @param output Output buffer. + */ +Result FSUSER_CardNorDirectRead(u8 commandId, u32 size, u8* output); + +/** + * @brief Executes a CARDNOR direct read with an address. + * @param commandId ID of the command. + * @param address Address to provide. + * @param size Size of the output buffer. + * @param output Output buffer. + */ +Result FSUSER_CardNorDirectReadWithAddress(u8 commandId, u32 address, u32 size, u8* output); + +/** + * @brief Executes a CARDNOR direct write. + * @param commandId ID of the command. + * @param size Size of the input buffer. + * @param output Input buffer. + */ +Result FSUSER_CardNorDirectWrite(u8 commandId, u32 size, u8* input); + +/** + * @brief Executes a CARDNOR direct write with an address. + * @param commandId ID of the command. + * @param address Address to provide. + * @param size Size of the input buffer. + * @param input Input buffer. + */ +Result FSUSER_CardNorDirectWriteWithAddress(u8 commandId, u32 address, u32 size, u8* input); + +/** + * @brief Executes a CARDNOR 4xIO direct read. + * @param commandId ID of the command. + * @param address Address to provide. + * @param size Size of the output buffer. + * @param output Output buffer. + */ +Result FSUSER_CardNorDirectRead_4xIO(u8 commandId, u32 address, u32 size, u8* output); + +/** + * @brief Executes a CARDNOR direct CPU write without verify. + * @param address Address to provide. + * @param size Size of the input buffer. + * @param output Input buffer. + */ +Result FSUSER_CardNorDirectCpuWriteWithoutVerify(u32 address, u32 size, u8* input); + +/** + * @brief Executes a CARDNOR direct sector erase without verify. + * @param address Address to provide. + */ +Result FSUSER_CardNorDirectSectorEraseWithoutVerify(u32 address); + +/** + * @brief Gets a process's product info. + * @param info Pointer to output the product info to. + * @param processId ID of the process. + */ +Result FSUSER_GetProductInfo(FS_ProductInfo* info, u32 processId); + +/** + * @brief Gets a process's program launch info. + * @param info Pointer to output the program launch info to. + * @param processId ID of the process. + */ +Result FSUSER_GetProgramLaunchInfo(FS_ProgramInfo* info, u32 processId); + +/** + * @brief Sets the CARDSPI baud rate. + * @param baudRate Baud rate to set. + */ +Result FSUSER_SetCardSpiBaudRate(FS_CardSpiBaudRate baudRate); + +/** + * @brief Sets the CARDSPI bus mode. + * @param baudRate Bus mode to set. + */ +Result FSUSER_SetCardSpiBusMode(FS_CardSpiBusMode busMode); + +/// Sends initialization info to ARM9. +Result FSUSER_SendInitializeInfoTo9(void); + +/** + * @brief Gets a special content's index. + * @param index Pointer to output the index to. + * @param mediaType Media type of the special content. + * @param programId Program ID owning the special content. + * @param type Type of special content. + */ +Result FSUSER_GetSpecialContentIndex(u16* index, FS_MediaType mediaType, u64 programId, FS_SpecialContentType type); + +/** + * @brief Gets the legacy ROM header of a program. + * @param mediaType Media type of the program. + * @param programId ID of the program. + * @param header Pointer to output the legacy ROM header to. (size = 0x3B4) + */ +Result FSUSER_GetLegacyRomHeader(FS_MediaType mediaType, u64 programId, u8* header); + +/** + * @brief Gets the legacy banner data of a program. + * @param mediaType Media type of the program. + * @param programId ID of the program. + * @param header Pointer to output the legacy banner data to. (size = 0x23C0) + */ +Result FSUSER_GetLegacyBannerData(FS_MediaType mediaType, u64 programId, u8* banner); + +/** + * @brief Checks a process's authority to access a save data archive. + * @param access Pointer to output the access status to. + * @param mediaType Media type of the save data. + * @param saveId ID of the save data. + * @param processId ID of the process to check. + */ +Result FSUSER_CheckAuthorityToAccessExtSaveData(bool* access, FS_MediaType mediaType, u64 saveId, u32 processId); + +/** + * @brief Queries the total quota size of a save data archive. + * @param quotaSize Pointer to output the quota size to. + * @param directories Number of directories. + * @param files Number of files. + * @param fileSizeCount Number of file sizes to provide. + * @param fileSizes File sizes to provide. + */ +Result FSUSER_QueryTotalQuotaSize(u64* quotaSize, u32 directories, u32 files, u32 fileSizeCount, u64* fileSizes); + +/** + * @brief Abnegates an access right. + * @param accessRight Access right to abnegate. + */ +Result FSUSER_AbnegateAccessRight(u32 accessRight); + +/// Deletes the 3DS SDMC root. +Result FSUSER_DeleteSdmcRoot(void); + +/// Deletes all ext save data on the NAND. +Result FSUSER_DeleteAllExtSaveDataOnNand(void); + +/// Initializes the CTR file system. +Result FSUSER_InitializeCtrFileSystem(void); + +/// Creates the FS seed. +Result FSUSER_CreateSeed(void); + +/** + * @brief Retrieves archive format info. + * @param totalSize Pointer to output the total size to. + * @param directories Pointer to output the number of directories to. + * @param files Pointer to output the number of files to. + * @param duplicateData Pointer to output whether to duplicate data to. + * @param archiveId ID of the archive. + * @param path Path of the archive. + */ +Result FSUSER_GetFormatInfo(u32* totalSize, u32* directories, u32* files, bool* duplicateData, FS_ArchiveID archiveId, FS_Path path); + +/** + * @brief Gets the legacy ROM header of a program. + * @param headerSize Size of the ROM header. + * @param mediaType Media type of the program. + * @param programId ID of the program. + * @param header Pointer to output the legacy ROM header to. + */ +Result FSUSER_GetLegacyRomHeader2(u32 headerSize, FS_MediaType mediaType, u64 programId, u8* header); + +/** + * @brief Gets the CTR SDMC root path. + * @param out Pointer to output the root path to. + * @param length Length of the output buffer. + */ +Result FSUSER_GetSdmcCtrRootPath(u8* out, u32 length); + +/** + * @brief Gets an archive's resource information. + * @param archiveResource Pointer to output the archive resource information to. + * @param mediaType Media type to check. + */ +Result FSUSER_GetArchiveResource(FS_ArchiveResource* archiveResource, FS_MediaType mediaType); + +/** + * @brief Exports the integrity verification seed. + * @param seed Pointer to output the seed to. + */ +Result FSUSER_ExportIntegrityVerificationSeed(FS_IntegrityVerificationSeed* seed); + +/** + * @brief Imports an integrity verification seed. + * @param seed Seed to import. + */ +Result FSUSER_ImportIntegrityVerificationSeed(FS_IntegrityVerificationSeed* seed); + +/** + * @brief Formats save data. + * @param archiveId ID of the save data archive. + * @param path Path of the save data. + * @param blocks Size of the save data in blocks. (512 bytes) + * @param directories Number of directories. + * @param files Number of files. + * @param directoryBuckets Directory hash tree bucket count. + * @param fileBuckets File hash tree bucket count. + * @param duplicateData Whether to store an internal duplicate of the data. + */ +Result FSUSER_FormatSaveData(FS_ArchiveID archiveId, FS_Path path, u32 blocks, u32 directories, u32 files, u32 directoryBuckets, u32 fileBuckets, bool duplicateData); + +/** + * @brief Gets the legacy sub banner data of a program. + * @param bannerSize Size of the banner. + * @param mediaType Media type of the program. + * @param programId ID of the program. + * @param header Pointer to output the legacy sub banner data to. + */ +Result FSUSER_GetLegacySubBannerData(u32 bannerSize, FS_MediaType mediaType, u64 programId, u8* banner); + +/** + * @brief Reads from a special file. + * @param bytesRead Pointer to output the number of bytes read to. + * @param fileOffset Offset of the file. + * @param size Size of the buffer. + * @param data Buffer to read to. + */ +Result FSUSER_ReadSpecialFile(u32* bytesRead, u64 fileOffset, u32 size, u8* data); + +/** + * @brief Gets the size of a special file. + * @param fileSize Pointer to output the size to. + */ +Result FSUSER_GetSpecialFileSize(u64* fileSize); + +/** + * @brief Creates ext save data. + * @param info Info of the save data. + * @param directories Number of directories. + * @param files Number of files. + * @param sizeLimit Size limit of the save data. + * @param smdhSize Size of the save data's SMDH data. + * @param smdh SMDH data. + */ +Result FSUSER_CreateExtSaveData(FS_ExtSaveDataInfo info, u32 directories, u32 files, u64 sizeLimit, u32 smdhSize, u8* smdh); + +/** + * @brief Deletes ext save data. + * @param info Info of the save data. + */ +Result FSUSER_DeleteExtSaveData(FS_ExtSaveDataInfo info); + +/** + * @brief Reads the SMDH icon of ext save data. + * @param bytesRead Pointer to output the number of bytes read to. + * @param info Info of the save data. + * @param smdhSize Size of the save data SMDH. + * @param smdh Pointer to output SMDH data to. + */ +Result FSUSER_ReadExtSaveDataIcon(u32* bytesRead, FS_ExtSaveDataInfo info, u32 smdhSize, u8* smdh); + +/** + * @brief Gets an ext data archive's block information. + * @param totalBlocks Pointer to output the total blocks to. + * @param freeBlocks Pointer to output the free blocks to. + * @param blockSize Pointer to output the block size to. + * @param info Info of the save data. + */ +Result FSUSER_GetExtDataBlockSize(u64* totalBlocks, u64* freeBlocks, u32* blockSize, FS_ExtSaveDataInfo info); + +/** + * @brief Enumerates ext save data. + * @param idsWritten Pointer to output the number of IDs written to. + * @param idsSize Size of the IDs buffer. + * @param mediaType Media type to enumerate over. + * @param idSize Size of each ID element. + * @param shared Whether to enumerate shared ext save data. + * @param ids Pointer to output IDs to. + */ +Result FSUSER_EnumerateExtSaveData(u32* idsWritten, u32 idsSize, FS_MediaType mediaType, u32 idSize, bool shared, u8* ids); + +/** + * @brief Creates system save data. + * @param info Info of the save data. + * @param totalSize Total size of the save data. + * @param blockSize Block size of the save data. (usually 0x1000) + * @param directories Number of directories. + * @param files Number of files. + * @param directoryBuckets Directory hash tree bucket count. + * @param fileBuckets File hash tree bucket count. + * @param duplicateData Whether to store an internal duplicate of the data. + */ +Result FSUSER_CreateSystemSaveData(FS_SystemSaveDataInfo info, u32 totalSize, u32 blockSize, u32 directories, u32 files, u32 directoryBuckets, u32 fileBuckets, bool duplicateData); + +/** + * @brief Deletes system save data. + * @param info Info of the save data. + */ +Result FSUSER_DeleteSystemSaveData(FS_SystemSaveDataInfo info); + +/** + * @brief Initiates a device move as the source device. + * @param context Pointer to output the context to. + */ +Result FSUSER_StartDeviceMoveAsSource(FS_DeviceMoveContext* context); + +/** + * @brief Initiates a device move as the destination device. + * @param context Context to use. + * @param clear Whether to clear the device's data first. + */ +Result FSUSER_StartDeviceMoveAsDestination(FS_DeviceMoveContext context, bool clear); + +/** + * @brief Sets an archive's priority. + * @param archive Archive to use. + * @param priority Priority to set. + */ +Result FSUSER_SetArchivePriority(FS_Archive archive, u32 priority); + +/** + * @brief Gets an archive's priority. + * @param priority Pointer to output the priority to. + * @param archive Archive to use. + */ +Result FSUSER_GetArchivePriority(u32* priority, FS_Archive archive); + +/** + * @brief Configures CTRCARD latency emulation. + * @param latency Latency to apply, in milliseconds. + * @param emulateEndurance Whether to emulate card endurance. + */ +Result FSUSER_SetCtrCardLatencyParameter(u64 latency, bool emulateEndurance); + +/** + * @brief Toggles cleaning up invalid save data. + * @param Whether to enable cleaning up invalid save data. + */ +Result FSUSER_SwitchCleanupInvalidSaveData(bool enable); + +/** + * @brief Enumerates system save data. + * @param idsWritten Pointer to output the number of IDs written to. + * @param idsSize Size of the IDs buffer. + * @param ids Pointer to output IDs to. + */ +Result FSUSER_EnumerateSystemSaveData(u32* idsWritten, u32 idsSize, u64* ids); + +/** + * @brief Initializes the FSUSER session with an SDK version. + * @param version SDK version to initialize with. + */ +Result FSUSER_InitializeWithSdkVersion(u32 version); + +/** + * @brief Sets the file system priority. + * @param priority Priority to set. + */ +Result FSUSER_SetPriority(u32 priority); + +/** + * @brief Gets the file system priority. + * @param priority Pointer to output the priority to. + */ +Result FSUSER_GetPriority(u32* priority); + +/** + * @brief Sets the save data secure value. + * @param value Secure value to set. + * @param slot Slot of the secure value. + * @param titleUniqueId Unique ID of the title. (default = 0) + * @param titleVariation Variation of the title. (default = 0) + */ +Result FSUSER_SetSaveDataSecureValue(u64 value, FS_SecureValueSlot slot, u32 titleUniqueId, u8 titleVariation); + +/** + * @brief Gets the save data secure value. + * @param exists Pointer to output whether the secure value exists to. + * @param value Pointer to output the secure value to. + * @param slot Slot of the secure value. + * @param titleUniqueId Unique ID of the title. (default = 0) + * @param titleVariation Variation of the title. (default = 0) + */ +Result FSUSER_GetSaveDataSecureValue(bool* exists, u64* value, FS_SecureValueSlot slot, u32 titleUniqueId, u8 titleVariation); + +/** + * @brief Performs a control operation on a secure save. + * @param action Action to perform. + * @param input Buffer to read input from. + * @param inputSize Size of the input. + * @param output Buffer to write output to. + * @param outputSize Size of the output. + */ +Result FSUSER_ControlSecureSave(FS_SecureSaveAction action, void* input, u32 inputSize, void* output, u32 outputSize); /** * @brief Gets the media type of the current application. - * @param mediatype Pointer to output the media type to. + * @param mediaType Pointer to output the media type to. */ -Result FSUSER_GetMediaType(u8* mediatype); +Result FSUSER_GetMediaType(FS_MediaType* mediaType); /** - * @brief Closes a file handle. - * @param handle File handle to close. + * @brief Performs a control operation on a file. + * @param handle Handle of the file. + * @param action Action to perform. + * @param input Buffer to read input from. + * @param inputSize Size of the input. + * @param output Buffer to write output to. + * @param outputSize Size of the output. */ -Result FSFILE_Close(Handle handle); +Result FSFILE_Control(Handle handle, FS_FileAction action, void* input, u32 inputSize, void* output, u32 outputSize); + +/** + * @brief Opens a handle to a sub-section of a file. + * @param handle Handle of the file. + * @param subFile Pointer to output the sub-file to. + * @param offset Offset of the sub-section. + * @param size Size of the sub-section. + */ +Result FSFILE_OpenSubFile(Handle handle, Handle* subFile, u64 offset, u64 size); /** * @brief Reads from a file. - * @param handle File handle to use. + * @param handle Handle of the file. * @param bytesRead Pointer to output the number of bytes read to. * @param offset Offset to read from. * @param buffer Buffer to read to. * @param size Size of the buffer. */ -Result FSFILE_Read(Handle handle, u32 *bytesRead, u64 offset, void *buffer, u32 size); +Result FSFILE_Read(Handle handle, u32* bytesRead, u64 offset, void* buffer, u32 size); /** * @brief Writes to a file. - * @param handle File handle to use. - * @param bytesRead Pointer to output the number of bytes written to. + * @param handle Handle of the file. + * @param bytesWritten Pointer to output the number of bytes written to. * @param offset Offset to write to. * @param buffer Buffer to write from. * @param size Size of the buffer. - * @param flushFlags Flush flags to apply after writing. + * @param flags Flags to use when writing. */ -Result FSFILE_Write(Handle handle, u32 *bytesWritten, u64 offset, const void *buffer, u32 size, u32 flushFlags); +Result FSFILE_Write(Handle handle, u32* bytesWritten, u64 offset, const void* buffer, u32 size, u32 flags); /** - * @brief Gets a file's size. - * @param handle File handle to use. + * @brief Gets the size of a file. + * @param handle Handle of the file. * @param size Pointer to output the size to. */ -Result FSFILE_GetSize(Handle handle, u64 *size); +Result FSFILE_GetSize(Handle handle, u64* size); /** - * @brief Sets a file's size. - * @param handle File handle to use. + * @brief Sets the size of a file. + * @param handle Handle of the file. * @param size Size to set. */ Result FSFILE_SetSize(Handle handle, u64 size); /** - * @brief Gets a file's attributes. - * @param handle File handle to use. + * @brief Gets the attributes of a file. + * @param handle Handle of the file. * @param attributes Pointer to output the attributes to. */ -Result FSFILE_GetAttributes(Handle handle, u32 *attributes); +Result FSFILE_GetAttributes(Handle handle, u32* attributes); /** - * @brief Sets a file's attributes. - * @param handle File handle to use. + * @brief Sets the attributes of a file. + * @param handle Handle of the file. * @param attributes Attributes to set. */ Result FSFILE_SetAttributes(Handle handle, u32 attributes); /** - * @brief Flushes a file to disk. - * @param handle File handle to flush. + * @brief Closes a file. + * @param handle Handle of the file. + */ +Result FSFILE_Close(Handle handle); + +/** + * @brief Flushes a file's contents. + * @param handle Handle of the file. */ Result FSFILE_Flush(Handle handle); /** - * @brief Reads one or more directory entries. - * @param handle Directory handle to read from. - * @param entriesRead Pointer to output the current number of read entries to. - * @param entrycount Number of entries to read. - * @param buffer Buffer to output directory entries to. + * @brief Sets a file's priority. + * @param handle Handle of the file. + * @param priority Priority to set. */ -Result FSDIR_Read(Handle handle, u32 *entriesRead, u32 entrycount, FS_dirent *buffer); +Result FSFILE_SetPriority(Handle handle, u32 priority); /** - * @brief Closes a directory handle. - * @param handle Directory handle to close. + * @brief Gets a file's priority. + * @param handle Handle of the file. + * @param priority Pointer to output the priority to. + */ +Result FSFILE_GetPriority(Handle handle, u32* priority); + +/** + * @brief Opens a duplicate handle to a file. + * @param handle Handle of the file. + * @param linkFile Pointer to output the link handle to. + */ +Result FSFILE_OpenLinkFile(Handle handle, Handle* linkFile); + +/** + * @brief Performs a control operation on a directory. + * @param handle Handle of the directory. + * @param action Action to perform. + * @param input Buffer to read input from. + * @param inputSize Size of the input. + * @param output Buffer to write output to. + * @param outputSize Size of the output. + */ +Result FSDIR_Control(Handle handle, FS_DirectoryAction action, void* input, u32 inputSize, void* output, u32 outputSize); + +/** + * @brief Reads one or more directory entries. + * @param handle Handle of the directory. + * @param entriesRead Pointer to output the number of entries read to. + * @param entryCount Number of entries to read. + * @param entryOut Pointer to output directory entries to. + */ +Result FSDIR_Read(Handle handle, u32* entriesRead, u32 entryCount, FS_DirectoryEntry* entries); + +/** + * @brief Closes a directory. + * @param handle Handle of the directory. */ Result FSDIR_Close(Handle handle); + +/** + * @brief Sets a directory's priority. + * @param handle Handle of the directory. + * @param priority Priority to set. + */ +Result FSDIR_SetPriority(Handle handle, u32 priority); + +/** + * @brief Gets a directory's priority. + * @param handle Handle of the directory. + * @param priority Pointer to output the priority to. + */ +Result FSDIR_GetPriority(Handle handle, u32* priority); diff --git a/libctru/include/3ds/types.h b/libctru/include/3ds/types.h index a2bb20e..6fa2dfe 100644 --- a/libctru/include/3ds/types.h +++ b/libctru/include/3ds/types.h @@ -11,14 +11,6 @@ /// The maximum value of a u64. #define U64_MAX UINT64_MAX -/// Possible media types. -typedef enum -{ - mediatype_NAND, ///< NAND - mediatype_SDMC, ///< SDMC - mediatype_GAMECARD, ///< Game card -} mediatypes_enum; - typedef uint8_t u8; ///< 8-bit unsigned integer typedef uint16_t u16; ///< 16-bit unsigned integer typedef uint32_t u32; ///< 32-bit unsigned integer diff --git a/libctru/source/ndsp/ndsp.c b/libctru/source/ndsp/ndsp.c index e5ead03..11445ba 100644 --- a/libctru/source/ndsp/ndsp.c +++ b/libctru/source/ndsp/ndsp.c @@ -400,10 +400,10 @@ static bool ndspFindAndLoadComponent(void) do { static const char dsp_filename[] = "/3ds/dspfirm.cdc"; - FS_archive arch = { ARCH_SDMC, { PATH_EMPTY, 1, (u8*)"" }, 0, 0 }; - FS_path path = { PATH_CHAR, sizeof(dsp_filename), (u8*)dsp_filename }; + FS_Archive arch = { ARCHIVE_SDMC, { PATH_EMPTY, 1, (u8*)"" }, 0 }; + FS_Path path = { PATH_ASCII, sizeof(dsp_filename), (u8*)dsp_filename }; - rc = FSUSER_OpenFileDirectly(&rsrc, arch, path, FS_OPEN_READ, FS_ATTRIBUTE_NONE); + rc = FSUSER_OpenFileDirectly(&rsrc, arch, path, FS_OPEN_READ, 0); if (R_FAILED(rc)) break; u64 size = 0; diff --git a/libctru/source/romfs_dev.c b/libctru/source/romfs_dev.c index 729a8ee..1706b78 100644 --- a/libctru/source/romfs_dev.c +++ b/libctru/source/romfs_dev.c @@ -137,10 +137,10 @@ Result romfsInit(void) if (units == (size_t)-1) return 3; __utf16path[units] = 0; - FS_archive arch = { ARCH_SDMC, { PATH_EMPTY, 1, (u8*)"" }, 0, 0 }; - FS_path path = { PATH_WCHAR, (units+1)*2, (u8*)__utf16path }; + FS_Archive arch = { ARCHIVE_SDMC, { PATH_EMPTY, 1, (u8*)"" }, 0 }; + FS_Path path = { PATH_UTF16, (units+1)*2, (u8*)__utf16path }; - Result rc = FSUSER_OpenFileDirectly(&romFS_file, arch, path, FS_OPEN_READ, FS_ATTRIBUTE_NONE); + Result rc = FSUSER_OpenFileDirectly(&romFS_file, arch, path, FS_OPEN_READ, 0); if (R_FAILED(rc)) return rc; _3DSX_Header hdr; @@ -155,10 +155,10 @@ Result romfsInit(void) u8 zeros[0xC]; memset(zeros, 0, sizeof(zeros)); - FS_archive arch = { ARCH_ROMFS, { PATH_EMPTY, 1, (u8*)"" }, 0, 0 }; - FS_path path = { PATH_BINARY, sizeof(zeros), zeros }; + FS_Archive arch = { ARCHIVE_ROMFS, { PATH_EMPTY, 1, (u8*)"" }, 0 }; + FS_Path path = { PATH_BINARY, sizeof(zeros), zeros }; - Result rc = FSUSER_OpenFileDirectly(&romFS_file, arch, path, FS_OPEN_READ, FS_ATTRIBUTE_NONE); + Result rc = FSUSER_OpenFileDirectly(&romFS_file, arch, path, FS_OPEN_READ, 0); if (R_FAILED(rc)) return rc; } diff --git a/libctru/source/sdmc_dev.c b/libctru/source/sdmc_dev.c index 47037dc..dc8d124 100644 --- a/libctru/source/sdmc_dev.c +++ b/libctru/source/sdmc_dev.c @@ -60,8 +60,8 @@ typedef struct /*! Open directory struct */ typedef struct { - Handle fd; /*! CTRU handle */ - FS_dirent entry_data; /*! Temporary storage for reading entries */ + Handle fd; /*! CTRU handle */ + FS_DirectoryEntry entry_data; /*! Temporary storage for reading entries */ } sdmc_dir_t; /*! SDMC devoptab */ @@ -97,9 +97,9 @@ sdmc_devoptab = }; /*! SDMC archive handle */ -static FS_archive sdmcArchive = +static FS_Archive sdmcArchive = { - .id = ARCH_SDMC, + .id = ARCHIVE_SDMC, .lowPath = { .type = PATH_EMPTY, @@ -178,12 +178,12 @@ sdmc_fixpath(struct _reent *r, return __fixedpath; } -static const FS_path +static const FS_Path sdmc_utf16path(struct _reent *r, const char *path) { size_t units; - FS_path fspath; + FS_Path fspath; fspath.data = NULL; @@ -205,7 +205,7 @@ sdmc_utf16path(struct _reent *r, __utf16path[units] = 0; - fspath.type = PATH_WCHAR; + fspath.type = PATH_UTF16; fspath.size = (units+1)*sizeof(uint16_t); fspath.data = (const u8*)__utf16path; @@ -316,11 +316,11 @@ sdmc_open(struct _reent *r, int flags, int mode) { - Handle fd; - Result rc; - u32 sdmc_flags = 0; - u32 attributes = FS_ATTRIBUTE_NONE; - FS_path fs_path; + Handle fd; + Result rc; + u32 sdmc_flags = 0; + u32 attributes = 0; + FS_Path fs_path; fs_path = sdmc_utf16path(r, path); if(fs_path.data == NULL) @@ -365,7 +365,7 @@ sdmc_open(struct _reent *r, /* Test O_EXCL. */ if((flags & O_CREAT) && (flags & O_EXCL)) { - rc = FSUSER_CreateFile(sdmcArchive, fs_path, 0); + rc = FSUSER_CreateFile(sdmcArchive, fs_path, attributes, 0); if(R_FAILED(rc)) { r->_errno = sdmc_translate_error(rc); @@ -662,14 +662,13 @@ sdmc_stat(struct _reent *r, { Handle fd; Result rc; - FS_path fs_path; + FS_Path fs_path; fs_path = sdmc_utf16path(r, file); if(fs_path.data == NULL) return -1; - if(R_SUCCEEDED(rc = FSUSER_OpenFile(&fd, sdmcArchive, fs_path, - FS_OPEN_READ, FS_ATTRIBUTE_NONE))) + if(R_SUCCEEDED(rc = FSUSER_OpenFile(&fd, sdmcArchive, fs_path, FS_OPEN_READ, 0))) { sdmc_file_t tmpfd = { .fd = fd }; rc = sdmc_fstat(r, (int)&tmpfd, st); @@ -721,7 +720,7 @@ sdmc_unlink(struct _reent *r, const char *name) { Result rc; - FS_path fs_path; + FS_Path fs_path; fs_path = sdmc_utf16path(r, name); if(fs_path.data == NULL) @@ -749,7 +748,7 @@ sdmc_chdir(struct _reent *r, { Handle fd; Result rc; - FS_path fs_path; + FS_Path fs_path; fs_path = sdmc_utf16path(r, name); if(fs_path.data == NULL) @@ -782,7 +781,7 @@ sdmc_rename(struct _reent *r, const char *newName) { Result rc; - FS_path fs_path_old, fs_path_new; + FS_Path fs_path_old, fs_path_new; static uint16_t __utf16path_old[PATH_MAX+1]; fs_path_old = sdmc_utf16path(r, oldName); @@ -823,7 +822,7 @@ sdmc_mkdir(struct _reent *r, int mode) { Result rc; - FS_path fs_path; + FS_Path fs_path; fs_path = sdmc_utf16path(r, path); if(fs_path.data == NULL) @@ -831,7 +830,7 @@ sdmc_mkdir(struct _reent *r, /* TODO: Use mode to set directory attributes. */ - rc = FSUSER_CreateDirectory(sdmcArchive, fs_path); + rc = FSUSER_CreateDirectory(sdmcArchive, fs_path, 0); if(R_SUCCEEDED(rc)) return 0; @@ -855,7 +854,7 @@ sdmc_diropen(struct _reent *r, { Handle fd; Result rc; - FS_path fs_path; + FS_Path fs_path; fs_path = sdmc_utf16path(r, path); @@ -931,7 +930,7 @@ sdmc_dirnext(struct _reent *r, /* fill in the stat info */ filestat->st_ino = 0; - if(dir->entry_data.isDirectory) + if(dir->entry_data.attributes & FS_ATTRIBUTE_DIRECTORY) filestat->st_mode = S_IFDIR; else filestat->st_mode = S_IFREG; @@ -999,24 +998,21 @@ sdmc_statvfs(struct _reent *r, struct statvfs *buf) { Result rc; - u32 clusterSize, numClusters, freeClusters; - u8 writable = 0; + FS_ArchiveResource resource; + bool writable = false; - rc = FSUSER_GetSdmcArchiveResource(NULL, - &clusterSize, - &numClusters, - &freeClusters); + rc = FSUSER_GetSdmcArchiveResource(&resource); if(R_SUCCEEDED(rc)) { - buf->f_bsize = clusterSize; - buf->f_frsize = clusterSize; - buf->f_blocks = numClusters; - buf->f_bfree = freeClusters; - buf->f_bavail = freeClusters; + buf->f_bsize = resource.clusterSize; + buf->f_frsize = resource.clusterSize; + buf->f_blocks = resource.totalClusters; + buf->f_bfree = resource.freeClusters; + buf->f_bavail = resource.freeClusters; buf->f_files = 0; //??? how to get - buf->f_ffree = freeClusters; - buf->f_favail = freeClusters; + buf->f_ffree = resource.freeClusters; + buf->f_favail = resource.freeClusters; buf->f_fsid = 0; //??? how to get buf->f_flag = ST_NOSUID; buf->f_namemax = 0; //??? how to get @@ -1141,7 +1137,7 @@ sdmc_rmdir(struct _reent *r, const char *name) { Result rc; - FS_path fs_path; + FS_Path fs_path; fs_path = sdmc_utf16path(r, name); if(fs_path.data == NULL) diff --git a/libctru/source/services/fs.c b/libctru/source/services/fs.c index 6186409..e949b36 100644 --- a/libctru/source/services/fs.c +++ b/libctru/source/services/fs.c @@ -20,9 +20,9 @@ Result fsInit(void) if (AtomicPostIncrement(&fsuRefCount)) return 0; ret = srvGetServiceHandle(&fsuHandle, "fs:USER"); - if (R_SUCCEEDED(ret) && __get_handle_from_list("fs:USER")==0) + if (R_SUCCEEDED(ret) && __get_handle_from_list("fs:USER") == 0) { - ret = FSUSER_Initialize(fsuHandle); + ret = FSUSER_Initialize(); if (R_FAILED(ret)) svcCloseHandle(fsuHandle); } @@ -36,17 +36,31 @@ void fsExit(void) svcCloseHandle(fsuHandle); } -Handle *fsGetSessionHandle(void) +Handle* fsGetSessionHandle(void) { return &fsuHandle; } -FS_path fsMakePath(FS_pathType type, const char *path) +Result FSUSER_Control(FS_Action action, void* input, u32 inputSize, void* output, u32 outputSize) { - return (FS_path){type, strlen(path)+1, (const u8*)path}; + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x401,3,4); // 0x40100C4 + cmdbuf[1] = action; + cmdbuf[2] = inputSize; + cmdbuf[3] = outputSize; + cmdbuf[4] = IPC_Desc_Buffer(inputSize, IPC_BUFFER_R); + cmdbuf[5] = (u32) input; + cmdbuf[6] = IPC_Desc_Buffer(outputSize, IPC_BUFFER_W); + cmdbuf[7] = (u32) output; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; } -Result FSUSER_Initialize(Handle handle) +Result FSUSER_Initialize(void) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -54,25 +68,25 @@ Result FSUSER_Initialize(Handle handle) cmdbuf[1] = IPC_Desc_CurProcessHandle(); Result ret = 0; - if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; return cmdbuf[1]; } -Result FSUSER_OpenFile(Handle *out, FS_archive archive, FS_path fileLowPath, u32 openFlags, u32 attributes) +Result FSUSER_OpenFile(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x802,7,2); // 0x80201C2 cmdbuf[1] = 0; - cmdbuf[2] = archive.handleLow; - cmdbuf[3] = archive.handleHigh; - cmdbuf[4] = fileLowPath.type; - cmdbuf[5] = fileLowPath.size; + cmdbuf[2] = (u32) archive.handle; + cmdbuf[3] = (u32) (archive.handle >> 32); + cmdbuf[4] = path.type; + cmdbuf[5] = path.size; cmdbuf[6] = openFlags; cmdbuf[7] = attributes; - cmdbuf[8] = IPC_Desc_StaticBuffer(fileLowPath.size,0); - cmdbuf[9] = (u32)fileLowPath.data; + cmdbuf[8] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[9] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -82,7 +96,7 @@ Result FSUSER_OpenFile(Handle *out, FS_archive archive, FS_path fileLowPath, u32 return cmdbuf[1]; } -Result FSUSER_OpenFileDirectly(Handle *out, FS_archive archive, FS_path fileLowPath, u32 openFlags, u32 attributes) +Result FSUSER_OpenFileDirectly(Handle* out, FS_Archive archive, FS_Path path, u32 openFlags, u32 attributes) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -91,14 +105,14 @@ Result FSUSER_OpenFileDirectly(Handle *out, FS_archive archive, FS_path fileLowP cmdbuf[2] = archive.id; cmdbuf[3] = archive.lowPath.type; cmdbuf[4] = archive.lowPath.size; - cmdbuf[5] = fileLowPath.type; - cmdbuf[6] = fileLowPath.size; + cmdbuf[5] = path.type; + cmdbuf[6] = path.size; cmdbuf[7] = openFlags; cmdbuf[8] = attributes; - cmdbuf[9] = IPC_Desc_StaticBuffer(archive.lowPath.size,2); - cmdbuf[10] = (u32)archive.lowPath.data; - cmdbuf[11] = IPC_Desc_StaticBuffer(fileLowPath.size,0); - cmdbuf[12] = (u32)fileLowPath.data; + cmdbuf[9] = IPC_Desc_StaticBuffer(archive.lowPath.size, 2); + cmdbuf[10] = (u32) archive.lowPath.data; + cmdbuf[11] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[12] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -108,18 +122,18 @@ Result FSUSER_OpenFileDirectly(Handle *out, FS_archive archive, FS_path fileLowP return cmdbuf[1]; } -Result FSUSER_DeleteFile(FS_archive archive, FS_path fileLowPath) +Result FSUSER_DeleteFile(FS_Archive archive, FS_Path path) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x804,5,2); // 0x8040142 cmdbuf[1] = 0; - cmdbuf[2] = archive.handleLow; - cmdbuf[3] = archive.handleHigh; - cmdbuf[4] = fileLowPath.type; - cmdbuf[5] = fileLowPath.size; - cmdbuf[6] = IPC_Desc_StaticBuffer(fileLowPath.size ,0); - cmdbuf[7] = (u32)fileLowPath.data; + cmdbuf[2] = (u32) archive.handle; + cmdbuf[3] = (u32) (archive.handle >> 32); + cmdbuf[4] = path.type; + cmdbuf[5] = path.size; + cmdbuf[6] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[7] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -127,24 +141,24 @@ Result FSUSER_DeleteFile(FS_archive archive, FS_path fileLowPath) return cmdbuf[1]; } -Result FSUSER_RenameFile(FS_archive srcArchive, FS_path srcFileLowPath, FS_archive destArchive, FS_path destFileLowPath) +Result FSUSER_RenameFile(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstArchive, FS_Path dstPath) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x805,9,4); // 0x8050244 cmdbuf[1] = 0; - cmdbuf[2] = srcArchive.handleLow; - cmdbuf[3] = srcArchive.handleHigh; - cmdbuf[4] = srcFileLowPath.type; - cmdbuf[5] = srcFileLowPath.size; - cmdbuf[6] = destArchive.handleLow; - cmdbuf[7] = destArchive.handleHigh; - cmdbuf[8] = destFileLowPath.type; - cmdbuf[9] = destFileLowPath.size; - cmdbuf[10] = IPC_Desc_StaticBuffer(srcFileLowPath.size,1); - cmdbuf[11] = (u32)srcFileLowPath.data; - cmdbuf[12] = IPC_Desc_StaticBuffer(destFileLowPath.size,2); - cmdbuf[13] = (u32)destFileLowPath.data; + cmdbuf[2] = (u32) srcArchive.handle; + cmdbuf[3] = (u32) (srcArchive.handle >> 32); + cmdbuf[4] = srcPath.type; + cmdbuf[5] = srcPath.size; + cmdbuf[6] = (u32) dstArchive.handle; + cmdbuf[7] = (u32) (dstArchive.handle >> 32); + cmdbuf[8] = dstPath.type; + cmdbuf[9] = dstPath.size; + cmdbuf[10] = IPC_Desc_StaticBuffer(srcPath.size, 1); + cmdbuf[11] = (u32) srcPath.data; + cmdbuf[12] = IPC_Desc_StaticBuffer(dstPath.size, 2); + cmdbuf[13] = (u32) dstPath.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -152,18 +166,18 @@ Result FSUSER_RenameFile(FS_archive srcArchive, FS_path srcFileLowPath, FS_archi return cmdbuf[1]; } -Result FSUSER_DeleteDirectory(FS_archive archive, FS_path dirLowPath) +Result FSUSER_DeleteDirectory(FS_Archive archive, FS_Path path) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x806,5,2); // 0x8060142 cmdbuf[1] = 0; - cmdbuf[2] = archive.handleLow; - cmdbuf[3] = archive.handleHigh; - cmdbuf[4] = dirLowPath.type; - cmdbuf[5] = dirLowPath.size; - cmdbuf[6] = IPC_Desc_StaticBuffer(dirLowPath.size,0); - cmdbuf[7] = (u32)dirLowPath.data; + cmdbuf[2] = (u32) archive.handle; + cmdbuf[3] = (u32) (archive.handle >> 32); + cmdbuf[4] = path.type; + cmdbuf[5] = path.size; + cmdbuf[6] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[7] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -171,18 +185,18 @@ Result FSUSER_DeleteDirectory(FS_archive archive, FS_path dirLowPath) return cmdbuf[1]; } -Result FSUSER_DeleteDirectoryRecursively(FS_archive archive, FS_path dirLowPath) +Result FSUSER_DeleteDirectoryRecursively(FS_Archive archive, FS_Path path) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x807,5,2); // 0x8070142 cmdbuf[1] = 0; - cmdbuf[2] = archive.handleLow; - cmdbuf[3] = archive.handleHigh; - cmdbuf[4] = dirLowPath.type; - cmdbuf[5] = dirLowPath.size; - cmdbuf[6] = IPC_Desc_StaticBuffer(dirLowPath.size,0); - cmdbuf[7] = (u32)dirLowPath.data; + cmdbuf[2] = (u32) archive.handle; + cmdbuf[3] = (u32) (archive.handle >> 32); + cmdbuf[4] = path.type; + cmdbuf[5] = path.size; + cmdbuf[6] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[7] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -190,21 +204,21 @@ Result FSUSER_DeleteDirectoryRecursively(FS_archive archive, FS_path dirLowPath) return cmdbuf[1]; } -Result FSUSER_CreateFile(FS_archive archive, FS_path fileLowPath, u32 fileSize) +Result FSUSER_CreateFile(FS_Archive archive, FS_Path path, u32 attributes, u64 fileSize) { u32 *cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x808,8,2); // 0x8080202 - cmdbuf[1] = 0; - cmdbuf[2] = archive.handleLow; - cmdbuf[3] = archive.handleHigh; - cmdbuf[4] = fileLowPath.type; - cmdbuf[5] = fileLowPath.size; - cmdbuf[6] = 0; - cmdbuf[7] = fileSize; - cmdbuf[8] = 0; - cmdbuf[9] = IPC_Desc_StaticBuffer(fileLowPath.size,0); - cmdbuf[10] = (u32)fileLowPath.data; + cmdbuf[0] = IPC_MakeHeader(0x808,8,2); // 0x8080202 + cmdbuf[1] = 0; + cmdbuf[2] = (u32) archive.handle; + cmdbuf[3] = (u32) (archive.handle >> 32); + cmdbuf[4] = path.type; + cmdbuf[5] = path.size; + cmdbuf[6] = attributes; + cmdbuf[7] = (u32) fileSize; + cmdbuf[8] = (u32) (fileSize >> 32); + cmdbuf[9] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[10] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -212,19 +226,19 @@ Result FSUSER_CreateFile(FS_archive archive, FS_path fileLowPath, u32 fileSize) return cmdbuf[1]; } -Result FSUSER_CreateDirectory(FS_archive archive, FS_path dirLowPath) +Result FSUSER_CreateDirectory(FS_Archive archive, FS_Path path, u32 attributes) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x809,6,2); // 0x8090182 cmdbuf[1] = 0; - cmdbuf[2] = archive.handleLow; - cmdbuf[3] = archive.handleHigh; - cmdbuf[4] = dirLowPath.type; - cmdbuf[5] = dirLowPath.size; - cmdbuf[6] = 0; - cmdbuf[7] = IPC_Desc_StaticBuffer(dirLowPath.size,0); - cmdbuf[8] = (u32)dirLowPath.data; + cmdbuf[2] = (u32) archive.handle; + cmdbuf[3] = (u32) (archive.handle >> 32); + cmdbuf[4] = path.type; + cmdbuf[5] = path.size; + cmdbuf[6] = attributes; + cmdbuf[7] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[8] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -232,24 +246,24 @@ Result FSUSER_CreateDirectory(FS_archive archive, FS_path dirLowPath) return cmdbuf[1]; } -Result FSUSER_RenameDirectory(FS_archive srcArchive, FS_path srcDirLowPath, FS_archive destArchive, FS_path destDirLowPath) +Result FSUSER_RenameDirectory(FS_Archive srcArchive, FS_Path srcPath, FS_Archive dstArchive, FS_Path dstPath) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x80A,9,4); // 0x80A0244 cmdbuf[1] = 0; - cmdbuf[2] = srcArchive.handleLow; - cmdbuf[3] = srcArchive.handleHigh; - cmdbuf[4] = srcDirLowPath.type; - cmdbuf[5] = srcDirLowPath.size; - cmdbuf[6] = destArchive.handleLow; - cmdbuf[7] = destArchive.handleHigh; - cmdbuf[8] = destDirLowPath.type; - cmdbuf[9] = destDirLowPath.size; - cmdbuf[10] = IPC_Desc_StaticBuffer(srcDirLowPath.size,1); - cmdbuf[11] = (u32)srcDirLowPath.data; - cmdbuf[12] = IPC_Desc_StaticBuffer(destDirLowPath.size,2); - cmdbuf[13] = (u32)destDirLowPath.data; + cmdbuf[2] = (u32) srcArchive.handle; + cmdbuf[3] = (u32) (srcArchive.handle >> 32); + cmdbuf[4] = srcPath.type; + cmdbuf[5] = srcPath.size; + cmdbuf[6] = (u32) dstArchive.handle; + cmdbuf[7] = (u32) (dstArchive.handle >> 32); + cmdbuf[8] = dstPath.type; + cmdbuf[9] = dstPath.size; + cmdbuf[10] = IPC_Desc_StaticBuffer(srcPath.size, 1); + cmdbuf[11] = (u32) srcPath.data; + cmdbuf[12] = IPC_Desc_StaticBuffer(dstPath.size, 2); + cmdbuf[13] = (u32) dstPath.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -257,17 +271,17 @@ Result FSUSER_RenameDirectory(FS_archive srcArchive, FS_path srcDirLowPath, FS_a return cmdbuf[1]; } -Result FSUSER_OpenDirectory(Handle *out, FS_archive archive, FS_path dirLowPath) +Result FSUSER_OpenDirectory(Handle* out, FS_Archive archive, FS_Path path) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x80B,4,2); // 0x80B0102 - cmdbuf[1] = archive.handleLow; - cmdbuf[2] = archive.handleHigh; - cmdbuf[3] = dirLowPath.type; - cmdbuf[4] = dirLowPath.size; - cmdbuf[5] = IPC_Desc_StaticBuffer(dirLowPath.size,0); - cmdbuf[6] = (u32)dirLowPath.data; + cmdbuf[1] = (u32) archive.handle; + cmdbuf[2] = (u32) (archive.handle >> 32); + cmdbuf[3] = path.type; + cmdbuf[4] = path.size; + cmdbuf[5] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[6] = (u32) path.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -277,7 +291,7 @@ Result FSUSER_OpenDirectory(Handle *out, FS_archive archive, FS_path dirLowPath) return cmdbuf[1]; } -Result FSUSER_OpenArchive(FS_archive *archive) +Result FSUSER_OpenArchive(FS_Archive* archive) { if(!archive) return -2; @@ -287,27 +301,47 @@ Result FSUSER_OpenArchive(FS_archive *archive) cmdbuf[1] = archive->id; cmdbuf[2] = archive->lowPath.type; cmdbuf[3] = archive->lowPath.size; - cmdbuf[4] = IPC_Desc_StaticBuffer(archive->lowPath.size,0); - cmdbuf[5] = (u32)archive->lowPath.data; + cmdbuf[4] = IPC_Desc_StaticBuffer(archive->lowPath.size, 0); + cmdbuf[5] = (u32) archive->lowPath.data; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; - archive->handleLow = cmdbuf[2]; - archive->handleHigh = cmdbuf[3]; + archive->handle = cmdbuf[2] | ((u64) cmdbuf[3] << 32); return cmdbuf[1]; } -Result FSUSER_CloseArchive(FS_archive *archive) +Result FSUSER_ControlArchive(FS_Archive archive, FS_ArchiveAction action, void* input, u32 inputSize, void* output, u32 outputSize) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x80D,5,4); // 0x80D0144 + cmdbuf[1] = (u32) archive.handle; + cmdbuf[2] = (u32) (archive.handle >> 32); + cmdbuf[3] = action; + cmdbuf[4] = inputSize; + cmdbuf[5] = outputSize; + cmdbuf[6] = IPC_Desc_Buffer(inputSize, IPC_BUFFER_R); + cmdbuf[7] = (u32) input; + cmdbuf[8] = IPC_Desc_Buffer(outputSize, IPC_BUFFER_W); + cmdbuf[9] = (u32) output; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CloseArchive(FS_Archive* archive) { if(!archive) return -2; u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x80E,2,0); // 0x80E0080 - cmdbuf[1] = archive->handleLow; - cmdbuf[2] = archive->handleHigh; + cmdbuf[1] = (u32) archive->handle; + cmdbuf[2] = (u32) (archive->handle >> 32); Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; @@ -315,7 +349,37 @@ Result FSUSER_CloseArchive(FS_archive *archive) return cmdbuf[1]; } -Result FSUSER_GetSdmcArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters) +Result FSUSER_GetFreeBytes(u64* freeBytes, FS_Archive archive) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x812,2,0); // 0x8120080 + cmdbuf[1] = (u32) archive.handle; + cmdbuf[2] = (u32) (archive.handle >> 32); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(freeBytes) *freeBytes = cmdbuf[2] | ((u64) cmdbuf[3] << 32); + + return cmdbuf[1]; +} + +Result FSUSER_GetCardType(FS_CardType* type) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x813,0,0); // 0x8130000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(type) *type = cmdbuf[2] & 0xFF; + + return cmdbuf[1]; +} + +Result FSUSER_GetSdmcArchiveResource(FS_ArchiveResource* archiveResource) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -324,15 +388,12 @@ Result FSUSER_GetSdmcArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *num Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; - if(sectorSize) *sectorSize = cmdbuf[2]; - if(clusterSize) *clusterSize = cmdbuf[3]; - if(numClusters) *numClusters = cmdbuf[4]; - if(freeClusters) *freeClusters = cmdbuf[5]; + if(archiveResource) memcpy(archiveResource, &cmdbuf[2], sizeof(FS_ArchiveResource)); return cmdbuf[1]; } -Result FSUSER_GetNandArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters) +Result FSUSER_GetNandArchiveResource(FS_ArchiveResource* archiveResource) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -341,15 +402,26 @@ Result FSUSER_GetNandArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *num Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; - if(sectorSize) *sectorSize = cmdbuf[2]; - if(clusterSize) *clusterSize = cmdbuf[3]; - if(numClusters) *numClusters = cmdbuf[4]; - if(freeClusters) *freeClusters = cmdbuf[5]; + if(archiveResource) memcpy(archiveResource, &cmdbuf[2], sizeof(FS_ArchiveResource)); return cmdbuf[1]; } -Result FSUSER_IsSdmcDetected(u8 *detected) +Result FSUSER_GetSdmcFatfsError(u32* error) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x816,0,0); // 0x8160000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(error) *error = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_IsSdmcDetected(bool *detected) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -363,21 +435,7 @@ Result FSUSER_IsSdmcDetected(u8 *detected) return cmdbuf[1]; } -Result FSUSER_GetMediaType(u8* mediatype) -{ - u32* cmdbuf = getThreadCommandBuffer(); - - cmdbuf[0] = IPC_MakeHeader(0x868,0,0); // 0x8680000 - - Result ret = 0; - if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; - - if(mediatype) *mediatype = cmdbuf[2] & 0xFF; - - return cmdbuf[1]; -} - -Result FSUSER_IsSdmcWritable(u8 *writable) +Result FSUSER_IsSdmcWritable(bool *writable) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -391,31 +449,1087 @@ Result FSUSER_IsSdmcWritable(u8 *writable) return cmdbuf[1]; } -Result FSFILE_Close(Handle handle) +Result FSUSER_GetSdmcCid(u8* out, u32 length) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x819,1,2); // 0x8190042 + cmdbuf[1] = length; + cmdbuf[2] = IPC_Desc_Buffer(length, IPC_BUFFER_W); + cmdbuf[3] = (u32) out; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetNandCid(u8* out, u32 length) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81A,1,2); // 0x81A0042 + cmdbuf[1] = length; + cmdbuf[2] = IPC_Desc_Buffer(length, IPC_BUFFER_W); + cmdbuf[3] = (u32) out; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetSdmcSpeedInfo(u32 *speedInfo) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81B,0,0); // 0x81B0000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(speedInfo) *speedInfo = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_GetNandSpeedInfo(u32 *speedInfo) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81C,0,0); // 0x81C0000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(speedInfo) *speedInfo = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_GetSdmcLog(u8* out, u32 length) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81D,1,2); // 0x81D0042 + cmdbuf[1] = length; + cmdbuf[2] = IPC_Desc_Buffer(length, IPC_BUFFER_W); + cmdbuf[3] = (u32) out; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetNandLog(u8* out, u32 length) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81E,1,2); // 0x81E0042 + cmdbuf[1] = length; + cmdbuf[2] = IPC_Desc_Buffer(length, IPC_BUFFER_W); + cmdbuf[3] = (u32) out; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_ClearSdmcLog(void) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x81F,0,0); // 0x81F0000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_ClearNandLog(void) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x820,0,0); // 0x8200000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardSlotIsInserted(bool* inserted) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x821,0,0); // 0x8210000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(inserted) *inserted = cmdbuf[2] & 0xFF; + + return cmdbuf[1]; +} + +Result FSUSER_CardSlotPowerOn(bool* status) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x822,0,0); // 0x8220000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(status) *status = cmdbuf[2] & 0xFF; + + return cmdbuf[1]; +} + +Result FSUSER_CardSlotPowerOff(bool* status) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x823,0,0); // 0x8230000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(status) *status = cmdbuf[2] & 0xFF; + + return cmdbuf[1]; +} + +Result FSUSER_CardSlotGetCardIFPowerStatus(bool* status) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x824,0,0); // 0x8240000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(status) *status = cmdbuf[2] & 0xFF; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectCommand(u8 commandId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x825,1,0); // 0x8250040 + cmdbuf[1] = commandId; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectCommandWithAddress(u8 commandId, u32 address) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x826,2,0); // 0x8260080 + cmdbuf[1] = commandId; + cmdbuf[2] = address; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectRead(u8 commandId, u32 size, u8* output) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x827,2,2); // 0x8270082 + cmdbuf[1] = commandId; + cmdbuf[2] = size; + cmdbuf[3] = IPC_Desc_Buffer(size * sizeof(u32), IPC_BUFFER_W); + cmdbuf[4] = (u32) output; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectReadWithAddress(u8 commandId, u32 address, u32 size, u8* output) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x828,3,2); // 0x82800C2 + cmdbuf[1] = commandId; + cmdbuf[2] = address; + cmdbuf[3] = size; + cmdbuf[4] = IPC_Desc_Buffer(size * sizeof(u32), IPC_BUFFER_W); + cmdbuf[5] = (u32) output; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectWrite(u8 commandId, u32 size, u8* input) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x829,2,2); // 0x8290082 + cmdbuf[1] = commandId; + cmdbuf[2] = size; + cmdbuf[3] = IPC_Desc_Buffer(size * sizeof(u32), IPC_BUFFER_R); + cmdbuf[4] = (u32) input; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectWriteWithAddress(u8 commandId, u32 address, u32 size, u8* input) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x82A,3,2); // 0x82A00C2 + cmdbuf[1] = commandId; + cmdbuf[2] = address; + cmdbuf[3] = size; + cmdbuf[4] = IPC_Desc_Buffer(size * sizeof(u32), IPC_BUFFER_R); + cmdbuf[5] = (u32) input; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectRead_4xIO(u8 commandId, u32 address, u32 size, u8* output) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x82B,3,2); // 0x82B00C2 + cmdbuf[1] = commandId; + cmdbuf[2] = address; + cmdbuf[3] = size; + cmdbuf[4] = IPC_Desc_Buffer(size * sizeof(u32), IPC_BUFFER_W); + cmdbuf[5] = (u32) output; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectCpuWriteWithoutVerify(u32 address, u32 size, u8* input) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x82C,2,2); // 0x82C0082 + cmdbuf[1] = address; + cmdbuf[2] = size; + cmdbuf[3] = IPC_Desc_Buffer(size * sizeof(u32), IPC_BUFFER_R); + cmdbuf[4] = (u32) input; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CardNorDirectSectorEraseWithoutVerify(u32 address) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x82D,1,0); // 0x82D0040 + cmdbuf[1] = address; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetProductInfo(FS_ProductInfo* info, u32 processId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x82E,1,0); // 0x82E0040 + cmdbuf[1] = processId; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(info) memcpy(info, &cmdbuf[2], sizeof(FS_ProductInfo)); + + return cmdbuf[1]; +} + +Result FSUSER_GetProgramLaunchInfo(FS_ProgramInfo* info, u32 processId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x82F,1,0); // 0x82F0040 + cmdbuf[1] = processId; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(info) memcpy(info, &cmdbuf[2], sizeof(FS_ProgramInfo)); + + return cmdbuf[1]; +} + +Result FSUSER_SetCardSpiBaudRate(FS_CardSpiBaudRate baudRate) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x837,1,0); // 0x8370040 + cmdbuf[1] = baudRate; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_SetCardSpiBusMode(FS_CardSpiBusMode busMode) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x838,1,0); // 0x8380040 + cmdbuf[1] = busMode; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_SendInitializeInfoTo9(void) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x839,0,0); // 0x8390000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetSpecialContentIndex(u16* index, FS_MediaType mediaType, u64 programId, FS_SpecialContentType type) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x83A,4,0); // 0x83A0100 + cmdbuf[1] = mediaType; + cmdbuf[2] = (u32) programId; + cmdbuf[3] = (u32) (programId >> 32); + cmdbuf[4] = type; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(index) *index = cmdbuf[2] & 0xFFFF; + + return cmdbuf[1]; +} + +Result FSUSER_GetLegacyRomHeader(FS_MediaType mediaType, u64 programId, u8* header) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x83B,3,2); // 0x83B00C2 + cmdbuf[1] = mediaType; + cmdbuf[2] = (u32) programId; + cmdbuf[3] = (u32) (programId >> 32); + cmdbuf[4] = IPC_Desc_Buffer(0x3B4, IPC_BUFFER_W); + cmdbuf[5] = (u32) header; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetLegacyBannerData(FS_MediaType mediaType, u64 programId, u8* banner) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x83C,3,2); // 0x83C00C2 + cmdbuf[1] = mediaType; + cmdbuf[2] = (u32) programId; + cmdbuf[3] = (u32) (programId >> 32); + cmdbuf[4] = IPC_Desc_Buffer(0x23C0, IPC_BUFFER_W); + cmdbuf[5] = (u32) banner; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CheckAuthorityToAccessExtSaveData(bool* access, FS_MediaType mediaType, u64 saveId, u32 processId) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x83D,4,0); // 0x83D0100 + cmdbuf[1] = mediaType; + cmdbuf[2] = (u32) saveId; + cmdbuf[3] = (u32) (saveId >> 32); + cmdbuf[4] = processId; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(access) *access = cmdbuf[2] & 0xFF; + + return cmdbuf[1]; +} + +Result FSUSER_QueryTotalQuotaSize(u64* quotaSize, u32 directories, u32 files, u32 fileSizeCount, u64* fileSizes) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x83E,3,2); // 0x83E00C2 + cmdbuf[1] = directories; + cmdbuf[2] = files; + cmdbuf[3] = fileSizeCount; + cmdbuf[4] = IPC_Desc_Buffer(fileSizeCount * 8, IPC_BUFFER_R); + cmdbuf[5] = (u32) fileSizes; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(quotaSize) *quotaSize = cmdbuf[2] | ((u64) cmdbuf[3] << 32); + + return cmdbuf[1]; +} + +Result FSUSER_AbnegateAccessRight(u32 accessRight) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x840,1,0); // 0x8400040 + cmdbuf[1] = accessRight; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_DeleteSdmcRoot(void) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x841,0,0); // 0x8410000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_DeleteAllExtSaveDataOnNand(void) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x842,1,0); // 0x8420040 + cmdbuf[1] = 0; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_InitializeCtrFileSystem(void) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x843,0,0); // 0x8430000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_CreateSeed(void) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x844,0,0); // 0x8440000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetFormatInfo(u32* totalSize, u32* directories, u32* files, bool* duplicateData, FS_ArchiveID archiveId, FS_Path path) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x845,3,2); // 0x84500C2 + cmdbuf[1] = archiveId; + cmdbuf[2] = path.type; + cmdbuf[3] = path.size; + cmdbuf[4] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[5] = (u32) path.data; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(totalSize) *totalSize = cmdbuf[2]; + if(directories) *directories = cmdbuf[3]; + if(files) *files = cmdbuf[4]; + if(duplicateData) *duplicateData = cmdbuf[5] & 0xFF; + + return cmdbuf[1]; +} + +Result FSUSER_GetLegacyRomHeader2(u32 headerSize, FS_MediaType mediaType, u64 programId, u8* header) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x846,4,2); // 0x8460102 + cmdbuf[1] = headerSize; + cmdbuf[2] = mediaType; + cmdbuf[3] = (u32) programId; + cmdbuf[4] = (u32) (programId >> 32); + cmdbuf[5] = IPC_Desc_Buffer(headerSize, IPC_BUFFER_W); + cmdbuf[6] = (u32) header; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetSdmcCtrRootPath(u8* out, u32 length) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x848,1,2); // 0x8480042 + cmdbuf[1] = length; + cmdbuf[2] = IPC_Desc_Buffer(length, IPC_BUFFER_W); + cmdbuf[3] = (u32) out; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetArchiveResource(FS_ArchiveResource* archiveResource, FS_MediaType mediaType) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x849,1,0); // 0x8490040 + cmdbuf[1] = mediaType; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(archiveResource) memcpy(archiveResource, &cmdbuf[2], sizeof(FS_ArchiveResource)); + + return cmdbuf[1]; +} + +Result FSUSER_ExportIntegrityVerificationSeed(FS_IntegrityVerificationSeed* seed) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x84A,0,2); // 0x84A0002 + cmdbuf[2] = IPC_Desc_Buffer(sizeof(FS_IntegrityVerificationSeed), IPC_BUFFER_W); + cmdbuf[3] = (u32) seed; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_ImportIntegrityVerificationSeed(FS_IntegrityVerificationSeed* seed) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x84B,0,2); // 0x84B0002 + cmdbuf[2] = IPC_Desc_Buffer(sizeof(FS_IntegrityVerificationSeed), IPC_BUFFER_R); + cmdbuf[3] = (u32) seed; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_FormatSaveData(FS_ArchiveID archiveId, FS_Path path, u32 blocks, u32 directories, u32 files, u32 directoryBuckets, u32 fileBuckets, bool duplicateData) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x84C,9,2); // 0x84C0242 + cmdbuf[1] = archiveId; + cmdbuf[2] = path.type; + cmdbuf[3] = path.size; + cmdbuf[4] = blocks; + cmdbuf[5] = directories; + cmdbuf[6] = files; + cmdbuf[7] = directoryBuckets; + cmdbuf[8] = fileBuckets; + cmdbuf[9] = duplicateData; + cmdbuf[10] = IPC_Desc_StaticBuffer(path.size, 0); + cmdbuf[11] = (u32) path.data; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetLegacySubBannerData(u32 bannerSize, FS_MediaType mediaType, u64 programId, u8* banner) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x84D,4,2); // 0x84D0102 + cmdbuf[1] = bannerSize; + cmdbuf[2] = mediaType; + cmdbuf[3] = (u32) programId; + cmdbuf[4] = (u32) (programId >> 32); + cmdbuf[5] = IPC_Desc_Buffer(bannerSize, IPC_BUFFER_W); + cmdbuf[6] = (u32) banner; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_ReadSpecialFile(u32* bytesRead, u64 fileOffset, u32 size, u8* data) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x84F,4,2); // 0x84F0102 + cmdbuf[1] = 0; + cmdbuf[2] = (u32) fileOffset; + cmdbuf[3] = (u32) (fileOffset >> 32); + cmdbuf[4] = size; + cmdbuf[5] = IPC_Desc_Buffer(size, IPC_BUFFER_W); + cmdbuf[6] = (u32) data; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(bytesRead) *bytesRead = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_GetSpecialFileSize(u64* fileSize) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x850,1,0); // 0x8500040 + cmdbuf[1] = 0; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(fileSize) *fileSize = cmdbuf[2] | ((u64) cmdbuf[3] << 32); + + return cmdbuf[1]; +} + +Result FSUSER_CreateExtSaveData(FS_ExtSaveDataInfo info, u32 directories, u32 files, u64 sizeLimit, u32 smdhSize, u8* smdh) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x851,9,2); // 0x8510242 + memcpy(&cmdbuf[1], &info, sizeof(FS_ExtSaveDataInfo)); + cmdbuf[5] = directories; + cmdbuf[6] = files; + cmdbuf[7] = (u32) sizeLimit; + cmdbuf[8] = (u32) (sizeLimit >> 32); + cmdbuf[9] = smdhSize; + cmdbuf[10] = IPC_Desc_Buffer(smdhSize, IPC_BUFFER_R); + cmdbuf[11] = (u32) smdh; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_DeleteExtSaveData(FS_ExtSaveDataInfo info) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x852,4,0); // 0x8520100 + memcpy(&cmdbuf[1], &info, sizeof(FS_ExtSaveDataInfo)); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_ReadExtSaveDataIcon(u32* bytesRead, FS_ExtSaveDataInfo info, u32 smdhSize, u8* smdh) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x853,5,2); // 0x8530142 + memcpy(&cmdbuf[1], &info, sizeof(FS_ExtSaveDataInfo)); + cmdbuf[5] = smdhSize; + cmdbuf[6] = IPC_Desc_Buffer(smdhSize, IPC_BUFFER_W); + cmdbuf[7] = (u32) smdh; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(bytesRead) *bytesRead = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_GetExtDataBlockSize(u64* totalBlocks, u64* freeBlocks, u32* blockSize, FS_ExtSaveDataInfo info) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x854,4,0); // 0x8540100 + memcpy(&cmdbuf[1], &info, sizeof(FS_ExtSaveDataInfo)); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(totalBlocks) *totalBlocks = cmdbuf[2] | ((u64) cmdbuf[3] << 32); + if(freeBlocks) *freeBlocks = cmdbuf[4] | ((u64) cmdbuf[5] << 32); + if(blockSize) *blockSize = cmdbuf[6]; + + return cmdbuf[1]; +} + +Result FSUSER_EnumerateExtSaveData(u32* idsWritten, u32 idsSize, FS_MediaType mediaType, u32 idSize, bool shared, u8* ids) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x855,4,2); // 0x8550102 + cmdbuf[1] = idsSize; + cmdbuf[2] = mediaType; + cmdbuf[3] = idSize; + cmdbuf[4] = shared; + cmdbuf[5] = IPC_Desc_Buffer(idsSize, IPC_BUFFER_W); + cmdbuf[6] = (u32) ids; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(idsWritten) *idsWritten = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_CreateSystemSaveData(FS_SystemSaveDataInfo info, u32 totalSize, u32 blockSize, u32 directories, u32 files, u32 directoryBuckets, u32 fileBuckets, bool duplicateData) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x856,9,0); // 0x8560240 + memcpy(&cmdbuf[1], &info, sizeof(FS_SystemSaveDataInfo)); + cmdbuf[3] = totalSize; + cmdbuf[4] = blockSize; + cmdbuf[5] = directories; + cmdbuf[6] = files; + cmdbuf[7] = directoryBuckets; + cmdbuf[8] = fileBuckets; + cmdbuf[9] = duplicateData; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_DeleteSystemSaveData(FS_SystemSaveDataInfo info) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x857,2,0); // 0x8570080 + memcpy(&cmdbuf[1], &info, sizeof(FS_SystemSaveDataInfo)); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_StartDeviceMoveAsSource(FS_DeviceMoveContext* context) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x858,0,0); // 0x8580000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(context) memcpy(context, &cmdbuf[2], sizeof(FS_DeviceMoveContext)); + + return cmdbuf[1]; +} + +Result FSUSER_StartDeviceMoveAsDestination(FS_DeviceMoveContext context, bool clear) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x859,9,0); // 0x8590240 + memcpy(&cmdbuf[1], &context, sizeof(FS_DeviceMoveContext)); + cmdbuf[9] = clear; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_SetArchivePriority(FS_Archive archive, u32 priority) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x85A,3,0); // 0x85A00C0 + cmdbuf[1] = (u32) archive.handle; + cmdbuf[2] = (u32) (archive.handle >> 32); + cmdbuf[3] = priority; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetArchivePriority(u32* priority, FS_Archive archive) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x85B,2,0); // 0x85B0080 + cmdbuf[1] = (u32) archive.handle; + cmdbuf[2] = (u32) (archive.handle >> 32); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(priority) *priority = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_SetCtrCardLatencyParameter(u64 latency, bool emulateEndurance) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x85C,3,0); // 0x85C00C0 + cmdbuf[1] = (u32) latency; + cmdbuf[2] = (u32) (latency >> 32); + cmdbuf[3] = emulateEndurance; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_SwitchCleanupInvalidSaveData(bool enable) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x85F,1,0); // 0x85F0040 + cmdbuf[1] = enable; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_EnumerateSystemSaveData(u32* idsWritten, u32 idsSize, u64* ids) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x860,1,2); // 0x8600042 + cmdbuf[1] = idsSize; + cmdbuf[2] = IPC_Desc_Buffer(idsSize, IPC_BUFFER_W); + cmdbuf[3] = (u32) ids; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(idsWritten) *idsWritten = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_InitializeWithSdkVersion(u32 version) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x861,1,2); // 0x8610042 + cmdbuf[1] = version; + cmdbuf[2] = IPC_Desc_CurProcessHandle(); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_SetPriority(u32 priority) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x862,1,0); // 0x8620040 + cmdbuf[1] = priority; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetPriority(u32* priority) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x863,0,0); // 0x8630000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(priority) *priority = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSUSER_SetSaveDataSecureValue(u64 value, FS_SecureValueSlot slot, u32 titleUniqueId, u8 titleVariation) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x865,5,0); // 0x8650140 + cmdbuf[1] = (u32) value; + cmdbuf[2] = (u32) (value >> 32); + cmdbuf[3] = slot; + cmdbuf[4] = titleUniqueId; + cmdbuf[5] = titleVariation; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetSaveDataSecureValue(bool* exists, u64* value, FS_SecureValueSlot slot, u32 titleUniqueId, u8 titleVariation) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x866,3,0); // 0x86600C0 + cmdbuf[1] = slot; + cmdbuf[2] = titleUniqueId; + cmdbuf[3] = titleVariation; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(exists) *exists = cmdbuf[2] & 0xFF; + if(value) *value = cmdbuf[3] | ((u64) cmdbuf[4] << 32); + + return cmdbuf[1]; +} + +Result FSUSER_ControlSecureSave(FS_SecureSaveAction action, void* input, u32 inputSize, void* output, u32 outputSize) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x867,3,4); // 0x86700C4 + cmdbuf[1] = action; + cmdbuf[2] = inputSize; + cmdbuf[3] = outputSize; + cmdbuf[4] = IPC_Desc_Buffer(inputSize, IPC_BUFFER_R); + cmdbuf[5] = (u32) input; + cmdbuf[6] = IPC_Desc_Buffer(outputSize, IPC_BUFFER_W); + cmdbuf[7] = (u32) output; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + return cmdbuf[1]; +} + +Result FSUSER_GetMediaType(FS_MediaType* mediaType) { u32* cmdbuf = getThreadCommandBuffer(); - cmdbuf[0] = IPC_MakeHeader(0x808,0,0); // 0x8080000 + cmdbuf[0] = IPC_MakeHeader(0x868,0,0); // 0x8680000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret; + + if(mediaType) *mediaType = cmdbuf[2] & 0xFF; + + return cmdbuf[1]; +} + +Result FSFILE_Control(Handle handle, FS_FileAction action, void* input, u32 inputSize, void* output, u32 outputSize) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x401,3,4); // 0x40100C4 + cmdbuf[1] = action; + cmdbuf[2] = inputSize; + cmdbuf[3] = outputSize; + cmdbuf[4] = IPC_Desc_Buffer(inputSize, IPC_BUFFER_R); + cmdbuf[5] = (u32) input; + cmdbuf[6] = IPC_Desc_Buffer(outputSize, IPC_BUFFER_W); + cmdbuf[7] = (u32) output; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; - ret = cmdbuf[1]; - if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle); - - return ret; + return cmdbuf[1]; } -Result FSFILE_Read(Handle handle, u32 *bytesRead, u64 offset, void *buffer, u32 size) +Result FSFILE_OpenSubFile(Handle handle, Handle* subFile, u64 offset, u64 size) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x801,4,0); // 0x8010100 + cmdbuf[1] = (u32) offset; + cmdbuf[2] = (u32) (offset >> 32); + cmdbuf[3] = (u32) size; + cmdbuf[4] = (u32) (size >> 32); + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + if(subFile) *subFile = cmdbuf[3]; + + return cmdbuf[1]; +} + +Result FSFILE_Read(Handle handle, u32* bytesRead, u64 offset, void* buffer, u32 size) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x802,3,2); // 0x80200C2 - cmdbuf[1] = (u32)offset; - cmdbuf[2] = (u32)(offset >> 32); + cmdbuf[1] = (u32) offset; + cmdbuf[2] = (u32) (offset >> 32); cmdbuf[3] = size; - cmdbuf[4] = IPC_Desc_Buffer(size,IPC_BUFFER_W); - cmdbuf[5] = (u32)buffer; + cmdbuf[4] = IPC_Desc_Buffer(size, IPC_BUFFER_W); + cmdbuf[5] = (u32) buffer; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; @@ -425,17 +1539,17 @@ Result FSFILE_Read(Handle handle, u32 *bytesRead, u64 offset, void *buffer, u32 return cmdbuf[1]; } -Result FSFILE_Write(Handle handle, u32 *bytesWritten, u64 offset, const void *buffer, u32 size, u32 flushFlags) +Result FSFILE_Write(Handle handle, u32* bytesWritten, u64 offset, const void* buffer, u32 size, u32 flags) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x803,4,2); // 0x8030102 - cmdbuf[1] = (u32)offset; - cmdbuf[2] = (u32)(offset >> 32); + cmdbuf[1] = (u32) offset; + cmdbuf[2] = (u32) (offset >> 32); cmdbuf[3] = size; - cmdbuf[4] = flushFlags; - cmdbuf[5] = IPC_Desc_Buffer(size,IPC_BUFFER_R); - cmdbuf[6] = (u32)buffer; + cmdbuf[4] = flags; + cmdbuf[5] = IPC_Desc_Buffer(size, IPC_BUFFER_R); + cmdbuf[6] = (u32) buffer; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; @@ -445,7 +1559,7 @@ Result FSFILE_Write(Handle handle, u32 *bytesWritten, u64 offset, const void *bu return cmdbuf[1]; } -Result FSFILE_GetSize(Handle handle, u64 *size) +Result FSFILE_GetSize(Handle handle, u64* size) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -454,7 +1568,7 @@ Result FSFILE_GetSize(Handle handle, u64 *size) Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; - if(size) *size = (u64)cmdbuf[2] | ((u64)cmdbuf[3] << 32); + if(size) *size = cmdbuf[2] | ((u64) cmdbuf[3] << 32); return cmdbuf[1]; } @@ -464,8 +1578,8 @@ Result FSFILE_SetSize(Handle handle, u64 size) u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x805,2,0); // 0x8050080 - cmdbuf[1] = (u32)size; - cmdbuf[2] = (u32)(size >> 32); + cmdbuf[1] = (u32) size; + cmdbuf[2] = (u32) (size >> 32); Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; @@ -473,7 +1587,7 @@ Result FSFILE_SetSize(Handle handle, u64 size) return cmdbuf[1]; } -Result FSFILE_GetAttributes(Handle handle, u32 *attributes) +Result FSFILE_GetAttributes(Handle handle, u32* attributes) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -500,6 +1614,21 @@ Result FSFILE_SetAttributes(Handle handle, u32 attributes) return cmdbuf[1]; } +Result FSFILE_Close(Handle handle) +{ + u32* cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x808,0,0); // 0x8080000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + ret = cmdbuf[1]; + if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle); + + return ret; +} + Result FSFILE_Flush(Handle handle) { u32 *cmdbuf = getThreadCommandBuffer(); @@ -512,14 +1641,74 @@ Result FSFILE_Flush(Handle handle) return cmdbuf[1]; } -Result FSDIR_Read(Handle handle, u32 *entriesRead, u32 entryCount, FS_dirent *buffer) +Result FSFILE_SetPriority(Handle handle, u32 priority) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x80A,1,0); // 0x80A0040 + cmdbuf[1] = priority; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + return cmdbuf[1]; +} + +Result FSFILE_GetPriority(Handle handle, u32* priority) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x80B,0,0); // 0x80B0000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + if(priority) *priority = cmdbuf[2]; + + return cmdbuf[1]; +} + +Result FSFILE_OpenLinkFile(Handle handle, Handle* linkFile) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x80C,0,0); // 0x80C0000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + if(linkFile) *linkFile = cmdbuf[3]; + + return cmdbuf[1]; +} + +Result FSDIR_Control(Handle handle, FS_DirectoryAction action, void* input, u32 inputSize, void* output, u32 outputSize) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x401,3,4); // 0x40100C4 + cmdbuf[1] = action; + cmdbuf[2] = inputSize; + cmdbuf[3] = outputSize; + cmdbuf[4] = IPC_Desc_Buffer(inputSize, IPC_BUFFER_R); + cmdbuf[5] = (u32) input; + cmdbuf[6] = IPC_Desc_Buffer(outputSize, IPC_BUFFER_W); + cmdbuf[7] = (u32) output; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + return cmdbuf[1]; +} + +Result FSDIR_Read(Handle handle, u32* entriesRead, u32 entryCount, FS_DirectoryEntry* entries) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = IPC_MakeHeader(0x801,1,2); // 0x8010042 cmdbuf[1] = entryCount; - cmdbuf[2] = IPC_Desc_Buffer(entryCount*0x228,IPC_BUFFER_W); - cmdbuf[3] = (u32)buffer; + cmdbuf[2] = IPC_Desc_Buffer(entryCount * sizeof(FS_DirectoryEntry), IPC_BUFFER_W); + cmdbuf[3] = (u32) entries; Result ret = 0; if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; @@ -543,3 +1732,30 @@ Result FSDIR_Close(Handle handle) return ret; } + +Result FSDIR_SetPriority(Handle handle, u32 priority) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x803,1,0); // 0x8030040 + cmdbuf[1] = priority; + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + return cmdbuf[1]; +} + +Result FSDIR_GetPriority(Handle handle, u32* priority) +{ + u32 *cmdbuf = getThreadCommandBuffer(); + + cmdbuf[0] = IPC_MakeHeader(0x804,0,0); // 0x8040000 + + Result ret = 0; + if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret; + + if(priority) *priority = cmdbuf[2]; + + return cmdbuf[1]; +}