mirror of https://github.com/AxioDL/kabufuda.git
Fix corruption issues while writing memory card to disk
This commit is contained in:
parent
106bb02fbf
commit
1111fb4839
|
@ -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;
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -38,56 +38,57 @@ 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 =
|
||||||
if (file.m_game[0] == 0xFF) {
|
std::find_if(std::begin(data.m_files) + start, std::end(data.m_files), [game, maker](const auto& file) {
|
||||||
return false;
|
if (file.m_game[0] == 0xFF) {
|
||||||
}
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue