diff --git a/include/kabufuda/Card.hpp b/include/kabufuda/Card.hpp index f45fa23..0667a07 100644 --- a/include/kabufuda/Card.hpp +++ b/include/kabufuda/Card.hpp @@ -17,15 +17,16 @@ namespace kabufuda { -class IFileHandle +class FileHandle { -protected: - uint32_t idx; - IFileHandle() = default; - IFileHandle(uint32_t idx) : idx(idx) {} + friend class Card; + uint32_t idx = 0; + int32_t offset = 0; + FileHandle(uint32_t idx) : idx(idx) {} public: + FileHandle() = default; uint32_t getFileNo() const { return idx; } - virtual ~IFileHandle(); + operator bool() const { return getFileNo() != 0; } }; enum class ECardResult @@ -136,7 +137,7 @@ class Card void _swapEndian(); void _updateDirAndBat(); void _updateChecksum(); - File* _fileFromHandle(const std::unique_ptr& fh) const; + File* _fileFromHandle(const FileHandle& fh) const; void _deleteFile(File& f); public: @@ -147,8 +148,8 @@ public: */ Card(const Card& other) = delete; Card& operator=(const Card& other) = delete; - Card(Card&& other) = default; - Card& operator=(Card&& other) = default; + Card(Card&& other); + Card& operator=(Card&& other); /** * @brief Card @@ -163,46 +164,53 @@ public: * @brief openFile * @param filename */ - ECardResult openFile(const char* filename, std::unique_ptr& handleOut); + ECardResult openFile(const char* filename, FileHandle& handleOut); /** * @brief openFile * @param fileno */ - ECardResult openFile(uint32_t fileno, std::unique_ptr& handleOut); + ECardResult openFile(uint32_t fileno, FileHandle& handleOut); /** * @brief createFile * @param filename * @return */ - ECardResult createFile(const char* filename, size_t size, std::unique_ptr& handleOut); + ECardResult createFile(const char* filename, size_t size, FileHandle& handleOut); + + /** + * @brief closeFile + * @param fh FileHandle to close + * @return + */ + ECardResult closeFile(FileHandle& fh); /** * @brief firstFile * @return */ - std::unique_ptr firstFile(); + FileHandle firstFile(); /** * @brief nextFile * @param cur * @return */ - std::unique_ptr nextFile(const std::unique_ptr& cur); + FileHandle nextFile(const FileHandle& cur); /** * @brief getFilename * @param fh * @return */ - const char* getFilename(const std::unique_ptr& fh); + const char* getFilename(const FileHandle& fh); /** * @brief deleteFile * @param fh */ - void deleteFile(const std::unique_ptr& fh); + void deleteFile(const FileHandle& fh); /** * @brief deleteFile @@ -229,7 +237,7 @@ public: * @param buf * @param size */ - void write(const std::unique_ptr& fh, const void* buf, size_t size); + ECardResult write(FileHandle& fh, const void* buf, size_t size); /** * @brief read @@ -237,7 +245,7 @@ public: * @param dst * @param size */ - void read(const std::unique_ptr& fh, void* dst, size_t size); + ECardResult read(FileHandle& fh, void* dst, size_t size); /** * @brief seek @@ -245,56 +253,56 @@ public: * @param pos * @param whence */ - void seek(const std::unique_ptr& fh, int32_t pos, SeekOrigin whence); + void seek(FileHandle& fh, int32_t pos, SeekOrigin whence); /** * @brief Returns the current offset of the specified file * @param fh The file to retrieve the offset from * @return The offset or -1 if an invalid handle is passed */ - int32_t tell(const std::unique_ptr& fh); + int32_t tell(const FileHandle& fh); /** * @brief setPublic * @param fh * @param pub */ - void setPublic(const std::unique_ptr& fh, bool pub); + void setPublic(const FileHandle& fh, bool pub); /** * @brief isPublic * @param fh * @return */ - bool isPublic(const std::unique_ptr& fh) const; + bool isPublic(const FileHandle& fh) const; /** * @brief setCanCopy * @param fh * @param copy */ - void setCanCopy(const std::unique_ptr& fh, bool copy) const; + void setCanCopy(const FileHandle& fh, bool copy) const; /** * @brief canCopy * @param fh * @return */ - bool canCopy(const std::unique_ptr& fh) const; + bool canCopy(const FileHandle& fh) const; /** * @brief setCanMove * @param fh * @param move */ - void setCanMove(const std::unique_ptr& fh, bool move); + void setCanMove(const FileHandle& fh, bool move); /** * @brief canMove * @param fh * @return */ - bool canMove(const std::unique_ptr& fh) const; + bool canMove(const FileHandle& fh) const; /** * @brief getStatus @@ -302,7 +310,15 @@ public: * @param statOut Structure to fill with file stat * @return NOFILE or READY */ - ECardResult getStatus(const std::unique_ptr& fh, CardStat& statOut) const; + ECardResult getStatus(const FileHandle& fh, CardStat& statOut) const; + + /** + * @brief getStatus + * @param fileNo Number of requested file + * @param statOut Structure to fill with file stat + * @return NOFILE or READY + */ + ECardResult getStatus(uint32_t fileNo, CardStat& statOut) const; /** * @brief setStatus @@ -310,49 +326,57 @@ public: * @param statOut Structure to access for file stat * @return NOFILE or READY */ - ECardResult setStatus(const std::unique_ptr& fh, const CardStat& stat); + ECardResult setStatus(const FileHandle& fh, const CardStat& stat); + + /** + * @brief setStatus + * @param fileNo Number of requested file + * @param statOut Structure to access for file stat + * @return NOFILE or READY + */ + ECardResult setStatus(uint32_t fileNo, const CardStat& stat); /** * @brief gameId * @param fh * @return */ - const char* gameId(const std::unique_ptr& fh) const; + const char* gameId(const FileHandle& fh) const; /** * @brief maker * @param fh * @return */ - const char* maker(const std::unique_ptr& fh) const; + const char* maker(const FileHandle& fh) const; /** * @brief setBannerFormat * @param fh * @param fmt */ - void setBannerFormat(const std::unique_ptr& fh, EImageFormat fmt); + void setBannerFormat(const FileHandle& fh, EImageFormat fmt); /** * @brief bannerFormat * @param fh * @return */ - EImageFormat bannerFormat(const std::unique_ptr& fh) const; + EImageFormat bannerFormat(const FileHandle& fh) const; /** * @brief setIconAnimationType * @param fh * @param type */ - void setIconAnimationType(const std::unique_ptr& fh, EAnimationType type); + void setIconAnimationType(const FileHandle& fh, EAnimationType type); /** * @brief iconAnimationType * @param fh * @return */ - EAnimationType iconAnimationType(const std::unique_ptr& fh) const; + EAnimationType iconAnimationType(const FileHandle& fh) const; /** * @brief setIconFormat @@ -360,7 +384,7 @@ public: * @param idx * @param fmt */ - void setIconFormat(const std::unique_ptr& fh, uint32_t idx, EImageFormat fmt); + void setIconFormat(const FileHandle& fh, uint32_t idx, EImageFormat fmt); /** * @brief iconFormat @@ -368,7 +392,7 @@ public: * @param idx * @return */ - EImageFormat iconFormat(const std::unique_ptr& fh, uint32_t idx) const; + EImageFormat iconFormat(const FileHandle& fh, uint32_t idx) const; /** * @brief setIconSpeed @@ -376,7 +400,7 @@ public: * @param idx * @param speed */ - void setIconSpeed(const std::unique_ptr& fh, uint32_t idx, EAnimationSpeed speed); + void setIconSpeed(const FileHandle& fh, uint32_t idx, EAnimationSpeed speed); /** * @brief iconSpeed @@ -384,35 +408,35 @@ public: * @param idx * @return */ - EAnimationSpeed iconSpeed(const std::unique_ptr& fh, uint32_t idx) const; + EAnimationSpeed iconSpeed(const FileHandle& fh, uint32_t idx) const; /** * @brief setImageAddress * @param fh * @param addr */ - void setImageAddress(const std::unique_ptr& fh, uint32_t addr); + void setImageAddress(const FileHandle& fh, uint32_t addr); /** * @brief imageAddress * @param fh * @return */ - int32_t imageAddress(const std::unique_ptr& fh) const; + int32_t imageAddress(const FileHandle& fh) const; /** * @brief setCommentAddress * @param fh * @param addr */ - void setCommentAddress(const std::unique_ptr& fh, uint32_t addr); + void setCommentAddress(const FileHandle& fh, uint32_t addr); /** * @brief commentAddress * @param fh * @return */ - int32_t commentAddress(const std::unique_ptr& fh) const; + int32_t commentAddress(const FileHandle& fh) const; /** * @brief Copies a file from the current Card instance to a specified Card instance @@ -420,7 +444,7 @@ public: * @param dest The destination Card instance * @return True if successful, false otherwise */ - bool copyFileTo(const std::unique_ptr& fh, Card& dest); + bool copyFileTo(FileHandle& fh, Card& dest); /** * @brief moveFileTo @@ -428,7 +452,7 @@ public: * @param dest * @return */ - bool moveFileTo(const std::unique_ptr& fh, Card& dest); + bool moveFileTo(FileHandle& fh, Card& dest); /** * @brief Sets the current game, if not null any openFile requests will only return files that match this game diff --git a/include/kabufuda/Util.hpp b/include/kabufuda/Util.hpp index af9f070..cfa8a5f 100644 --- a/include/kabufuda/Util.hpp +++ b/include/kabufuda/Util.hpp @@ -358,7 +358,6 @@ static inline int Stat(const SystemChar* path, Sstat* statOut) * @param checksumInv */ void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv); -void calculateChecksumLE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv); } #endif // __KABU_UTIL_HPP__ diff --git a/lib/kabufuda/BlockAllocationTable.cpp b/lib/kabufuda/BlockAllocationTable.cpp index c0a9412..f77a27d 100644 --- a/lib/kabufuda/BlockAllocationTable.cpp +++ b/lib/kabufuda/BlockAllocationTable.cpp @@ -16,14 +16,19 @@ void BlockAllocationTable::swapEndian() void BlockAllocationTable::updateChecksum() { - calculateChecksumLE(reinterpret_cast(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv); + swapEndian(); + calculateChecksumBE(reinterpret_cast(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv); + swapEndian(); } bool BlockAllocationTable::valid() const { uint16_t ckSum, ckSumInv; - calculateChecksumLE(reinterpret_cast(__raw + 4), 0xFFE, &ckSum, &ckSumInv); - return (ckSum == m_checksum && ckSumInv == m_checksumInv); + const_cast(*this).swapEndian(); + calculateChecksumBE(reinterpret_cast(__raw + 4), 0xFFE, &ckSum, &ckSumInv); + bool res = (ckSum == m_checksum && ckSumInv == m_checksumInv); + const_cast(*this).swapEndian(); + return res; } BlockAllocationTable::BlockAllocationTable(uint32_t blockCount) diff --git a/lib/kabufuda/Card.cpp b/lib/kabufuda/Card.cpp index 2a56323..eb8ea86 100644 --- a/lib/kabufuda/Card.cpp +++ b/lib/kabufuda/Card.cpp @@ -10,21 +10,6 @@ namespace kabufuda #define ROUND_UP_8192(val) (((val) + 8191) & ~8191) -IFileHandle::~IFileHandle() {} - -class FileHandle : public IFileHandle -{ - friend class Card; - int32_t offset = 0; - -public: - FileHandle() = default; - FileHandle(uint32_t idx) : IFileHandle(idx) {} - virtual ~FileHandle(); -}; - -FileHandle::~FileHandle() {} - void Card::_swapEndian() { m_formatTime = SBig(m_formatTime); @@ -41,6 +26,44 @@ void Card::_swapEndian() Card::Card() { memset(__raw, 0xFF, BlockSize); } +Card::Card(Card&& other) +{ + memmove(__raw, other.__raw, BlockSize); + m_filename = std::move(other.m_filename); + m_fileHandle = other.m_fileHandle; + other.m_fileHandle = nullptr; + m_dirs[0] = std::move(other.m_dirs[0]); + m_dirs[1] = std::move(other.m_dirs[1]); + m_bats[0] = std::move(other.m_bats[0]); + m_bats[1] = std::move(other.m_bats[1]); + m_currentDir = other.m_currentDir; + m_currentBat = other.m_currentBat; + + m_maxBlock = other.m_maxBlock; + memmove(m_game, other.m_game, 5); + memmove(m_maker, other.m_maker, 3); +} + +Card& Card::operator=(Card&& other) +{ + memmove(__raw, other.__raw, BlockSize); + m_filename = std::move(other.m_filename); + m_fileHandle = other.m_fileHandle; + other.m_fileHandle = nullptr; + m_dirs[0] = std::move(other.m_dirs[0]); + m_dirs[1] = std::move(other.m_dirs[1]); + m_bats[0] = std::move(other.m_bats[0]); + m_bats[1] = std::move(other.m_bats[1]); + m_currentDir = other.m_currentDir; + m_currentBat = other.m_currentBat; + + m_maxBlock = other.m_maxBlock; + memmove(m_game, other.m_game, 5); + memmove(m_maker, other.m_maker, 3); + + return *this; +} + Card::Card(const SystemString& filename, const char* game, const char* maker) : m_filename(filename) { memset(__raw, 0xFF, BlockSize); @@ -97,31 +120,30 @@ Card::~Card() commit(); if (m_fileHandle) fclose(m_fileHandle); - m_fileHandle = nullptr; } -ECardResult Card::openFile(const char* filename, std::unique_ptr& handleOut) +ECardResult Card::openFile(const char* filename, FileHandle& handleOut) { - handleOut.reset(); + handleOut = {}; File* f = m_dirs[m_currentDir].getFile(m_game, m_maker, filename); if (!f || f->m_game[0] == 0xFF) return ECardResult::NOFILE; int32_t idx = m_dirs[m_currentDir].indexForFile(f); if (idx != -1) { - handleOut = std::make_unique(idx); + handleOut = FileHandle(idx); return ECardResult::READY; } return ECardResult::FATAL_ERROR; } -ECardResult Card::openFile(uint32_t fileno, std::unique_ptr& handleOut) +ECardResult Card::openFile(uint32_t fileno, FileHandle& handleOut) { - handleOut.reset(); + handleOut = {}; File* f = m_dirs[m_currentDir].getFile(fileno); if (!f || f->m_game[0] == 0xFF) return ECardResult::NOFILE; - handleOut = std::make_unique(fileno); + handleOut = FileHandle(fileno); return ECardResult::READY; } @@ -140,26 +162,20 @@ void Card::_updateDirAndBat() void Card::_updateChecksum() { - calculateChecksumLE(reinterpret_cast(__raw), 0xFE, &m_checksum, &m_checksumInv); + _swapEndian(); + calculateChecksumBE(reinterpret_cast(__raw), 0xFE, &m_checksum, &m_checksumInv); + _swapEndian(); } -File* Card::_fileFromHandle(const std::unique_ptr& fh) const +File* Card::_fileFromHandle(const FileHandle& fh) const { - if (!fh) - return nullptr; - - FileHandle* handle = dynamic_cast(fh.get()); - if (!handle) - return nullptr; - - File* file = const_cast(m_dirs[m_currentDir]).getFile(handle->idx); - return file; + return const_cast(m_dirs[m_currentDir]).getFile(fh.idx); } ECardResult Card::createFile(const char* filename, size_t size, - std::unique_ptr& handleOut) + FileHandle& handleOut) { - handleOut.reset(); + handleOut = {}; if (size <= 0) return ECardResult::FATAL_ERROR; @@ -182,35 +198,37 @@ ECardResult Card::createFile(const char* filename, size_t size, f->m_firstBlock = block; f->m_blockCount = neededBlocks; - handleOut = std::make_unique(m_dirs[m_currentDir].indexForFile(f)); + handleOut = FileHandle(m_dirs[m_currentDir].indexForFile(f)); return ECardResult::READY; } return ECardResult::FATAL_ERROR; } -std::unique_ptr Card::firstFile() +ECardResult Card::closeFile(FileHandle& fh) +{ + fh.offset = 0; + return ECardResult::READY; +} + +FileHandle Card::firstFile() { File* f = m_dirs[m_currentDir].getFirstNonFreeFile(0, m_game, m_maker); if (f) - return std::make_unique(m_dirs[m_currentDir].indexForFile(f)); + return FileHandle(m_dirs[m_currentDir].indexForFile(f)); - return nullptr; + return {}; } -std::unique_ptr Card::nextFile(const std::unique_ptr& cur) +FileHandle Card::nextFile(const FileHandle& cur) { - FileHandle* handle = dynamic_cast(cur.get()); - if (!handle) - return nullptr; - - File* next = m_dirs[m_currentDir].getFirstNonFreeFile(handle->idx + 1, m_game, m_maker); + File* next = m_dirs[m_currentDir].getFirstNonFreeFile(cur.idx + 1, m_game, m_maker); if (!next) - return nullptr; - return std::make_unique(m_dirs[m_currentDir].indexForFile(next)); + return {}; + return FileHandle(m_dirs[m_currentDir].indexForFile(next)); } -const char* Card::getFilename(const std::unique_ptr& fh) +const char* Card::getFilename(const FileHandle& fh) { File* f = _fileFromHandle(fh); if (!f) @@ -231,13 +249,10 @@ void Card::_deleteFile(File& f) f = File(); } -void Card::deleteFile(const std::unique_ptr& fh) +void Card::deleteFile(const FileHandle& fh) { _updateDirAndBat(); - if (!fh) - return; - FileHandle* f = dynamic_cast(fh.get()); - _deleteFile(*m_dirs[m_currentDir].getFile(f->idx)); + _deleteFile(*m_dirs[m_currentDir].getFile(fh.idx)); } ECardResult Card::deleteFile(const char* filename) @@ -276,42 +291,39 @@ ECardResult Card::renameFile(const char* oldName, const char* newName) return ECardResult::READY; } -void Card::write(const std::unique_ptr& fh, const void* buf, size_t size) +ECardResult Card::write(FileHandle& fh, const void* buf, size_t size) { - if (!fh) - return; - if (m_fileHandle) { - FileHandle* f = dynamic_cast(fh.get()); - File* file = m_dirs[m_currentDir].getFile(f->idx); + File* file = m_dirs[m_currentDir].getFile(fh.idx); if (!file) - return; + return ECardResult::NOFILE; /* Block handling is a little different from cache handling, * since each block can be in an arbitrary location we must * first find our starting block. */ - const uint16_t blockId = uint16_t(f->offset / BlockSize); + const uint16_t blockId = uint16_t(fh.offset / BlockSize); uint16_t block = file->m_firstBlock; for (uint16_t i = 0; i < blockId; i++) block = m_bats[m_currentBat].getNextBlock(block); const uint8_t* tmpBuf = reinterpret_cast(buf); uint16_t curBlock = block; - uint32_t blockOffset = f->offset % BlockSize; + uint32_t blockOffset = fh.offset % BlockSize; size_t rem = size; while (rem) { if (curBlock == 0xFFFF) - return; + return ECardResult::NOFILE; size_t cacheSize = rem; if (cacheSize + blockOffset > BlockSize) cacheSize = BlockSize - blockOffset; uint32_t offset = (curBlock * BlockSize) + blockOffset; fseek(m_fileHandle, offset, SEEK_SET); - fwrite(tmpBuf, 1, cacheSize, m_fileHandle); + if (fwrite(tmpBuf, 1, cacheSize, m_fileHandle) != cacheSize) + return ECardResult::IOERROR; tmpBuf += cacheSize; rem -= cacheSize; blockOffset += cacheSize; @@ -321,45 +333,44 @@ void Card::write(const std::unique_ptr& fh, const void* buf, size_t blockOffset = 0; } } - f->offset += size; + fh.offset += size; } + + return ECardResult::READY; } -void Card::read(const std::unique_ptr& fh, void* dst, size_t size) +ECardResult Card::read(FileHandle& fh, void* dst, size_t size) { - if (!fh) - return; - if (m_fileHandle) { - FileHandle* f = dynamic_cast(fh.get()); - File* file = m_dirs[m_currentDir].getFile(f->idx); + File* file = m_dirs[m_currentDir].getFile(fh.idx); if (!file) - return; + return ECardResult::NOFILE; /* Block handling is a little different from cache handling, * since each block can be in an arbitrary location we must * first find our starting block. */ - const uint16_t blockId = uint16_t(f->offset / BlockSize); + const uint16_t blockId = uint16_t(fh.offset / BlockSize); uint16_t block = file->m_firstBlock; for (uint16_t i = 0; i < blockId; i++) block = m_bats[m_currentBat].getNextBlock(block); uint8_t* tmpBuf = reinterpret_cast(dst); uint16_t curBlock = block; - uint32_t blockOffset = f->offset % BlockSize; + uint32_t blockOffset = fh.offset % BlockSize; size_t rem = size; while (rem) { if (curBlock == 0xFFFF) - return; + return ECardResult::NOFILE; size_t cacheSize = rem; if (cacheSize + blockOffset > BlockSize) cacheSize = BlockSize - blockOffset; uint32_t offset = (curBlock * BlockSize) + blockOffset; fseek(m_fileHandle, offset, SEEK_SET); - fread(tmpBuf, 1, cacheSize, m_fileHandle); + if (fread(tmpBuf, 1, cacheSize, m_fileHandle) != cacheSize) + return ECardResult::IOERROR; tmpBuf += cacheSize; rem -= cacheSize; blockOffset += cacheSize; @@ -369,45 +380,38 @@ void Card::read(const std::unique_ptr& fh, void* dst, size_t size) blockOffset = 0; } } - f->offset += size; + fh.offset += size; } + + return ECardResult::READY; } -void Card::seek(const std::unique_ptr& fh, int32_t pos, SeekOrigin whence) +void Card::seek(FileHandle& fh, int32_t pos, SeekOrigin whence) { - if (!fh) - return; - - FileHandle* f = dynamic_cast(fh.get()); - File* file = m_dirs[m_currentDir].getFile(f->idx); + File* file = m_dirs[m_currentDir].getFile(fh.idx); if (!file) return; switch (whence) { case SeekOrigin::Begin: - f->offset = pos; + fh.offset = pos; break; case SeekOrigin::Current: - f->offset += pos; + fh.offset += pos; break; case SeekOrigin::End: - f->offset = int32_t(file->m_blockCount * BlockSize) - pos; + fh.offset = int32_t(file->m_blockCount * BlockSize) - pos; break; } } -int32_t Card::tell(const std::unique_ptr& fh) +int32_t Card::tell(const FileHandle& fh) { - if (!fh) - return -1; - FileHandle* handle = dynamic_cast(fh.get()); - if (!handle) - return -1; - return handle->offset; + return fh.offset; } -void Card::setPublic(const std::unique_ptr& fh, bool pub) +void Card::setPublic(const FileHandle& fh, bool pub) { File* file = _fileFromHandle(fh); if (!file) @@ -419,7 +423,7 @@ void Card::setPublic(const std::unique_ptr& fh, bool pub) file->m_permissions &= ~EPermissions::Public; } -bool Card::isPublic(const std::unique_ptr& fh) const +bool Card::isPublic(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -428,7 +432,7 @@ bool Card::isPublic(const std::unique_ptr& fh) const return bool(file->m_permissions & EPermissions::Public); } -void Card::setCanCopy(const std::unique_ptr& fh, bool copy) const +void Card::setCanCopy(const FileHandle& fh, bool copy) const { File* file = _fileFromHandle(fh); if (!file) @@ -440,7 +444,7 @@ void Card::setCanCopy(const std::unique_ptr& fh, bool copy) const file->m_permissions |= EPermissions::NoCopy; } -bool Card::canCopy(const std::unique_ptr& fh) const +bool Card::canCopy(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -449,7 +453,7 @@ bool Card::canCopy(const std::unique_ptr& fh) const return !bool(file->m_permissions & EPermissions::NoCopy); } -void Card::setCanMove(const std::unique_ptr& fh, bool move) +void Card::setCanMove(const FileHandle& fh, bool move) { File* file = _fileFromHandle(fh); if (!file) @@ -461,7 +465,7 @@ void Card::setCanMove(const std::unique_ptr& fh, bool move) file->m_permissions |= EPermissions::NoMove; } -bool Card::canMove(const std::unique_ptr& fh) const +bool Card::canMove(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -511,9 +515,14 @@ static uint32_t TlutSize(EImageFormat fmt) } } -ECardResult Card::getStatus(const std::unique_ptr& fh, CardStat& statOut) const +ECardResult Card::getStatus(const FileHandle& fh, CardStat& statOut) const { - File* file = _fileFromHandle(fh); + return getStatus(fh.idx, statOut); +} + +ECardResult Card::getStatus(uint32_t fileNo, CardStat& statOut) const +{ + File* file = const_cast(m_dirs[m_currentDir]).getFile(fileNo); if (!file || file->m_game[0] == 0xFF) return ECardResult::NOFILE; @@ -567,9 +576,14 @@ ECardResult Card::getStatus(const std::unique_ptr& fh, CardStat& st return ECardResult::READY; } -ECardResult Card::setStatus(const std::unique_ptr& fh, const CardStat& stat) +ECardResult Card::setStatus(const FileHandle& fh, const CardStat& stat) { - File* file = _fileFromHandle(fh); + return setStatus(fh.idx, stat); +} + +ECardResult Card::setStatus(uint32_t fileNo, const CardStat& stat) +{ + File* file = m_dirs[m_currentDir].getFile(fileNo); if (!file || file->m_game[0] == 0xFF) return ECardResult::NOFILE; @@ -582,7 +596,7 @@ ECardResult Card::setStatus(const std::unique_ptr& fh, const CardSt return ECardResult::READY; } -const char* Card::gameId(const std::unique_ptr& fh) const +const char* Card::gameId(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -590,7 +604,7 @@ const char* Card::gameId(const std::unique_ptr& fh) const return reinterpret_cast(file->m_game); } -const char* Card::maker(const std::unique_ptr& fh) const +const char* Card::maker(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -598,7 +612,7 @@ const char* Card::maker(const std::unique_ptr& fh) const return reinterpret_cast(file->m_maker); } -void Card::setBannerFormat(const std::unique_ptr& fh, EImageFormat fmt) +void Card::setBannerFormat(const FileHandle& fh, EImageFormat fmt) { File* file = _fileFromHandle(fh); if (!file) @@ -606,7 +620,7 @@ void Card::setBannerFormat(const std::unique_ptr& fh, EImageFormat file->m_bannerFlags = (file->m_bannerFlags & ~3) | (uint8_t(fmt)); } -EImageFormat Card::bannerFormat(const std::unique_ptr& fh) const +EImageFormat Card::bannerFormat(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -614,7 +628,7 @@ EImageFormat Card::bannerFormat(const std::unique_ptr& fh) const return EImageFormat(file->m_bannerFlags & 3); } -void Card::setIconAnimationType(const std::unique_ptr& fh, EAnimationType type) +void Card::setIconAnimationType(const FileHandle& fh, EAnimationType type) { File* file = _fileFromHandle(fh); if (!file) @@ -622,7 +636,7 @@ void Card::setIconAnimationType(const std::unique_ptr& fh, EAnimati file->m_bannerFlags = (file->m_bannerFlags & ~4) | uint8_t(type); } -EAnimationType Card::iconAnimationType(const std::unique_ptr& fh) const +EAnimationType Card::iconAnimationType(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -631,7 +645,7 @@ EAnimationType Card::iconAnimationType(const std::unique_ptr& fh) c return EAnimationType(file->m_bannerFlags & 4); } -void Card::setIconFormat(const std::unique_ptr& fh, uint32_t idx, EImageFormat fmt) +void Card::setIconFormat(const FileHandle& fh, uint32_t idx, EImageFormat fmt) { File* file = _fileFromHandle(fh); if (!file) @@ -640,7 +654,7 @@ void Card::setIconFormat(const std::unique_ptr& fh, uint32_t idx, E file->m_iconFmt = (file->m_iconFmt & ~(3 << (2 * idx))) | (uint16_t(fmt) << (2 * idx)); } -EImageFormat Card::iconFormat(const std::unique_ptr& fh, uint32_t idx) const +EImageFormat Card::iconFormat(const FileHandle& fh, uint32_t idx) const { File* file = _fileFromHandle(fh); if (!file) @@ -649,7 +663,7 @@ EImageFormat Card::iconFormat(const std::unique_ptr& fh, uint32_t i return EImageFormat(file->m_iconFmt >> (2 * (idx)) & 3); } -void Card::setIconSpeed(const std::unique_ptr& fh, uint32_t idx, EAnimationSpeed speed) +void Card::setIconSpeed(const FileHandle& fh, uint32_t idx, EAnimationSpeed speed) { File* file = _fileFromHandle(fh); if (!file) @@ -658,7 +672,7 @@ void Card::setIconSpeed(const std::unique_ptr& fh, uint32_t idx, EA file->m_animSpeed = (file->m_animSpeed & ~(3 << (2 * idx))) | (uint16_t(speed) << (2 * idx)); } -EAnimationSpeed Card::iconSpeed(const std::unique_ptr& fh, uint32_t idx) const +EAnimationSpeed Card::iconSpeed(const FileHandle& fh, uint32_t idx) const { File* file = _fileFromHandle(fh); if (!file) @@ -667,7 +681,7 @@ EAnimationSpeed Card::iconSpeed(const std::unique_ptr& fh, uint32_t return EAnimationSpeed((file->m_animSpeed >> (2 * (idx))) & 3); } -void Card::setImageAddress(const std::unique_ptr& fh, uint32_t addr) +void Card::setImageAddress(const FileHandle& fh, uint32_t addr) { File* file = _fileFromHandle(fh); if (!file) @@ -675,7 +689,7 @@ void Card::setImageAddress(const std::unique_ptr& fh, uint32_t addr file->m_iconAddress = addr; } -int32_t Card::imageAddress(const std::unique_ptr& fh) const +int32_t Card::imageAddress(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -683,7 +697,7 @@ int32_t Card::imageAddress(const std::unique_ptr& fh) const return file->m_iconAddress; } -void Card::setCommentAddress(const std::unique_ptr& fh, uint32_t addr) +void Card::setCommentAddress(const FileHandle& fh, uint32_t addr) { File* file = _fileFromHandle(fh); if (!file) @@ -691,7 +705,7 @@ void Card::setCommentAddress(const std::unique_ptr& fh, uint32_t ad file->m_commentAddr = addr; } -int32_t Card::commentAddress(const std::unique_ptr& fh) const +int32_t Card::commentAddress(const FileHandle& fh) const { File* file = _fileFromHandle(fh); if (!file) @@ -699,11 +713,8 @@ int32_t Card::commentAddress(const std::unique_ptr& fh) const return file->m_commentAddr; } -bool Card::copyFileTo(const std::unique_ptr& fh, Card& dest) +bool Card::copyFileTo(FileHandle& fh, Card& dest) { - if (!fh) - return false; - if (!canCopy(fh)) return false; @@ -717,7 +728,7 @@ bool Card::copyFileTo(const std::unique_ptr& fh, Card& dest) return false; /* Check to make sure dest does not already contain fh */ - std::unique_ptr tmpHandle; + FileHandle tmpHandle; dest.openFile(toCopy->m_filename, tmpHandle); if (tmpHandle) return false; @@ -750,7 +761,7 @@ bool Card::copyFileTo(const std::unique_ptr& fh, Card& dest) return true; } -bool Card::moveFileTo(const std::unique_ptr& fh, Card& dest) +bool Card::moveFileTo(FileHandle& fh, Card& dest) { if (copyFileTo(fh, dest) && canMove(fh)) { @@ -928,8 +939,12 @@ ECardResult Card::getError() const return ECardResult::NOCARD; uint16_t ckSum, ckSumInv; - calculateChecksumLE(reinterpret_cast(__raw), 0xFE, &ckSum, &ckSumInv); - if (ckSum != m_checksum || ckSumInv != m_checksumInv) + const_cast(*this)._swapEndian(); + calculateChecksumBE(reinterpret_cast(__raw), 0xFE, &ckSum, &ckSumInv); + bool res = (ckSum == m_checksum && ckSumInv == m_checksumInv); + const_cast(*this)._swapEndian(); + + if (!res) return ECardResult::BROKEN; if (!m_dirs[0].valid() && !m_dirs[1].valid()) return ECardResult::BROKEN; diff --git a/lib/kabufuda/Directory.cpp b/lib/kabufuda/Directory.cpp index 6854bb7..a375b6c 100644 --- a/lib/kabufuda/Directory.cpp +++ b/lib/kabufuda/Directory.cpp @@ -15,14 +15,19 @@ void Directory::swapEndian() void Directory::updateChecksum() { - calculateChecksumLE(reinterpret_cast(__raw), 0xFFE, &m_checksum, &m_checksumInv); + swapEndian(); + calculateChecksumBE(reinterpret_cast(__raw), 0xFFE, &m_checksum, &m_checksumInv); + swapEndian(); } bool Directory::valid() const { uint16_t ckSum, ckSumInv; - calculateChecksumLE(reinterpret_cast(__raw), 0xFFE, &ckSum, &ckSumInv); - return (ckSum == m_checksum && ckSumInv == m_checksumInv); + const_cast(*this).swapEndian(); + calculateChecksumBE(reinterpret_cast(__raw), 0xFFE, &ckSum, &ckSumInv); + bool res = (ckSum == m_checksum && ckSumInv == m_checksumInv); + const_cast(*this).swapEndian(); + return res; } Directory::Directory() @@ -36,7 +41,7 @@ Directory::Directory(uint8_t data[]) { memcpy(__raw, data, BlockSize); } bool Directory::hasFreeFile() const { - for (uint16_t i = 0; i < 127; i++) + for (uint16_t i = 1; i < 127; i++) if (m_files[i].m_game[0] == 0xFF) return true; return false; @@ -45,7 +50,7 @@ bool Directory::hasFreeFile() const int32_t Directory::numFreeFiles() const { int32_t ret = 0; - for (uint16_t i = 0; i < 127; i++) + for (uint16_t i = 1; i < 127; i++) if (m_files[i].m_game[0] == 0xFF) ++ret; return ret; @@ -53,7 +58,7 @@ int32_t Directory::numFreeFiles() const File* Directory::getFirstFreeFile(const char* game, const char* maker, const char* filename) { - for (uint16_t i = 0; i < 127; i++) + for (uint16_t i = 1; i < 127; i++) { if (m_files[i].m_game[0] == 0xFF) { @@ -92,7 +97,7 @@ File* Directory::getFirstNonFreeFile(uint32_t start, const char* game, const cha File* Directory::getFile(const char* game, const char* maker, const char* filename) { - for (uint16_t i = 0; i < 127; i++) + for (uint16_t i = 1; i < 127; i++) { if (game && strlen(game) == 4 && memcmp(m_files[i].m_game, game, 4)) continue; diff --git a/lib/kabufuda/Util.cpp b/lib/kabufuda/Util.cpp index 6186ffa..00c4110 100644 --- a/lib/kabufuda/Util.cpp +++ b/lib/kabufuda/Util.cpp @@ -42,19 +42,4 @@ void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, u *checksumInv = 0; } -void calculateChecksumLE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv) -{ - *checksum = 0; - *checksumInv = 0; - for (size_t i = 0; i < len; ++i) - { - *checksum += data[i]; - *checksumInv += uint16_t(data[i] ^ 0xFFFF); - } - - if (*checksum == 0xFFFF) - *checksum = 0; - if (*checksumInv == 0xFFFF) - *checksumInv = 0; -} } diff --git a/test/main.cpp b/test/main.cpp index d5af4aa..72e38a5 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -8,7 +8,7 @@ int main() uint64_t a = 0; mc.getSerial(a); - std::unique_ptr f; + kabufuda::FileHandle f; mc.openFile("MetroidPrime A", f); for (uint32_t i = 0; i < 127; i++) {