mirror of https://github.com/AxioDL/kabufuda.git
Finalize directory structure
Remove unrelated classes from Card.{cpp,hpp}
This commit is contained in:
parent
4cd0330e22
commit
2a9c18534a
|
@ -11,11 +11,15 @@ include_directories(include)
|
||||||
set(KABUFUDA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE PATH "kabufuda include path" FORCE)
|
set(KABUFUDA_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/include CACHE PATH "kabufuda include path" FORCE)
|
||||||
|
|
||||||
add_library(kabufuda STATIC
|
add_library(kabufuda STATIC
|
||||||
include/kabufuda/Card.hpp lib/Card.cpp
|
include/kabufuda/Constants.hpp
|
||||||
include/kabufuda/Util.hpp lib/Util.cpp
|
include/kabufuda/BlockAllocationTable.hpp lib/kabufuda/BlockAllocationTable.cpp
|
||||||
include/kabufuda/SRAM.hpp lib/SRAM.cpp
|
include/kabufuda/Card.hpp lib/kabufuda/Card.cpp
|
||||||
include/kabufuda/WideStringConvert.hpp lib/WideStringConvert.cpp)
|
include/kabufuda/Directory.hpp lib/kabufuda/Directory.cpp
|
||||||
|
include/kabufuda/File.hpp lib/kabufuda/File.cpp
|
||||||
|
include/kabufuda/Util.hpp lib/kabufuda/Util.cpp
|
||||||
|
include/kabufuda/SRAM.hpp lib/kabufuda/SRAM.cpp
|
||||||
|
include/kabufuda/WideStringConvert.hpp lib/kabufuda/WideStringConvert.cpp)
|
||||||
|
|
||||||
if (NOT TARGET urde)
|
if (NOT TARGET hecl)
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
endif()
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef __KABU_BLOCKALLOCATIONATABLE_HPP__
|
||||||
|
#define __KABU_BLOCKALLOCATIONATABLE_HPP__
|
||||||
|
|
||||||
|
#include "Constants.hpp"
|
||||||
|
|
||||||
|
namespace kabufuda
|
||||||
|
{
|
||||||
|
class BlockAllocationTable
|
||||||
|
{
|
||||||
|
friend class Card;
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint16_t m_checksum;
|
||||||
|
uint16_t m_checksumInv;
|
||||||
|
uint16_t m_updateCounter;
|
||||||
|
uint16_t m_freeBlocks;
|
||||||
|
uint16_t m_lastAllocated;
|
||||||
|
uint16_t m_map[0xFFB];
|
||||||
|
};
|
||||||
|
uint8_t __raw[BlockSize];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
void swapEndian();
|
||||||
|
void updateChecksum();
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit BlockAllocationTable(uint32_t blockCount = (uint32_t(ECardSize::Card2043Mb) * MbitToBlocks));
|
||||||
|
BlockAllocationTable(uint8_t data[BlockSize]);
|
||||||
|
~BlockAllocationTable() {}
|
||||||
|
|
||||||
|
uint16_t getNextBlock(uint16_t block) const;
|
||||||
|
uint16_t nextFreeBlock(uint16_t maxBlock, uint16_t startingBlock) const;
|
||||||
|
bool clear(uint16_t first, uint16_t count);
|
||||||
|
uint16_t allocateBlocks(uint16_t count, uint16_t maxBlocks);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // __KABU_BLOCKALLOCATIONATABLE_HPP__
|
|
@ -1,109 +1,17 @@
|
||||||
#ifndef __CARD_HPP__
|
#ifndef __KABU_CARD_HPP__
|
||||||
#define __CARD_HPP__
|
#define __KABU_CARD_HPP__
|
||||||
|
|
||||||
|
#include "BlockAllocationTable.hpp"
|
||||||
|
#include "Directory.hpp"
|
||||||
|
#include "File.hpp"
|
||||||
|
#include "Util.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "Util.hpp"
|
|
||||||
|
|
||||||
namespace kabufuda
|
namespace kabufuda
|
||||||
{
|
{
|
||||||
uint32_t constexpr BlockSize = 0x2000;
|
|
||||||
uint32_t constexpr MaxFiles = 127;
|
|
||||||
uint32_t constexpr FSTBlocks = 5;
|
|
||||||
uint32_t constexpr MbitToBlocks = 0x10;
|
|
||||||
uint32_t constexpr BATSize = 0xFFB;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The EPermissions enum
|
|
||||||
*/
|
|
||||||
enum class EPermissions : uint8_t
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The EBannerFlags enum
|
|
||||||
*/
|
|
||||||
enum class EBannerFlags : uint8_t
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SeekOrigin
|
|
||||||
{
|
|
||||||
Begin,
|
|
||||||
Current,
|
|
||||||
End
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The EDeviceId enum
|
|
||||||
*/
|
|
||||||
enum class EDeviceId : uint16_t
|
|
||||||
{
|
|
||||||
SlotA,
|
|
||||||
SlotB
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The ECardSize enum
|
|
||||||
*/
|
|
||||||
enum class ECardSize : uint16_t
|
|
||||||
{
|
|
||||||
Card59Mb = 0x04,
|
|
||||||
Card123Mb = 0x08,
|
|
||||||
Card251Mb = 0x10,
|
|
||||||
Card507Mb = 0x20,
|
|
||||||
Card1019Mb = 0x40,
|
|
||||||
Card2043Mb = 0x80
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief The EEncoding enum
|
|
||||||
*/
|
|
||||||
enum class EEncoding : uint16_t
|
|
||||||
{
|
|
||||||
ASCII, /**< Standard ASCII Encoding */
|
|
||||||
SJIS /**< SJIS Encoding for japanese */
|
|
||||||
};
|
|
||||||
|
|
||||||
class File
|
|
||||||
{
|
|
||||||
friend class FileHandle;
|
|
||||||
friend class Directory;
|
|
||||||
friend class Card;
|
|
||||||
#pragma pack(push, 4)
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint8_t m_id[4];
|
|
||||||
uint8_t m_maker[2];
|
|
||||||
uint8_t m_reserved;
|
|
||||||
uint8_t m_bannerFlags;
|
|
||||||
char m_filename[0x20];
|
|
||||||
uint32_t m_modifiedTime;
|
|
||||||
uint32_t m_imageOffset;
|
|
||||||
uint16_t m_iconFmt;
|
|
||||||
uint16_t m_animSpeed;
|
|
||||||
uint8_t m_permissions;
|
|
||||||
int8_t m_copyCounter;
|
|
||||||
uint16_t m_firstBlock;
|
|
||||||
uint16_t m_blockCount;
|
|
||||||
uint16_t m_reserved2;
|
|
||||||
uint32_t m_commentAddr;
|
|
||||||
};
|
|
||||||
uint8_t __raw[0x40];
|
|
||||||
};
|
|
||||||
|
|
||||||
#pragma pack(pop)
|
|
||||||
void swapEndian();
|
|
||||||
|
|
||||||
public:
|
|
||||||
File();
|
|
||||||
File(char data[0x40]);
|
|
||||||
File(const char* filename);
|
|
||||||
~File() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
class IFileHandle
|
class IFileHandle
|
||||||
{
|
{
|
||||||
|
@ -111,73 +19,6 @@ public:
|
||||||
virtual ~IFileHandle();
|
virtual ~IFileHandle();
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlockAllocationTable
|
|
||||||
{
|
|
||||||
friend class Card;
|
|
||||||
#pragma pack(push, 4)
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint16_t m_checksum;
|
|
||||||
uint16_t m_checksumInv;
|
|
||||||
uint16_t m_updateCounter;
|
|
||||||
uint16_t m_freeBlocks;
|
|
||||||
uint16_t m_lastAllocated;
|
|
||||||
uint16_t m_map[0xFFB];
|
|
||||||
};
|
|
||||||
uint8_t __raw[BlockSize];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
void swapEndian();
|
|
||||||
void updateChecksum();
|
|
||||||
bool valid() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit BlockAllocationTable(uint32_t blockCount = (uint32_t(ECardSize::Card2043Mb) * MbitToBlocks));
|
|
||||||
BlockAllocationTable(uint8_t data[BlockSize]);
|
|
||||||
~BlockAllocationTable() {}
|
|
||||||
|
|
||||||
uint16_t getNextBlock(uint16_t block) const;
|
|
||||||
uint16_t nextFreeBlock(uint16_t maxBlock, uint16_t startingBlock) const;
|
|
||||||
bool clear(uint16_t first, uint16_t count);
|
|
||||||
uint16_t allocateBlocks(uint16_t count, uint16_t maxBlocks);
|
|
||||||
};
|
|
||||||
|
|
||||||
class Directory
|
|
||||||
{
|
|
||||||
friend class Card;
|
|
||||||
#pragma pack(push, 4)
|
|
||||||
union
|
|
||||||
{
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
File m_files[MaxFiles];
|
|
||||||
uint8_t __padding[0x3a];
|
|
||||||
uint16_t m_updateCounter;
|
|
||||||
uint16_t m_checksum;
|
|
||||||
uint16_t m_checksumInv;
|
|
||||||
};
|
|
||||||
uint8_t __raw[BlockSize];
|
|
||||||
};
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
void swapEndian();
|
|
||||||
void updateChecksum();
|
|
||||||
bool valid() const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
Directory();
|
|
||||||
Directory(uint8_t data[BlockSize]);
|
|
||||||
Directory(const Directory& other);
|
|
||||||
void operator=(const Directory& other);
|
|
||||||
~Directory() {}
|
|
||||||
|
|
||||||
File* getFirstFreeFile(const char* game, const char* maker, const char* filename);
|
|
||||||
File* getFile(const char* game, const char* maker, const char* filename);
|
|
||||||
};
|
|
||||||
|
|
||||||
class Card
|
class Card
|
||||||
{
|
{
|
||||||
#pragma pack(push, 4)
|
#pragma pack(push, 4)
|
||||||
|
@ -293,15 +134,6 @@ public:
|
||||||
|
|
||||||
operator bool() const;
|
operator bool() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief calculateChecksum
|
|
||||||
* @param data
|
|
||||||
* @param len
|
|
||||||
* @param checksum
|
|
||||||
* @param checksumInv
|
|
||||||
*/
|
|
||||||
void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __CARD_HPP__
|
#endif // __CARD_HPP__
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef __KABU_CONSTANTS_HPP__
|
||||||
|
#define __KABU_CONSTANTS_HPP__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace kabufuda
|
||||||
|
{
|
||||||
|
uint32_t constexpr BlockSize = 0x2000;
|
||||||
|
uint32_t constexpr MaxFiles = 127;
|
||||||
|
uint32_t constexpr FSTBlocks = 5;
|
||||||
|
uint32_t constexpr MbitToBlocks = 0x10;
|
||||||
|
uint32_t constexpr BATSize = 0xFFB;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The EPermissions enum
|
||||||
|
*/
|
||||||
|
enum class EPermissions : uint8_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The EBannerFlags enum
|
||||||
|
*/
|
||||||
|
enum class EBannerFlags : uint8_t
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SeekOrigin
|
||||||
|
{
|
||||||
|
Begin,
|
||||||
|
Current,
|
||||||
|
End
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The EDeviceId enum
|
||||||
|
*/
|
||||||
|
enum class EDeviceId : uint16_t
|
||||||
|
{
|
||||||
|
SlotA,
|
||||||
|
SlotB
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The ECardSize enum
|
||||||
|
*/
|
||||||
|
enum class ECardSize : uint16_t
|
||||||
|
{
|
||||||
|
Card59Mb = 0x04,
|
||||||
|
Card123Mb = 0x08,
|
||||||
|
Card251Mb = 0x10,
|
||||||
|
Card507Mb = 0x20,
|
||||||
|
Card1019Mb = 0x40,
|
||||||
|
Card2043Mb = 0x80
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The EEncoding enum
|
||||||
|
*/
|
||||||
|
enum class EEncoding : uint16_t
|
||||||
|
{
|
||||||
|
ASCII, /**< Standard ASCII Encoding */
|
||||||
|
SJIS /**< SJIS Encoding for japanese */
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif // __KABU_CONSTANTS_HPP__
|
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef __KABU_DIRECTORY_HPP__
|
||||||
|
#define __KABU_DIRECTORY_HPP__
|
||||||
|
|
||||||
|
#include "File.hpp"
|
||||||
|
|
||||||
|
namespace kabufuda
|
||||||
|
{
|
||||||
|
class Directory
|
||||||
|
{
|
||||||
|
friend class Card;
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
File m_files[MaxFiles];
|
||||||
|
uint8_t __padding[0x3a];
|
||||||
|
uint16_t m_updateCounter;
|
||||||
|
uint16_t m_checksum;
|
||||||
|
uint16_t m_checksumInv;
|
||||||
|
};
|
||||||
|
uint8_t __raw[BlockSize];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
void swapEndian();
|
||||||
|
void updateChecksum();
|
||||||
|
bool valid() const;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Directory();
|
||||||
|
Directory(uint8_t data[BlockSize]);
|
||||||
|
Directory(const Directory& other);
|
||||||
|
void operator=(const Directory& other);
|
||||||
|
~Directory() {}
|
||||||
|
|
||||||
|
File* getFirstFreeFile(const char* game, const char* maker, const char* filename);
|
||||||
|
File* getFile(const char* game, const char* maker, const char* filename);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __KABU_DIRECTORY_HPP__
|
|
@ -0,0 +1,49 @@
|
||||||
|
#ifndef __KABU_FILE_HPP__
|
||||||
|
#define __KABU_FILE_HPP__
|
||||||
|
|
||||||
|
#include "Constants.hpp"
|
||||||
|
|
||||||
|
namespace kabufuda
|
||||||
|
{
|
||||||
|
class File
|
||||||
|
{
|
||||||
|
friend class IFileHandle;
|
||||||
|
friend class Directory;
|
||||||
|
friend class Card;
|
||||||
|
#pragma pack(push, 4)
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint8_t m_id[4];
|
||||||
|
uint8_t m_maker[2];
|
||||||
|
uint8_t m_reserved;
|
||||||
|
uint8_t m_bannerFlags;
|
||||||
|
char m_filename[0x20];
|
||||||
|
uint32_t m_modifiedTime;
|
||||||
|
uint32_t m_imageOffset;
|
||||||
|
uint16_t m_iconFmt;
|
||||||
|
uint16_t m_animSpeed;
|
||||||
|
uint8_t m_permissions;
|
||||||
|
int8_t m_copyCounter;
|
||||||
|
uint16_t m_firstBlock;
|
||||||
|
uint16_t m_blockCount;
|
||||||
|
uint16_t m_reserved2;
|
||||||
|
uint32_t m_commentAddr;
|
||||||
|
};
|
||||||
|
uint8_t __raw[0x40];
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
void swapEndian();
|
||||||
|
|
||||||
|
public:
|
||||||
|
File();
|
||||||
|
File(char data[0x40]);
|
||||||
|
File(const char* filename);
|
||||||
|
~File() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __KABU_FILE_HPP__
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef __UTIL_HPP__
|
#ifndef __KABU_UTIL_HPP__
|
||||||
#define __UTIL_HPP__
|
#define __KABU_UTIL_HPP__
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -305,6 +305,15 @@ static inline int Stat(const SystemChar* path, Sstat* statOut)
|
||||||
return stat(path, statOut);
|
return stat(path, statOut);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief calculateChecksum
|
||||||
|
* @param data
|
||||||
|
* @param len
|
||||||
|
* @param checksum
|
||||||
|
* @param checksumInv
|
||||||
|
*/
|
||||||
|
void calculateChecksumBE(const uint16_t* data, size_t len, uint16_t* checksum, uint16_t* checksumInv);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __UTIL_HPP__
|
#endif // __KABU_UTIL_HPP__
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
#ifndef __KABU_WIDESTRINGCONVERT_HPP__
|
||||||
|
#define __KABU_WIDESTRINGCONVERT_HPP__
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace kabufuda
|
namespace kabufuda
|
||||||
|
@ -5,3 +8,5 @@ namespace kabufuda
|
||||||
std::string WideToUTF8(const std::wstring& src);
|
std::string WideToUTF8(const std::wstring& src);
|
||||||
std::wstring UTF8ToWide(const std::string& src);
|
std::wstring UTF8ToWide(const std::string& src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif // __KABU_WIDESTRINGCONVERT_HPP__
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
#include "kabufuda/BlockAllocationTable.hpp"
|
||||||
|
#include "kabufuda/Util.hpp"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
|
||||||
|
namespace kabufuda
|
||||||
|
{
|
||||||
|
void BlockAllocationTable::swapEndian()
|
||||||
|
{
|
||||||
|
m_checksum = SBig(m_checksum);
|
||||||
|
m_checksumInv = SBig(m_checksumInv);
|
||||||
|
m_updateCounter = SBig(m_updateCounter);
|
||||||
|
m_freeBlocks = SBig(m_freeBlocks);
|
||||||
|
m_lastAllocated = SBig(m_lastAllocated);
|
||||||
|
std::for_each(std::begin(m_map), std::end(m_map), [](uint16_t& val){
|
||||||
|
val = SBig(val);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockAllocationTable::updateChecksum()
|
||||||
|
{
|
||||||
|
swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv);
|
||||||
|
swapEndian();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BlockAllocationTable::valid() const
|
||||||
|
{
|
||||||
|
uint16_t ckSum, ckSumInv;
|
||||||
|
BlockAllocationTable tmp = *this;
|
||||||
|
tmp.swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<const uint16_t*>(tmp.__raw + 4), 0xFFE, &ckSum, &ckSumInv);
|
||||||
|
return (SBig(ckSum) == m_checksum && SBig(ckSumInv) == m_checksumInv);
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockAllocationTable::BlockAllocationTable(uint32_t blockCount)
|
||||||
|
{
|
||||||
|
memset(__raw, 0, BlockSize);
|
||||||
|
m_freeBlocks = uint16_t(blockCount - FSTBlocks);
|
||||||
|
m_lastAllocated = 4;
|
||||||
|
updateChecksum();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t BlockAllocationTable::getNextBlock(uint16_t block) const
|
||||||
|
{
|
||||||
|
if ((block < FSTBlocks) || (block > (BATSize - FSTBlocks)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return m_map[block - FSTBlocks];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t BlockAllocationTable::nextFreeBlock(uint16_t maxBlock, uint16_t startingBlock) const
|
||||||
|
{
|
||||||
|
if (m_freeBlocks > 0)
|
||||||
|
{
|
||||||
|
maxBlock = std::min(maxBlock, uint16_t(BATSize));
|
||||||
|
for (uint16_t i = startingBlock; i < maxBlock; ++i)
|
||||||
|
if (m_map[i - FSTBlocks] == 0)
|
||||||
|
return i;
|
||||||
|
|
||||||
|
for (uint16_t i = FSTBlocks; i < startingBlock; ++i)
|
||||||
|
if (m_map[i - FSTBlocks] == 0)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BlockAllocationTable::clear(uint16_t first, uint16_t count)
|
||||||
|
{
|
||||||
|
std::vector<uint16_t> blocks;
|
||||||
|
while (first != 0xFFFF && first != 0)
|
||||||
|
{
|
||||||
|
blocks.push_back(first);
|
||||||
|
first = getNextBlock(first);
|
||||||
|
}
|
||||||
|
if (first > 0)
|
||||||
|
{
|
||||||
|
size_t length = blocks.size();
|
||||||
|
if (length != count)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (size_t i= 0 ; i < length ; ++i)
|
||||||
|
m_map[blocks.at(i) - FSTBlocks] = 0;
|
||||||
|
m_freeBlocks += count;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t BlockAllocationTable::allocateBlocks(uint16_t count, uint16_t maxBlocks)
|
||||||
|
{
|
||||||
|
uint16_t firstBlock = nextFreeBlock(maxBlocks - FSTBlocks, m_lastAllocated + 1);
|
||||||
|
uint16_t freeBlock = firstBlock;
|
||||||
|
if (freeBlock != 0xFFFF)
|
||||||
|
{
|
||||||
|
uint16_t tmpCount = count;
|
||||||
|
while ((count--) > 0)
|
||||||
|
{
|
||||||
|
m_map[(freeBlock - FSTBlocks)] = 0xFFFF;
|
||||||
|
if (count != 0)
|
||||||
|
{
|
||||||
|
m_map[(freeBlock - FSTBlocks)] = nextFreeBlock(maxBlocks - FSTBlocks, m_lastAllocated + 1);
|
||||||
|
freeBlock = m_map[(freeBlock - FSTBlocks)];
|
||||||
|
}
|
||||||
|
m_lastAllocated = freeBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_freeBlocks -= tmpCount;
|
||||||
|
}
|
||||||
|
return firstBlock;
|
||||||
|
}
|
||||||
|
}
|
|
@ -493,241 +493,4 @@ Card::operator bool() const
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
File::File(char data[])
|
|
||||||
{
|
|
||||||
memcpy(__raw, data, 0x40);
|
|
||||||
}
|
|
||||||
|
|
||||||
File::File(const char* filename)
|
|
||||||
{
|
|
||||||
memset(__raw, 0xFF, 0x40);
|
|
||||||
memset(m_filename, 0, 32);
|
|
||||||
size_t len = strlen(filename);
|
|
||||||
len = std::min<size_t>(len, 32);
|
|
||||||
memcpy(m_filename, filename, len);
|
|
||||||
}
|
|
||||||
void File::swapEndian()
|
|
||||||
{
|
|
||||||
m_modifiedTime = SBig(m_modifiedTime);
|
|
||||||
m_imageOffset = SBig(m_imageOffset);
|
|
||||||
m_iconFmt = SBig(m_iconFmt);
|
|
||||||
m_animSpeed = SBig(m_animSpeed);
|
|
||||||
m_firstBlock = SBig(m_firstBlock);
|
|
||||||
m_blockCount = SBig(m_blockCount);
|
|
||||||
m_reserved2 = SBig(m_reserved2);
|
|
||||||
m_commentAddr = SBig(m_commentAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
File::File()
|
|
||||||
{
|
|
||||||
memset(__raw, 0xFF, 0x40);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockAllocationTable::swapEndian()
|
|
||||||
{
|
|
||||||
m_checksum = SBig(m_checksum);
|
|
||||||
m_checksumInv = SBig(m_checksumInv);
|
|
||||||
m_updateCounter = SBig(m_updateCounter);
|
|
||||||
m_freeBlocks = SBig(m_freeBlocks);
|
|
||||||
m_lastAllocated = SBig(m_lastAllocated);
|
|
||||||
std::for_each(std::begin(m_map), std::end(m_map), [](uint16_t& val){
|
|
||||||
val = SBig(val);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockAllocationTable::updateChecksum()
|
|
||||||
{
|
|
||||||
swapEndian();
|
|
||||||
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw + 4), 0xFFE, &m_checksum, &m_checksumInv);
|
|
||||||
swapEndian();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockAllocationTable::valid() const
|
|
||||||
{
|
|
||||||
uint16_t ckSum, ckSumInv;
|
|
||||||
BlockAllocationTable tmp = *this;
|
|
||||||
tmp.swapEndian();
|
|
||||||
calculateChecksumBE(reinterpret_cast<const uint16_t*>(tmp.__raw + 4), 0xFFE, &ckSum, &ckSumInv);
|
|
||||||
return (SBig(ckSum) == m_checksum && SBig(ckSumInv) == m_checksumInv);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockAllocationTable::BlockAllocationTable(uint32_t blockCount)
|
|
||||||
{
|
|
||||||
memset(__raw, 0, BlockSize);
|
|
||||||
m_freeBlocks = uint16_t(blockCount - FSTBlocks);
|
|
||||||
m_lastAllocated = 4;
|
|
||||||
updateChecksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t BlockAllocationTable::getNextBlock(uint16_t block) const
|
|
||||||
{
|
|
||||||
if ((block < FSTBlocks) || (block > (BATSize - FSTBlocks)))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return m_map[block - FSTBlocks];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t BlockAllocationTable::nextFreeBlock(uint16_t maxBlock, uint16_t startingBlock) const
|
|
||||||
{
|
|
||||||
if (m_freeBlocks > 0)
|
|
||||||
{
|
|
||||||
maxBlock = std::min(maxBlock, uint16_t(BATSize));
|
|
||||||
for (uint16_t i = startingBlock; i < maxBlock; ++i)
|
|
||||||
if (m_map[i - FSTBlocks] == 0)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
for (uint16_t i = FSTBlocks; i < startingBlock; ++i)
|
|
||||||
if (m_map[i - FSTBlocks] == 0)
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BlockAllocationTable::clear(uint16_t first, uint16_t count)
|
|
||||||
{
|
|
||||||
std::vector<uint16_t> blocks;
|
|
||||||
while (first != 0xFFFF && first != 0)
|
|
||||||
{
|
|
||||||
blocks.push_back(first);
|
|
||||||
first = getNextBlock(first);
|
|
||||||
}
|
|
||||||
if (first > 0)
|
|
||||||
{
|
|
||||||
size_t length = blocks.size();
|
|
||||||
if (length != count)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for (size_t i= 0 ; i < length ; ++i)
|
|
||||||
m_map[blocks.at(i) - FSTBlocks] = 0;
|
|
||||||
m_freeBlocks += count;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t BlockAllocationTable::allocateBlocks(uint16_t count, uint16_t maxBlocks)
|
|
||||||
{
|
|
||||||
uint16_t firstBlock = nextFreeBlock(maxBlocks - FSTBlocks, m_lastAllocated + 1);
|
|
||||||
uint16_t freeBlock = firstBlock;
|
|
||||||
if (freeBlock != 0xFFFF)
|
|
||||||
{
|
|
||||||
uint16_t tmpCount = count;
|
|
||||||
while ((count--) > 0)
|
|
||||||
{
|
|
||||||
m_map[(freeBlock - FSTBlocks)] = 0xFFFF;
|
|
||||||
if (count != 0)
|
|
||||||
{
|
|
||||||
m_map[(freeBlock - FSTBlocks)] = nextFreeBlock(maxBlocks - FSTBlocks, m_lastAllocated + 1);
|
|
||||||
freeBlock = m_map[(freeBlock - FSTBlocks)];
|
|
||||||
}
|
|
||||||
m_lastAllocated = freeBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_freeBlocks -= tmpCount;
|
|
||||||
}
|
|
||||||
return firstBlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Directory::swapEndian()
|
|
||||||
{
|
|
||||||
std::for_each(std::begin(m_files), std::end(m_files), [](File& f){
|
|
||||||
f.swapEndian();
|
|
||||||
});
|
|
||||||
|
|
||||||
m_updateCounter = SBig(m_updateCounter);
|
|
||||||
m_checksum = SBig(m_checksum);
|
|
||||||
m_checksumInv = SBig(m_checksumInv);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Directory::updateChecksum()
|
|
||||||
{
|
|
||||||
swapEndian();
|
|
||||||
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFFE, &m_checksum, &m_checksumInv);
|
|
||||||
swapEndian();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Directory::valid() const
|
|
||||||
{
|
|
||||||
uint16_t ckSum, ckSumInv;
|
|
||||||
Directory tmp = *this;
|
|
||||||
tmp.swapEndian();
|
|
||||||
calculateChecksumBE(reinterpret_cast<const uint16_t*>(tmp.__raw), 0xFFE, &ckSum, &ckSumInv);
|
|
||||||
return (SBig(ckSum) == m_checksum && SBig(ckSumInv) == m_checksumInv);
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory::Directory()
|
|
||||||
{
|
|
||||||
memset(__raw, 0xFF, BlockSize);
|
|
||||||
m_updateCounter = 0;
|
|
||||||
updateChecksum();
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory::Directory(uint8_t data[])
|
|
||||||
{
|
|
||||||
memcpy(__raw, data, BlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
Directory::Directory(const Directory& other)
|
|
||||||
{
|
|
||||||
memcpy(__raw, other.__raw, BlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Directory::operator=(const Directory& other)
|
|
||||||
{
|
|
||||||
memcpy(__raw, other.__raw, BlockSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
File* Directory::getFirstFreeFile(const char* game, const char* maker, const char* filename)
|
|
||||||
{
|
|
||||||
for (uint16_t i = 0 ; i < 127 ; i++)
|
|
||||||
{
|
|
||||||
if (m_files[i].m_id[0] == 0xFF)
|
|
||||||
{
|
|
||||||
File* ret = &m_files[i];
|
|
||||||
*ret = File(filename);
|
|
||||||
if (game && strlen(game) == 4)
|
|
||||||
memcpy(ret->m_id, game, 4);
|
|
||||||
if (maker && strlen(maker) == 2)
|
|
||||||
memcpy(ret->m_maker, maker, 2);
|
|
||||||
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))
|
|
||||||
continue;
|
|
||||||
if (maker && strlen(maker) == 2 && memcmp(m_files[i].m_maker, maker, 2))
|
|
||||||
continue;
|
|
||||||
if (!strcmp(m_files[i].m_filename, filename))
|
|
||||||
return &m_files[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void calculateChecksumBE(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 += SBig(data[i]);
|
|
||||||
*checksumInv += SBig(uint16_t(data[i] ^ 0xFFFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
*checksum = SBig(*checksum);
|
|
||||||
*checksumInv = SBig(*checksumInv);
|
|
||||||
if (*checksum == 0xFFFF)
|
|
||||||
*checksum = 0;
|
|
||||||
if (*checksumInv == 0xFFFF)
|
|
||||||
*checksumInv = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
#include "kabufuda/Directory.hpp"
|
||||||
|
#include "kabufuda/Util.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
namespace kabufuda
|
||||||
|
{
|
||||||
|
void Directory::swapEndian()
|
||||||
|
{
|
||||||
|
std::for_each(std::begin(m_files), std::end(m_files), [](File& f){
|
||||||
|
f.swapEndian();
|
||||||
|
});
|
||||||
|
|
||||||
|
m_updateCounter = SBig(m_updateCounter);
|
||||||
|
m_checksum = SBig(m_checksum);
|
||||||
|
m_checksumInv = SBig(m_checksumInv);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Directory::updateChecksum()
|
||||||
|
{
|
||||||
|
swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<uint16_t*>(__raw), 0xFFE, &m_checksum, &m_checksumInv);
|
||||||
|
swapEndian();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Directory::valid() const
|
||||||
|
{
|
||||||
|
uint16_t ckSum, ckSumInv;
|
||||||
|
Directory tmp = *this;
|
||||||
|
tmp.swapEndian();
|
||||||
|
calculateChecksumBE(reinterpret_cast<const uint16_t*>(tmp.__raw), 0xFFE, &ckSum, &ckSumInv);
|
||||||
|
return (SBig(ckSum) == m_checksum && SBig(ckSumInv) == m_checksumInv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory::Directory()
|
||||||
|
{
|
||||||
|
memset(__raw, 0xFF, BlockSize);
|
||||||
|
m_updateCounter = 0;
|
||||||
|
updateChecksum();
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory::Directory(uint8_t data[])
|
||||||
|
{
|
||||||
|
memcpy(__raw, data, BlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
Directory::Directory(const Directory& other)
|
||||||
|
{
|
||||||
|
memcpy(__raw, other.__raw, BlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Directory::operator=(const Directory& other)
|
||||||
|
{
|
||||||
|
memcpy(__raw, other.__raw, BlockSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
File* Directory::getFirstFreeFile(const char* game, const char* maker, const char* filename)
|
||||||
|
{
|
||||||
|
for (uint16_t i = 0 ; i < 127 ; i++)
|
||||||
|
{
|
||||||
|
if (m_files[i].m_id[0] == 0xFF)
|
||||||
|
{
|
||||||
|
File* ret = &m_files[i];
|
||||||
|
*ret = File(filename);
|
||||||
|
if (game && strlen(game) == 4)
|
||||||
|
memcpy(ret->m_id, game, 4);
|
||||||
|
if (maker && strlen(maker) == 2)
|
||||||
|
memcpy(ret->m_maker, maker, 2);
|
||||||
|
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))
|
||||||
|
continue;
|
||||||
|
if (maker && strlen(maker) == 2 && memcmp(m_files[i].m_maker, maker, 2))
|
||||||
|
continue;
|
||||||
|
if (!strcmp(m_files[i].m_filename, filename))
|
||||||
|
return &m_files[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include "kabufuda/File.hpp"
|
||||||
|
#include "kabufuda/Util.hpp"
|
||||||
|
|
||||||
|
namespace kabufuda
|
||||||
|
{
|
||||||
|
File::File(char data[])
|
||||||
|
{
|
||||||
|
memcpy(__raw, data, 0x40);
|
||||||
|
}
|
||||||
|
|
||||||
|
File::File(const char* filename)
|
||||||
|
{
|
||||||
|
memset(__raw, 0xFF, 0x40);
|
||||||
|
memset(m_filename, 0, 32);
|
||||||
|
size_t len = strlen(filename);
|
||||||
|
len = std::min<size_t>(len, 32);
|
||||||
|
memcpy(m_filename, filename, len);
|
||||||
|
}
|
||||||
|
void File::swapEndian()
|
||||||
|
{
|
||||||
|
m_modifiedTime = SBig(m_modifiedTime);
|
||||||
|
m_imageOffset = SBig(m_imageOffset);
|
||||||
|
m_iconFmt = SBig(m_iconFmt);
|
||||||
|
m_animSpeed = SBig(m_animSpeed);
|
||||||
|
m_firstBlock = SBig(m_firstBlock);
|
||||||
|
m_blockCount = SBig(m_blockCount);
|
||||||
|
m_reserved2 = SBig(m_reserved2);
|
||||||
|
m_commentAddr = SBig(m_commentAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
File::File()
|
||||||
|
{
|
||||||
|
memset(__raw, 0xFF, 0x40);
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,4 +23,22 @@ uint64_t getGCTime()
|
||||||
|
|
||||||
return (uint64_t)(sysTime + tzDiff + tzDST) - 0x386D4380;
|
return (uint64_t)(sysTime + tzDiff + tzDST) - 0x386D4380;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void calculateChecksumBE(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 += SBig(data[i]);
|
||||||
|
*checksumInv += SBig(uint16_t(data[i] ^ 0xFFFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
*checksum = SBig(*checksum);
|
||||||
|
*checksumInv = SBig(*checksumInv);
|
||||||
|
if (*checksum == 0xFFFF)
|
||||||
|
*checksum = 0;
|
||||||
|
if (*checksumInv == 0xFFFF)
|
||||||
|
*checksumInv = 0;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue