mirror of https://github.com/AxioDL/kabufuda.git
Basic writing capabilities (WIP)
This commit is contained in:
parent
b56ac5e112
commit
8b17918205
|
@ -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"
|
||||||
|
|
56
src/Card.cpp
56
src/Card.cpp
|
@ -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];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue