/* Code by Oddx @ GBAtemp.net */ #include #include #include #include "cache.hpp" #include "usbloader/disc.h" #include "settings/CSettings.h" #include "FileOperations/fileops.h" #include "memory/memory.h" #include "Channels/channels.h" #include "usbloader/GameList.h" #include "GameCube/GCGames.h" #include "FileOperations/DirList.h" #include "wad/nandtitle.h" #include "Controls/DeviceHandler.hpp" #include "gecko.h" void ResetGameHeaderCache() { RemoveDirectory(Settings.GameHeaderCachePath); } void GetDirectoryList(const char *path, std::string &list) { DirList dir(path, 0, DirList::Files | DirList::Dirs); for (int i = 0; i < dir.GetFilecount(); ++i) list.append(dir.GetFilepath(i)); } void GetListWBFS(std::string &list) { char drive[11]; int portPart; u16 partitions = DeviceHandler::GetUSBPartitionCount(); for (u16 i = 0; i < partitions; ++i) { PartitionHandle *usb = DeviceHandler::Instance()->GetUSBHandleFromPartition(i); if (!usb) continue; portPart = DeviceHandler::PartitionToPortPartition(i); snprintf(drive, sizeof(drive), "%s:/wbfs", usb->MountName(portPart)); gprintf("Partition: %d - %s\n", i, drive); GetDirectoryList(drive, list); } } bool isCacheCurrent() { if (!Settings.CacheTitles) return true; char filepath[256] = {}; std::string list; // GameCube snprintf(filepath, sizeof(filepath), "%s", Settings.GameCubePath); GetDirectoryList(filepath, list); snprintf(filepath, sizeof(filepath), "%s", Settings.GameCubeSDPath); GetDirectoryList(filepath, list); // Wii GetListWBFS(list); // EmuNAND snprintf(filepath, sizeof(filepath), "%s/title/00010001", Settings.NandEmuChanPath); GetDirectoryList(filepath, list); snprintf(filepath, sizeof(filepath), "%s/title/00010002", Settings.NandEmuChanPath); GetDirectoryList(filepath, list); snprintf(filepath, sizeof(filepath), "%s/title/00010004", Settings.NandEmuChanPath); GetDirectoryList(filepath, list); // NAND u32 types[3] = {0x00010001, 0x00010002, 0x00010004}; for (u32 i = 0; i < 3; ++i) { u32 num_titles = NandTitles.SetType(types[i]); for (u32 x = 0; x < num_titles; ++x) { u64 tid = NandTitles.Next(); if (!tid) break; snprintf(filepath, sizeof(filepath), "%016llx", tid); list.append(filepath); } } // Generate a CRC-32 hash u32 crc = crc32(0L, Z_NULL, 0); crc = crc32(crc, (u8 *)list.c_str(), list.length()); if (Settings.CacheCheckCRC == crc) return true; gprintf("Resetting cache\n"); Settings.CacheCheckCRC = crc; return false; } // EmuNAND void SaveGameHeaderCache(std::vector &list) { std::string path = std::string(Settings.GameHeaderCachePath) + EMUNAND_HEADER_CACHE_FILE; if (list.empty()) RemoveFile(path.c_str()); CreateSubfolder(Settings.GameHeaderCachePath); FILE *cache = fopen(path.c_str(), "wb"); if (!cache) return; fwrite((void *)&list[0], 1, list.size() * sizeof(struct discHdr), cache); fclose(cache); } void LoadGameHeaderCache(std::vector &list) { std::string path = std::string(Settings.GameHeaderCachePath) + EMUNAND_HEADER_CACHE_FILE; FILE *cache = fopen(path.c_str(), "rb"); if (!cache) return; struct discHdr tmp; fseek(cache, 0, SEEK_END); u64 fileSize = ftell(cache); fseek(cache, 0, SEEK_SET); u32 count = (u32)(fileSize / sizeof(struct discHdr)); list.reserve(count + list.size()); for (u32 i = 0; i < count; ++i) { fseek(cache, i * sizeof(struct discHdr), SEEK_SET); fread((void *)&tmp, 1, sizeof(struct discHdr), cache); list.push_back(tmp); } fclose(cache); } // Wii void SaveGameHeaderCache(std::vector &list, std::vector &plist) { std::string path = std::string(Settings.GameHeaderCachePath) + WII_HEADER_CACHE_FILE; if (list.empty() || plist.empty()) RemoveFile(path.c_str()); std::vector wiictmp; struct wiiCache gtmp; for (u32 i = 0; i < list.size(); ++i) { memset(>mp, 0, sizeof(struct wiiCache)); gtmp.header = list[i]; gtmp.part = plist[i]; wiictmp.push_back(gtmp); } CreateSubfolder(Settings.GameHeaderCachePath); FILE *cache = fopen(path.c_str(), "wb"); if (!cache) return; fwrite((void *)&wiictmp[0], 1, wiictmp.size() * sizeof(struct wiiCache), cache); fclose(cache); } void LoadGameHeaderCache(std::vector &list, std::vector &plist) { std::string path = std::string(Settings.GameHeaderCachePath) + WII_HEADER_CACHE_FILE; FILE *cache = fopen(path.c_str(), "rb"); if (!cache) return; struct wiiCache wiictmp; fseek(cache, 0, SEEK_END); u64 fileSize = ftell(cache); fseek(cache, 0, SEEK_SET); u32 count = (u32)(fileSize / sizeof(struct wiiCache)); list.reserve(count + list.size()); plist.reserve(count + plist.size()); for (u32 i = 0; i < count; ++i) { fseek(cache, i * sizeof(struct wiiCache), SEEK_SET); fread((void *)&wiictmp, 1, sizeof(struct wiiCache), cache); list.push_back(wiictmp.header); plist.push_back(wiictmp.part); } fclose(cache); } // GameCube void SaveGameHeaderCache(std::vector &list, std::vector &plist) { std::string path = std::string(Settings.GameHeaderCachePath) + GAMECUBE_HEADER_CACHE_FILE; if (list.empty() || plist.empty()) RemoveFile(path.c_str()); std::vector gcctmp; struct gcCache gtmp; for (u32 i = 0; i < list.size(); ++i) { memset(>mp, 0, sizeof(gcCache)); gtmp.header = list[i]; strcpy((char *)gtmp.path, plist[i].c_str()); gcctmp.push_back(gtmp); } CreateSubfolder(Settings.GameHeaderCachePath); FILE *cache = fopen(path.c_str(), "wb"); if (!cache) return; fwrite((void *)&gcctmp[0], 1, gcctmp.size() * sizeof(struct gcCache), cache); fclose(cache); } void LoadGameHeaderCache(std::vector &list, std::vector &plist) { std::string path = std::string(Settings.GameHeaderCachePath) + GAMECUBE_HEADER_CACHE_FILE; FILE *cache = fopen(path.c_str(), "rb"); if (!cache) return; struct gcCache gcctmp; fseek(cache, 0, SEEK_END); u64 fileSize = ftell(cache); fseek(cache, 0, SEEK_SET); u32 count = (u32)(fileSize / sizeof(struct gcCache)); list.reserve(count + list.size()); plist.reserve(count + plist.size()); for (u32 i = 0; i < count; ++i) { fseek(cache, i * sizeof(struct gcCache), SEEK_SET); fread((void *)&gcctmp, 1, sizeof(struct gcCache), cache); list.push_back(gcctmp.header); std::string tmp((char *)gcctmp.path); plist.push_back(tmp); } fclose(cache); } bool isCacheFile(std::string filename) { std::string path = std::string(Settings.GameHeaderCachePath) + filename; return CheckFile(path.c_str()); }