From 81623e5b22acd33d71b30489d0648420d71199e9 Mon Sep 17 00:00:00 2001 From: Arisotura Date: Wed, 27 Oct 2021 02:00:53 +0200 Subject: [PATCH] here have more code --- src/ARM.cpp | 2 - src/FATStorage.cpp | 317 +++++++++++++++++++++++++-------------------- src/FATStorage.h | 11 +- src/NDSCart.cpp | 2 +- 4 files changed, 185 insertions(+), 147 deletions(-) diff --git a/src/ARM.cpp b/src/ARM.cpp index fc9c2662..03844b60 100644 --- a/src/ARM.cpp +++ b/src/ARM.cpp @@ -461,8 +461,6 @@ void ARM::UpdateMode(u32 oldmode, u32 newmode) break; } - #undef SWAP - if (Num == 0) { /*if ((newmode & 0x1F) == 0x10) diff --git a/src/FATStorage.cpp b/src/FATStorage.cpp index f55f5334..c887cb4e 100644 --- a/src/FATStorage.cpp +++ b/src/FATStorage.cpp @@ -25,20 +25,17 @@ namespace fs = std::filesystem; -FATStorage::FATStorage() +FATStorage::FATStorage(std::string filename, u64 size, bool readonly, std::string sourcedir) { - printf("FATStorage begin\n"); - //bool res = Build("dldi", 0x20000000, "melonDLDI.bin"); - bool res = Build("dldi", 0x3F000000, "melonDLDI.bin"); - printf("FATStorage result: %d\n", res); + ReadOnly = readonly; + Load(filename, size, sourcedir); File = nullptr; } FATStorage::~FATStorage() { - printf("SAVING DLDI SHIT\n"); - Save("dldi"); + if (!ReadOnly) Save(); } @@ -47,7 +44,6 @@ bool FATStorage::Open() File = Platform::OpenLocalFile(FilePath.c_str(), "r+b"); if (!File) { - File = nullptr; return false; } } @@ -66,6 +62,7 @@ u32 FATStorage::ReadSectors(u32 start, u32 num, u8* data) u32 FATStorage::WriteSectors(u32 start, u32 num, u8* data) { + if (ReadOnly) return 0; return WriteSectorsInternal(File, FileSize, start, num, data); } @@ -349,7 +346,7 @@ void FATStorage::ExportDirectory(std::string path, std::string outbase, int leve FF_DIR dir; FF_FILINFO info; FRESULT res; -printf("EXPORTING DIRECTORY %s (base %s level %d)\n", path.c_str(), outbase.c_str(), level); + std::string fullpath = "0:/" + path; res = f_opendir(&dir, fullpath.c_str()); if (res != FR_OK) return; @@ -383,7 +380,7 @@ printf("EXPORTING DIRECTORY %s (base %s level %d)\n", path.c_str(), outbase.c_st else { bool doexport = false; -printf("- FILE %s ATTRIB %08X\n", fullpath.c_str(), info.fattrib); + if (FileIndex.count(fullpath) < 1) { doexport = true; @@ -410,7 +407,6 @@ printf("- FILE %s ATTRIB %08X\n", fullpath.c_str(), info.fattrib); if (doexport) { - printf("EXPORTING FILE 0:/%s TO %s/%s\n", fullpath.c_str(), outbase.c_str(), fullpath.c_str()); fs::file_time_type modtime; if (ExportFile("0:/"+fullpath, outbase+"/"+fullpath, modtime)) { @@ -447,7 +443,7 @@ bool FATStorage::DeleteHostDirectory(std::string path, std::string outbase, int std::vector filedeletelist; std::vector dirdeletelist; -printf("-- PURGING HOST DIRECTORY %s (base %s) LEVEL=%d\n", path.c_str(), outbase.c_str(), level); + int outlen = outbase.length(); for (auto& entry : fs::directory_iterator(outbase + "/" + path)) { @@ -462,7 +458,7 @@ printf("-- PURGING HOST DIRECTORY %s (base %s) LEVEL=%d\n", path.c_str(), outbas if (innerpath[i] == '\\') innerpath[i] = '/'; } -printf("---- ENTRY %s (%d)\n", innerpath.c_str(), entry.is_directory()); + if (entry.is_directory()) { dirdeletelist.push_back(innerpath); @@ -495,14 +491,14 @@ printf("---- ENTRY %s (%d)\n", innerpath.c_str(), entry.is_directory()); { std::string fullpath = outbase + "/" + path; - printf("DELETING DIR ITSELF: %s\n", fullpath.c_str()); + std::error_code err; fs::permissions(fullpath, fs::perms::owner_read | fs::perms::owner_write, fs::perm_options::add, err); - if (!fs::remove(fullpath)){printf("DICKPILE %d\n", errno); - return false;} + if (!fs::remove(fullpath)) + return false; DirIndex.erase(path); } @@ -542,7 +538,7 @@ void FATStorage::ExportChanges(std::string outbase) for (const auto& key : deletelist) { std::string fullpath = outbase + "/" + key; - printf("DELETING FILE %s\n", fullpath.c_str()); + std::error_code err; fs::permissions(fullpath, fs::perms::owner_read | fs::perms::owner_write, @@ -575,7 +571,6 @@ void FATStorage::ExportChanges(std::string outbase) for (const auto& key : deletelist) { - printf("DELETING DIRECTORY %s\n", key.c_str()); DeleteHostDirectory(key, outbase, 0); } @@ -593,8 +588,7 @@ bool FATStorage::CanFitFile(u32 len) if (res != FR_OK) return false; u32 clustersize = fs->csize * 0x200; - printf("CHECK IF FILE CAN FIT: len=%d, clus=%d, num=%d, free=%d\n", - len, clustersize, (len + clustersize - 1) / clustersize, freeclusters); + len = (len + clustersize - 1) / clustersize; return (freeclusters >= len); } @@ -668,7 +662,7 @@ void FATStorage::CleanupDirectory(std::string sourcedir, std::string path, int l FF_DIR dir; FF_FILINFO info; FRESULT res; -printf("CLEANING UP DIRECTORY %s (level=%d)\n", path.c_str(), level); + std::string fullpath = "0:/" + path; res = f_opendir(&dir, fullpath.c_str()); if (res != FR_OK) return; @@ -684,9 +678,7 @@ printf("CLEANING UP DIRECTORY %s (level=%d)\n", path.c_str(), level); if (!info.fname[0]) break; std::string fullpath = path + info.fname; -printf("FOUND ENTRY %s %08X (%d/%d, %d)\n", - fullpath.c_str(), info.fattrib, FileIndex.count(fullpath), DirIndex.count(fullpath), - fs::exists(sourcedir+"/"+fullpath)); + if (info.fattrib & AM_DIR) { if (DirIndex.count(fullpath) < 1) @@ -778,131 +770,144 @@ bool FATStorage::ImportFile(std::string path, std::string in) return true; } -bool FATStorage::BuildSubdirectory(const char* sourcedir, const char* path, int level) +bool FATStorage::ImportDirectory(std::string sourcedir) { - if (level >= 32) + // remove whatever isn't in the index + CleanupDirectory(sourcedir, "", 0); + + int srclen = sourcedir.length(); + + // iterate through the host directory: + // * directories will be added if they aren't in the index + // * files will be added if they aren't in the index, or if the size or last-modified-date don't match + for (auto& entry : fs::recursive_directory_iterator(sourcedir)) { - printf("FATStorage::BuildSubdirectory: too many subdirectory levels, skipping\n"); - return false; - } + std::string fullpath = entry.path().string(); + std::string innerpath = fullpath.substr(srclen); + if (innerpath[0] == '/' || innerpath[0] == '\\') + innerpath = innerpath.substr(1); - if (level == 0) - { - // remove whatever isn't in the index - CleanupDirectory(sourcedir, "", 0); - - int srclen = strlen(sourcedir); - - // iterate through the host directory: - // * directories will be added if they aren't in the index - // * files will be added if they aren't in the index, or if the size or last-modified-date don't match - for (auto& entry : fs::recursive_directory_iterator(sourcedir)) + int ilen = innerpath.length(); + for (int i = 0; i < ilen; i++) { - std::string fullpath = entry.path().string(); - std::string innerpath = fullpath.substr(srclen); - if (innerpath[0] == '/' || innerpath[0] == '\\') - innerpath = innerpath.substr(1); - - int ilen = innerpath.length(); - for (int i = 0; i < ilen; i++) - { - if (innerpath[i] == '\\') - innerpath[i] = '/'; - } - - bool readonly = (entry.status().permissions() & fs::perms::owner_write) == fs::perms::none; - - //std::chrono::duration bourf(lastmodified_raw); - //printf("DORP: %016llX\n", bourf.count()); - - if (entry.is_directory()) - { - if (DirIndex.count(innerpath) < 1) - { - DirIndexEntry ientry; - ientry.Path = innerpath; - ientry.IsReadOnly = readonly; - - innerpath = "0:/" + innerpath; - FRESULT res = f_mkdir(innerpath.c_str()); - if (res == FR_OK) - { - DirIndex[ientry.Path] = ientry; - - printf("IMPORTING DIR %s (FROM %s), %d\n", innerpath.c_str(), fullpath.c_str(), readonly); - } - } - } - else if (entry.is_regular_file()) - { - u64 filesize = entry.file_size(); - - auto lastmodified = entry.last_write_time(); - s64 lastmodified_raw = std::chrono::duration_cast(lastmodified.time_since_epoch()).count(); - - bool import = false; - if (FileIndex.count(innerpath) < 1) - { - import = true; - } - else - { - FileIndexEntry& chk = FileIndex[innerpath]; - if (chk.Size != filesize) import = true; - if (chk.LastModified != lastmodified_raw) import = true; - } - - if (import) - { - FileIndexEntry ientry; - ientry.Path = innerpath; - ientry.IsReadOnly = readonly; - ientry.Size = filesize; - ientry.LastModified = lastmodified_raw; - - innerpath = "0:/" + innerpath; - if (ImportFile(innerpath, fullpath)) - { - FF_FILINFO finfo; - f_stat(innerpath.c_str(), &finfo); - - ientry.LastModifiedInternal = (finfo.fdate << 16) | finfo.ftime; - - FileIndex[ientry.Path] = ientry; - - printf("IMPORTING FILE %s (FROM %s), %d\n", innerpath.c_str(), fullpath.c_str(), readonly); - } - } - } - - f_chmod(innerpath.c_str(), readonly?AM_RDO:0, AM_RDO); + if (innerpath[i] == '\\') + innerpath[i] = '/'; } - SaveIndex(); + bool readonly = (entry.status().permissions() & fs::perms::owner_write) == fs::perms::none; - return false; + if (entry.is_directory()) + { + if (DirIndex.count(innerpath) < 1) + { + DirIndexEntry ientry; + ientry.Path = innerpath; + ientry.IsReadOnly = readonly; + + innerpath = "0:/" + innerpath; + FRESULT res = f_mkdir(innerpath.c_str()); + if (res == FR_OK) + { + DirIndex[ientry.Path] = ientry; + } + } + } + else if (entry.is_regular_file()) + { + u64 filesize = entry.file_size(); + + auto lastmodified = entry.last_write_time(); + s64 lastmodified_raw = std::chrono::duration_cast(lastmodified.time_since_epoch()).count(); + + bool import = false; + if (FileIndex.count(innerpath) < 1) + { + import = true; + } + else + { + FileIndexEntry& chk = FileIndex[innerpath]; + if (chk.Size != filesize) import = true; + if (chk.LastModified != lastmodified_raw) import = true; + } + + if (import) + { + FileIndexEntry ientry; + ientry.Path = innerpath; + ientry.IsReadOnly = readonly; + ientry.Size = filesize; + ientry.LastModified = lastmodified_raw; + + innerpath = "0:/" + innerpath; + if (ImportFile(innerpath, fullpath)) + { + FF_FILINFO finfo; + f_stat(innerpath.c_str(), &finfo); + + ientry.LastModifiedInternal = (finfo.fdate << 16) | finfo.ftime; + + FileIndex[ientry.Path] = ientry; + } + } + } + + f_chmod(innerpath.c_str(), readonly?AM_RDO:0, AM_RDO); } + SaveIndex(); - return false; + return true; } -bool FATStorage::Build(const char* sourcedir, u64 size, const char* filename) +u64 FATStorage::GetDirectorySize(std::string sourcedir) +{ + u64 ret = 0; + u32 csize = 0x1000; // this is an estimate + + for (auto& entry : fs::recursive_directory_iterator(sourcedir)) + { + if (entry.is_directory()) + { + ret += csize; + } + else if (entry.is_regular_file()) + { + u64 filesize = entry.file_size(); + + filesize = (filesize + (csize-1)) & ~(csize-1); + ret += filesize; + } + } + + return ret; +} + +bool FATStorage::Load(std::string filename, u64 size, std::string sourcedir) { FilePath = filename; FileSize = size; + SourceDir = sourcedir; + + bool hasdir = !sourcedir.empty(); + + // 'auto' size management: (size=0) + // * if an index exists: the size from the index is used + // * if no index, and an image file exists: the file size is used + // * if no image: if sourcing from a directory, size is calculated from that + // with a 64MB extra, otherwise size is defaulted to 512MB bool isnew = false; - FF_File = Platform::OpenLocalFile(filename, "r+b"); + FF_File = Platform::OpenLocalFile(filename.c_str(), "r+b"); if (!FF_File) { - FF_File = Platform::OpenLocalFile(filename, "w+b"); + FF_File = Platform::OpenLocalFile(filename.c_str(), "w+b"); if (!FF_File) return false; isnew = true; } - +printf("IMAGE FILE NEW: %d\n", isnew); IndexPath = FilePath + ".idx"; if (isnew) { @@ -911,29 +916,58 @@ bool FATStorage::Build(const char* sourcedir, u64 size, const char* filename) SaveIndex(); } else + { LoadIndex(); + printf("INDEX SIZE %016llX\n", FileSize); + if (FileSize == 0) + { + fseek(FF_File, 0, SEEK_END); + FileSize = ftell(FF_File); + } + } - FF_FileSize = size; - ff_disk_open(FF_ReadStorage, FF_WriteStorage, (LBA_t)(size>>9)); - - FRESULT res; - FATFS fs; bool needformat = false; + FATFS fs; + FRESULT res; - res = f_mount(&fs, "0:", 1); - if (res != FR_OK) + if (FileSize == 0) { needformat = true; } - else if (size != FileSize) + else { - printf("VOLUME NEEDS REFORMATTING BECAUSE SIZE CHANGED (%016llX != %016llX)\n", size, FileSize); - needformat = true; + FF_FileSize = FileSize; + ff_disk_open(FF_ReadStorage, FF_WriteStorage, (LBA_t)(FF_FileSize>>9)); + + res = f_mount(&fs, "0:", 1); + if (res != FR_OK) + { + needformat = true; + } + else if (size > 0 && size != FileSize) + { + needformat = true; + } } if (needformat) { FileSize = size; + if (FileSize == 0) + { + if (hasdir) + { + FileSize = GetDirectorySize(sourcedir); + FileSize += 0x4000000ULL; // 64MB leeway + } + else + FileSize = 0x20000000ULL; // 512MB + } +printf("CREATING IMAGE FILE WITH SIZE %016llX\n", FileSize); + FF_FileSize = FileSize; + ff_disk_close(); + ff_disk_open(FF_ReadStorage, FF_WriteStorage, (LBA_t)(FF_FileSize>>9)); + DirIndex.clear(); FileIndex.clear(); SaveIndex(); @@ -943,7 +977,7 @@ bool FATStorage::Build(const char* sourcedir, u64 size, const char* filename) // 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) + if (FileSize >= 0x40000000ULL) fsopt.fmt = FM_FAT32; else fsopt.fmt = FM_FAT; @@ -959,9 +993,12 @@ bool FATStorage::Build(const char* sourcedir, u64 size, const char* filename) if (res == FR_OK) res = f_mount(&fs, "0:", 1); } - +printf("USING IMAGE FILE WITH SIZE %016llX\n", FileSize); if (res == FR_OK) - BuildSubdirectory(sourcedir, "", 0); + { + if (hasdir) + ImportDirectory(sourcedir); + } f_unmount("0:"); @@ -972,7 +1009,7 @@ bool FATStorage::Build(const char* sourcedir, u64 size, const char* filename) return true; } -bool FATStorage::Save(std::string sourcedir) +bool FATStorage::Save() { FF_File = Platform::OpenLocalFile(FilePath.c_str(), "r+b"); if (!FF_File) @@ -995,7 +1032,7 @@ bool FATStorage::Save(std::string sourcedir) return false; } - ExportChanges("dldi"); + ExportChanges(SourceDir); SaveIndex(); diff --git a/src/FATStorage.h b/src/FATStorage.h index e0f0faea..4574ab78 100644 --- a/src/FATStorage.h +++ b/src/FATStorage.h @@ -31,7 +31,7 @@ class FATStorage { public: - FATStorage(); + FATStorage(std::string filename, u64 size, bool readonly, std::string sourcedir); ~FATStorage(); bool Open(); @@ -43,6 +43,8 @@ public: private: std::string FilePath; std::string IndexPath; + std::string SourceDir; + bool ReadOnly; FILE* File; u64 FileSize; @@ -67,10 +69,11 @@ private: bool DeleteDirectory(std::string path, int level); void CleanupDirectory(std::string sourcedir, std::string path, int level); bool ImportFile(std::string path, std::string in); - bool BuildSubdirectory(const char* sourcedir, const char* path, int level); + bool ImportDirectory(std::string sourcedir); + u64 GetDirectorySize(std::string sourcedir); - bool Build(const char* sourcedir, u64 size, const char* filename); - bool Save(std::string sourcedir); + bool Load(std::string filename, u64 size, std::string sourcedir); + bool Save(); typedef struct { diff --git a/src/NDSCart.cpp b/src/NDSCart.cpp index f15af659..db7cd264 100644 --- a/src/NDSCart.cpp +++ b/src/NDSCart.cpp @@ -1168,7 +1168,7 @@ CartHomebrew::CartHomebrew(u8* rom, u32 len, u32 chipid) : CartCommon(rom, len, if (true) { ApplyDLDIPatch(melonDLDI, sizeof(melonDLDI), true); - SD = new FATStorage(); + SD = new FATStorage("melonDLDI.bin", 0, false, "dldi"); SD->Open(); } else