diff --git a/include/kabufuda/Card.hpp b/include/kabufuda/Card.hpp index 0667a07..e6157cd 100644 --- a/include/kabufuda/Card.hpp +++ b/include/kabufuda/Card.hpp @@ -135,10 +135,10 @@ class Card char m_maker[3] = {'\0'}; void _swapEndian(); - void _updateDirAndBat(); + void _updateDirAndBat(const Directory& dir, const BlockAllocationTable& bat); void _updateChecksum(); File* _fileFromHandle(const FileHandle& fh) const; - void _deleteFile(File& f); + void _deleteFile(File& f, BlockAllocationTable& bat); public: Card(); diff --git a/lib/kabufuda/Card.cpp b/lib/kabufuda/Card.cpp index eb8ea86..5f298c6 100644 --- a/lib/kabufuda/Card.cpp +++ b/lib/kabufuda/Card.cpp @@ -46,6 +46,10 @@ Card::Card(Card&& other) Card& Card::operator=(Card&& other) { + commit(); + if (m_fileHandle) + fclose(m_fileHandle); + memmove(__raw, other.__raw, BlockSize); m_filename = std::move(other.m_filename); m_fileHandle = other.m_fileHandle; @@ -147,17 +151,19 @@ ECardResult Card::openFile(uint32_t fileno, FileHandle& handleOut) return ECardResult::READY; } -void Card::_updateDirAndBat() +void Card::_updateDirAndBat(const Directory& dir, const BlockAllocationTable& bat) { - Directory updateDir = m_dirs[m_currentDir]; - updateDir.m_updateCounter++; - m_dirs[!m_currentDir] = updateDir; m_currentDir = !m_currentDir; + Directory& updateDir = m_dirs[m_currentDir]; + updateDir = dir; + updateDir.m_updateCounter++; + updateDir.updateChecksum(); - BlockAllocationTable updateBat = m_bats[m_currentBat]; - updateBat.m_updateCounter++; - m_bats[!m_currentBat] = updateBat; m_currentBat = !m_currentBat; + BlockAllocationTable& updateBat = m_bats[m_currentBat]; + updateBat = bat; + updateBat.m_updateCounter++; + updateBat.updateChecksum(); } void Card::_updateChecksum() @@ -189,9 +195,10 @@ ECardResult Card::createFile(const char* filename, size_t size, if (!m_dirs[m_currentDir].hasFreeFile()) return ECardResult::NOENT; - _updateDirAndBat(); - File* f = m_dirs[m_currentDir].getFirstFreeFile(m_game, m_maker, filename); - uint16_t block = m_bats[m_currentBat].allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks); + Directory dir = m_dirs[m_currentDir]; + BlockAllocationTable bat = m_bats[m_currentBat]; + File* f = dir.getFirstFreeFile(m_game, m_maker, filename); + uint16_t block = bat.allocateBlocks(neededBlocks, m_maxBlock - FSTBlocks); if (f && block != 0xFFFF) { f->m_modifiedTime = uint32_t(getGCTime()); @@ -199,6 +206,7 @@ ECardResult Card::createFile(const char* filename, size_t size, f->m_blockCount = neededBlocks; handleOut = FileHandle(m_dirs[m_currentDir].indexForFile(f)); + _updateDirAndBat(dir, bat); return ECardResult::READY; } @@ -236,14 +244,14 @@ const char* Card::getFilename(const FileHandle& fh) return f->m_filename; } -void Card::_deleteFile(File& f) +void Card::_deleteFile(File& f, BlockAllocationTable& bat) { uint16_t block = f.m_firstBlock; while (block != 0xFFFF) { /* TODO: add a fragmentation check */ - uint16_t nextBlock = m_bats[m_currentBat].getNextBlock(block); - m_bats[m_currentBat].clear(block, 1); + uint16_t nextBlock = bat.getNextBlock(block); + bat.clear(block, 1); block = nextBlock; } f = File(); @@ -251,29 +259,35 @@ void Card::_deleteFile(File& f) void Card::deleteFile(const FileHandle& fh) { - _updateDirAndBat(); - _deleteFile(*m_dirs[m_currentDir].getFile(fh.idx)); + Directory dir = m_dirs[m_currentDir]; + BlockAllocationTable bat = m_bats[m_currentBat]; + _deleteFile(*dir.getFile(fh.idx), bat); + _updateDirAndBat(dir, bat); } ECardResult Card::deleteFile(const char* filename) { - _updateDirAndBat(); - File* f = m_dirs[m_currentDir].getFile(m_game, m_maker, filename); + Directory dir = m_dirs[m_currentDir]; + File* f = dir.getFile(m_game, m_maker, filename); if (!f) return ECardResult::NOFILE; - _deleteFile(*f); + BlockAllocationTable bat = m_bats[m_currentBat]; + _deleteFile(*f, bat); + _updateDirAndBat(dir, bat); return ECardResult::READY; } ECardResult Card::deleteFile(uint32_t fileno) { - _updateDirAndBat(); - File* f = m_dirs[m_currentDir].getFile(fileno); + Directory dir = m_dirs[m_currentDir]; + File* f = dir.getFile(fileno); if (!f) return ECardResult::NOFILE; - _deleteFile(*f); + BlockAllocationTable bat = m_bats[m_currentBat]; + _deleteFile(*f, bat); + _updateDirAndBat(dir, bat); return ECardResult::READY; } @@ -282,12 +296,13 @@ ECardResult Card::renameFile(const char* oldName, const char* newName) if (strlen(newName) > 32) return ECardResult::NAMETOOLONG; - _updateDirAndBat(); - File* f = m_dirs[m_currentDir].getFile(m_game, m_maker, oldName); + Directory dir = m_dirs[m_currentDir]; + File* f = dir.getFile(m_game, m_maker, oldName); if (!f) return ECardResult::NOFILE; strncpy(f->m_filename, newName, 32); + _updateDirAndBat(dir, m_bats[m_currentBat]); return ECardResult::READY; } @@ -930,6 +945,8 @@ void Card::commit() tmpBat.updateChecksum(); tmpBat.swapEndian(); fwrite(tmpBat.__raw, 1, BlockSize, m_fileHandle); + + fflush(m_fileHandle); } }