mirror of https://github.com/AxioDL/kabufuda.git
Add directory iteration
This commit is contained in:
parent
369d2cc23f
commit
a34b38f8e3
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue