Fix corruption issues while writing memory card to disk

This commit is contained in:
Phillip Stephens 2021-05-02 15:05:34 -07:00
parent 106bb02fbf
commit 1111fb4839
Signed by: Antidote
GPG Key ID: F8BEE4C83DACA60D
5 changed files with 49 additions and 49 deletions

View File

@ -97,9 +97,10 @@ class Card {
}; };
void _swapEndian(); void _swapEndian();
}; };
#pragma pack(pop)
CardHeader m_ch; CardHeader m_ch;
CardHeader m_tmpCh; CardHeader m_tmpCh;
#pragma pack(pop)
SystemString m_filename; SystemString m_filename;
AsyncIO m_fileHandle; AsyncIO m_fileHandle;

View File

@ -7,22 +7,23 @@
namespace kabufuda { namespace kabufuda {
class Directory { class Directory {
friend class Card; friend class Card;
#pragma pack(push, 4) #pragma pack(push, 4)
using RawData = std::array<uint8_t, BlockSize>;
struct Data { struct Data {
std::array<File, MaxFiles> m_files; File m_files[MaxFiles];
std::array<uint8_t, 0x3a> padding; uint8_t padding[0x3a];
uint16_t m_updateCounter; uint16_t m_updateCounter;
uint16_t m_checksum; uint16_t m_checksum;
uint16_t m_checksumInv; uint16_t m_checksumInv;
}; };
#pragma pack(pop)
using RawData = std::array<uint8_t, BlockSize>;
union { union {
Data data; Data data;
RawData raw; RawData raw;
}; };
#pragma pack(pop)
void swapEndian(); void swapEndian();
void updateChecksum(); void updateChecksum();

View File

@ -11,11 +11,10 @@ class File {
friend class Card; friend class Card;
#pragma pack(push, 4) #pragma pack(push, 4)
using RawData = std::array<uint8_t, 0x40>; using RawData = std::array<uint8_t, 0x40>;
union { union {
struct { struct {
std::array<uint8_t, 4> m_game; uint8_t m_game[4];
std::array<uint8_t, 2> m_maker; uint8_t m_maker[2];
uint8_t m_reserved; uint8_t m_reserved;
uint8_t m_bannerFlags; uint8_t m_bannerFlags;
#if __GNUC__ && !__clang__ #if __GNUC__ && !__clang__
@ -35,7 +34,6 @@ class File {
}; };
RawData raw; RawData raw;
}; };
#pragma pack(pop) #pragma pack(pop)
void swapEndian(); void swapEndian();

View File

@ -329,12 +329,12 @@ ECardResult Card::renameFile(const char* oldName, const char* newName) {
if (File* replF = dir.getFile(m_game, m_maker, newName)) { if (File* replF = dir.getFile(m_game, m_maker, newName)) {
BlockAllocationTable bat = m_bats[m_currentBat]; BlockAllocationTable bat = m_bats[m_currentBat];
_deleteFile(*replF, bat); _deleteFile(*replF, bat);
std::memset(f->m_filename, 0, std::size(f->m_filename)); std::memset(f->m_filename, 0, 32);
std::strncpy(f->m_filename, newName, std::size(m_filename) - 1); std::strncpy(f->m_filename, newName, 32);
_updateDirAndBat(dir, bat); _updateDirAndBat(dir, bat);
} else { } else {
std::memset(f->m_filename, 0, std::size(f->m_filename)); std::memset(f->m_filename, 0, 32);
std::strncpy(f->m_filename, newName, std::size(m_filename) - 1); std::strncpy(f->m_filename, newName, 32);
_updateDirAndBat(dir, m_bats[m_currentBat]); _updateDirAndBat(dir, m_bats[m_currentBat]);
} }
return ECardResult::READY; return ECardResult::READY;
@ -573,8 +573,8 @@ ECardResult Card::getStatus(uint32_t fileNo, CardStat& statOut) const {
std::strncpy(statOut.x0_fileName, file->m_filename, 32); std::strncpy(statOut.x0_fileName, file->m_filename, 32);
statOut.x20_length = file->m_blockCount * BlockSize; statOut.x20_length = file->m_blockCount * BlockSize;
statOut.x24_time = file->m_modifiedTime; statOut.x24_time = file->m_modifiedTime;
statOut.x28_gameName = file->m_game; memmove(statOut.x28_gameName.data(), file->m_game, 4);
statOut.x2c_company = file->m_maker; memmove(statOut.x2c_company.data(), file->m_maker, 4);
statOut.x2e_bannerFormat = file->m_bannerFlags; statOut.x2e_bannerFormat = file->m_bannerFlags;
statOut.x30_iconAddr = file->m_iconAddress; statOut.x30_iconAddr = file->m_iconAddress;

View File

@ -38,48 +38,49 @@ Directory::Directory() {
Directory::Directory(const RawData& rawData) : raw{rawData} {} Directory::Directory(const RawData& rawData) : raw{rawData} {}
bool Directory::hasFreeFile() const { bool Directory::hasFreeFile() const {
return std::any_of(data.m_files.cbegin(), data.m_files.cend(), return std::any_of(std::cbegin(data.m_files), std::cend(data.m_files),
[](const auto& file) { return file.m_game[0] == 0xFF; }); [](const auto& file) { return file.m_game[0] == 0xFF; });
} }
int32_t Directory::numFreeFiles() const { int32_t Directory::numFreeFiles() const {
return int32_t(std::count_if(data.m_files.cbegin(), data.m_files.cend(), return int32_t(std::count_if(std::cbegin(data.m_files), std::cend(data.m_files),
[](const auto& file) { return file.m_game[0] == 0xFF; })); [](const auto& file) { return file.m_game[0] == 0xFF; }));
} }
File* Directory::getFirstFreeFile(const char* game, const char* maker, const char* filename) { File* Directory::getFirstFreeFile(const char* game, const char* maker, const char* filename) {
const auto iter = const auto iter = std::find_if(std::begin(data.m_files), std::end(data.m_files),
std::find_if(data.m_files.begin(), data.m_files.end(), [](const auto& file) { return file.m_game[0] == 0xFF; }); [](const auto& file) { return file.m_game[0] == 0xFF; });
if (iter == data.m_files.cend()) { if (iter == std::end(data.m_files)) {
return nullptr; return nullptr;
} }
*iter = File(filename); *iter = File(filename);
if (game != nullptr && std::strlen(game) == iter->m_game.size()) { if (game != nullptr && std::strlen(game) == 4) {
std::memcpy(iter->m_game.data(), game, iter->m_game.size()); std::memcpy(iter->m_game, game, 4);
} }
if (maker != nullptr && std::strlen(maker) == iter->m_maker.size()) { if (maker != nullptr && std::strlen(maker) == 2) {
std::memcpy(iter->m_maker.data(), maker, iter->m_maker.size()); std::memcpy(iter->m_maker, maker, 2);
} }
return &*iter; return &*iter;
} }
File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const char* maker) { File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const char* maker) {
const auto iter = std::find_if(data.m_files.begin() + start, data.m_files.end(), [game, maker](const auto& file) { const auto iter =
std::find_if(std::begin(data.m_files) + start, std::end(data.m_files), [game, maker](const auto& file) {
if (file.m_game[0] == 0xFF) { if (file.m_game[0] == 0xFF) {
return false; return false;
} }
const auto* const game_ptr = reinterpret_cast<const char*>(file.m_game.data()); const auto* const game_ptr = reinterpret_cast<const char*>(file.m_game);
const auto game_size = file.m_game.size(); const auto game_size = 4;
if (game != nullptr && std::strlen(game) == game_size && std::strncmp(game_ptr, game, game_size) != 0) { if (game != nullptr && std::strlen(game) == game_size && std::strncmp(game_ptr, game, game_size) != 0) {
return false; return false;
} }
const auto* const maker_ptr = reinterpret_cast<const char*>(file.m_maker.data()); const auto* const maker_ptr = reinterpret_cast<const char*>(file.m_maker);
const auto maker_size = file.m_maker.size(); const auto maker_size = 2;
if (maker != nullptr && std::strlen(maker) == maker_size && std::strncmp(maker_ptr, maker, maker_size) != 0) { if (maker != nullptr && std::strlen(maker) == maker_size && std::strncmp(maker_ptr, maker, maker_size) != 0) {
return false; return false;
} }
@ -87,7 +88,7 @@ File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const cha
return true; return true;
}); });
if (iter == data.m_files.cend()) { if (iter == std::end(data.m_files)) {
return nullptr; return nullptr;
} }
@ -95,22 +96,21 @@ File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const cha
} }
File* Directory::getFile(const char* game, const char* maker, const char* filename) { File* Directory::getFile(const char* game, const char* maker, const char* filename) {
const auto iter = std::find_if(data.m_files.begin(), data.m_files.end(), [=](const auto& file) { const auto iter = std::find_if(std::begin(data.m_files), std::end(data.m_files), [=](const auto& file) {
const auto game_size = file.m_game.size(); const auto game_size = 4;
if (game != nullptr && std::strlen(game) == game_size && std::memcmp(file.m_game.data(), game, game_size) != 0) { if (game != nullptr && std::strlen(game) == game_size && std::memcmp(file.m_game, game, game_size) != 0) {
return false; return false;
} }
const auto maker_size = file.m_maker.size(); const auto maker_size = 2;
if (maker != nullptr && std::strlen(maker) == maker_size && if (maker != nullptr && std::strlen(maker) == maker_size && std::memcmp(file.m_maker, maker, maker_size) != 0) {
std::memcmp(file.m_maker.data(), maker, maker_size) != 0) {
return false; return false;
} }
return std::strncmp(file.m_filename, filename, 32) == 0; return std::strncmp(file.m_filename, filename, 32) == 0;
}); });
if (iter == data.m_files.cend()) { if (iter == std::cend(data.m_files)) {
return nullptr; return nullptr;
} }
@ -118,7 +118,7 @@ File* Directory::getFile(const char* game, const char* maker, const char* filena
} }
File* Directory::getFile(uint32_t idx) { File* Directory::getFile(uint32_t idx) {
if (idx >= data.m_files.size()) { if (idx >= MaxFiles) {
return nullptr; return nullptr;
} }