From ca8a19b1f97881804ede0088a7c41715e4b22c7a Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sun, 2 May 2021 15:05:34 -0700 Subject: [PATCH] Fix corruption issues while writing memory card to disk --- include/kabufuda/Card.hpp | 3 +- include/kabufuda/Directory.hpp | 9 +++-- include/kabufuda/File.hpp | 6 +-- lib/kabufuda/Card.cpp | 12 +++--- lib/kabufuda/Directory.cpp | 68 +++++++++++++++++----------------- 5 files changed, 49 insertions(+), 49 deletions(-) diff --git a/include/kabufuda/Card.hpp b/include/kabufuda/Card.hpp index 873ae28..6de40aa 100644 --- a/include/kabufuda/Card.hpp +++ b/include/kabufuda/Card.hpp @@ -97,9 +97,10 @@ class Card { }; void _swapEndian(); }; +#pragma pack(pop) + CardHeader m_ch; CardHeader m_tmpCh; -#pragma pack(pop) SystemString m_filename; AsyncIO m_fileHandle; diff --git a/include/kabufuda/Directory.hpp b/include/kabufuda/Directory.hpp index 6f1806f..146323a 100644 --- a/include/kabufuda/Directory.hpp +++ b/include/kabufuda/Directory.hpp @@ -7,22 +7,23 @@ namespace kabufuda { class Directory { friend class Card; + #pragma pack(push, 4) + using RawData = std::array; struct Data { - std::array m_files; - std::array padding; + File m_files[MaxFiles]; + uint8_t padding[0x3a]; uint16_t m_updateCounter; uint16_t m_checksum; uint16_t m_checksumInv; }; +#pragma pack(pop) - using RawData = std::array; union { Data data; RawData raw; }; -#pragma pack(pop) void swapEndian(); void updateChecksum(); diff --git a/include/kabufuda/File.hpp b/include/kabufuda/File.hpp index 42135cc..cacdf77 100644 --- a/include/kabufuda/File.hpp +++ b/include/kabufuda/File.hpp @@ -11,11 +11,10 @@ class File { friend class Card; #pragma pack(push, 4) using RawData = std::array; - union { struct { - std::array m_game; - std::array m_maker; + uint8_t m_game[4]; + uint8_t m_maker[2]; uint8_t m_reserved; uint8_t m_bannerFlags; #if __GNUC__ && !__clang__ @@ -35,7 +34,6 @@ class File { }; RawData raw; }; - #pragma pack(pop) void swapEndian(); diff --git a/lib/kabufuda/Card.cpp b/lib/kabufuda/Card.cpp index 365ac8d..bcb3dd3 100644 --- a/lib/kabufuda/Card.cpp +++ b/lib/kabufuda/Card.cpp @@ -329,12 +329,12 @@ ECardResult Card::renameFile(const char* oldName, const char* newName) { if (File* replF = dir.getFile(m_game, m_maker, newName)) { BlockAllocationTable bat = m_bats[m_currentBat]; _deleteFile(*replF, bat); - std::memset(f->m_filename, 0, std::size(f->m_filename)); - std::strncpy(f->m_filename, newName, std::size(m_filename) - 1); + std::memset(f->m_filename, 0, 32); + std::strncpy(f->m_filename, newName, 32); _updateDirAndBat(dir, bat); } else { - std::memset(f->m_filename, 0, std::size(f->m_filename)); - std::strncpy(f->m_filename, newName, std::size(m_filename) - 1); + std::memset(f->m_filename, 0, 32); + std::strncpy(f->m_filename, newName, 32); _updateDirAndBat(dir, m_bats[m_currentBat]); } 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); statOut.x20_length = file->m_blockCount * BlockSize; statOut.x24_time = file->m_modifiedTime; - statOut.x28_gameName = file->m_game; - statOut.x2c_company = file->m_maker; + memmove(statOut.x28_gameName.data(), file->m_game, 4); + memmove(statOut.x2c_company.data(), file->m_maker, 4); statOut.x2e_bannerFormat = file->m_bannerFlags; statOut.x30_iconAddr = file->m_iconAddress; diff --git a/lib/kabufuda/Directory.cpp b/lib/kabufuda/Directory.cpp index b1c5b4e..36c6b2c 100644 --- a/lib/kabufuda/Directory.cpp +++ b/lib/kabufuda/Directory.cpp @@ -38,56 +38,57 @@ Directory::Directory() { Directory::Directory(const RawData& rawData) : raw{rawData} {} 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; }); } 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; })); } File* Directory::getFirstFreeFile(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) { return file.m_game[0] == 0xFF; }); + const auto iter = std::find_if(std::begin(data.m_files), std::end(data.m_files), + [](const auto& file) { return file.m_game[0] == 0xFF; }); - if (iter == data.m_files.cend()) { + if (iter == std::end(data.m_files)) { return nullptr; } *iter = File(filename); - if (game != nullptr && std::strlen(game) == iter->m_game.size()) { - std::memcpy(iter->m_game.data(), game, iter->m_game.size()); + if (game != nullptr && std::strlen(game) == 4) { + std::memcpy(iter->m_game, game, 4); } - if (maker != nullptr && std::strlen(maker) == iter->m_maker.size()) { - std::memcpy(iter->m_maker.data(), maker, iter->m_maker.size()); + if (maker != nullptr && std::strlen(maker) == 2) { + std::memcpy(iter->m_maker, maker, 2); } return &*iter; } 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) { - if (file.m_game[0] == 0xFF) { - return false; - } + 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) { + return false; + } - const auto* const game_ptr = reinterpret_cast(file.m_game.data()); - const auto game_size = file.m_game.size(); - if (game != nullptr && std::strlen(game) == game_size && std::strncmp(game_ptr, game, game_size) != 0) { - return false; - } + const auto* const game_ptr = reinterpret_cast(file.m_game); + const auto game_size = 4; + if (game != nullptr && std::strlen(game) == game_size && std::strncmp(game_ptr, game, game_size) != 0) { + return false; + } - const auto* const maker_ptr = reinterpret_cast(file.m_maker.data()); - const auto maker_size = file.m_maker.size(); - if (maker != nullptr && std::strlen(maker) == maker_size && std::strncmp(maker_ptr, maker, maker_size) != 0) { - return false; - } + const auto* const maker_ptr = reinterpret_cast(file.m_maker); + const auto maker_size = 2; + if (maker != nullptr && std::strlen(maker) == maker_size && std::strncmp(maker_ptr, maker, maker_size) != 0) { + return false; + } - return true; - }); + return true; + }); - if (iter == data.m_files.cend()) { + if (iter == std::end(data.m_files)) { 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) { - const auto iter = std::find_if(data.m_files.begin(), data.m_files.end(), [=](const auto& file) { - const auto game_size = file.m_game.size(); - if (game != nullptr && std::strlen(game) == game_size && std::memcmp(file.m_game.data(), game, game_size) != 0) { + const auto iter = std::find_if(std::begin(data.m_files), std::end(data.m_files), [=](const auto& file) { + const auto game_size = 4; + if (game != nullptr && std::strlen(game) == game_size && std::memcmp(file.m_game, game, game_size) != 0) { return false; } - const auto maker_size = file.m_maker.size(); - if (maker != nullptr && std::strlen(maker) == maker_size && - std::memcmp(file.m_maker.data(), maker, maker_size) != 0) { + const auto maker_size = 2; + if (maker != nullptr && std::strlen(maker) == maker_size && std::memcmp(file.m_maker, maker, maker_size) != 0) { return false; } return std::strncmp(file.m_filename, filename, 32) == 0; }); - if (iter == data.m_files.cend()) { + if (iter == std::cend(data.m_files)) { return nullptr; } @@ -118,7 +118,7 @@ File* Directory::getFile(const char* game, const char* maker, const char* filena } File* Directory::getFile(uint32_t idx) { - if (idx >= data.m_files.size()) { + if (idx >= MaxFiles) { return nullptr; }