MCPcopy Create free account
hub / github.com/BernardoGiordano/Checkpoint / importTitleListCache

Method importTitleListCache

3ds/source/loader.cpp:238–315  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

236}
237
238void TitleCatalog::importTitleListCache(std::vector<Title>& saves, std::vector<Title>& extdatas, IconStore& icons)
239{
240 FSStream inputsaves(Archive::sdmc(), saveCachePath, FS_OPEN_READ);
241 u32 bytesSaves = inputsaves.size();
242 std::unique_ptr<u8[]> cachesaves(new u8[bytesSaves]);
243 u32 readSaves = inputsaves.read(cachesaves.get(), bytesSaves);
244 inputsaves.close();
245 // A cache whose size isn't a whole number of entries, or that read short, is
246 // corrupt: treat it as empty rather than decoding desynced/garbage entries.
247 u32 sizesaves = (bytesSaves % TitleCache::ENTRY_SIZE == 0 && readSaves == bytesSaves) ? bytesSaves / TitleCache::ENTRY_SIZE : 0;
248
249 FSStream inputextdatas(Archive::sdmc(), extdataCachePath, FS_OPEN_READ);
250 u32 bytesExtdatas = inputextdatas.size();
251 std::unique_ptr<u8[]> cacheextdatas(new u8[bytesExtdatas]);
252 u32 readExtdatas = inputextdatas.read(cacheextdatas.get(), bytesExtdatas);
253 inputextdatas.close();
254 u32 sizeextdatas = (bytesExtdatas % TitleCache::ENTRY_SIZE == 0 && readExtdatas == bytesExtdatas) ? bytesExtdatas / TitleCache::ENTRY_SIZE : 0;
255
256 mLimit = sizesaves + sizeextdatas;
257
258 saves.reserve(sizesaves);
259 extdatas.reserve(sizeextdatas);
260
261 // fill the lists with blank titles first
262 for (size_t i = 0, sz = std::max(sizesaves, sizeextdatas); i < sz; i++) {
263 Title title;
264 title.load();
265 if (i < sizesaves) {
266 saves.push_back(title);
267 }
268 if (i < sizeextdatas) {
269 extdatas.push_back(title);
270 }
271 }
272
273 // Map each already-loaded save id to its first and last index in `saves`, so
274 // the extdata pass can reuse a decoded save (they share entries) with an O(1)
275 // lookup instead of a linear scan per extdata — this runs on the startup fast
276 // path. Duplicate ids only occur for the cartridge title, hence tracking both
277 // ends (see the i != 0 && first == 0 case below).
278 std::unordered_map<u64, size_t> firstIdx;
279 std::unordered_map<u64, size_t> lastIdx;
280 firstIdx.reserve(sizesaves);
281 lastIdx.reserve(sizesaves);
282
283 for (size_t i = 0; i < sizesaves; i++) {
284 const u8* titleData = cachesaves.get() + i * TitleCache::ENTRY_SIZE;
285 saves.at(i) = TitleCache::decode(titleData, icons);
286 u64 id = TitleCache::readId(titleData);
287 firstIdx.emplace(id, i); // keeps the first occurrence
288 lastIdx[id] = i; // always the latest occurrence
289
290 mCounter++;
291 }
292
293 for (size_t i = 0; i < sizeextdatas; i++) {
294 const u8* titleData = cacheextdatas.get() + i * TitleCache::ENTRY_SIZE;
295

Callers

nothing calls this directly

Calls 11

decodeFunction · 0.85
atMethod · 0.80
emplaceMethod · 0.80
findMethod · 0.80
sizeMethod · 0.45
readMethod · 0.45
getMethod · 0.45
closeMethod · 0.45
loadMethod · 0.45
push_backMethod · 0.45
endMethod · 0.45

Tested by

no test coverage detected