Basic writing capabilities (WIP)

This commit is contained in:
Phillip Stephens 2016-03-26 20:46:52 -07:00
parent b56ac5e112
commit 8b17918205
3 changed files with 45 additions and 44 deletions

View File

@ -95,6 +95,13 @@ public:
~File() {} ~File() {}
}; };
struct FileHandle
{
File* file = nullptr;
uint32_t offset =0;
operator bool() const { return file != nullptr; }
};
class BlockAllocationTable class BlockAllocationTable
{ {
friend class Card; friend class Card;
@ -142,7 +149,7 @@ class Directory
uint8_t __raw[BlockSize]; uint8_t __raw[BlockSize];
}; };
#pragma pop() #pragma pop()
void commitFiles(FILE* mc);
public: public:
Directory(); Directory();
Directory(uint8_t data[BlockSize]); Directory(uint8_t data[BlockSize]);
@ -178,6 +185,7 @@ class Card
uint8_t __raw[BlockSize]; uint8_t __raw[BlockSize];
}; };
#pragma pop() #pragma pop()
SystemString m_filename; SystemString m_filename;
Directory m_dir; Directory m_dir;
Directory m_dirBackup; Directory m_dirBackup;
@ -203,14 +211,14 @@ public:
* @brief openFile * @brief openFile
* @param filename * @param filename
*/ */
File* openFile(const char* filename); FileHandle openFile(const char* filename);
/** /**
* @brief createFile * @brief createFile
* @param filename * @param filename
* @return * @return
*/ */
File* createFile(const char* filename, size_t size); FileHandle createFile(const char* filename, size_t size);
void write(File* f, void* buf, 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 * @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" * @param game The target game id, e.g "GM8E"

View File

@ -43,33 +43,42 @@ Card::Card(const SystemString& filename, const char* game, const char* maker)
Card::~Card() 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); File* f = m_dirInUse->getFirstFreeFile(m_game, m_maker, filename);
uint16_t block = m_batInUse->allocateBlocks(size / BlockSize); uint16_t block = m_batInUse->allocateBlocks(size / BlockSize);
if (f && block != 0xFFFF) if (f && block != 0xFFFF)
{ {
//f->m_modifiedTime = SBig(uint32_t(getGCTime()));
f->m_firstBlock = SBig(block); f->m_firstBlock = SBig(block);
f->m_blockCount = SBig(uint16_t(size / BlockSize)); f->m_blockCount = SBig(uint16_t(size / BlockSize));
commit(); 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) 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() void Card::commit()
{ {
FILE* f = Fopen(m_filename.c_str(), _S("wb")); FILE* f = Fopen(m_filename.c_str(), _S("r+"));
if (f) if (f)
{ {
fwrite(__raw, 1, BlockSize, f); fwrite(__raw, 1, BlockSize, f);
@ -193,11 +202,6 @@ void Card::commit()
fwrite(m_dirBackup.__raw, 1, BlockSize, f); fwrite(m_dirBackup.__raw, 1, BlockSize, f);
fwrite(m_bat.__raw, 1, BlockSize, f); fwrite(m_bat.__raw, 1, BlockSize, f);
fwrite(m_batBackup.__raw, 1, BlockSize, f); fwrite(m_batBackup.__raw, 1, BlockSize, f);
uint32_t dataLen = ((uint32_t(m_sizeMb) * MbitToBlocks) - 5) * BlockSize;
std::unique_ptr<uint8_t[]> data(new uint8_t[dataLen]);
memset(data.get(), 0xFF, dataLen);
fwrite(data.get(), 1, dataLen, f);
m_dirInUse->commitFiles(f);
fclose(f); fclose(f);
} }
} }
@ -210,7 +214,9 @@ File::File(char data[])
File::File(const char* filename) File::File(const char* filename)
{ {
memset(m_filename, 0, 0x20); memset(m_filename, 0, 0x20);
memcpy(m_filename, filename, 32 - strlen(filename)); size_t len = strlen(filename);
len = std::min<size_t>(len, 32);
memcpy(m_filename, filename, len);
} }
BlockAllocationTable::BlockAllocationTable(uint32_t blockCount) BlockAllocationTable::BlockAllocationTable(uint32_t blockCount)
@ -283,21 +289,6 @@ uint16_t BlockAllocationTable::allocateBlocks(uint16_t count)
return freeBlock; 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() Directory::Directory()
{ {
memset(__raw, 0xFF, BlockSize); memset(__raw, 0xFF, BlockSize);
@ -307,7 +298,7 @@ Directory::Directory()
Directory::Directory(uint8_t data[]) Directory::Directory(uint8_t data[])
{ {
memcpy((uint16_t*)__raw, data, BlockSize); memcpy(__raw, data, BlockSize);
} }
Directory::Directory(const Directory& other) 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) if (m_files[i].m_id[0] == 0xFF)
{ {
File* ret = &m_files[i]; File* ret = &m_files[i];
*ret = File(filename);
if (game && strlen(game) == 4) if (game && strlen(game) == 4)
memcpy(ret->m_id, game, 4); memcpy(ret->m_id, game, 4);
if (maker && strlen(maker) == 2) if (maker && strlen(maker) == 2)
memcpy(ret->m_maker, 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]; return &m_files[i];
} }
} }

View File

@ -5,12 +5,15 @@ int main()
{ {
kabufuda::Card mc{_S("test.USA.raw"), "GM8E", "01"}; kabufuda::Card mc{_S("test.USA.raw"), "GM8E", "01"};
mc.format(kabufuda::EDeviceId::SlotA, kabufuda::ECardSize::Card123Mb); mc.format(kabufuda::EDeviceId::SlotA, kabufuda::ECardSize::Card123Mb);
mc.createFile("MetroidPrime A", kabufuda::BlockSize * 2); mc.createFile("MetroidPrime A", kabufuda::BlockSize);
//kabufuda::File* f = mc.openFile("MetroidPrime A"); kabufuda::FileHandle f = mc.openFile("MetroidPrime A");
// if (f) if (f)
// { {
// char test[] = "Metroid Prime is Cool\0"; const char* test = "Metroid Prime is Cool";
// mc.write(f, test, strlen(test)); size_t len = strlen(test);
// } mc.write(&f, test, len + 1);
uint16_t derp = 1234;
mc.write(&f, &derp, 2);
}
return 0; return 0;
} }