| 124 | } |
| 125 | |
| 126 | Title TitleCache::decode(const u8* src, IconStore& icons) |
| 127 | { |
| 128 | u64 id; |
| 129 | u8 productCode[16]; |
| 130 | u8 accessibleSaveRaw; |
| 131 | bool accessibleExtdata; |
| 132 | char shortDescription[SHORT_LEN]; |
| 133 | char longDescription[LONG_LEN]; |
| 134 | char savePath[PATH_LEN]; |
| 135 | char extdataPath[PATH_LEN]; |
| 136 | FS_MediaType media; |
| 137 | FS_CardType cardType; |
| 138 | CardType card; |
| 139 | |
| 140 | std::memcpy(&id, src + OFF_ID, sizeof(u64)); |
| 141 | std::memcpy(productCode, src + OFF_PRODUCT, 16); |
| 142 | std::memcpy(&accessibleSaveRaw, src + OFF_ACCESS, sizeof(u8)); |
| 143 | std::memcpy(&accessibleExtdata, src + OFF_ACCESS_EXT, sizeof(u8)); |
| 144 | std::memcpy(shortDescription, src + OFF_SHORT, SHORT_LEN); |
| 145 | std::memcpy(longDescription, src + OFF_LONG, LONG_LEN); |
| 146 | std::memcpy(savePath, src + OFF_SAVE_PATH, PATH_LEN); |
| 147 | std::memcpy(extdataPath, src + OFF_EXT_PATH, PATH_LEN); |
| 148 | std::memcpy(&media, src + OFF_MEDIA, sizeof(u8)); |
| 149 | std::memcpy(&cardType, src + OFF_FS_CARD, sizeof(u8)); |
| 150 | std::memcpy(&card, src + OFF_CARD, sizeof(u8)); |
| 151 | |
| 152 | // encode() clamps to FIELD_LEN-1 and zero-fills, but a stale/corrupt cache |
| 153 | // could carry an unterminated field; force NUL so the char[] -> string |
| 154 | // constructions below can't run off the end. |
| 155 | shortDescription[SHORT_LEN - 1] = 0; |
| 156 | longDescription[LONG_LEN - 1] = 0; |
| 157 | savePath[PATH_LEN - 1] = 0; |
| 158 | extdataPath[PATH_LEN - 1] = 0; |
| 159 | |
| 160 | bool accessibleSave = accessibleSaveRaw & 1; |
| 161 | bool saveIsGBA = accessibleSaveRaw & 2; |
| 162 | |
| 163 | Title title; |
| 164 | title.load(id, productCode, accessibleSave, saveIsGBA, accessibleExtdata, shortDescription, longDescription, StringUtils::UTF8toUTF16(savePath), |
| 165 | StringUtils::UTF8toUTF16(extdataPath), media, cardType, card); |
| 166 | |
| 167 | if (cardType == CARD_CTR) { |
| 168 | // OFF_ICON is not u16-aligned in the packed entry; copy into an aligned |
| 169 | // buffer before handing the pixels to the store. |
| 170 | u16 bigIconData[0x900]; |
| 171 | std::memcpy(bigIconData, src + OFF_ICON, ICON_BYTES); |
| 172 | icons.storeCtrIcon(id, bigIconData); |
| 173 | } |
| 174 | else if (media == MEDIATYPE_NAND) { |
| 175 | u16 dsIconData[0x400]; |
| 176 | std::memcpy(dsIconData, src + OFF_ICON, DS_ICON_BYTES); |
| 177 | icons.storeDsPixels(id, dsIconData); |
| 178 | } |
| 179 | |
| 180 | return title; |
| 181 | } |
| 182 | |
| 183 | u64 TitleCache::readId(const u8* src) |