mirror of https://github.com/AxioDL/kabufuda.git
getStatus and setStatus implementation
This commit is contained in:
parent
223ea9a56e
commit
7315a1dedd
|
@ -55,14 +55,14 @@ struct ProbeResults
|
||||||
|
|
||||||
struct CardStat
|
struct CardStat
|
||||||
{
|
{
|
||||||
/* read-only (Set by CARDGetStatus) */
|
/* read-only (Set by Card::getStatus) */
|
||||||
char x0_fileName[CARD_FILENAME_MAX];
|
char x0_fileName[CARD_FILENAME_MAX];
|
||||||
uint32_t x20_length;
|
uint32_t x20_length;
|
||||||
uint32_t x24_time; /* seconds since 01/01/2000 midnight */
|
uint32_t x24_time; /* seconds since 01/01/2000 midnight */
|
||||||
uint8_t x28_gameName[4];
|
uint8_t x28_gameName[4];
|
||||||
uint8_t x2c_company[2];
|
uint8_t x2c_company[2];
|
||||||
|
|
||||||
/* read/write (Set by CARDGetStatus/CARDSetStatus) */
|
/* read/write (Set by Card::getStatus/Card::setStatus) */
|
||||||
uint8_t x2e_bannerFormat;
|
uint8_t x2e_bannerFormat;
|
||||||
uint8_t x2f___padding;
|
uint8_t x2f___padding;
|
||||||
uint32_t x30_iconAddr; /* offset to the banner, bannerTlut, icon, iconTlut data set. */
|
uint32_t x30_iconAddr; /* offset to the banner, bannerTlut, icon, iconTlut data set. */
|
||||||
|
@ -70,7 +70,7 @@ struct CardStat
|
||||||
uint16_t x36_iconSpeed;
|
uint16_t x36_iconSpeed;
|
||||||
uint32_t x38_commentAddr; /* offset to the pair of 32 byte character strings. */
|
uint32_t x38_commentAddr; /* offset to the pair of 32 byte character strings. */
|
||||||
|
|
||||||
/* read-only (Set by CARDGetStatus) */
|
/* read-only (Set by Card::getStatus) */
|
||||||
uint32_t x3c_offsetBanner;
|
uint32_t x3c_offsetBanner;
|
||||||
uint32_t x40_offsetBannerTlut;
|
uint32_t x40_offsetBannerTlut;
|
||||||
uint32_t x44_offsetIcon[CARD_ICON_MAX];
|
uint32_t x44_offsetIcon[CARD_ICON_MAX];
|
||||||
|
@ -163,13 +163,13 @@ public:
|
||||||
* @brief openFile
|
* @brief openFile
|
||||||
* @param filename
|
* @param filename
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<IFileHandle> openFile(const char* filename);
|
ECardResult openFile(const char* filename, std::unique_ptr<IFileHandle>& handleOut);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief openFile
|
* @brief openFile
|
||||||
* @param fileno
|
* @param fileno
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<IFileHandle> openFile(uint32_t fileno);
|
ECardResult openFile(uint32_t fileno, std::unique_ptr<IFileHandle>& handleOut);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief createFile
|
* @brief createFile
|
||||||
|
@ -296,6 +296,22 @@ public:
|
||||||
*/
|
*/
|
||||||
bool canMove(const std::unique_ptr<IFileHandle>& fh) const;
|
bool canMove(const std::unique_ptr<IFileHandle>& fh) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getStatus
|
||||||
|
* @param fh Handle of requested file
|
||||||
|
* @param statOut Structure to fill with file stat
|
||||||
|
* @return NOFILE or READY
|
||||||
|
*/
|
||||||
|
ECardResult getStatus(const std::unique_ptr<IFileHandle>& fh, CardStat& statOut) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief setStatus
|
||||||
|
* @param fh Handle of requested file
|
||||||
|
* @param statOut Structure to access for file stat
|
||||||
|
* @return NOFILE or READY
|
||||||
|
*/
|
||||||
|
ECardResult setStatus(const std::unique_ptr<IFileHandle>& fh, const CardStat& stat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief gameId
|
* @brief gameId
|
||||||
* @param fh
|
* @param fh
|
||||||
|
|
|
@ -123,22 +123,29 @@ Card::~Card()
|
||||||
m_fileHandle = nullptr;
|
m_fileHandle = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IFileHandle> Card::openFile(const char* filename)
|
ECardResult Card::openFile(const char* filename, std::unique_ptr<IFileHandle>& handleOut)
|
||||||
{
|
{
|
||||||
|
handleOut.reset();
|
||||||
File* f = m_currentDir->getFile(m_game, m_maker, filename);
|
File* f = m_currentDir->getFile(m_game, m_maker, filename);
|
||||||
|
if (!f || f->m_game[0] == 0xFF)
|
||||||
|
return ECardResult::NOFILE;
|
||||||
int32_t idx = m_currentDir->indexForFile(f);
|
int32_t idx = m_currentDir->indexForFile(f);
|
||||||
if (f && idx != -1)
|
if (idx != -1)
|
||||||
{
|
{
|
||||||
return std::make_unique<FileHandle>(idx);
|
handleOut = std::make_unique<FileHandle>(idx);
|
||||||
|
return ECardResult::READY;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return ECardResult::FATAL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<IFileHandle> Card::openFile(uint32_t fileno)
|
ECardResult Card::openFile(uint32_t fileno, std::unique_ptr<IFileHandle>& handleOut)
|
||||||
{
|
{
|
||||||
if (fileno >= 127)
|
handleOut.reset();
|
||||||
return nullptr;
|
File* f = m_currentDir->getFile(fileno);
|
||||||
return std::make_unique<FileHandle>(fileno);
|
if (!f || f->m_game[0] == 0xFF)
|
||||||
|
return ECardResult::NOFILE;
|
||||||
|
handleOut = std::make_unique<FileHandle>(fileno);
|
||||||
|
return ECardResult::READY;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Card::_updateDirAndBat()
|
void Card::_updateDirAndBat()
|
||||||
|
@ -177,6 +184,8 @@ File* Card::_fileFromHandle(const std::unique_ptr<IFileHandle>& fh) const
|
||||||
ECardResult Card::createFile(const char* filename, size_t size,
|
ECardResult Card::createFile(const char* filename, size_t size,
|
||||||
std::unique_ptr<IFileHandle>& handleOut)
|
std::unique_ptr<IFileHandle>& handleOut)
|
||||||
{
|
{
|
||||||
|
handleOut.reset();
|
||||||
|
|
||||||
if (strlen(filename) > 32)
|
if (strlen(filename) > 32)
|
||||||
return ECardResult::NAMETOOLONG;
|
return ECardResult::NAMETOOLONG;
|
||||||
if (m_currentDir->getFile(m_game, m_maker, filename))
|
if (m_currentDir->getFile(m_game, m_maker, filename))
|
||||||
|
@ -484,6 +493,118 @@ bool Card::canMove(const std::unique_ptr<IFileHandle>& fh) const
|
||||||
return !bool(file->m_permissions & EPermissions::NoMove);
|
return !bool(file->m_permissions & EPermissions::NoMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t BannerSize(EImageFormat fmt)
|
||||||
|
{
|
||||||
|
switch (fmt)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case EImageFormat::None:
|
||||||
|
return 0;
|
||||||
|
case EImageFormat::C8:
|
||||||
|
return 3584;
|
||||||
|
case EImageFormat::RGB5A3:
|
||||||
|
return 6144;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t IconSize(EImageFormat fmt)
|
||||||
|
{
|
||||||
|
switch (fmt)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case EImageFormat::None:
|
||||||
|
return 0;
|
||||||
|
case EImageFormat::C8:
|
||||||
|
return 1024;
|
||||||
|
case EImageFormat::RGB5A3:
|
||||||
|
return 2048;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t TlutSize(EImageFormat fmt)
|
||||||
|
{
|
||||||
|
switch (fmt)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
case EImageFormat::None:
|
||||||
|
case EImageFormat::RGB5A3:
|
||||||
|
return 0;
|
||||||
|
case EImageFormat::C8:
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ECardResult Card::getStatus(const std::unique_ptr<IFileHandle>& fh, CardStat& statOut) const
|
||||||
|
{
|
||||||
|
File* file = _fileFromHandle(fh);
|
||||||
|
if (!file || file->m_game[0] == 0xFF)
|
||||||
|
return ECardResult::NOFILE;
|
||||||
|
|
||||||
|
strncpy(statOut.x0_fileName, file->m_filename, 32);
|
||||||
|
statOut.x20_length = file->m_blockCount * BlockSize;
|
||||||
|
statOut.x24_time = file->m_modifiedTime;
|
||||||
|
memcpy(statOut.x28_gameName, file->m_game, 4);
|
||||||
|
memcpy(statOut.x2c_company, file->m_maker, 2);
|
||||||
|
|
||||||
|
statOut.x2e_bannerFormat = file->m_bannerFlags;
|
||||||
|
statOut.x30_iconAddr = file->m_iconAddress;
|
||||||
|
statOut.x34_iconFormat = file->m_iconFmt;
|
||||||
|
statOut.x36_iconSpeed = file->m_animSpeed;
|
||||||
|
statOut.x38_commentAddr = file->m_commentAddr;
|
||||||
|
|
||||||
|
if (file->m_iconAddress == -1)
|
||||||
|
{
|
||||||
|
statOut.x3c_offsetBanner = -1;
|
||||||
|
statOut.x40_offsetBannerTlut = -1;
|
||||||
|
for (int i=0 ; i<CARD_ICON_MAX ; ++i)
|
||||||
|
statOut.x44_offsetIcon[i] = -1;
|
||||||
|
statOut.x64_offsetIconTlut = -1;
|
||||||
|
statOut.x68_offsetData = file->m_commentAddr + 64;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t cur = file->m_iconAddress;
|
||||||
|
statOut.x3c_offsetBanner = cur;
|
||||||
|
cur += BannerSize(statOut.GetBannerFormat());
|
||||||
|
statOut.x40_offsetBannerTlut = cur;
|
||||||
|
cur += TlutSize(statOut.GetBannerFormat());
|
||||||
|
bool palette = false;
|
||||||
|
for (int i=0 ; i<CARD_ICON_MAX ; ++i)
|
||||||
|
{
|
||||||
|
statOut.x44_offsetIcon[i] = cur;
|
||||||
|
EImageFormat fmt = statOut.GetIconFormat(i);
|
||||||
|
if (fmt == EImageFormat::C8)
|
||||||
|
palette = true;
|
||||||
|
cur += IconSize(fmt);
|
||||||
|
}
|
||||||
|
if (palette)
|
||||||
|
{
|
||||||
|
statOut.x64_offsetIconTlut = cur;
|
||||||
|
cur += TlutSize(EImageFormat::C8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
statOut.x64_offsetIconTlut = -1;
|
||||||
|
statOut.x68_offsetData = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ECardResult::READY;
|
||||||
|
}
|
||||||
|
|
||||||
|
ECardResult Card::setStatus(const std::unique_ptr<IFileHandle>& fh, const CardStat& stat)
|
||||||
|
{
|
||||||
|
File* file = _fileFromHandle(fh);
|
||||||
|
if (!file || file->m_game[0] == 0xFF)
|
||||||
|
return ECardResult::NOFILE;
|
||||||
|
|
||||||
|
file->m_bannerFlags = stat.x2e_bannerFormat;
|
||||||
|
file->m_iconAddress = stat.x30_iconAddr;
|
||||||
|
file->m_iconFmt = stat.x34_iconFormat;
|
||||||
|
file->m_animSpeed = stat.x36_iconSpeed;
|
||||||
|
file->m_commentAddr = stat.x38_commentAddr;
|
||||||
|
|
||||||
|
return ECardResult::READY;
|
||||||
|
}
|
||||||
|
|
||||||
const char* Card::gameId(const std::unique_ptr<IFileHandle>& fh) const
|
const char* Card::gameId(const std::unique_ptr<IFileHandle>& fh) const
|
||||||
{
|
{
|
||||||
File* file = _fileFromHandle(fh);
|
File* file = _fileFromHandle(fh);
|
||||||
|
@ -619,11 +740,12 @@ bool Card::copyFileTo(const std::unique_ptr<IFileHandle>& fh, Card& dest)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Check to make sure dest does not already contain fh */
|
/* Check to make sure dest does not already contain fh */
|
||||||
if (dest.openFile(toCopy->m_filename) != nullptr)
|
std::unique_ptr<IFileHandle> tmpHandle;
|
||||||
|
dest.openFile(toCopy->m_filename, tmpHandle);
|
||||||
|
if (tmpHandle)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
/* Try to allocate a new file */
|
/* Try to allocate a new file */
|
||||||
std::unique_ptr<IFileHandle> tmpHandle;
|
|
||||||
dest.createFile(toCopy->m_filename, toCopy->m_blockCount * BlockSize, tmpHandle);
|
dest.createFile(toCopy->m_filename, toCopy->m_blockCount * BlockSize, tmpHandle);
|
||||||
if (!tmpHandle)
|
if (!tmpHandle)
|
||||||
return false;
|
return false;
|
||||||
|
@ -792,7 +914,7 @@ void Card::format(ECardSlot id, ECardSize size, EEncoding encoding)
|
||||||
ProbeResults Card::probeCardFile(const SystemString& filename)
|
ProbeResults Card::probeCardFile(const SystemString& filename)
|
||||||
{
|
{
|
||||||
Sstat stat;
|
Sstat stat;
|
||||||
if (Stat(filename.c_str(), &stat))
|
if (Stat(filename.c_str(), &stat) || !S_ISREG(stat.st_mode))
|
||||||
return { ECardResult::NOCARD, 0, 0 };
|
return { ECardResult::NOCARD, 0, 0 };
|
||||||
return { ECardResult::READY, uint32_t(stat.st_size / BlockSize) / MbitToBlocks, 0x2000 };
|
return { ECardResult::READY, uint32_t(stat.st_size / BlockSize) / MbitToBlocks, 0x2000 };
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,9 +11,7 @@ File::File(const char* filename)
|
||||||
{
|
{
|
||||||
memset(__raw, 0, 0x40);
|
memset(__raw, 0, 0x40);
|
||||||
memset(m_filename, 0, 32);
|
memset(m_filename, 0, 32);
|
||||||
size_t len = strlen(filename);
|
strncpy(m_filename, filename, 32);
|
||||||
len = std::min<size_t>(len, 32);
|
|
||||||
memcpy(m_filename, filename, len);
|
|
||||||
}
|
}
|
||||||
void File::swapEndian()
|
void File::swapEndian()
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,8 @@ int main()
|
||||||
if (!mc2)
|
if (!mc2)
|
||||||
mc2.format(kabufuda::ECardSlot::SlotA, kabufuda::ECardSize::Card2043Mb);
|
mc2.format(kabufuda::ECardSlot::SlotA, kabufuda::ECardSize::Card2043Mb);
|
||||||
|
|
||||||
std::unique_ptr<kabufuda::IFileHandle> f = mc.openFile("MetroidPrime A");
|
std::unique_ptr<kabufuda::IFileHandle> f;
|
||||||
|
mc.openFile("MetroidPrime A", f);
|
||||||
if (!f)
|
if (!f)
|
||||||
{
|
{
|
||||||
mc.createFile("MetroidPrime A", kabufuda::BlockSize, f);
|
mc.createFile("MetroidPrime A", kabufuda::BlockSize, f);
|
||||||
|
|
Loading…
Reference in New Issue