getStatus and setStatus implementation

This commit is contained in:
Jack Andersen 2016-12-28 11:39:10 -10:00
parent 223ea9a56e
commit 7315a1dedd
4 changed files with 157 additions and 20 deletions

View File

@ -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

View File

@ -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 };
}

View File

@ -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()
{

View File

@ -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);