size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const std::string& _szDirectory, u64 _NameTableOffset) { size_t CurrentIndex = _FirstIndex; while (CurrentIndex < _LastIndex) { SFileInfo& rFileInfo = m_FileInfoVector[CurrentIndex]; u64 const uOffset = _NameTableOffset + (rFileInfo.m_NameOffset & 0xFFFFFF); std::string const offset_str { GetStringFromOffset(uOffset) }; bool const is_dir = rFileInfo.IsDirectory(); rFileInfo.m_FullPath.reserve(_szDirectory.size() + offset_str.size()); rFileInfo.m_FullPath.append(_szDirectory.data(), _szDirectory.size()) .append(offset_str.data(), offset_str.size()) .append("/", size_t(is_dir)); if (!is_dir) { ++CurrentIndex; continue; } // check next index CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo.m_FileSize, rFileInfo.m_FullPath, _NameTableOffset); } return CurrentIndex; }
size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const std::string& _szDirectory, u64 _NameTableOffset) { size_t CurrentIndex = _FirstIndex; while (CurrentIndex < _LastIndex) { SFileInfo& rFileInfo = m_FileInfoVector[CurrentIndex]; u64 const uOffset = _NameTableOffset + (rFileInfo.m_NameOffset & 0xFFFFFF); rFileInfo.m_FullPath = _szDirectory + GetStringFromOffset(uOffset); // check next index if (rFileInfo.IsDirectory()) { rFileInfo.m_FullPath += '/'; CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo.m_FileSize, rFileInfo.m_FullPath, _NameTableOffset); } else { ++CurrentIndex; } } return CurrentIndex; }
// Changed this stuff from C++ string to C strings for speed in debug mode. Doesn't matter in release, but // std::string is SLOW in debug mode. size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const char* _szDirectory, u64 _NameTableOffset) { size_t CurrentIndex = _FirstIndex; while (CurrentIndex < _LastIndex) { SFileInfo *rFileInfo = &m_FileInfoVector[CurrentIndex]; u64 uOffset = _NameTableOffset + (rFileInfo->m_NameOffset & 0xFFFFFF); std::string filename = GetStringFromOffset(uOffset); // check next index if (rFileInfo->IsDirectory()) { // this is a directory, build up the new szDirectory if (_szDirectory != NULL) CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s/", _szDirectory, filename.c_str()); else CharArrayFromFormat(rFileInfo->m_FullPath, "%s/", filename.c_str()); CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo->m_FileSize, rFileInfo->m_FullPath, _NameTableOffset); } else { // this is a filename if (_szDirectory != NULL) CharArrayFromFormat(rFileInfo->m_FullPath, "%s%s", _szDirectory, filename.c_str()); else CharArrayFromFormat(rFileInfo->m_FullPath, "%s", filename.c_str()); CurrentIndex++; } } return CurrentIndex; }
size_t CFileSystemGCWii::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const std::string& _szDirectory, u64 _NameTableOffset) { size_t CurrentIndex = _FirstIndex; while (CurrentIndex < _LastIndex) { SFileInfo *rFileInfo = &m_FileInfoVector[CurrentIndex]; u64 uOffset = _NameTableOffset + (rFileInfo->m_NameOffset & 0xFFFFFF); std::string filename = GetStringFromOffset(uOffset); // check next index if (rFileInfo->IsDirectory()) { if (_szDirectory.empty()) rFileInfo->m_FullPath += StringFromFormat("%s/", filename.c_str()); else rFileInfo->m_FullPath += StringFromFormat("%s%s/", _szDirectory.c_str(), filename.c_str()); CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo->m_FileSize, rFileInfo->m_FullPath, _NameTableOffset); } else // This is a filename { if (_szDirectory.empty()) rFileInfo->m_FullPath += filename; else rFileInfo->m_FullPath += StringFromFormat("%s%s", _szDirectory.c_str(), filename.c_str()); CurrentIndex++; } } return CurrentIndex; }
void CFileSystemGCWii::InitFileSystem() { m_Initialized = true; u32 const shift = GetOffsetShift(); // read the whole FST u32 fst_offset_unshifted; if (!m_rVolume->ReadSwapped(0x424, &fst_offset_unshifted, m_Wii)) return; u64 FSTOffset = static_cast<u64>(fst_offset_unshifted) << shift; // read all fileinfos u32 name_offset, offset, size; if (!m_rVolume->ReadSwapped(FSTOffset + 0x0, &name_offset, m_Wii) || !m_rVolume->ReadSwapped(FSTOffset + 0x4, &offset, m_Wii) || !m_rVolume->ReadSwapped(FSTOffset + 0x8, &size, m_Wii)) return; SFileInfo root = {name_offset, static_cast<u64>(offset) << shift, size}; if (!root.IsDirectory()) return; // 12 bytes (the size of a file entry) times 10 * 1024 * 1024 is 120 MiB, // more than total RAM in a Wii. No file system should use anywhere near that much. static const u32 ARBITRARY_FILE_SYSTEM_SIZE_LIMIT = 10 * 1024 * 1024; if (root.m_FileSize > ARBITRARY_FILE_SYSTEM_SIZE_LIMIT) { // Without this check, Dolphin can crash by trying to allocate too much // memory when loading the file systems of certain malformed disc images. ERROR_LOG(DISCIO, "File system is abnormally large! Aborting loading"); return; } if (m_FileInfoVector.size()) PanicAlert("Wtf?"); u64 NameTableOffset = FSTOffset; m_FileInfoVector.reserve((size_t)root.m_FileSize); for (u32 i = 0; i < root.m_FileSize; i++) { const u64 read_offset = FSTOffset + (i * 0xC); name_offset = 0; m_rVolume->ReadSwapped(read_offset + 0x0, &name_offset, m_Wii); offset = 0; m_rVolume->ReadSwapped(read_offset + 0x4, &offset, m_Wii); size = 0; m_rVolume->ReadSwapped(read_offset + 0x8, &size, m_Wii); m_FileInfoVector.emplace_back(name_offset, static_cast<u64>(offset) << shift, size); NameTableOffset += 0xC; } BuildFilenames(1, m_FileInfoVector.size(), "", NameTableOffset); }
size_t CARCFile::BuildFilenames(const size_t _FirstIndex, const size_t _LastIndex, const char* _szDirectory, const char* _szNameTable) { size_t CurrentIndex = _FirstIndex; while (CurrentIndex < _LastIndex) { SFileInfo& rFileInfo = m_FileInfoVector[CurrentIndex]; int uOffset = rFileInfo.m_NameOffset & 0xFFFFFF; // check next index if (rFileInfo.IsDirectory()) { // this is a directory, build up the new szDirectory if (_szDirectory != NULL) { sprintf(rFileInfo.m_FullPath, "%s%s/", _szDirectory, &_szNameTable[uOffset]); } else { sprintf(rFileInfo.m_FullPath, "%s/", &_szNameTable[uOffset]); } CurrentIndex = BuildFilenames(CurrentIndex + 1, (size_t) rFileInfo.m_FileSize, rFileInfo.m_FullPath, _szNameTable); } else { // this is a filename if (_szDirectory != NULL) { sprintf(rFileInfo.m_FullPath, "%s%s", _szDirectory, &_szNameTable[uOffset]); } else { sprintf(rFileInfo.m_FullPath, "%s", &_szNameTable[uOffset]); } CurrentIndex++; } } return(CurrentIndex); }
bool CARCFile::ParseBuffer() { // check ID u32 ID = Common::swap32(*(u32*)(m_pBuffer)); if (ID != ARC_ID) return false; // read header u32 FSTOffset = Common::swap32(*(u32*)(m_pBuffer + 0x4)); //u32 FSTSize = Common::swap32(*(u32*)(m_pBuffer + 0x8)); //u32 FileOffset = Common::swap32(*(u32*)(m_pBuffer + 0xC)); // read all file infos SFileInfo Root; Root.m_NameOffset = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x0)); Root.m_Offset = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x4)); Root.m_FileSize = Common::swap32(*(u32*)(m_pBuffer + FSTOffset + 0x8)); if (Root.IsDirectory()) { m_FileInfoVector.resize((unsigned int)Root.m_FileSize); const char* szNameTable = (char*)(m_pBuffer + FSTOffset); for (size_t i = 0; i < m_FileInfoVector.size(); i++) { u8* Offset = m_pBuffer + FSTOffset + (i * 0xC); m_FileInfoVector[i].m_NameOffset = Common::swap32(*(u32*)(Offset + 0x0)); m_FileInfoVector[i].m_Offset = Common::swap32(*(u32*)(Offset + 0x4)); m_FileInfoVector[i].m_FileSize = Common::swap32(*(u32*)(Offset + 0x8)); szNameTable += 0xC; } BuildFilenames(1, m_FileInfoVector.size(), NULL, szNameTable); } return(true); }
void CFileSystemGCWii::InitFileSystem() { m_Initialized = true; u32 const shift = GetOffsetShift(); // read the whole FST u64 FSTOffset = static_cast<u64>(m_rVolume->Read32(0x424, m_Wii)) << shift; // u32 FSTSize = Read32(0x428); // u32 FSTMaxSize = Read32(0x42C); // read all fileinfos SFileInfo Root { m_rVolume->Read32(FSTOffset + 0x0, m_Wii), static_cast<u64>(FSTOffset + 0x4) << shift, m_rVolume->Read32(FSTOffset + 0x8, m_Wii) }; if (!Root.IsDirectory()) return; if (m_FileInfoVector.size()) PanicAlert("Wtf?"); u64 NameTableOffset = FSTOffset; m_FileInfoVector.reserve((size_t)Root.m_FileSize); for (u32 i = 0; i < Root.m_FileSize; i++) { u64 const read_offset = FSTOffset + (i * 0xC); u64 const name_offset = m_rVolume->Read32(read_offset + 0x0, m_Wii); u64 const offset = static_cast<u64>(m_rVolume->Read32(read_offset + 0x4, m_Wii)) << shift; u64 const size = m_rVolume->Read32(read_offset + 0x8, m_Wii); m_FileInfoVector.emplace_back(name_offset, offset, size); NameTableOffset += 0xC; } BuildFilenames(1, m_FileInfoVector.size(), "", NameTableOffset); }
void CFileSystemGCWii::InitFileSystem() { m_Initialized = true; // read the whole FST u64 FSTOffset = (u64)Read32(0x424) << m_OffsetShift; // u32 FSTSize = Read32(0x428); // u32 FSTMaxSize = Read32(0x42C); // read all fileinfos SFileInfo Root; Root.m_NameOffset = Read32(FSTOffset + 0x0); Root.m_Offset = (u64)Read32(FSTOffset + 0x4) << m_OffsetShift; Root.m_FileSize = Read32(FSTOffset + 0x8); if (Root.IsDirectory()) { if (m_FileInfoVector.size()) PanicAlert("Wtf?"); u64 NameTableOffset = FSTOffset; m_FileInfoVector.reserve((unsigned int)Root.m_FileSize); for (u32 i = 0; i < Root.m_FileSize; i++) { SFileInfo sfi; u64 Offset = FSTOffset + (i * 0xC); sfi.m_NameOffset = Read32(Offset + 0x0); sfi.m_Offset = (u64)Read32(Offset + 0x4) << m_OffsetShift; sfi.m_FileSize = Read32(Offset + 0x8); m_FileInfoVector.push_back(sfi); NameTableOffset += 0xC; } BuildFilenames(1, m_FileInfoVector.size(), "", NameTableOffset); } }