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
|
||||
{
|
||||
/* read-only (Set by CARDGetStatus) */
|
||||
/* read-only (Set by Card::getStatus) */
|
||||
char x0_fileName[CARD_FILENAME_MAX];
|
||||
uint32_t x20_length;
|
||||
uint32_t x24_time; /* seconds since 01/01/2000 midnight */
|
||||
uint8_t x28_gameName[4];
|
||||
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 x2f___padding;
|
||||
uint32_t x30_iconAddr; /* offset to the banner, bannerTlut, icon, iconTlut data set. */
|
||||
|
@ -70,7 +70,7 @@ struct CardStat
|
|||
uint16_t x36_iconSpeed;
|
||||
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 x40_offsetBannerTlut;
|
||||
uint32_t x44_offsetIcon[CARD_ICON_MAX];
|
||||
|
@ -163,13 +163,13 @@ public:
|
|||
* @brief openFile
|
||||
* @param filename
|
||||
*/
|
||||
std::unique_ptr<IFileHandle> openFile(const char* filename);
|
||||
ECardResult openFile(const char* filename, std::unique_ptr<IFileHandle>& handleOut);
|
||||
|
||||
/**
|
||||
* @brief openFile
|
||||
* @param fileno
|
||||
*/
|
||||
std::unique_ptr<IFileHandle> openFile(uint32_t fileno);
|
||||
ECardResult openFile(uint32_t fileno, std::unique_ptr<IFileHandle>& handleOut);
|
||||
|
||||
/**
|
||||
* @brief createFile
|
||||
|
@ -296,6 +296,22 @@ public:
|
|||
*/
|
||||
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
|
||||
* @param fh
|
||||
|
|
|
@ -123,22 +123,29 @@ Card::~Card()
|
|||
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);
|
||||
if (!f || f->m_game[0] == 0xFF)
|
||||
return ECardResult::NOFILE;
|
||||
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)
|
||||
return nullptr;
|
||||
return std::make_unique<FileHandle>(fileno);
|
||||
handleOut.reset();
|
||||
File* f = m_currentDir->getFile(fileno);
|
||||
if (!f || f->m_game[0] == 0xFF)
|
||||
return ECardResult::NOFILE;
|
||||
handleOut = std::make_unique<FileHandle>(fileno);
|
||||
return ECardResult::READY;
|
||||
}
|
||||
|
||||
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,
|
||||
std::unique_ptr<IFileHandle>& handleOut)
|
||||
{
|
||||
handleOut.reset();
|
||||
|
||||
if (strlen(filename) > 32)
|
||||
return ECardResult::NAMETOOLONG;
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
File* file = _fileFromHandle(fh);
|
||||
|
@ -619,11 +740,12 @@ bool Card::copyFileTo(const std::unique_ptr<IFileHandle>& fh, Card& dest)
|
|||
return false;
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Try to allocate a new file */
|
||||
std::unique_ptr<IFileHandle> tmpHandle;
|
||||
dest.createFile(toCopy->m_filename, toCopy->m_blockCount * BlockSize, tmpHandle);
|
||||
if (!tmpHandle)
|
||||
return false;
|
||||
|
@ -792,7 +914,7 @@ void Card::format(ECardSlot id, ECardSize size, EEncoding encoding)
|
|||
ProbeResults Card::probeCardFile(const SystemString& filename)
|
||||
{
|
||||
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::READY, uint32_t(stat.st_size / BlockSize) / MbitToBlocks, 0x2000 };
|
||||
}
|
||||
|
|
|
@ -11,9 +11,7 @@ File::File(const char* filename)
|
|||
{
|
||||
memset(__raw, 0, 0x40);
|
||||
memset(m_filename, 0, 32);
|
||||
size_t len = strlen(filename);
|
||||
len = std::min<size_t>(len, 32);
|
||||
memcpy(m_filename, filename, len);
|
||||
strncpy(m_filename, filename, 32);
|
||||
}
|
||||
void File::swapEndian()
|
||||
{
|
||||
|
|
|
@ -13,7 +13,8 @@ int main()
|
|||
if (!mc2)
|
||||
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)
|
||||
{
|
||||
mc.createFile("MetroidPrime A", kabufuda::BlockSize, f);
|
||||
|
|
Loading…
Reference in New Issue