diff --git a/include/nn/spm.h b/include/nn/spm.h new file mode 100644 index 00000000..0e7ebb23 --- /dev/null +++ b/include/nn/spm.h @@ -0,0 +1,8 @@ +#pragma once + +/** + * \defgroup nn_spm nn_spm + * Functions for extended storage + */ + +#include diff --git a/include/nn/spm/storage.h b/include/nn/spm/storage.h new file mode 100644 index 00000000..62ee48fe --- /dev/null +++ b/include/nn/spm/storage.h @@ -0,0 +1,172 @@ +#pragma once +#include + +/** + * \defgroup nn_spm + * \ingroup nn_spm + * Functions for extended storage (see nn::spm) + * @{ + */ + +#ifdef __cplusplus + +#include + +namespace nn { +namespace spm { + +enum StorageType : uint32_t +{ + STORAGE_TYPE_RAW, + STORAGE_TYPE_WFS, +}; + +using StorageIndex = uint64_t; + +struct VolumeId +{ + VolumeId() = default; + + VolumeId(char const* id){ + strncpy(this->id, id, sizeof(this->id)); + } + + /** + * Compares this VolumeId with another one + * + * \return + * 0 if equal + */ + int32_t + Compare(VolumeId const& other) const + asm("Compare__Q3_2nn3spm8VolumeIdCFRCQ3_2nn3spm8VolumeId"); + + char id[16]; +}; +WUT_CHECK_SIZE(VolumeId, 0x10); + +struct StorageListItem +{ + StorageIndex index; + WUT_UNKNOWN_BYTES(0x04); + StorageType type; +}; +WUT_CHECK_OFFSET(StorageListItem, 0x00, index); +WUT_CHECK_OFFSET(StorageListItem, 0x0c, type); +WUT_CHECK_SIZE(StorageListItem, 0x10); + +struct StorageInfo +{ + //! The mount path (e.g. "/vol/storage_usb01") + char path[0x280]; + //! The connection type (e.g. "usb") + char connection_type_string[8]; + //! The drive format (e.g. "raw" / "wfs") + char format_string[8]; + WUT_UNKNOWN_BYTES(4); + StorageType type; + VolumeId volumeId; +}; +WUT_CHECK_OFFSET(StorageInfo, 0x000, path); +WUT_CHECK_OFFSET(StorageInfo, 0x280, connection_type_string); +WUT_CHECK_OFFSET(StorageInfo, 0x288, format_string); +WUT_CHECK_OFFSET(StorageInfo, 0x294, type); +WUT_CHECK_OFFSET(StorageInfo, 0x298, volumeId); +WUT_CHECK_SIZE(StorageInfo, 0x2a8); + +void +Initialize() + asm("Initialize__Q2_2nn3spmFv"); + +void +Finalize() + asm("Finalize__Q2_2nn3spmFv"); + +void +SetAutoFatal(bool enabled) + asm("SetAutoFatal__Q2_2nn3spmFb"); + +/** + * Sets the storage drive which should be used for extended storage + * + * \return + * 0 on success. + */ +int32_t +SetExtendedStorage(StorageIndex* index) + asm("SetExtendedStorage__Q2_2nn3spmFQ3_2nn3spm12StorageIndex"); + +/** + * Sets the id of the default extended storage drive + */ +void +SetDefaultExtendedStorageVolumeId(VolumeId const& id) + asm("SetDefaultExtendedStorageVolumeId__Q2_2nn3spmFRCQ3_2nn3spm8VolumeId"); + +/** + * Gets the id of the default extended storage drive + */ +void +GetDefaultExtendedStorageVolumeId(VolumeId* id) + asm("GetDefaultExtendedStorageVolumeId__Q2_2nn3spmFv"); + +bool +GetPreviousExtendedStorageVolumeId(bool*, VolumeId* outVolumeId) + asm("GetPreviousExtendedStorageVolumeId__Q2_2nn3spmFPbPQ3_2nn3spm8VolumeId"); + +bool +FindStorageByVolumeId(StorageIndex* outIndex, VolumeId const& volumeId) + asm("FindStorageByVolumeId__Q2_2nn3spmFPQ3_2nn3spm12StorageIndexRCQ3_2nn3spm8VolumeId"); + +int32_t +GetExtendedStorageIndex(StorageIndex* outIndex) + asm("GetExtendedStorageIndex__Q2_2nn3spmFPQ3_2nn3spm12StorageIndex"); + +int32_t +GetStorageList(StorageListItem* items, uint32_t maxNumItems) + asm("GetStorageList__Q2_2nn3spmFPQ3_2nn3spm15StorageListItemUi"); + +int32_t +GetStorageInfo(StorageInfo* outInfo, StorageIndex* index) + asm("GetStorageInfo__Q2_2nn3spmFPQ3_2nn3spm11StorageInfoQ3_2nn3spm12StorageIndex"); + +/** + * Reads the first 512 bytes of the storage head into the buffer + * + * \return + * 0 on success. + */ +int32_t +ReadRawStorageHead512(StorageIndex* index, char* outBuffer) + asm("ReadRawStorageHead512__Q2_2nn3spmFQ3_2nn3spm12StorageIndexPc"); + +/** + * + * \param isPcFormatted + * True if the drive contains a valid MBR with at least one active partition + * + * \return + * 0 on success. + */ +int32_t +IsStorageMaybePcFormatted(bool* isPcFormatted, StorageIndex* index) + asm("IsStorageMaybePcFormatted__Q2_2nn3spmFPbQ3_2nn3spm12StorageIndex"); + +/** + * + * \param isWfsFormatted + * True if the drive does not contain a valid MBR + * + * \return + * 0 on success. + */ +int32_t +IsStorageMaybeWfsFormatted(bool* isWfsFormatted, StorageIndex* index) + asm("IsStorageMaybeWfsFormatted__Q2_2nn3spmFPbQ3_2nn3spm12StorageIndex"); + +}; +}; + +#endif + +/** @} */ diff --git a/tests/test_compile_headers_common/test_compile_headers_list.h b/tests/test_compile_headers_common/test_compile_headers_list.h index 34f8d4ae..098d0af2 100644 --- a/tests/test_compile_headers_common/test_compile_headers_list.h +++ b/tests/test_compile_headers_common/test_compile_headers_list.h @@ -88,12 +88,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include #include #include