Add directory iteration

This commit is contained in:
Phillip Stephens 2016-06-30 10:36:04 -07:00
parent 369d2cc23f
commit a34b38f8e3
6 changed files with 243 additions and 31 deletions

View File

@ -65,7 +65,17 @@ class Card
File* _fileFromHandle(const std::unique_ptr<IFileHandle>& fh) const;
public:
Card();
/**
* @brief Card
* @param other
*/
Card(const Card& other);
/**
* @brief Card
* @param filepath
* @param game
* @param maker
*/
Card(const SystemString& filepath, const char* game = nullptr, const char* maker=nullptr);
~Card();
@ -82,6 +92,24 @@ public:
*/
std::unique_ptr<IFileHandle> createFile(const char* filename, size_t size);
/**
* @brief firstFile
* @return
*/
std::unique_ptr<IFileHandle> firstFile();
/**
* @brief nextFile
* @param cur
* @return
*/
std::unique_ptr<IFileHandle> nextFile(const std::unique_ptr<IFileHandle>& cur);
/**
* @brief getFilename
* @param fh
* @return
*/
const char* getFilename(const std::unique_ptr<IFileHandle>& fh);
/**
* @brief deleteFile
* @param fh
@ -161,17 +189,106 @@ public:
*/
bool canMove(const std::unique_ptr<IFileHandle>& fh) const;
/**
* @brief gameId
* @param fh
* @return
*/
const char* gameId(const std::unique_ptr<IFileHandle>& fh) const;
/**
* @brief maker
* @param fh
* @return
*/
const char* maker(const std::unique_ptr<IFileHandle>& fh) const;
/**
* @brief setBannerFormat
* @param fh
* @param fmt
*/
void setBannerFormat(const std::unique_ptr<IFileHandle>& fh, EImageFormat fmt);
/**
* @brief bannerFormat
* @param fh
* @return
*/
EImageFormat bannerFormat(const std::unique_ptr<IFileHandle>& fh) const;
/**
* @brief setIconAnimationType
* @param fh
* @param type
*/
void setIconAnimationType(const std::unique_ptr<IFileHandle>& fh, EAnimationType type);
/**
* @brief iconAnimationType
* @param fh
* @return
*/
EAnimationType iconAnimationType(const std::unique_ptr<IFileHandle>& fh) const;
/**
* @brief setIconFormat
* @param fh
* @param idx
* @param fmt
*/
void setIconFormat(const std::unique_ptr<IFileHandle>& fh, uint32_t idx, EImageFormat fmt);
/**
* @brief iconFormat
* @param fh
* @param idx
* @return
*/
EImageFormat iconFormat(const std::unique_ptr<IFileHandle>& fh, uint32_t idx) const;
/**
* @brief setIconSpeed
* @param fh
* @param idx
* @param speed
*/
void setIconSpeed(const std::unique_ptr<IFileHandle>& fh, uint32_t idx, EAnimationSpeed speed);
/**
* @brief iconSpeed
* @param fh
* @param idx
* @return
*/
EAnimationSpeed iconSpeed(const std::unique_ptr<IFileHandle>& fh, uint32_t idx) const;
/**
* @brief setImageAddress
* @param fh
* @param addr
*/
void setImageAddress(const std::unique_ptr<IFileHandle>& fh, uint32_t addr);
/**
* @brief imageAddress
* @param fh
* @return
*/
int32_t imageAddress(const std::unique_ptr<IFileHandle>& fh) const;
/**
* @brief setCommentAddress
* @param fh
* @param addr
*/
void setCommentAddress(const std::unique_ptr<IFileHandle>& fh, uint32_t addr);
/**
* @brief commentAddress
* @param fh
* @return
*/
int32_t commentAddress(const std::unique_ptr<IFileHandle>& fh) const;
/**
@ -195,26 +312,26 @@ public:
* @param game The target game id, e.g "GM8E"
* @sa openFile
*/
void setGame(const char* game);
void setCurrentGame(const char* game);
/**
* @brief Returns the currently selected game
* @return The selected game, or nullptr
*/
const uint8_t* getGame() const;
const uint8_t* getCurrentGame() const;
/**
* @brief Sets the current maker, if not null any openFile requests will only return files that match this maker
* @param maker The target maker id, e.g "01"
* @sa openFile
*/
void setMaker(const char* maker);
void setCurrentMaker(const char* maker);
/**
* @brief Returns the currently selected maker
* @return The selected maker, or nullptr
*/
const uint8_t* getMaker() const;
const uint8_t* getCurrentMaker() const;
/**
* @brief Retrieves the format assigned serial in two 32bit parts

View File

@ -35,7 +35,10 @@ public:
~Directory();
File* getFirstFreeFile(const char* game, const char* maker, const char* filename);
File* getFirstNonFreeFile(uint32_t start, const char* game, const char* maker);
File* getFile(const char* game, const char* maker, const char* filename);
File* getFile(uint32_t idx);
int32_t indexForFile(File* f);
};
}

View File

@ -15,7 +15,7 @@ class File
{
struct
{
uint8_t m_id[4];
uint8_t m_game[4];
uint8_t m_maker[2];
uint8_t m_reserved;
uint8_t m_bannerFlags;

View File

@ -15,16 +15,12 @@ IFileHandle::~IFileHandle()
class FileHandle : public IFileHandle
{
friend class Card;
const char* game;
const char* maker;
const char* filename;
uint32_t idx;
int32_t offset =0;
public:
FileHandle() = default;
FileHandle(const char* game, const char* maker, const char* filename)
: game(game),
maker(maker),
filename(filename)
FileHandle(uint32_t idx)
: idx(idx)
{}
virtual ~FileHandle();
};
@ -139,8 +135,12 @@ Card::~Card()
std::unique_ptr<IFileHandle> Card::openFile(const char* filename)
{
File* f = m_currentDir->getFile(m_game, m_maker, filename);
if (f)
return std::unique_ptr<IFileHandle>(new FileHandle(m_game, m_maker, filename));
int32_t idx = m_currentDir->indexForFile(f);
if (f && idx != -1)
{
return std::unique_ptr<IFileHandle>(new FileHandle(idx));
}
return nullptr;
}
@ -173,7 +173,7 @@ File* Card::_fileFromHandle(const std::unique_ptr<IFileHandle> &fh) const
if (!handle)
return nullptr;
File* file = m_currentDir->getFile(handle->game, handle->maker, handle->filename);
File* file = m_currentDir->getFile(handle->idx);
return file;
}
@ -189,18 +189,47 @@ std::unique_ptr<IFileHandle> Card::createFile(const char* filename, size_t size)
f->m_blockCount = uint16_t(size / BlockSize);
return std::unique_ptr<FileHandle>(new FileHandle(m_game, m_maker, filename));
return std::unique_ptr<IFileHandle>(new FileHandle(m_currentDir->indexForFile(f)));
}
return nullptr;
}
void Card::deleteFile(const std::unique_ptr<IFileHandle> &fh)
std::unique_ptr<IFileHandle> Card::firstFile()
{
File* f = m_currentDir->getFirstNonFreeFile(0, m_game, m_maker);
if (f)
return std::unique_ptr<IFileHandle>(new FileHandle(m_currentDir->indexForFile(f)));
return nullptr;
}
std::unique_ptr<IFileHandle> Card::nextFile(const std::unique_ptr<IFileHandle>& cur)
{
FileHandle* handle = dynamic_cast<FileHandle*>(cur.get());
if (!handle)
return nullptr;
File* next = m_currentDir->getFirstNonFreeFile(handle->idx + 1, m_game, m_maker);
if (!next)
return nullptr;
return std::unique_ptr<IFileHandle>(new FileHandle(m_currentDir->indexForFile(next)));
}
const char* Card::getFilename(const std::unique_ptr<IFileHandle>& fh)
{
File* f = _fileFromHandle(fh);
if (!f)
return nullptr;
return f->m_filename;
}
void Card::deleteFile(const std::unique_ptr<IFileHandle>& fh)
{
_updateDirAndBat();
if (!fh)
return;
FileHandle* f = dynamic_cast<FileHandle*>(fh.get());
uint16_t block = m_currentDir->getFile(f->game, f->maker, f->filename)->m_firstBlock;
uint16_t block = m_currentDir->getFile(f->idx)->m_firstBlock;
while(block != 0xFFFF)
{
@ -209,7 +238,7 @@ void Card::deleteFile(const std::unique_ptr<IFileHandle> &fh)
m_currentBat->clear(block, 1);
block = nextBlock;
}
*m_currentDir->getFile(f->game, f->maker, f->filename) = File();
*m_currentDir->getFile(f->idx) = File();
}
@ -221,7 +250,7 @@ void Card::write(const std::unique_ptr<IFileHandle>& fh, const void* buf, size_t
if (m_fileHandle)
{
FileHandle* f = dynamic_cast<FileHandle*>(fh.get());
File* file = m_currentDir->getFile(f->game, f->maker, f->filename);
File* file = m_currentDir->getFile(f->idx);
if (!file)
return;
@ -270,7 +299,7 @@ void Card::read(const std::unique_ptr<IFileHandle> &fh, void *dst, size_t size)
if (m_fileHandle)
{
FileHandle* f = dynamic_cast<FileHandle*>(fh.get());
File* file = m_currentDir->getFile(f->game, f->maker, f->filename);
File* file = m_currentDir->getFile(f->idx);
if (!file)
return;
/* Block handling is a little different from cache handling,
@ -316,7 +345,7 @@ void Card::seek(const std::unique_ptr<IFileHandle> &fh, int32_t pos, SeekOrigin
return;
FileHandle* f = dynamic_cast<FileHandle*>(fh.get());
File* file = m_currentDir->getFile(f->game, f->maker, f->filename);
File* file = m_currentDir->getFile(f->idx);
if (!file)
return;
@ -407,6 +436,22 @@ bool Card::canMove(const std::unique_ptr<IFileHandle> &fh) const
return !bool(file->m_permissions & EPermissions::NoMove);
}
const char* Card::gameId(const std::unique_ptr<IFileHandle> &fh) const
{
File* file = _fileFromHandle(fh);
if (!file)
return nullptr;
return reinterpret_cast<const char*>(file->m_game);
}
const char *Card::maker(const std::unique_ptr<IFileHandle> &fh) const
{
File* file = _fileFromHandle(fh);
if (!file)
return nullptr;
return reinterpret_cast<const char*>(file->m_maker);
}
void Card::setBannerFormat(const std::unique_ptr<IFileHandle>& fh, EImageFormat fmt)
{
File* file = _fileFromHandle(fh);
@ -564,7 +609,7 @@ bool Card::moveFileTo(const std::unique_ptr<IFileHandle> &fh, Card &dest)
return false;
}
void Card::setGame(const char* game)
void Card::setCurrentGame(const char* game)
{
if (game == nullptr)
{
@ -578,7 +623,7 @@ void Card::setGame(const char* game)
memcpy(m_game, game, 4);
}
const uint8_t* Card::getGame() const
const uint8_t* Card::getCurrentGame() const
{
if (strlen(m_game) == 4)
return reinterpret_cast<const uint8_t*>(m_game);
@ -586,7 +631,7 @@ const uint8_t* Card::getGame() const
return nullptr;
}
void Card::setMaker(const char* maker)
void Card::setCurrentMaker(const char* maker)
{
if (maker == nullptr)
{
@ -600,7 +645,7 @@ void Card::setMaker(const char* maker)
memcpy(m_maker, maker, 2);
}
const uint8_t* Card::getMaker() const
const uint8_t* Card::getCurrentMaker() const
{
if (strlen(m_maker) == 2)
return reinterpret_cast<const uint8_t*>(m_maker);

View File

@ -1,5 +1,6 @@
#include "kabufuda/Directory.hpp"
#include "kabufuda/Util.hpp"
#include <cstring>
namespace kabufuda
@ -61,12 +62,12 @@ File* Directory::getFirstFreeFile(const char* game, const char* maker, const cha
{
for (uint16_t i = 0 ; i < 127 ; i++)
{
if (m_files[i].m_id[0] == 0xFF)
if (m_files[i].m_game[0] == 0xFF)
{
File* ret = &m_files[i];
*ret = File(filename);
if (game && strlen(game) == 4)
memcpy(ret->m_id, game, 4);
memcpy(ret->m_game, game, 4);
if (maker && strlen(maker) == 2)
memcpy(ret->m_maker, maker, 2);
return ret;
@ -76,11 +77,29 @@ File* Directory::getFirstFreeFile(const char* game, const char* maker, const cha
return nullptr;
}
File *Directory::getFirstNonFreeFile(uint32_t start, const char *game, const char *maker)
{
for (uint16_t i = start ; i < 127 ; i++)
{
if (m_files[i].m_game[0] != 0xFF)
{
File* ret = &m_files[i];
if (game && std::strlen(game) == 4 && std::strncmp(reinterpret_cast<const char*>(ret->m_game), game, 4) != 0)
continue;
if (maker && std::strlen(maker) == 2 && std::strncmp(reinterpret_cast<const char*>(ret->m_maker), maker, 2) != 0)
continue;
return ret;
}
}
return nullptr;
}
File* Directory::getFile(const char* game, const char* maker, const char* filename)
{
for (uint16_t i = 0 ; i < 127 ; i++)
{
if (game && strlen(game) == 4 && memcmp(m_files[i].m_id, game, 4))
if (game && strlen(game) == 4 && memcmp(m_files[i].m_game, game, 4))
continue;
if (maker && strlen(maker) == 2 && memcmp(m_files[i].m_maker, maker, 2))
continue;
@ -90,4 +109,25 @@ File* Directory::getFile(const char* game, const char* maker, const char* filena
return nullptr;
}
File* Directory::getFile(uint32_t idx)
{
if (idx >= 127)
return nullptr;
return &m_files[idx];
}
int32_t Directory::indexForFile(File *f)
{
if (!f)
return -1;
auto it = std::find_if(std::begin(m_files), std::end(m_files), [&f](const File& file)->bool{
return f == &file;
});
if (it == std::end(m_files))
return -1;
return it - std::begin(m_files);
}
}

View File

@ -10,10 +10,10 @@ int main()
if (!mc2)
mc2.format(kabufuda::EDeviceId::SlotA, kabufuda::ECardSize::Card2043Mb);
std::unique_ptr<kabufuda::IFileHandle> f = mc.openFile("MetroidPrime B");
std::unique_ptr<kabufuda::IFileHandle> f = mc.openFile("MetroidPrime A");
if (!f)
{
f = mc.createFile("MetroidPrime B", kabufuda::BlockSize);
f = mc.createFile("MetroidPrime A", kabufuda::BlockSize);
mc.setPublic(f, true);
mc.setCanCopy(f, true);
mc.setCanMove(f, true);
@ -40,6 +40,13 @@ int main()
printf("Copy succeeded!\n");
else
printf("Copy failed...\n");
std::unique_ptr<kabufuda::IFileHandle> it = mc.firstFile();
while (it)
{
printf("%.4s%.2s-%s\n", mc.gameId(it), mc.maker(it), mc.getFilename(it));
it = mc.nextFile(it);
}
}
return 0;
}