diff --git a/nx/include/switch/services/mii.h b/nx/include/switch/services/mii.h index 0c0cb0bc..914ff638 100644 --- a/nx/include/switch/services/mii.h +++ b/nx/include/switch/services/mii.h @@ -113,6 +113,15 @@ typedef struct { u8 unk_x57; } MiiCharInfo; +typedef struct { + u8 data[0x44]; +} MiiStoreData; + +// Mii format used in 3DS (https://www.3dbrew.org/wiki/Mii#Mii_format). +typedef struct { + u8 data[0x60]; +} MiiVer3StoreData; + // Original Mii colors and types before Ver3StoreData conversion typedef struct { u8 faceline_color; diff --git a/nx/include/switch/services/nfc.h b/nx/include/switch/services/nfc.h index 107daf97..779984ab 100644 --- a/nx/include/switch/services/nfc.h +++ b/nx/include/switch/services/nfc.h @@ -23,11 +23,6 @@ typedef enum { NfcServiceType_System = 1, ///< Initializes nfc:sys. } NfcServiceType; -typedef enum { - NfpState_NonInitialized = 0, - NfpState_Initialized = 1, -} NfpState; - typedef enum { NfcState_NonInitialized = 0, NfcState_Initialized = 1, @@ -40,7 +35,6 @@ typedef enum { NfpDeviceState_TagRemoved = 3, NfpDeviceState_TagMounted = 4, NfpDeviceState_Unavailable = 5, - NfpDeviceState_Finalized = 6, } NfpDeviceState; typedef enum { @@ -49,16 +43,23 @@ typedef enum { NfcDeviceState_TagFound = 2, NfcDeviceState_TagRemoved = 3, NfcDeviceState_TagMounted = 4, - NfcDeviceState_Unavailable = 5, - NfcDeviceState_Finalized = 6, } NfcDeviceState; typedef enum { - NfpApplicationAreaVersion_3DS = 0, - NfpApplicationAreaVersion_WiiU = 1, - NfpApplicationAreaVersion_3DSv2 = 2, - NfpApplicationAreaVersion_Switch = 3, - NfpApplicationAreaVersion_NotSet = 0xFF, + NfcMifareDeviceState_Initialized = 0, + NfcMifareDeviceState_SearchingForTag = 1, + NfcMifareDeviceState_TagFound = 2, + NfcMifareDeviceState_TagRemoved = 3, + NfcMifareDeviceState_TagMounted = 4, + NfcMifareDeviceState_Unavailable = 5, +} NfcMifareDeviceState; + +typedef enum { + NfpApplicationAreaVersion_3DS = 0, ///< Application area created by a 3DS game. + NfpApplicationAreaVersion_WiiU = 1, ///< Application area created by a Wii U game. + NfpApplicationAreaVersion_3DSv2 = 2, ///< Application area created by a (new?) 3DS game. + NfpApplicationAreaVersion_Switch = 3, ///< Application area created by a Switch game. + NfpApplicationAreaVersion_Invalid = 0xFF, ///< Invalid value (application area not created). } NfpApplicationAreaVersion; typedef enum { @@ -66,9 +67,9 @@ typedef enum { } NfpDeviceType; typedef enum { - NfpMountTarget_Rom = 1, - NfpMountTarget_Ram = 2, - NfpMountTarget_All = 3, + NfpMountTarget_Rom = BIT(0), + NfpMountTarget_Ram = BIT(1), + NfpMountTarget_All = NfpMountTarget_Rom | NfpMountTarget_Ram, } NfpMountTarget; typedef enum { @@ -102,63 +103,73 @@ typedef enum { NfcMifareCommand_Store = 0xC2, } NfcMifareCommand; +typedef enum { + NfpAmiiboFlag_Valid = BIT(0), ///< Initialized in system settings. + NfpAmiiboFlag_ApplicationAreaExists = BIT(1), ///< Application area exists. +} NfpAmiiboFlag; + typedef struct { - u8 uuid[10]; - u8 uuid_length; - u8 reserved1[0x15]; - u32 protocol; - u32 tag_type; - u8 reserved2[0x30]; + u16 year; + u8 month; + u8 day; +} NX_PACKED NfpDate; + +typedef struct { + u8 uid[10]; ///< UUID. + u8 uid_length; ///< UUID length. + u8 reserved1[0x15]; +} NX_PACKED NfcTagUid; + +typedef struct { + NfcTagUid uid; ///< UUID. + u32 protocol; ///< \ref NfcProtocol + u32 tag_type; ///< \ref NfcTagType + u8 reserved2[0x30]; } NX_PACKED NfpTagInfo; typedef struct { - u8 uuid[10]; - u8 uuid_length; - u8 reserved1[0x15]; - u32 protocol; - u32 tag_type; - u8 reserved2[0x30]; + NfcTagUid uid; ///< UUID. + u32 protocol; ///< \ref NfcProtocol + u32 tag_type; ///< \ref NfcTagType + u8 reserved2[0x30]; } NX_PACKED NfcTagInfo; typedef struct { - u16 last_write_year; - u8 last_write_month; - u8 last_write_day; + NfpDate last_write_date; u16 write_counter; u16 version; u32 application_area_size; - u8 reserved[0x34]; + u8 reserved[0x34]; } NX_PACKED NfpCommonInfo; typedef struct { - u8 amiibo_id[0x8]; - u8 reserved[0x38]; + u8 character_id[3]; + u8 series_id; + u16 numbering_id; + u8 nfp_type; + u8 reserved1[0x39]; } NX_PACKED NfpModelInfo; typedef struct { MiiCharInfo mii; - u16 first_write_year; - u8 first_write_month; - u8 first_write_day; - char amiibo_name[(10*4)+1]; ///< utf-8, null-terminated + NfpDate first_write_date; + char amiibo_name[(10*4)+1]; ///< Amiibo name (utf-8, null-terminated). u8 font_region; u8 reserved[0x7A]; } NX_PACKED NfpRegisterInfo; typedef struct { - u8 mii_store_data[0x44]; - u16 first_write_year; - u8 first_write_month; - u8 first_write_day; - char amiibo_name[(10*4)+1]; ///< utf-8, null-terminated + MiiStoreData mii_store_data; + NfpDate first_write_date; + char amiibo_name[(10*4)+1]; ///< Amiibo name (utf-8, null-terminated). u8 font_region; u8 reserved[0x8E]; } NX_PACKED NfpRegisterInfoPrivate; typedef struct { u64 application_id; - u32 application_area_id; - u16 crc_change_counter; + u32 access_id; + u16 crc32_change_counter; u8 flags; u8 tag_type; u8 application_area_version; @@ -166,39 +177,34 @@ typedef struct { } NX_PACKED NfpAdminInfo; typedef struct { - u8 magic; + u8 tag_magic; ///< Tag magic (always 0xA5: https://www.3dbrew.org/wiki/Amiibo#Page_layout). u8 reserved1[0x1]; - u8 write_counter; - u8 reserved2[0x1]; - u32 settings_crc; - u8 reserved3[0x38]; - u16 last_write_year; - u8 last_write_month; - u8 last_write_day; - u16 application_write_counter; - u16 version; - u32 application_area_size; - u8 reserved4[0x34]; - MiiCharInfo mii; - MiiNfpStoreDataExtension mii_store_data_extension; - u16 first_write_year; - u8 first_write_month; - u8 first_write_day; - u16 amiibo_name[10+1]; ///< utf-16, null-terminated - u8 settings_flag; ///< bit4 = amiibo was initialized in console settings, bit5 = has application area - u8 unknown1; ///< Normally zero - u32 register_info_crc; - u32 unknown2[0x5]; ///< Normally zero - u8 reserved5[0x64]; - u64 application_id; - u32 access_id; - u16 settings_crc_counter; - u8 font_region; - u8 tag_type; - u8 console_type; - u8 application_id_byte; ///< (Original Program ID >> 0x24) & 0xF byte (Program ID has this byte swapped with console type) - u8 reserved6[0x2E]; - u8 application_area[0xD8]; + u16 tag_write_counter; ///< Incremented every tag write. + u32 crc32_1; ///< CRC32 of some internal 8-byte data. + u8 reserved2[0x38]; + NfpDate last_write_date; ///< Updated every write. + u16 write_counter; ///< Incremented every write, until it maxes out at 0xFFFF. + u16 version; ///< Version. + u32 application_area_size; ///< Size of the application area. + u8 reserved3[0x34]; + MiiVer3StoreData mii_v3; ///< Ver3StoreData (Mii format used in 3DS). + MiiNfpStoreDataExtension mii_store_data_extension; ///< StoreDataExtension + NfpDate first_write_date; ///< Set when the amiibo is first written to. + u16 amiibo_name[10+1]; ///< Amiibo name (utf-16, null-terminated). + u8 font_region; ///< Font region. + u8 unknown1; ///< Normally zero + u32 crc32_2; ///< CRC32 of Ver3StoreData + application_id_byte + unknown1 + StoreDataExtension + unknown2 (0x7E bytes total) + u32 unknown2[0x5]; ///< Normally zero + u8 reserved4[0x64]; + u64 application_id; ///< Modified application ID (Application ID & 0xFFFFFFFF0FFFFFFF | 0x30000000) + u32 access_id; ///< Application area access ID + u16 settings_crc32_change_counter; + u8 flags; ///< \ref NfpAmiiboFlag + u8 tag_type; ///< \ref NfcTagType + u8 application_area_version; ///< \ref NfpApplicationAreaVersion + u8 application_id_byte; ///< Application ID byte ((Application ID >> 28) & 0xFF) + u8 reserved5[0x2E]; + u8 application_area[0xD8]; ///< Application area. } NX_PACKED NfpData; typedef struct { @@ -347,7 +353,7 @@ Result nfcMfAttachActivateEvent(const NfcDeviceHandle *handle, Event *out_event) /// Returned event will have autoclear off. Result nfcMfAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_event); -Result nfpGetState(NfpState *out); +Result nfpGetState(NfcState *out); Result nfpGetDeviceState(const NfcDeviceHandle *handle, NfpDeviceState *out); Result nfpGetNpadId(const NfcDeviceHandle *handle, u32 *out); @@ -359,7 +365,7 @@ Result nfcGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out); Result nfcGetNpadId(const NfcDeviceHandle *handle, u32 *out); Result nfcMfGetState(NfcState *out); -Result nfcMfGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out); +Result nfcMfGetDeviceState(const NfcDeviceHandle *handle, NfcMifareDeviceState *out); Result nfcMfGetNpadId(const NfcDeviceHandle *handle, u32 *out); /// Returned event will have autoclear on. diff --git a/nx/source/services/nfc.c b/nx/source/services/nfc.c index 388f011d..9d753c20 100644 --- a/nx/source/services/nfc.c +++ b/nx/source/services/nfc.c @@ -493,7 +493,7 @@ Result nfcMfAttachDeactivateEvent(const NfcDeviceHandle *handle, Event *out_even return _nfcCmdInDevhandleOutEvent(&g_nfcMfInterface, handle, out_event, 9); } -Result nfpGetState(NfpState *out) { +Result nfpGetState(NfcState *out) { u32 tmp=0; Result rc = _nfcCmdNoInOutU32(&g_nfpInterface, &tmp, 19); if (R_SUCCEEDED(rc) && out) *out = tmp; @@ -531,7 +531,7 @@ Result nfcGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out) { return rc; } -Result nfcMfGetDeviceState(const NfcDeviceHandle *handle, NfcDeviceState *out) { +Result nfcMfGetDeviceState(const NfcDeviceHandle *handle, NfcMifareDeviceState *out) { u32 tmp=0; Result rc = _nfcCmdInDevhandleOutU32(&g_nfcMfInterface, handle, &tmp, 11); if (R_SUCCEEDED(rc) && out) *out = tmp;