more intelligence regarding volume size

This commit is contained in:
Arisotura 2021-10-12 03:04:52 +02:00
parent 71f15f99f6
commit b96b0297d4
1 changed files with 49 additions and 35 deletions

View File

@ -16,13 +16,7 @@
with melonDS. If not, see http://www.gnu.org/licenses/. with melonDS. If not, see http://www.gnu.org/licenses/.
*/ */
#ifdef __WIN32__
#include <windows.h>
#else
#include <sys/types.h>
#endif // __WIN32__
#include <dirent.h> #include <dirent.h>
#include <errno.h>
#include <inttypes.h> #include <inttypes.h>
#include "FATStorage.h" #include "FATStorage.h"
@ -31,26 +25,11 @@
namespace fs = std::filesystem; namespace fs = std::filesystem;
static int GetDirEntryType(const char* path, struct dirent* entry)
{
#ifdef __WIN32__
DWORD res = GetFileAttributesA(path);
if (res == INVALID_FILE_ATTRIBUTES) return -1;
if (res & FILE_ATTRIBUTE_DIRECTORY) return 1;
if (res & (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_DEVICE | FILE_ATTRIBUTE_VIRTUAL)) return -1;
return 0;
#else
if (entry->d_type == DT_DIR) return 1;
if (entry->d_type == DT_REG) return 0;
return -1;
#endif // __WIN32__
}
FATStorage::FATStorage() FATStorage::FATStorage()
{ {
printf("FATStorage begin\n"); printf("FATStorage begin\n");
bool res = Build("dldi", 0x20000000, "melonDLDI.bin"); //bool res = Build("dldi", 0x20000000, "melonDLDI.bin");
bool res = Build("dldi", 0x3F000000, "melonDLDI.bin");
printf("FATStorage result: %d\n", res); printf("FATStorage result: %d\n", res);
} }
@ -128,7 +107,15 @@ void FATStorage::LoadIndex()
if (fgets(linebuf, 1536, f) == nullptr) if (fgets(linebuf, 1536, f) == nullptr)
break; break;
if (linebuf[0] == 'D') if (linebuf[0] == 'S')
{
u64 fsize;
int ret = sscanf(linebuf, "SIZE %" PRIu64, &fsize);
if (ret < 1) continue;
FileSize = fsize;
}
else if (linebuf[0] == 'D')
{ {
u32 readonly; u32 readonly;
char fpath[1536] = {0}; char fpath[1536] = {0};
@ -246,6 +233,8 @@ void FATStorage::SaveIndex()
FILE* f = Platform::OpenLocalFile(IndexPath.c_str(), "w"); FILE* f = Platform::OpenLocalFile(IndexPath.c_str(), "w");
if (!f) return; if (!f) return;
fprintf(f, "SIZE %" PRIu64 "\r\n", FileSize);
for (const auto& [key, val] : DirIndex) for (const auto& [key, val] : DirIndex)
{ {
fprintf(f, "DIR %u %s\r\n", fprintf(f, "DIR %u %s\r\n",
@ -862,37 +851,62 @@ bool FATStorage::Build(const char* sourcedir, u64 size, const char* filename)
FilePath = filename; FilePath = filename;
FileSize = size; FileSize = size;
bool isnew = false;
FF_File = Platform::OpenLocalFile(filename, "r+b"); FF_File = Platform::OpenLocalFile(filename, "r+b");
if (!FF_File) if (!FF_File)
{ {
FF_File = Platform::OpenLocalFile(filename, "w+b"); FF_File = Platform::OpenLocalFile(filename, "w+b");
if (!FF_File) if (!FF_File)
return false; return false;
isnew = true;
} }
IndexPath = FilePath + ".idx"; IndexPath = FilePath + ".idx";
LoadIndex(); if (isnew)
{
DirIndex.clear();
FileIndex.clear();
SaveIndex();
}
else
LoadIndex();
FF_FileSize = size; FF_FileSize = size;
ff_disk_open(FF_ReadStorage, FF_WriteStorage, (LBA_t)(size>>9)); ff_disk_open(FF_ReadStorage, FF_WriteStorage, (LBA_t)(size>>9));
FRESULT res; FRESULT res;
FATFS fs; FATFS fs;
bool needformat = false;
res = f_mount(&fs, "0:", 1); res = f_mount(&fs, "0:", 1);
if (res != FR_OK) if (res != FR_OK)
{ {
// TODO: determine proper FAT type! needformat = true;
// for example: libfat tries to determine the FAT type from the number of clusters }
// which doesn't match the way fatfs handles autodetection else if (size != FileSize)
// {
// partition->dataStart = partition->rootDirStart + (( u8array_to_u16(sectorBuffer, BPB_rootEntries) * DIR_ENTRY_DATA_SIZE) / partition->bytesPerSector); printf("VOLUME NEEDS REFORMATTING BECAUSE SIZE CHANGED (%016llX != %016llX)\n", size, FileSize);
// uint32_t clusterCount = (partition->numberOfSectors - (uint32_t)(partition->dataStart - startSector)) / partition->sectorsPerCluster; needformat = true;
// FAT12: max cluster count 4085 }
// FAT16; max cluster count: 65525
// if (needformat)
{
FileSize = size;
DirIndex.clear();
FileIndex.clear();
SaveIndex();
FF_MKFS_PARM fsopt; FF_MKFS_PARM fsopt;
fsopt.fmt = FM_FAT;// | FM_FAT32;
// FAT type: we force it to FAT32 for any volume that is 1GB or more
// libfat attempts to determine the FAT type from the volume size and other parameters
// which can lead to it trying to interpret a FAT16 volume as FAT32
if (size >= 0x40000000ULL)
fsopt.fmt = FM_FAT32;
else
fsopt.fmt = FM_FAT;
fsopt.au_size = 0; fsopt.au_size = 0;
fsopt.align = 1; fsopt.align = 1;
fsopt.n_fat = 1; fsopt.n_fat = 1;