diff --git a/include/Card.hpp b/include/Card.hpp index 19349ea..7865bb3 100644 --- a/include/Card.hpp +++ b/include/Card.hpp @@ -95,6 +95,13 @@ public: ~File() {} }; +struct FileHandle +{ + File* file = nullptr; + uint32_t offset =0; + operator bool() const { return file != nullptr; } +}; + class BlockAllocationTable { friend class Card; @@ -142,7 +149,7 @@ class Directory uint8_t __raw[BlockSize]; }; #pragma pop() - void commitFiles(FILE* mc); + public: Directory(); Directory(uint8_t data[BlockSize]); @@ -178,6 +185,7 @@ class Card uint8_t __raw[BlockSize]; }; #pragma pop() + SystemString m_filename; Directory m_dir; Directory m_dirBackup; @@ -203,14 +211,14 @@ public: * @brief openFile * @param filename */ - File* openFile(const char* filename); + FileHandle openFile(const char* filename); /** * @brief createFile * @param filename * @return */ - File* createFile(const char* filename, size_t size); - void write(File* f, void* buf, size_t size); + FileHandle createFile(const char* filename, size_t size); + void write(FileHandle* f, const void* buf, size_t size); /** * @brief Sets the current game, if not null any openFile requests will only return files that match this game * @param game The target game id, e.g "GM8E" diff --git a/src/Card.cpp b/src/Card.cpp index 581e62f..7131a1b 100644 --- a/src/Card.cpp +++ b/src/Card.cpp @@ -43,33 +43,42 @@ Card::Card(const SystemString& filename, const char* game, const char* maker) Card::~Card() { + commit(); } -File* Card::openFile(const char* filename) +FileHandle Card::openFile(const char* filename) { - return m_dirInUse->getFile(m_game, m_maker, filename); + return {m_dirInUse->getFile(m_game, m_maker, filename)}; } -File* Card::createFile(const char* filename, size_t size) +FileHandle Card::createFile(const char* filename, size_t size) { File* f = m_dirInUse->getFirstFreeFile(m_game, m_maker, filename); uint16_t block = m_batInUse->allocateBlocks(size / BlockSize); if (f && block != 0xFFFF) { + //f->m_modifiedTime = SBig(uint32_t(getGCTime())); f->m_firstBlock = SBig(block); f->m_blockCount = SBig(uint16_t(size / BlockSize)); commit(); - return f; + return {f}; } - return nullptr; + return {}; } -void Card::write(File* f, void* buf, size_t size) +void Card::write(FileHandle* f, const void* buf, size_t size) { - FILE* mc = Fopen(m_filename.c_str(), _S("rb")); + FILE* mc = Fopen(m_filename.c_str(), _S("r+")); + rewind(mc); if (mc) { - fseek(mc, BlockSize * 5, SEEK_SET); + f->file->m_modifiedTime = SBig(uint32_t(getGCTime())); + size_t blockOffset = (SBig(f->file->m_firstBlock) * BlockSize) + f->offset; + fseek(mc, blockOffset, SEEK_SET); + fwrite(buf, 1, size, mc); + fclose(mc); + f->offset += size; + commit(); } } @@ -185,7 +194,7 @@ uint32_t Card::getSizeMbitFromFile(const SystemString& filename) void Card::commit() { - FILE* f = Fopen(m_filename.c_str(), _S("wb")); + FILE* f = Fopen(m_filename.c_str(), _S("r+")); if (f) { fwrite(__raw, 1, BlockSize, f); @@ -193,11 +202,6 @@ void Card::commit() fwrite(m_dirBackup.__raw, 1, BlockSize, f); fwrite(m_bat.__raw, 1, BlockSize, f); fwrite(m_batBackup.__raw, 1, BlockSize, f); - uint32_t dataLen = ((uint32_t(m_sizeMb) * MbitToBlocks) - 5) * BlockSize; - std::unique_ptr data(new uint8_t[dataLen]); - memset(data.get(), 0xFF, dataLen); - fwrite(data.get(), 1, dataLen, f); - m_dirInUse->commitFiles(f); fclose(f); } } @@ -210,7 +214,9 @@ File::File(char data[]) File::File(const char* filename) { memset(m_filename, 0, 0x20); - memcpy(m_filename, filename, 32 - strlen(filename)); + size_t len = strlen(filename); + len = std::min(len, 32); + memcpy(m_filename, filename, len); } BlockAllocationTable::BlockAllocationTable(uint32_t blockCount) @@ -283,21 +289,6 @@ uint16_t BlockAllocationTable::allocateBlocks(uint16_t count) return freeBlock; } -void Directory::commitFiles(FILE* mc) -{ - for (size_t i = 0 ; i < 127 ; i++) - { - if (m_files[i].m_id[0] == 0xFF && m_files[i].m_id[1] == 0xFF && - m_files[i].m_id[2] == 0xFF && m_files[i].m_id[3] == 0xFF) - continue; - if (m_files[i].m_firstBlock == 0xFFFF) - continue; - - fseek(mc, m_files[i].m_firstBlock * BlockSize, SEEK_SET); - //fwrite(m_files[i].m_data.get(), 1, m_files[i].m_blockCount * BlockSize, mc); - } -} - Directory::Directory() { memset(__raw, 0xFF, BlockSize); @@ -307,7 +298,7 @@ Directory::Directory() Directory::Directory(uint8_t data[]) { - memcpy((uint16_t*)__raw, data, BlockSize); + memcpy(__raw, data, BlockSize); } Directory::Directory(const Directory& other) @@ -327,12 +318,11 @@ File* Directory::getFirstFreeFile(char* game, char* maker, const char* filename) if (m_files[i].m_id[0] == 0xFF) { File* ret = &m_files[i]; + *ret = File(filename); if (game && strlen(game) == 4) memcpy(ret->m_id, game, 4); if (maker && strlen(maker) == 2) memcpy(ret->m_maker, maker, 2); - memset(ret->m_filename, 0, 32); - memcpy(ret->m_filename, filename, 32 - strlen(filename)); return &m_files[i]; } } diff --git a/test/main.cpp b/test/main.cpp index 2cec4f9..35af412 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -5,12 +5,15 @@ int main() { kabufuda::Card mc{_S("test.USA.raw"), "GM8E", "01"}; mc.format(kabufuda::EDeviceId::SlotA, kabufuda::ECardSize::Card123Mb); - mc.createFile("MetroidPrime A", kabufuda::BlockSize * 2); - //kabufuda::File* f = mc.openFile("MetroidPrime A"); -// if (f) -// { -// char test[] = "Metroid Prime is Cool\0"; -// mc.write(f, test, strlen(test)); -// } + mc.createFile("MetroidPrime A", kabufuda::BlockSize); + kabufuda::FileHandle f = mc.openFile("MetroidPrime A"); + if (f) + { + const char* test = "Metroid Prime is Cool"; + size_t len = strlen(test); + mc.write(&f, test, len + 1); + uint16_t derp = 1234; + mc.write(&f, &derp, 2); + } return 0; }