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() {}
};
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"

View File

@ -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<uint8_t[]> 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<size_t>(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];
}
}

View File

@ -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;
}