#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)
-/// @}
-
-///@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)
-/// @}
-
-///@name FS Flush Flags
-///@{
-/// Don't flush
-#define FS_WRITE_NOFLUSH (0x00000000)
-/// Flush
-#define FS_WRITE_FLUSH (0x00010001)
-/// @}
-
-/// FS path type.
+/// 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.
+};
+
+/// Write flags.
+enum
+{
+ FS_WRITE_FLUSH = BIT(0), ///< Flush.
+ FS_WRITE_UPDATE_TIME = BIT(8), ///< Update file timestamp.
+};
+
+/// 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.
+};
+
+/// 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;
-
-/// FS archive IDs.
+ MEDIATYPE_NAND = 0, ///< NAND.
+ MEDIATYPE_SD = 1, ///< SD card.
+ MEDIATYPE_GAME_CARD = 2, ///< Game card.
+} FS_MediaType;
+
+/// 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.
+/// Path types.
+typedef enum
+{
+ 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;
+
+/// Secure value slot.
+typedef enum
+{
+ 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
{
- FS_pathType type; ///< FS path type.
- u32 size; ///< FS path size.
- const u8 *data; ///< Pointer to FS path data.
-} FS_path;
+ 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;
-/// FS archive.
+/// Archive resource information.
typedef struct
{
- u32 id; ///< Archive ID.
- FS_path lowPath; ///< FS path.
- Handle handleLow; ///< High word of handle.
- Handle handleHigh; ///< Low word of handle.
-} FS_archive;
+ 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;
-/// Directory entry.
+/// 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
{
- // 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;
+ 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);
* @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 an archive.
- * @param archive Archive to open.
+ * @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_OpenArchive(FS_archive* archive);
+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 to open the directory from.
- * @param dirLowPath Path of the directory.
+ * @param archive Archive containing the directory.
+ * @param path Path of the directory.
*/
-Result FSUSER_OpenDirectory(Handle* out, FS_archive archive, FS_path dirLowPath);
+Result FSUSER_OpenDirectory(Handle *out, FS_Archive archive, FS_Path path);
/**
- * @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.
+ * @brief Opens an archive.
+ * @param archive Archive to open.
*/
-Result FSUSER_OpenFile(Handle* out, FS_archive archive, FS_path fileLowPath, u32 openflags, u32 attributes);
+Result FSUSER_OpenArchive(FS_Archive* archive);
/**
- * @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.
+ * @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_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_GetSdmcArchiveResource(FS_ArchiveResource* archiveResource);
+
+/**
+ * @brief Gets the NAND archive resource information.
+ * @param archiveResource Pointer to output the archive resource information to.
+ */
+Result FSUSER_GetNandArchiveResource(FS_ArchiveResource* archiveResource);
+
+/**
+ * @brief Gets the last SDMC fatfs error.
+ * @param error Pointer to output the error to.
+ */
+Result FSUSER_GetSdmcFatfsError(u32* error);
+
+/**
+ * @brief Gets whether an SD card is detected.
+ * @param detected Pointer to output the detection status to.
+ */
+Result FSUSER_IsSdmcDetected(bool *detected);
+
+/**
+ * @brief Gets whether the SD card is writable.
+ * @param detected Pointer to output the writable status to.
+ */
+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_DeleteFile(FS_archive archive, FS_path fileLowPath);
+Result FSUSER_CardNorDirectCommand(u8 commandId);
/**
- * @brief Deletes a directory.
+ * @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 dirLowPath Path of the directory.
+ * @param priority Priority to set.
*/
-Result FSUSER_DeleteDirectory(FS_archive archive, FS_path dirLowPath);
+Result FSUSER_SetArchivePriority(FS_Archive archive, u32 priority);
/**
- * @brief Deletes a directory recursively.
+ * @brief Gets an archive's priority.
+ * @param priority Pointer to output the priority to.
* @param archive Archive to use.
- * @param dirLowPath Path of the directory.
*/
-Result FSUSER_DeleteDirectoryRecursively(FS_archive archive, FS_path dirLowPath);
+Result FSUSER_GetArchivePriority(u32* priority, FS_Archive archive);
/**
- * @brief Renames a file.
- * @param srcArchive Source archive.
- * @param srcFileLowPath Source file.
- * @param destArchive Destination archive.
- * @param destFileLowPath Destination file.
+ * @brief Configures CTRCARD latency emulation.
+ * @param latency Latency to apply, in milliseconds.
+ * @param emulateEndurance Whether to emulate card endurance.
*/
-Result FSUSER_RenameFile(FS_archive srcArchive, FS_path srcFileLowPath, FS_archive destArchive, FS_path destFileLowPath);
+Result FSUSER_SetCtrCardLatencyParameter(u64 latency, bool emulateEndurance);
/**
- * @brief Renames a directory.
- * @param srcArchive Source archive.
- * @param srcDirLowPath Source directory.
- * @param destArchive Destination archive.
- * @param destDirLowPath Destination directory.
+ * @brief Toggles cleaning up invalid save data.
+ * @param Whether to enable cleaning up invalid save data.
*/
-Result FSUSER_RenameDirectory(FS_archive srcArchive, FS_path srcDirLowPath, FS_archive destArchive, FS_path destDirLowPath);
+Result FSUSER_SwitchCleanupInvalidSaveData(bool enable);
/**
- * @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.
+ * @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_GetSdmcArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters);
+Result FSUSER_EnumerateSystemSaveData(u32* idsWritten, u32 idsSize, u64* ids);
/**
- * @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.
+ * @brief Initializes the FSUSER session with an SDK version.
+ * @param version SDK version to initialize with.
*/
-Result FSUSER_GetNandArchiveResource(u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters);
+Result FSUSER_InitializeWithSdkVersion(u32 version);
/**
- * @brief Gets whether an SD card is detected.
- * @param detected Pointer to output the SD detection state to.
+ * @brief Sets the file system priority.
+ * @param priority Priority to set.
*/
-Result FSUSER_IsSdmcDetected(u8 *detected);
+Result FSUSER_SetPriority(u32 priority);
/**
- * @brief Gets whether the SD card is writable.
- * @param detected Pointer to output the SD writable state to.
+ * @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_IsSdmcWritable(u8 *writable);
+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 Sets a file's priority.
+ * @param handle Handle of the file.
+ * @param priority Priority to set.
+ */
+Result FSFILE_SetPriority(Handle handle, u32 priority);
+
+/**
+ * @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 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.
+ * @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_dirent *buffer);
+Result FSDIR_Read(Handle handle, u32* entriesRead, u32 entryCount, FS_DirectoryEntry* entries);
/**
- * @brief Closes a directory handle.
- * @param handle Directory handle to close.
+ * @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);
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);
}
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();
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;
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();
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;
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;
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;
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;
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;
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;
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;
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;
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;
return cmdbuf[1];
}
-Result FSUSER_OpenArchive(FS_archive *archive)
+Result FSUSER_OpenArchive(FS_Archive* archive)
{
if(!archive) return -2;
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_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)
+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;
+
+ return cmdbuf[1];
+}
+
+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(u32 *sectorSize, u32 *clusterSize, u32 *numClusters, u32 *freeClusters)
+Result FSUSER_GetSdmcArchiveResource(FS_ArchiveResource* archiveResource)
{
u32 *cmdbuf = getThreadCommandBuffer();
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();
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(0x817,0,0); // 0x8170000
+ cmdbuf[0] = IPC_MakeHeader(0x816,0,0); // 0x8160000
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- if(detected) *detected = cmdbuf[2] & 0xFF;
+ if(error) *error = cmdbuf[2];
return cmdbuf[1];
}
-Result FSUSER_GetMediaType(u8* mediatype)
+Result FSUSER_IsSdmcDetected(bool *detected)
{
- u32* cmdbuf = getThreadCommandBuffer();
+ u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x868,0,0); // 0x8680000
+ cmdbuf[0] = IPC_MakeHeader(0x817,0,0); // 0x8170000
Result ret = 0;
if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- if(mediatype) *mediatype = cmdbuf[2] & 0xFF;
+ if(detected) *detected = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
-Result FSUSER_IsSdmcWritable(u8 *writable)
+Result FSUSER_IsSdmcWritable(bool *writable)
{
u32 *cmdbuf = getThreadCommandBuffer();
return cmdbuf[1];
}
-Result FSFILE_Close(Handle handle)
+Result FSUSER_GetSdmcCid(u8* out, u32 length)
{
- u32* cmdbuf = getThreadCommandBuffer();
+ u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x808,0,0); // 0x8080000
+ 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(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- ret = cmdbuf[1];
- if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle);
+ return cmdbuf[1];
+}
- return ret;
+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 FSFILE_Read(Handle handle, u32 *bytesRead, u64 offset, void *buffer, u32 size)
+Result FSUSER_GetSdmcSpeedInfo(u32 *speedInfo)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x802,3,2); // 0x80200C2
- 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[0] = IPC_MakeHeader(0x81B,0,0); // 0x81B0000
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- if(bytesRead) *bytesRead = cmdbuf[2];
+ if(speedInfo) *speedInfo = cmdbuf[2];
return cmdbuf[1];
}
-Result FSFILE_Write(Handle handle, u32 *bytesWritten, u64 offset, const void *buffer, u32 size, u32 flushFlags)
+Result FSUSER_GetNandSpeedInfo(u32 *speedInfo)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x803,4,2); // 0x8030102
- 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[0] = IPC_MakeHeader(0x81C,0,0); // 0x81C0000
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- if(bytesWritten) *bytesWritten = cmdbuf[2];
+ if(speedInfo) *speedInfo = cmdbuf[2];
return cmdbuf[1];
}
-Result FSFILE_GetSize(Handle handle, u64 *size)
+Result FSUSER_GetSdmcLog(u8* out, u32 length)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x804,0,0); // 0x8040000
+ 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(handle))) return ret;
+ 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;
- if(size) *size = (u64)cmdbuf[2] | ((u64)cmdbuf[3] << 32);
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
return cmdbuf[1];
}
-Result FSFILE_SetSize(Handle handle, u64 size)
+Result FSUSER_ClearSdmcLog(void)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x805,2,0); // 0x8050080
- cmdbuf[1] = (u32)size;
- cmdbuf[2] = (u32)(size >> 32);
+ cmdbuf[0] = IPC_MakeHeader(0x81F,0,0); // 0x81F0000
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
return cmdbuf[1];
}
-Result FSFILE_GetAttributes(Handle handle, u32 *attributes)
+Result FSUSER_ClearNandLog(void)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x806,0,0); // 0x8060000
+ cmdbuf[0] = IPC_MakeHeader(0x820,0,0); // 0x8200000
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- if(attributes) *attributes = cmdbuf[2];
+ 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 FSFILE_SetAttributes(Handle handle, u32 attributes)
+Result FSUSER_CardSlotPowerOn(bool* status)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x807,1,0); // 0x8070040
- cmdbuf[1] = attributes;
+ cmdbuf[0] = IPC_MakeHeader(0x822,0,0); // 0x8220000
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
+
+ if(status) *status = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
-Result FSFILE_Flush(Handle handle)
+Result FSUSER_CardSlotPowerOff(bool* status)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x809,0,0); // 0x8090000
+ cmdbuf[0] = IPC_MakeHeader(0x823,0,0); // 0x8230000
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
+
+ if(status) *status = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
-Result FSDIR_Read(Handle handle, u32 *entriesRead, u32 entryCount, FS_dirent *buffer)
+Result FSUSER_CardSlotGetCardIFPowerStatus(bool* status)
{
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[0] = IPC_MakeHeader(0x824,0,0); // 0x8240000
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- if(entriesRead) *entriesRead = cmdbuf[2];
+ if(status) *status = cmdbuf[2] & 0xFF;
return cmdbuf[1];
}
-Result FSDIR_Close(Handle handle)
+Result FSUSER_CardNorDirectCommand(u8 commandId)
{
u32 *cmdbuf = getThreadCommandBuffer();
- cmdbuf[0] = IPC_MakeHeader(0x802,0,0); // 0x8020000
+ cmdbuf[0] = IPC_MakeHeader(0x825,1,0); // 0x8250040
+ cmdbuf[1] = commandId;
Result ret = 0;
- if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+ if(R_FAILED(ret = svcSendSyncRequest(fsuHandle))) return ret;
- ret = cmdbuf[1];
- if(R_SUCCEEDED(ret)) ret = svcCloseHandle(handle);
+ return cmdbuf[1];
+}
- return ret;
+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(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;
+
+ return cmdbuf[1];
+}
+
+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[3] = size;
+ cmdbuf[4] = IPC_Desc_Buffer(size, IPC_BUFFER_W);
+ cmdbuf[5] = (u32) buffer;
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ if(bytesRead) *bytesRead = cmdbuf[2];
+
+ return cmdbuf[1];
+}
+
+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[3] = size;
+ 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;
+
+ if(bytesWritten) *bytesWritten = cmdbuf[2];
+
+ return cmdbuf[1];
+}
+
+Result FSFILE_GetSize(Handle handle, u64* size)
+{
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x804,0,0); // 0x8040000
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ if(size) *size = cmdbuf[2] | ((u64) cmdbuf[3] << 32);
+
+ return cmdbuf[1];
+}
+
+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);
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ return cmdbuf[1];
+}
+
+Result FSFILE_GetAttributes(Handle handle, u32* attributes)
+{
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x806,0,0); // 0x8060000
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ if(attributes) *attributes = cmdbuf[2];
+
+ return cmdbuf[1];
+}
+
+Result FSFILE_SetAttributes(Handle handle, u32 attributes)
+{
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x807,1,0); // 0x8070040
+ cmdbuf[1] = attributes;
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ 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();
+
+ cmdbuf[0] = IPC_MakeHeader(0x809,0,0); // 0x8090000
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ return cmdbuf[1];
+}
+
+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 * sizeof(FS_DirectoryEntry), IPC_BUFFER_W);
+ cmdbuf[3] = (u32) entries;
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ if(entriesRead) *entriesRead = cmdbuf[2];
+
+ return cmdbuf[1];
+}
+
+Result FSDIR_Close(Handle handle)
+{
+ u32 *cmdbuf = getThreadCommandBuffer();
+
+ cmdbuf[0] = IPC_MakeHeader(0x802,0,0); // 0x8020000
+
+ Result ret = 0;
+ if(R_FAILED(ret = svcSendSyncRequest(handle))) return ret;
+
+ ret = cmdbuf[1];
+ if(R_SUCCEEDED(ret)) ret = svcCloseHandle(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];
}